/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.apache.coyote;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConnection;

import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.parser.Host;
import org.apache.tomcat.util.log.UserDataHelper;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.DispatchType;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SocketEvent;
import org.apache.tomcat.util.net.SocketWrapperBase;
import org.apache.tomcat.util.res.StringManager;

/**
 * Provides functionality and attributes common to all supported protocols (currently HTTP and AJP) for processing a
 * single request/response.
 */
public abstract class AbstractProcessor extends AbstractProcessorLight implements ActionHook {

    /** The string manager for this class. */
    private static final StringManager sm = StringManager.getManager(AbstractProcessor.class);

    /** Used to avoid useless B2C conversion on the host name. */
    private char[] hostNameC = new char[0];

    /** The adapter for this processor. */
    protected final Adapter adapter;
    /** State machine for async processing. */
    protected final AsyncStateMachine asyncStateMachine;
    private volatile long asyncTimeout = -1;
    /*
     * Tracks the current async generation when a timeout is dispatched. In the time it takes for a container thread to
     * be allocated and the timeout processing to start, it is possible that the application completes this generation
     * of async processing and starts a new one. If the timeout is then processed against the new generation, response
     * mix-up can occur. This field is used to ensure that any timeout event processed is for the current async
     * generation. This prevents the response mix-up.
     */
    private volatile long asyncTimeoutGeneration = 0;
    /** The request being processed. */
    protected final Request request;
    /** The response being processed. */
    protected final Response response;
    /** The socket wrapper for this processor. */
    protected volatile SocketWrapperBase<?> socketWrapper = null;
    /** SSL support for this connection. */
    protected volatile SSLSupport sslSupport;


    /**
     * Error state for the request/response currently being processed.
     */
    private ErrorState errorState = ErrorState.NONE;

    /** User data helper for logging. */
    protected final UserDataHelper userDataHelper;

    /**
     * Creates a new processor with the given adapter.
     *
     * @param adapter The adapter for this processor
     */
    public AbstractProcessor(Adapter adapter) {
        this(adapter, new Request(), new Response());
    }


    /**
     * Constructs a new processor with the given adapter, request, and response.
     *
     * @param adapter The adapter for this processor
     * @param coyoteRequest The coyote request
     * @param coyoteResponse The coyote response
     */
    protected AbstractProcessor(Adapter adapter, Request coyoteRequest, Response coyoteResponse) {
        this.adapter = adapter;
        asyncStateMachine = new AsyncStateMachine(this);
        request = coyoteRequest;
        response = coyoteResponse;
        response.setHook(this);
        request.setResponse(response);
        request.setHook(this);
        userDataHelper = new UserDataHelper(getLog());
    }


    /**
     * Update the current error state to the new error state if the new error state is more severe than the current
     * error state.
     *
     * @param errorState The error status details
     * @param t          The error which occurred
     */
    protected void setErrorState(ErrorState errorState, Throwable t) {
        if (getLog().isDebugEnabled()) {
            getLog().debug(sm.getString("abstractProcessor.setErrorState", errorState), t);
        }
        // Mark the response as errored. Async error deduplication is
        // handled by asyncStateMachine.asyncError() below.
        response.setError();
        boolean blockIo = this.errorState.isIoAllowed() && !errorState.isIoAllowed();
        this.errorState = this.errorState.getMostSevere(errorState);
        // Don't change the status code for IOException since that is almost
        // certainly a client disconnect in which case it is preferable to keep
        // the original status code http://markmail.org/message/4cxpwmxhtgnrwh7n
        if (response.getStatus() < 400 && !(t instanceof IOException)) {
            response.setStatus(500);
        }
        if (t != null) {
            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
        }
        if (blockIo && isAsync()) {
            if (asyncStateMachine.asyncError()) {
                processSocketEvent(SocketEvent.ERROR, true);
            }
        }
    }


    /**
     * Gets the current error state.
     *
     * @return the current error state
     */
    protected ErrorState getErrorState() {
        return errorState;
    }


    @Override
    public Request getRequest() {
        return request;
    }


    /**
     * Get the associated adapter.
     *
     * @return the associated adapter
     */
    public Adapter getAdapter() {
        return adapter;
    }


    /**
     * Set the socket wrapper being used.
     *
     * @param socketWrapper The socket wrapper
     */
    protected void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
        this.socketWrapper = socketWrapper;
    }


    /**
     * Get the socket wrapper being used.
     *
     * @return the socket wrapper being used.
     */
    protected final SocketWrapperBase<?> getSocketWrapper() {
        return socketWrapper;
    }


    @Override
    public final void setSslSupport(SSLSupport sslSupport) {
        this.sslSupport = sslSupport;
    }


    /**
     * Provides a mechanism to trigger processing on a container thread.
     *
     * @param runnable The task representing the processing that needs to take place on a container thread
     */
    protected void execute(Runnable runnable) {
        SocketWrapperBase<?> socketWrapper = this.socketWrapper;
        if (socketWrapper == null) {
            throw new RejectedExecutionException(sm.getString("abstractProcessor.noExecute"));
        } else {
            socketWrapper.execute(runnable);
        }
    }


    @Override
    public boolean isAsync() {
        return asyncStateMachine.isAsync();
    }


    @Override
    public SocketState asyncPostProcess() throws IOException {
        return asyncStateMachine.asyncPostProcess();
    }


    @Override
    public final SocketState dispatch(SocketEvent status) throws IOException {

        if (status == SocketEvent.OPEN_WRITE && response.getWriteListener() != null) {
            asyncStateMachine.asyncOperation();
            try {
                if (flushBufferedWrite()) {
                    return SocketState.LONG;
                }
            } catch (IOException ioe) {
                if (getLog().isDebugEnabled()) {
                    getLog().debug(sm.getString("abstractProcessor.asyncFail"), ioe);
                }
                status = SocketEvent.ERROR;
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
            }
        } else if (status == SocketEvent.OPEN_READ && request.getReadListener() != null) {
            dispatchNonBlockingRead();
        } else if (status == SocketEvent.ERROR) {
            // An I/O error occurred on a non-container thread. This includes:
            // - read/write timeouts fired by the Poller in NIO
            // - completion handler failures in NIO2

            if (request.getAttribute(RequestDispatcher.ERROR_EXCEPTION) == null) {
                // Because the error did not occur on a container thread the
                // request's error attribute has not been set. If an exception
                // is available from the socketWrapper, use it to set the
                // request's error attribute here so it is visible to the error
                // handling.
                request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, socketWrapper.getError());
            }

            if (request.getReadListener() != null || response.getWriteListener() != null) {
                // The error occurred during non-blocking I/O. Set the correct
                // state else the error handling will trigger an ISE.
                asyncStateMachine.asyncOperation();
            }
        }

        RequestInfo rp = request.getRequestProcessor();
        try {
            rp.setStage(Constants.STAGE_SERVICE);
            if (!getAdapter().asyncDispatch(request, response, status)) {
                setErrorState(ErrorState.CLOSE_NOW, null);
            }
        } catch (InterruptedIOException e) {
            setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setErrorState(ErrorState.CLOSE_NOW, t);
            getLog().error(sm.getString("http11processor.request.process"), t);
        }

        rp.setStage(Constants.STAGE_ENDED);

        SocketState state;

        if (getErrorState().isError()) {
            request.updateCounters();
            state = SocketState.CLOSED;
        } else if (isAsync()) {
            state = SocketState.LONG;
        } else {
            request.updateCounters();
            state = dispatchEndRequest();
        }

        if (getLog().isTraceEnabled()) {
            getLog().trace("Socket: [" + socketWrapper + "], Status in: [" + status + "], State out: [" + state + "]");
        }

        return state;
    }


    /**
     * Parses the Host header value and populates the server name and port.
     *
     * @param valueMB The MessageBytes containing the Host header value
     */
    protected void parseHost(MessageBytes valueMB) {
        if (valueMB == null || valueMB.isNull()) {
            populateHost();
            populatePort();
            return;
        } else if (valueMB.getLength() == 0) {
            // Empty Host header so set sever name to empty string
            request.serverName().setString("");
            populatePort();
            return;
        }

        ByteChunk valueBC = valueMB.getByteChunk();
        byte[] valueB = valueBC.getBytes();
        int valueL = valueBC.getLength();
        int valueS = valueBC.getStart();
        if (hostNameC.length < valueL) {
            hostNameC = new char[valueL];
        }

        try {
            // Validates the host name
            int colonPos = Host.parse(valueMB);

            // Extract the port information first, if any
            if (colonPos != -1) {
                int port = 0;
                for (int i = colonPos + 1; i < valueL; i++) {
                    char c = (char) valueB[i + valueS];
                    if (c < '0' || c > '9') {
                        response.setStatus(400);
                        setErrorState(ErrorState.CLOSE_CLEAN, null);
                        return;
                    }
                    int digit = c - '0';
                    if (port > (Integer.MAX_VALUE - digit) / 10) {
                        response.setStatus(400);
                        setErrorState(ErrorState.CLOSE_CLEAN, null);
                        return;
                    }
                    port = port * 10 + digit;
                }
                request.setServerPort(port);

                // Only need to copy the host name up to the :
                valueL = colonPos;
            }

            // Extract the host name
            for (int i = 0; i < valueL; i++) {
                hostNameC[i] = (char) valueB[i + valueS];
            }
            request.serverName().setChars(hostNameC, 0, valueL);

        } catch (IllegalArgumentException e) {
            // IllegalArgumentException indicates that the host name is invalid
            UserDataHelper.Mode logMode = userDataHelper.getNextMode();
            if (logMode != null) {
                String message = sm.getString("abstractProcessor.hostInvalid", valueMB.toString());
                switch (logMode) {
                    case INFO_THEN_DEBUG:
                        message += sm.getString("abstractProcessor.fallToDebug");
                        //$FALL-THROUGH$
                    case INFO:
                        getLog().info(message, e);
                        break;
                    case DEBUG:
                        getLog().debug(message, e);
                }
            }

            response.setStatus(400);
            setErrorState(ErrorState.CLOSE_CLEAN, e);
        }
    }


    /**
     * Called when a host header is not present in the request (e.g. HTTP/1.0). It populates the server name with
     * appropriate information. The source is expected to vary by protocol.
     * <p>
     * The default implementation is a NO-OP.
     */
    protected void populateHost() {
        // NO-OP
    }


    /**
     * Called when a host header is not present or is empty in the request (e.g. HTTP/1.0). It populates the server port
     * with appropriate information. The source is expected to vary by protocol.
     * <p>
     * The default implementation is a NO-OP.
     */
    protected void populatePort() {
        // NO-OP
    }


    @Override
    public final void action(ActionCode actionCode, Object param) {
        switch (actionCode) {
            // 'Normal' servlet support
            case COMMIT: {
                if (!response.isCommitted()) {
                    try {
                        // Validate and write response headers
                        prepareResponse();
                    } catch (IOException ioe) {
                        handleIOException(ioe);
                    }
                }
                break;
            }
            case CLOSE: {
                action(ActionCode.COMMIT, null);
                try {
                    finishResponse();
                } catch (IOException ioe) {
                    handleIOException(ioe);
                }
                break;
            }
            case ACK: {
                ack((ContinueResponseTiming) param);
                break;
            }
            case EARLY_HINTS: {
                try {
                    earlyHints();
                } catch (IOException ioe) {
                    handleIOException(ioe);
                }
                break;
            }
            case CLIENT_FLUSH: {
                action(ActionCode.COMMIT, null);
                try {
                    flush();
                } catch (IOException ioe) {
                    handleIOException(ioe);
                    response.setErrorException(ioe);
                }
                break;
            }
            case AVAILABLE: {
                request.setAvailable(available(Boolean.TRUE.equals(param)));
                break;
            }
            case REQ_SET_BODY_REPLAY: {
                ByteChunk body = (ByteChunk) param;
                setRequestBody(body);
                break;
            }

            // Error handling
            case IS_ERROR: {
                ((AtomicBoolean) param).set(getErrorState().isError());
                break;
            }
            case IS_IO_ALLOWED: {
                ((AtomicBoolean) param).set(getErrorState().isIoAllowed());
                break;
            }
            case CLOSE_NOW: {
                // Prevent further writes to the response
                setSwallowResponse();
                if (param instanceof Throwable) {
                    setErrorState(ErrorState.CLOSE_NOW, (Throwable) param);
                } else {
                    setErrorState(ErrorState.CLOSE_NOW, null);
                }
                break;
            }
            case DISABLE_SWALLOW_INPUT: {
                // Cancelled upload or similar.
                // No point reading the remainder of the request.
                disableSwallowRequest();
                // This is an error state. Make sure it is marked as such.
                setErrorState(ErrorState.CLOSE_CLEAN, null);
                break;
            }

            // Request attribute support
            case REQ_HOST_ADDR_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.remoteAddr().setString(socketWrapper.getRemoteAddr());
                }
                break;
            }
            case REQ_PEER_ADDR_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.peerAddr().setString(socketWrapper.getRemoteAddr());
                }
                break;
            }
            case REQ_HOST_ATTRIBUTE: {
                populateRequestAttributeRemoteHost();
                break;
            }
            case REQ_LOCALPORT_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.setLocalPort(socketWrapper.getLocalPort());
                }
                break;
            }
            case REQ_LOCAL_ADDR_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.localAddr().setString(socketWrapper.getLocalAddr());
                }
                break;
            }
            case REQ_LOCAL_NAME_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.localName().setString(socketWrapper.getLocalName());
                }
                break;
            }
            case REQ_REMOTEPORT_ATTRIBUTE: {
                if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
                    request.setRemotePort(socketWrapper.getRemotePort());
                }
                break;
            }

            // SSL request attribute support
            case REQ_SSL_ATTRIBUTE: {
                populateSslRequestAttributes();
                break;
            }
            case REQ_SSL_CERTIFICATE: {
                try {
                    sslReHandShake();
                } catch (IOException ioe) {
                    setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe);
                }
                break;
            }

            // Servlet 3.0 asynchronous support
            case ASYNC_START: {
                asyncStateMachine.asyncStart((AsyncContextCallback) param);
                break;
            }
            case ASYNC_COMPLETE: {
                clearDispatches();
                if (asyncStateMachine.asyncComplete()) {
                    processSocketEvent(SocketEvent.OPEN_READ, true);
                }
                break;
            }
            case ASYNC_DISPATCH: {
                if (asyncStateMachine.asyncDispatch()) {
                    processSocketEvent(SocketEvent.OPEN_READ, true);
                }
                break;
            }
            case ASYNC_DISPATCHED: {
                asyncStateMachine.asyncDispatched();
                break;
            }
            case ASYNC_ERROR: {
                asyncStateMachine.asyncError();
                break;
            }
            case ASYNC_IS_ASYNC: {
                ((AtomicBoolean) param).set(asyncStateMachine.isAsync());
                break;
            }
            case ASYNC_IS_COMPLETING: {
                ((AtomicBoolean) param).set(asyncStateMachine.isCompleting());
                break;
            }
            case ASYNC_IS_DISPATCHING: {
                ((AtomicBoolean) param).set(asyncStateMachine.isAsyncDispatching());
                break;
            }
            case ASYNC_IS_ERROR: {
                ((AtomicBoolean) param).set(asyncStateMachine.isAsyncError());
                break;
            }
            case ASYNC_IS_STARTED: {
                ((AtomicBoolean) param).set(asyncStateMachine.isAsyncStarted());
                break;
            }
            case ASYNC_IS_TIMINGOUT: {
                ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
                break;
            }
            case ASYNC_RUN: {
                asyncStateMachine.asyncRun((Runnable) param);
                break;
            }
            case ASYNC_SETTIMEOUT: {
                if (param == null) {
                    return;
                }
                long timeout = ((Long) param).longValue();
                setAsyncTimeout(timeout);
                break;
            }
            case ASYNC_TIMEOUT: {
                AtomicBoolean result = (AtomicBoolean) param;
                result.set(asyncStateMachine.asyncTimeout());
                break;
            }
            case ASYNC_POST_PROCESS: {
                try {
                    asyncStateMachine.asyncPostProcess();
                } catch (IOException ioe) {
                    handleIOException(ioe);
                }
                break;
            }

            // Servlet 3.1 non-blocking I/O
            case REQUEST_BODY_FULLY_READ: {
                AtomicBoolean result = (AtomicBoolean) param;
                result.set(isRequestBodyFullyRead());
                break;
            }
            case NB_READ_INTEREST: {
                AtomicBoolean isReady = (AtomicBoolean) param;
                isReady.set(isReadyForRead());
                break;
            }
            case NB_WRITE_INTEREST: {
                AtomicBoolean isReady = (AtomicBoolean) param;
                isReady.set(isReadyForWrite());
                break;
            }
            case DISPATCH_READ: {
                addDispatch(DispatchType.NON_BLOCKING_READ);
                break;
            }
            case DISPATCH_WRITE: {
                addDispatch(DispatchType.NON_BLOCKING_WRITE);
                break;
            }
            case DISPATCH_ERROR: {
                addDispatch(DispatchType.NON_BLOCKING_ERROR);
                break;
            }
            case DISPATCH_EXECUTE: {
                executeDispatches();
                break;
            }

            // Servlet 3.1 HTTP Upgrade
            case UPGRADE: {
                doHttpUpgrade((UpgradeToken) param);
                break;
            }

            // Servlet 4.0 Trailers
            case IS_TRAILER_FIELDS_READY: {
                AtomicBoolean result = (AtomicBoolean) param;
                result.set(isTrailerFieldsReady());
                break;
            }
            case IS_TRAILER_FIELDS_SUPPORTED: {
                AtomicBoolean result = (AtomicBoolean) param;
                result.set(isTrailerFieldsSupported());
                break;
            }

            // Identifiers
            case PROTOCOL_REQUEST_ID: {
                @SuppressWarnings("unchecked")
                AtomicReference<Object> result = (AtomicReference<Object>) param;
                result.set(getProtocolRequestId());
                break;
            }
            case SERVLET_CONNECTION: {
                @SuppressWarnings("unchecked")
                AtomicReference<Object> result = (AtomicReference<Object>) param;
                result.set(getServletConnection());
                break;
            }
        }
    }


    private void handleIOException(IOException ioe) {
        if (ioe instanceof CloseNowException) {
            // Close the channel but keep the connection open
            setErrorState(ErrorState.CLOSE_NOW, ioe);
        } else {
            // Close the connection and all channels within that connection
            setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe);
        }
    }


    /**
     * Perform any necessary processing for a non-blocking read before dispatching to the adapter.
     */
    protected void dispatchNonBlockingRead() {
        asyncStateMachine.asyncOperation();
    }


    /**
     * {@inheritDoc}
     * <p>
     * Subclasses of this base class represent a single request/response pair. The timeout to be processed is,
     * therefore, the Servlet asynchronous processing timeout.
     */
    @Override
    public void timeoutAsync(long now) {
        if (now < 0) {
            doTimeoutAsync();
        } else {
            long asyncTimeout = getAsyncTimeout();
            if (asyncTimeout > 0) {
                long asyncStart = asyncStateMachine.getLastAsyncStart();
                if ((now - asyncStart) > asyncTimeout) {
                    doTimeoutAsync();
                }
            } else if (!asyncStateMachine.isAvailable()) {
                // Timeout the async process if the associated web application
                // is no longer running.
                doTimeoutAsync();
            }
        }
    }


    private void doTimeoutAsync() {
        // Avoid multiple timeouts
        setAsyncTimeout(-1);
        asyncTimeoutGeneration = asyncStateMachine.getCurrentGeneration();
        processSocketEvent(SocketEvent.TIMEOUT, true);
    }


    @Override
    public boolean checkAsyncTimeoutGeneration() {
        return asyncTimeoutGeneration == asyncStateMachine.getCurrentGeneration();
    }


    /**
     * Sets the async timeout.
     *
     * @param timeout The timeout in milliseconds
     */
    public void setAsyncTimeout(long timeout) {
        asyncTimeout = timeout;
    }


    /**
     * Gets the async timeout.
     *
     * @return the async timeout in milliseconds
     */
    public long getAsyncTimeout() {
        return asyncTimeout;
    }


    @Override
    public void recycle() {
        errorState = ErrorState.NONE;
        asyncStateMachine.recycle();
    }


    /**
     * When committing the response, we have to validate the set of headers, as well as set up the response filters.
     *
     * @throws IOException IO exception during commit
     */
    protected abstract void prepareResponse() throws IOException;


    /**
     * Finish the current response.
     *
     * @throws IOException IO exception during the write
     */
    protected abstract void finishResponse() throws IOException;


    /**
     * Process acknowledgment of the request.
     *
     * @param continueResponseTiming specifies when an acknowledgment should be sent
     */
    protected abstract void ack(ContinueResponseTiming continueResponseTiming);


    /**
     * Process early hints (103 Early Hints).
     *
     * @throws IOException IO exception during processing
     */
    protected abstract void earlyHints() throws IOException;


    /**
     * Callback to write data from the buffer.
     *
     * @throws IOException IO exception during the write
     */
    protected abstract void flush() throws IOException;


    /**
     * Queries if bytes are available in buffers.
     *
     * @param doRead {@code true} to perform a read when no bytes are availble
     *
     * @return the amount of bytes that are known to be available
     */
    protected abstract int available(boolean doRead);


    /**
     * Set the specified byte chunk as the request body that will be read. This allows saving and processing requests.
     *
     * @param body the byte chunk containing all the request bytes
     */
    protected abstract void setRequestBody(ByteChunk body);


    /**
     * The response is finished and no additional bytes need to be sent to the client.
     */
    protected abstract void setSwallowResponse();


    /**
     * Swallowing bytes is required for pipelining requests, so this allows to avoid doing extra operations in case an
     * error occurs and the connection is to be closed instead.
     */
    protected abstract void disableSwallowRequest();


    /**
     * Processors that populate request attributes directly (e.g. AJP) should over-ride this method and return
     * {@code false}.
     *
     * @return {@code true} if the SocketWrapper should be used to populate the request attributes, otherwise
     *             {@code false}.
     */
    protected boolean getPopulateRequestAttributesFromSocket() {
        return true;
    }


    /**
     * Populate the remote host request attribute. Processors (e.g. AJP) that populate this from an alternative source
     * should override this method.
     */
    protected void populateRequestAttributeRemoteHost() {
        if (getPopulateRequestAttributesFromSocket() && socketWrapper != null) {
            request.remoteHost().setString(socketWrapper.getRemoteHost());
        }
    }


    /**
     * Populate the TLS related request attributes from the {@link SSLSupport} instance associated with this processor.
     * Protocols that populate TLS attributes from a different source (e.g. AJP) should override this method.
     */
    protected void populateSslRequestAttributes() {
        try {
            if (sslSupport != null) {
                Object sslO = sslSupport.getProtocol();
                if (sslO != null) {
                    request.setAttribute(SSLSupport.SECURE_PROTOCOL_KEY, sslO);
                }
                sslO = sslSupport.getCipherSuite();
                if (sslO != null) {
                    request.setAttribute(SSLSupport.CIPHER_SUITE_KEY, sslO);
                }
                sslO = sslSupport.getPeerCertificateChain();
                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);
                }
                sslO = sslSupport.getRequestedProtocols();
                if (sslO != null) {
                    request.setAttribute(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY, sslO);
                }
                sslO = sslSupport.getRequestedCiphers();
                if (sslO != null) {
                    request.setAttribute(SSLSupport.REQUESTED_CIPHERS_KEY, sslO);
                }
                request.setAttribute(SSLSupport.SESSION_MGR, sslSupport);
            }
        } catch (Exception e) {
            getLog().warn(sm.getString("abstractProcessor.socket.ssl"), e);
        }
    }


    /**
     * Processors that can perform a TLS re-handshake (e.g. HTTP/1.1) should override this method and implement the
     * re-handshake.
     *
     * @throws IOException If authentication is required then there will be I/O with the client and this exception will
     *                         be thrown if that goes wrong
     */
    protected void sslReHandShake() throws IOException {
        // NO-OP
    }


    /**
     * Processes a socket event.
     *
     * @param event The socket event to process
     * @param dispatch {@code true} to dispatch to a container thread
     */
    protected void processSocketEvent(SocketEvent event, boolean dispatch) {
        SocketWrapperBase<?> socketWrapper = getSocketWrapper();
        if (socketWrapper != null) {
            socketWrapper.processSocket(event, dispatch);
        }
    }


    /**
     * Checks if the processor is ready for reading.
     *
     * @return {@code true} if there is data available or read interest is registered
     */
    protected boolean isReadyForRead() {
        if (available(true) > 0) {
            return true;
        }

        if (!isRequestBodyFullyRead()) {
            registerReadInterest();
        }

        return false;
    }


    /**
     * Checks if the request body has been fully read.
     *
     * @return {@code true} if it is known that the request body has been fully read
     */
    protected abstract boolean isRequestBodyFullyRead();


    /**
     * When using non blocking IO, register to get a callback when polling determines that bytes are available for
     * reading.
     */
    protected abstract void registerReadInterest();


    /**
     * Checks if the processor is ready for writing.
     *
     * @return {@code true} if bytes can be written without blocking
     */
    protected abstract boolean isReadyForWrite();


    /**
     * Executes any pending non-blocking dispatches.
     */
    protected void executeDispatches() {
        SocketWrapperBase<?> socketWrapper = getSocketWrapper();
        Iterator<DispatchType> dispatches = getIteratorAndClearDispatches();
        if (socketWrapper != null) {
            Lock lock = socketWrapper.getLock();
            lock.lock();
            try {
                /*
                 * This method is called when non-blocking IO is initiated by defining a read and/or write listener in a
                 * non-container thread. It is called once the non-container thread completes so that the first calls to
                 * onWritePossible() and/or onDataAvailable() as appropriate are made by the container.
                 *
                 * Processing the dispatches requires (TODO confirm applies without APR) that the socket has been added
                 * to the waitingRequests queue. This may not have occurred by the time that the non-container thread
                 * completes triggering the call to this method. Therefore, the coded syncs on the SocketWrapper as the
                 * container thread that initiated this non-container thread holds a lock on the SocketWrapper. The
                 * container thread will add the socket to the waitingRequests queue before releasing the lock on the
                 * socketWrapper. Therefore, by obtaining the lock on socketWrapper before processing the dispatches, we
                 * can be sure that the socket has been added to the waitingRequests queue.
                 */
                while (dispatches != null && dispatches.hasNext()) {
                    DispatchType dispatchType = dispatches.next();
                    socketWrapper.processSocket(dispatchType.getSocketStatus(), false);
                }
            } finally {
                lock.unlock();
            }
        }
    }


    /**
     * {@inheritDoc} Processors that implement HTTP upgrade must override this method and provide the necessary token.
     */
    @Override
    public UpgradeToken getUpgradeToken() {
        // Should never reach this code but in case we do...
        throw new IllegalStateException(sm.getString("abstractProcessor.httpupgrade.notsupported"));
    }


    /**
     * Process an HTTP upgrade. Processors that support HTTP upgrade should override this method and process the
     * provided token.
     *
     * @param upgradeToken Contains all the information necessary for the Processor to process the upgrade
     *
     * @throws UnsupportedOperationException if the protocol does not support HTTP upgrade
     */
    protected void doHttpUpgrade(UpgradeToken upgradeToken) {
        // Should never happen
        throw new UnsupportedOperationException(sm.getString("abstractProcessor.httpupgrade.notsupported"));
    }


    /**
     * {@inheritDoc} Processors that implement HTTP upgrade must override this method.
     */
    @Override
    public ByteBuffer getLeftoverInput() {
        // Should never reach this code but in case we do...
        throw new IllegalStateException(sm.getString("abstractProcessor.httpupgrade.notsupported"));
    }


    /**
     * {@inheritDoc} Processors that implement HTTP upgrade must override this method.
     */
    @Override
    public boolean isUpgrade() {
        return false;
    }


    /**
     * Checks if trailer fields are ready.
     *
     * @return {@code true} if trailer fields are ready
     */
    protected abstract boolean isTrailerFieldsReady();


    /**
     * Protocols that support trailer fields should override this method and return {@code true}.
     *
     * @return {@code true} if trailer fields are supported by this processor, otherwise {@code false}.
     */
    protected boolean isTrailerFieldsSupported() {
        return false;
    }


    /**
     * Protocols that provide per HTTP request IDs (e.g. Stream ID for HTTP/2) should override this method and return
     * the appropriate ID.
     *
     * @return The ID associated with this request or the empty string if no such ID is defined
     */
    protected Object getProtocolRequestId() {
        return null;
    }


    /**
     * Protocols must override this method and return an appropriate ServletConnection instance
     *
     * @return the ServletConnection instance associated with the current request.
     */
    protected abstract ServletConnection getServletConnection();


    /**
     * Flush any pending writes. Used during non-blocking writes to flush any remaining data from a previous incomplete
     * write.
     *
     * @return <code>true</code> if data remains to be flushed at the end of method
     *
     * @throws IOException If an I/O error occurs while attempting to flush the data
     */
    protected abstract boolean flushBufferedWrite() throws IOException;


    /**
     * Perform any necessary clean-up processing if the dispatch resulted in the completion of processing for the
     * current request.
     *
     * @return The state to return for the socket once the clean-up for the current request has completed
     *
     * @throws IOException If an I/O error occurs while attempting to end the request
     */
    protected abstract SocketState dispatchEndRequest() throws IOException;


    @Override
    protected final void logAccess(SocketWrapperBase<?> socketWrapper) throws IOException {
        // Set the socket wrapper so the access log can read the socket related
        // information (e.g. client IP)
        setSocketWrapper(socketWrapper);
        // Set up the minimal request information
        request.markStartTime();
        // Set up the minimal response information
        response.setStatus(400);
        response.setError();
        getAdapter().log(request, response, 0);
    }
}
