private ControlMessage processControlMessage(ControlMessage ctrlmsg) throws IOException {
    NetworkMessage netmsg = new NetworkMessage(ControlMessage.marshal(ctrlmsg));

    netmsg.writeTo(this.output_stream);
    netmsg = NetworkMessage.readFrom(this.input_stream);

    try {
      ctrlmsg = ControlMessage.unmarshal(netmsg.getData());
    } catch (ParseException ex) {
      throw new IOException(
          "Received an invalid message from remote server '"
              + this.server_address
              + "': "
              + ex.getMessage()
              + ".");
    }

    if (ctrlmsg.getType() != ControlMessage.ControlType.SUCCESS
        && ctrlmsg.getType() != ControlMessage.ControlType.FAILURE) {
      throw new IOException(
          "Remote server '" + this.server_address + "' does not follow the protocol.");
    }

    return ctrlmsg;
  }
 public void shutDown() throws IOException {
   try {
     if (this.connected && !this.socket.isOutputShutdown()) {
       ControlMessage ctrlmsg = new ControlMessage(ControlMessage.ControlType.SHUTDOWN);
       NetworkMessage netmsg = new NetworkMessage(ControlMessage.marshal(ctrlmsg));
       netmsg.writeTo(this.output_stream);
     }
     if (this.input_stream != null) {
       this.input_stream.close();
     }
     if (this.output_stream != null) {
       this.output_stream.close();
     }
     if (this.socket != null && !this.socket.isClosed()) {
       this.socket.close();
     }
   } catch (IOException ex) {
     logger.warn(
         "Warning! Unable to tear down connection to server ("
             + this.server_address
             + "): "
             + ex.getMessage());
   }
   this.connected = false;
   logger.info("Remote server at '" + this.server_address + "' shut down.");
 }