@Override
  protected void setRequestLineReadTimeout() throws IOException {

    /*
     * When there is no data in the buffer and this is not the first
     * request on this connection and timeouts are being used the
     * first read for this request may need a different timeout to
     * take account of time spent waiting for a processing thread.
     *
     * This is a little hacky but better than exposing the socket
     * and the timeout info to the InputBuffer
     */
    if (inputBuffer.lastValid == 0 && socket.getLastAccess() > -1) {
      int firstReadTimeout;
      if (keepAliveTimeout == -1) {
        firstReadTimeout = 0;
      } else {
        long queueTime = System.currentTimeMillis() - socket.getLastAccess();

        if (queueTime >= keepAliveTimeout) {
          // Queued for longer than timeout but there might be
          // data so use shortest possible timeout
          firstReadTimeout = 1;
        } else {
          // Cast is safe since queueTime must be less than
          // keepAliveTimeout which is an int
          firstReadTimeout = keepAliveTimeout - (int) queueTime;
        }
      }
      socket.getSocket().setSoTimeout(firstReadTimeout);
      if (!inputBuffer.fill()) {
        throw new EOFException(sm.getString("iib.eof.error"));
      }
      // Once the first byte has been read, the standard timeout should be
      // used so restore it here.
      socket.getSocket().setSoTimeout(endpoint.getSoTimeout());
    }
  }
  /**
   * Send an action to the connector.
   *
   * @param actionCode Type of the action
   * @param param Action parameter
   */
  @Override
  public void actionInternal(ActionCode actionCode, Object param) {

    if (actionCode == ActionCode.REQ_SSL_ATTRIBUTE) {

      try {
        if (sslSupport != null) {
          Object sslO = sslSupport.getCipherSuite();
          if (sslO != null) request.setAttribute(SSLSupport.CIPHER_SUITE_KEY, sslO);
          sslO = sslSupport.getPeerCertificateChain(false);
          if (sslO != null) request.setAttribute(SSLSupport.CERTIFICATE_KEY, sslO);
          sslO = sslSupport.getKeySize();
          if (sslO != null) request.setAttribute(SSLSupport.KEY_SIZE_KEY, sslO);
          sslO = sslSupport.getSessionId();
          if (sslO != null) request.setAttribute(SSLSupport.SESSION_ID_KEY, sslO);
          request.setAttribute(SSLSupport.SESSION_MGR, sslSupport);
        }
      } catch (Exception e) {
        log.warn(sm.getString("http11processor.socket.ssl"), e);
      }

    } else if (actionCode == ActionCode.REQ_HOST_ADDR_ATTRIBUTE) {

      if ((remoteAddr == null) && (socket != null)) {
        InetAddress inetAddr = socket.getSocket().getInetAddress();
        if (inetAddr != null) {
          remoteAddr = inetAddr.getHostAddress();
        }
      }
      request.remoteAddr().setString(remoteAddr);

    } else if (actionCode == ActionCode.REQ_LOCAL_NAME_ATTRIBUTE) {

      if ((localName == null) && (socket != null)) {
        InetAddress inetAddr = socket.getSocket().getLocalAddress();
        if (inetAddr != null) {
          localName = inetAddr.getHostName();
        }
      }
      request.localName().setString(localName);

    } else if (actionCode == ActionCode.REQ_HOST_ATTRIBUTE) {

      if ((remoteHost == null) && (socket != null)) {
        InetAddress inetAddr = socket.getSocket().getInetAddress();
        if (inetAddr != null) {
          remoteHost = inetAddr.getHostName();
        }
        if (remoteHost == null) {
          if (remoteAddr != null) {
            remoteHost = remoteAddr;
          } else { // all we can do is punt
            request.remoteHost().recycle();
          }
        }
      }
      request.remoteHost().setString(remoteHost);

    } else if (actionCode == ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE) {

      if (localAddr == null) localAddr = socket.getSocket().getLocalAddress().getHostAddress();

      request.localAddr().setString(localAddr);

    } else if (actionCode == ActionCode.REQ_REMOTEPORT_ATTRIBUTE) {

      if ((remotePort == -1) && (socket != null)) {
        remotePort = socket.getSocket().getPort();
      }
      request.setRemotePort(remotePort);

    } else if (actionCode == ActionCode.REQ_LOCALPORT_ATTRIBUTE) {

      if ((localPort == -1) && (socket != null)) {
        localPort = socket.getSocket().getLocalPort();
      }
      request.setLocalPort(localPort);

    } else if (actionCode == ActionCode.REQ_SSL_CERTIFICATE) {
      if (sslSupport != null) {
        /*
         * Consume and buffer the request body, so that it does not
         * interfere with the client's handshake messages
         */
        InputFilter[] inputFilters = inputBuffer.getFilters();
        ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]).setLimit(maxSavePostSize);
        inputBuffer.addActiveFilter(inputFilters[Constants.BUFFERED_FILTER]);
        try {
          Object sslO = sslSupport.getPeerCertificateChain(true);
          if (sslO != null) {
            request.setAttribute(SSLSupport.CERTIFICATE_KEY, sslO);
          }
        } catch (Exception e) {
          log.warn(sm.getString("http11processor.socket.ssl"), e);
        }
      }
    } else if (actionCode == ActionCode.ASYNC_COMPLETE) {
      if (asyncStateMachine.asyncComplete()) {
        ((JIoEndpoint) endpoint).processSocketAsync(this.socket, SocketStatus.OPEN);
      }
    } else if (actionCode == ActionCode.ASYNC_SETTIMEOUT) {
      if (param == null) return;
      long timeout = ((Long) param).longValue();
      // if we are not piggy backing on a worker thread, set the timeout
      socket.setTimeout(timeout);
    } else if (actionCode == ActionCode.ASYNC_DISPATCH) {
      if (asyncStateMachine.asyncDispatch()) {
        ((JIoEndpoint) endpoint).processSocketAsync(this.socket, SocketStatus.OPEN);
      }
    }
  }