@Override
  public State nextState() {
    // Receive message from client
    Message msg = super.clientConnection.receiveMessage();

    // Move straight to exit state if connection closed or invalid message
    if (msg == null || msg.getMessageCode() == COD_EXIT) {
      return endConnection();
    }
    // Ignore invalid messages
    if (!this.isValid(msg)) {
      errorNumber++;
      logger.log(Level.INFO, "Invalid message received ({0})", errorNumber);
      if (errorNumber >= INVALID_MSG_NUM) {
        // End connection after too many invalid messages
        return endConnection();
      } else {
        return this;
      }
    }
    // reset counter
    errorNumber = 0;

    logger.log(
        Level.INFO,
        "Connected to: {0} ({1})",
        new Object[] {msg.getUserAgent(), super.clientConnection.getSocket().getInetAddress()});

    // Send handshake response with server version
    Message response = new Message(msg.getReceiver(), msg.getSender(), "", COD_HELLO);
    response.setUserAgent(Server.SERVER_VERSION);
    boolean isSent = super.clientConnection.send(response);
    if (!isSent) {
      // End connection if sending failed
      return endConnection();
    }

    // Move on to messaging state
    return new MessageState(super.clientConnection);
  }
  private boolean isValid(Message msg) {
    if (msg == null) {
      return false;
    }
    if (msg.getMessage().length != msg.getMessageSize()) {
      return false;
    }
    if (msg.getSender().length() < 1) {
      return false;
    }
    if (msg.getReceiver().length() < 1) {
      return false;
    }
    if (msg.getSendTime() < 0 || msg.getSendTime() > System.currentTimeMillis()) {
      return false;
    }
    if (msg.getMessageCode() != COD_HELLO) {
      return false;
    }

    return true;
  }