All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.server.AsyncHttpConnection Maven / Gradle / Ivy

There is a newer version: 11.0.0.beta1
Show newest version
package org.eclipse.jetty.server;

import java.io.IOException;

import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

public class AsyncHttpConnection extends HttpConnection
{
    private final static int NO_PROGRESS_INFO = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_INFO",100);
    private final static int NO_PROGRESS_CLOSE = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_CLOSE",200);

    private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
    private int _total_no_progress;

    public AsyncHttpConnection(Connector connector, EndPoint endpoint, Server server)
    {
        super(connector,endpoint,server);
    }

    public Connection handle() throws IOException
    {
        Connection connection = this;
        boolean some_progress=false;
        boolean progress=true;

        // Loop while more in buffer
        try
        {
            setCurrentConnection(this);

            boolean more_in_buffer =false;

            while (_endp.isOpen() && (more_in_buffer || progress) && connection==this)
            {
                progress=false;
                try
                {

                    // Handle resumed request
                    if (_request._async.isAsync() && !_request._async.isComplete())
                        handleRequest();

                    // else Parse more input
                    else if (!_parser.isComplete() && _parser.parseAvailable()>0)
                        progress=true;

                    // Generate more output
                    if (_generator.isCommitted() && !_generator.isComplete() && _generator.flushBuffer()>0)
                        progress=true;

                    // Flush output from buffering endpoint
                    if (_endp.isBufferingOutput())
                        _endp.flush();

                    // Special case close handling.
                    // If we were dispatched and have made no progress, but io is shutdown, then close
                    if (!progress && !some_progress && (_endp.isInputShutdown()||_endp.isOutputShutdown()))
                       _endp.close();
                }
                catch (HttpException e)
                {
                    if (LOG.isDebugEnabled())
                    {
                        LOG.debug("uri="+_uri);
                        LOG.debug("fields="+_requestFields);
                        LOG.debug(e);
                    }
                    _generator.sendError(e.getStatus(), e.getReason(), null, true);
                    _parser.reset();
                    _endp.close();
                }
                finally
                {
                    // Do we need to complete a half close?
                    if (_endp.isInputShutdown() && (_parser.isIdle() || _parser.isComplete()))
                    {
                        LOG.debug("complete half close {}",this);
                        more_in_buffer=false;
                        _endp.close();
                        reset(true);
                    }

                    // else Is this request/response round complete?
                    else if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
                    {
                        // look for a switched connection instance?
                        if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
                        {
                            Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
                            if (switched!=null)
                            {
                                _parser.reset();
                                _generator.reset(true);
                                connection=switched;
                            }
                        }

                        // Reset the parser/generator
                        // keep the buffers as we will cycle
                        progress=true;
                        reset(false);
                        more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
                    }
                    // else Are we suspended?
                    else if (_request.isAsyncStarted())
                    {
                        LOG.debug("suspended {}",this);
                        more_in_buffer=false;
                        progress=false;
                    }
                    else
                        more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();

                    some_progress|=progress|((SelectChannelEndPoint)_endp).isProgressing();
                }
            }
        }
        finally
        {
            setCurrentConnection(null);
            _parser.returnBuffers();
            _generator.returnBuffers();

            // Check if we are write blocked
            if (_generator.isCommitted() && !_generator.isComplete() && _endp.isOpen() && !_endp.isOutputShutdown())
                ((AsyncEndPoint)_endp).scheduleWrite(); // TODO. This should not be required

            if (some_progress)
            {
                _total_no_progress=0;
            }
            else
            {
                int totalNoProgress=++_total_no_progress;

                if (NO_PROGRESS_INFO>0 && totalNoProgress==NO_PROGRESS_INFO && (NO_PROGRESS_CLOSE<=0 || totalNoProgress0 && totalNoProgress==NO_PROGRESS_CLOSE)
                {
                    LOG.warn("Closing EndPoint making no progress: {} {}", totalNoProgress, _endp);
                    if (_endp instanceof SelectChannelEndPoint)
                    {
                        System.err.println(((SelectChannelEndPoint)_endp).getSelectManager().dump());
                        ((SelectChannelEndPoint)_endp).getChannel().close();
                    }
                }
            }
        }
        return connection;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy