@Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("messageReceived: Got " + e.getMessage().getClass());
    }
    // Authorize: client is allowed to doRequest() if and only if the client
    // has successfully authenticated with this server.
    SaslNettyServer saslNettyServer = NettyServer.CHANNEL_SASL_NETTY_SERVERS.get(ctx.getChannel());
    if (saslNettyServer == null) {
      LOG.warn(
          "messageReceived: This client is *NOT* authorized to perform "
              + "this action since there's no saslNettyServer to "
              + "authenticate the client: "
              + "refusing to perform requested action: "
              + e.getMessage());
      return;
    }

    if (!saslNettyServer.isComplete()) {
      LOG.warn(
          "messageReceived: This client is *NOT* authorized to perform "
              + "this action because SASL authentication did not complete: "
              + "refusing to perform requested action: "
              + e.getMessage());
      // Return now *WITHOUT* sending upstream here, since client
      // not authorized.
      return;
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "messageReceived: authenticated client: "
              + saslNettyServer.getUserName()
              + " is authorized to do request "
              + "on server.");
    }
    // We call sendUpstream() since the client is allowed to perform this
    // request. The client's request will now proceed to the next
    // pipeline component, namely, RequestServerHandler.
    ctx.sendUpstream(e);
  }
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("messageReceived: Got " + e.getMessage().getClass());
    }

    WritableRequest writableRequest = (WritableRequest) e.getMessage();
    // Simulate a closed connection on the first request (if desired)
    // TODO: Move out into a separate, dedicated handler.
    if (closeFirstRequest && !ALREADY_CLOSED_FIRST_REQUEST) {
      LOG.info(
          "messageReceived: Simulating closing channel on first "
              + "request "
              + writableRequest.getRequestId()
              + " from "
              + writableRequest.getClientId());
      setAlreadyClosedFirstRequest();
      ctx.getChannel().close();
      return;
    }

    if (writableRequest.getType() == RequestType.SASL_TOKEN_MESSAGE_REQUEST) {
      // initialize server-side SASL functionality, if we haven't yet
      // (in which case we are looking at the first SASL message from the
      // client).
      SaslNettyServer saslNettyServer =
          NettyServer.CHANNEL_SASL_NETTY_SERVERS.get(ctx.getChannel());
      if (saslNettyServer == null) {
        if (LOG.isDebugEnabled()) {
          LOG.debug(
              "No saslNettyServer for "
                  + ctx.getChannel()
                  + " yet; creating now, with secret manager: "
                  + secretManager);
        }
        saslNettyServer = new SaslNettyServer(secretManager);
        NettyServer.CHANNEL_SASL_NETTY_SERVERS.set(ctx.getChannel(), saslNettyServer);
      } else {
        if (LOG.isDebugEnabled()) {
          LOG.debug(
              "Found existing saslNettyServer on server:"
                  + ctx.getChannel().getLocalAddress()
                  + " for client "
                  + ctx.getChannel().getRemoteAddress());
        }
      }

      ((SaslTokenMessageRequest) writableRequest).processToken(saslNettyServer);
      // Send response to client.
      ctx.getChannel().write(writableRequest);
      if (saslNettyServer.isComplete()) {
        // If authentication of client is complete, we will also send a
        // SASL-Complete message to the client.
        if (LOG.isDebugEnabled()) {
          LOG.debug(
              "SASL authentication is complete for client with "
                  + "username: "******"Removing SaslServerHandler from pipeline since SASL "
                  + "authentication is complete.");
        }
        ctx.getPipeline().remove(this);
      }
      // do not send upstream to other handlers: no further action needs to be
      // done for SASL_TOKEN_MESSAGE_REQUEST requests.
      return;
    } else {
      // Client should not be sending other-than-SASL messages before
      // SaslServerHandler has removed itself from the pipeline. Such non-SASL
      // requests will be denied by the Authorize channel handler (the next
      // handler upstream in the server pipeline) if SASL authentication has
      // not completed.
      LOG.warn("Sending upstream an unexpected non-SASL message :  " + writableRequest);
      ctx.sendUpstream(e);
    }
  }
 /**
  * Constructor
  *
  * @param conf Configuration
  */
 public SaslServerHandler(Configuration conf) throws IOException {
   SaslNettyServer.init(conf);
   setupSecretManager(conf);
   closeFirstRequest = NETTY_SIMULATE_FIRST_REQUEST_CLOSED.get(conf);
 }