/**
   * @return
   * @throws IOException
   */
  protected SshMessage processMessages() throws IOException {
    byte[] msgdata = null;
    SshMessage msg;
    SshMessageStore ms;

    while (state.getValue() != TransportProtocolState.DISCONNECTED) {
      long currentTime = System.currentTimeMillis();

      transferredKB = sshIn.getNumBytesTransfered() / 1024 + sshOut.getNumBytesTransfered() / 1024;

      long kbLimit = transferredKB - lastTriggeredKB;

      if (((currentTime - startTime) > kexTimeout) || (kbLimit > kexTransferLimitKB)) {
        //    ((sshIn.getNumBytesTransfered() +
        //    sshOut.getNumBytesTransfered()) > kexTransferLimit)) {
        startTime = currentTime;
        lastTriggeredKB = transferredKB;
        if (log.isDebugEnabled()) {
          log.info("rekey");
        }
        sendKeyExchangeInit();
      }

      boolean hasmsg = false;

      while (!hasmsg) {
        try {
          msgdata = sshIn.readMessage();
          hasmsg = true;
        } catch (InterruptedIOException ex /*SocketTimeoutException ex*/) {
          log.info("Possible timeout on transport inputstream");

          Iterator it = eventHandlers.iterator();
          TransportProtocolEventHandler eventHandler;

          while (it.hasNext()) {
            eventHandler = (TransportProtocolEventHandler) it.next();
            eventHandler.onSocketTimeout(this /*,
                        provider.isConnected()*/);
          }
        }
      }

      Integer messageId = SshMessage.getMessageId(msgdata);

      if (!messageStore.isRegisteredMessage(messageId)) {
        try {
          ms = getMessageStore(messageId);
          msg = ms.createMessage(msgdata);

          if (log.isDebugEnabled()) {
            log.info("Received " + msg.getMessageName());
          }

          ms.addMessage(msg);
        } catch (MessageNotRegisteredException mnre) {
          log.info("Unimplemented message received " + String.valueOf(messageId.intValue()));
          msg = new SshMsgUnimplemented(sshIn.getSequenceNo());
          sendMessage(msg, this);
        }
      } else {
        return messageStore.createMessage(msgdata);
      }
    }

    throw new IOException("The transport protocol has disconnected");
  }
  /**
   * @param filter
   * @return
   * @throws IOException
   */
  public SshMessage readMessage(int[] filter) throws IOException {
    byte[] msgdata = null;
    SshMessage msg;

    while (state.getValue() != TransportProtocolState.DISCONNECTED) {
      boolean hasmsg = false;

      while (!hasmsg) {
        msgdata = sshIn.readMessage();
        hasmsg = true;
      }

      Integer messageId = SshMessage.getMessageId(msgdata);

      // First check the filter
      for (int i = 0; i < filter.length; i++) {
        if (filter[i] == messageId.intValue()) {
          if (messageStore.isRegisteredMessage(messageId)) {
            return messageStore.createMessage(msgdata);
          } else {
            SshMessageStore ms = getMessageStore(messageId);
            msg = ms.createMessage(msgdata);

            if (log.isDebugEnabled()) {
              log.debug("Processing " + msg.getMessageName());
            }

            return msg;
          }
        }
      }

      if (messageStore.isRegisteredMessage(messageId)) {
        msg = messageStore.createMessage(msgdata);

        switch (messageId.intValue()) {
          case SshMsgDisconnect.SSH_MSG_DISCONNECT:
            {
              onMsgDisconnect((SshMsgDisconnect) msg);

              break;
            }

          case SshMsgIgnore.SSH_MSG_IGNORE:
            {
              onMsgIgnore((SshMsgIgnore) msg);

              break;
            }

          case SshMsgUnimplemented.SSH_MSG_UNIMPLEMENTED:
            {
              onMsgUnimplemented((SshMsgUnimplemented) msg);

              break;
            }

          case SshMsgDebug.SSH_MSG_DEBUG:
            {
              onMsgDebug((SshMsgDebug) msg);

              break;
            }

          default: // Exception not allowed
            throw new IOException("Unexpected transport protocol message");
        }
      } else {
        throw new IOException("Unexpected message received");
      }
    }

    throw new IOException("The transport protocol disconnected");
  }