예제 #1
0
 private void Execute()
 {
     MessageBody = MessageBody.For(
         HttpVersion,
         RequestHeaders,
         this);
     _keepAlive   = MessageBody.RequestKeepAlive;
     RequestBody  = new FrameRequestStream(MessageBody);
     ResponseBody = new FrameResponseStream(this);
     DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
     SocketInput.Free();
     Task.Run(ExecuteAsync);
 }
예제 #2
0
        public Frame(ConnectionContext context,
                     IPEndPoint remoteEndPoint,
                     IPEndPoint localEndPoint,
                     Action <IFeatureCollection> prepareRequest)
            : base(context)
        {
            _remoteEndPoint = remoteEndPoint;
            _localEndPoint  = localEndPoint;
            _prepareRequest = prepareRequest;
            _pathBase       = context.ServerAddress.PathBase;
            if (ReuseStreams)
            {
                _requestBody  = new FrameRequestStream();
                _responseBody = new FrameResponseStream(this);
                _duplexStream = new FrameDuplexStream(_requestBody, _responseBody);
            }

            FrameControl = this;
            Reset();
        }
예제 #3
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the 
        /// application delegate for as long as the socket is intended to remain open.
        /// The resulting Task from this loop is preserved in a field which is used when the server needs
        /// to drain and close all currently active connections.
        /// </summary>
        public async Task RequestProcessingAsync()
        {
            try
            {
                var terminated = false;
                while (!terminated && !_requestProcessingStopping)
                {
                    while (!terminated && !_requestProcessingStopping && !TakeStartLine(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    if (!terminated && !_requestProcessingStopping)
                    {
                        MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
                        _keepAlive = MessageBody.RequestKeepAlive;
                        RequestBody = new FrameRequestStream(MessageBody);
                        ResponseBody = new FrameResponseStream(this);
                        DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);

                        Exception error = null;
                        try
                        {
                            await Application.Invoke(this).ConfigureAwait(false);

                            // Trigger FireOnStarting if ProduceStart hasn't been called yet.
                            // We call it here, so it can go through our normal error handling
                            // and respond with a 500 if an OnStarting callback throws.
                            if (!_responseStarted)
                            {
                                FireOnStarting();
                            }
                        }
                        catch (Exception ex)
                        {
                            error = ex;
                        }
                        finally
                        {
                            FireOnCompleted();
                            ProduceEnd(error);
                        }

                        terminated = !_keepAlive;
                    }

                    Reset();
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning("Connection processing ended abnormally", ex);
            }
            finally
            {
                try
                {
                    // Inform client no more data will ever arrive
                    ConnectionControl.End(ProduceEndType.SocketShutdownSend);

                    // Wait for client to either disconnect or send unexpected data
                    await SocketInput;

                    // Dispose socket
                    ConnectionControl.End(ProduceEndType.SocketDisconnect);
                }
                catch (Exception ex)
                {
                    Log.LogWarning("Connection shutdown abnormally", ex);
                }
            }
        }
예제 #4
0
 private void Execute()
 {
     MessageBody = MessageBody.For(
         HttpVersion,
         RequestHeaders,
         this);
     _keepAlive = MessageBody.RequestKeepAlive;
     RequestBody = new FrameRequestStream(MessageBody);
     ResponseBody = new FrameResponseStream(this);
     DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
     SocketInput.Free();
     Task.Run(ExecuteAsync);
 }
예제 #5
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
        /// application delegate for as long as the socket is intended to remain open.
        /// The resulting Task from this loop is preserved in a field which is used when the server needs
        /// to drain and close all currently active connections.
        /// </summary>
        public async Task RequestProcessingAsync()
        {
            try
            {
                var terminated = false;
                while (!terminated && !_requestProcessingStopping)
                {
                    while (!terminated && !_requestProcessingStopping && !TakeStartLine(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    if (!terminated && !_requestProcessingStopping)
                    {
                        MessageBody  = MessageBody.For(HttpVersion, _requestHeaders, this);
                        _keepAlive   = MessageBody.RequestKeepAlive;
                        RequestBody  = new FrameRequestStream(MessageBody);
                        ResponseBody = new FrameResponseStream(this);
                        DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);

                        Exception error = null;
                        try
                        {
                            await Application.Invoke(this).ConfigureAwait(false);

                            // Trigger FireOnStarting if ProduceStart hasn't been called yet.
                            // We call it here, so it can go through our normal error handling
                            // and respond with a 500 if an OnStarting callback throws.
                            if (!_responseStarted)
                            {
                                FireOnStarting();
                            }
                        }
                        catch (Exception ex)
                        {
                            error = ex;
                        }
                        finally
                        {
                            FireOnCompleted();
                            ProduceEnd(error);
                        }

                        terminated = !_keepAlive;
                    }

                    Reset();
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning("Connection processing ended abnormally", ex);
            }
            finally
            {
                try
                {
                    // Inform client no more data will ever arrive
                    ConnectionControl.End(ProduceEndType.SocketShutdownSend);

                    // Wait for client to either disconnect or send unexpected data
                    await SocketInput;

                    // Dispose socket
                    ConnectionControl.End(ProduceEndType.SocketDisconnect);
                }
                catch (Exception ex)
                {
                    Log.LogWarning("Connection shutdown abnormally", ex);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
        /// application delegate for as long as the socket is intended to remain open.
        /// The resulting Task from this loop is preserved in a field which is used when the server needs
        /// to drain and close all currently active connections.
        /// </summary>
        public override async Task RequestProcessingAsync()
        {
            try
            {
                while (!_requestProcessingStopping)
                {
                    while (!_requestProcessingStopping && !TakeStartLine(SocketInput))
                    {
                        if (SocketInput.RemoteIntakeFin)
                        {
                            return;
                        }
                        await SocketInput;
                    }

                    while (!_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
                    {
                        if (SocketInput.RemoteIntakeFin)
                        {
                            return;
                        }
                        await SocketInput;
                    }

                    if (!_requestProcessingStopping)
                    {
                        var messageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
                        _keepAlive = messageBody.RequestKeepAlive;

                        // _duplexStream may be null if flag switched while running
                        if (!ReuseStreams || _duplexStream == null)
                        {
                            _requestBody  = new FrameRequestStream();
                            _responseBody = new FrameResponseStream(this);
                            _duplexStream = new FrameDuplexStream(_requestBody, _responseBody);
                        }

                        RequestBody  = _requestBody.StartAcceptingReads(messageBody);
                        ResponseBody = _responseBody.StartAcceptingWrites();
                        DuplexStream = _duplexStream;

                        _abortedCts = null;
                        _manuallySetRequestAbortToken = null;

                        var context = _application.CreateContext(this);
                        try
                        {
                            await _application.ProcessRequestAsync(context).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            ReportApplicationError(ex);
                        }
                        finally
                        {
                            // Trigger OnStarting if it hasn't been called yet and the app hasn't
                            // already failed. If an OnStarting callback throws we can go through
                            // our normal error handling in ProduceEnd.
                            // https://github.com/aspnet/KestrelHttpServer/issues/43
                            if (!_responseStarted && _applicationException == null && _onStarting != null)
                            {
                                await FireOnStarting();
                            }

                            _requestBody.PauseAcceptingReads();
                            _responseBody.PauseAcceptingWrites();

                            if (_onCompleted != null)
                            {
                                await FireOnCompleted();
                            }

                            _application.DisposeContext(context, _applicationException);

                            // If _requestAbort is set, the connection has already been closed.
                            if (!_requestAborted)
                            {
                                _responseBody.ResumeAcceptingWrites();
                                await ProduceEnd();

                                if (_keepAlive)
                                {
                                    _requestBody.ResumeAcceptingReads();
                                    // Finish reading the request body in case the app did not.
                                    await messageBody.Consume();
                                }
                            }

                            _requestBody.StopAcceptingReads();
                            _responseBody.StopAcceptingWrites();
                        }

                        if (!_keepAlive)
                        {
                            return;
                        }
                    }

                    Reset();
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning("Connection processing ended abnormally", ex);
            }
            finally
            {
                try
                {
                    _abortedCts = null;

                    // If _requestAborted is set, the connection has already been closed.
                    if (!_requestAborted)
                    {
                        // Inform client no more data will ever arrive
                        ConnectionControl.End(ProduceEndType.SocketShutdownSend);

                        // Wait for client to either disconnect or send unexpected data
                        await SocketInput;

                        // Dispose socket
                        ConnectionControl.End(ProduceEndType.SocketDisconnect);
                    }
                }
                catch (Exception ex)
                {
                    Log.LogWarning("Connection shutdown abnormally", ex);
                }
            }
        }
예제 #7
0
        public Frame(ConnectionContext context,
                     IPEndPoint remoteEndPoint,
                     IPEndPoint localEndPoint,
                     Action<IFeatureCollection> prepareRequest)
            : base(context)
        {
            _remoteEndPoint = remoteEndPoint;
            _localEndPoint = localEndPoint;
            _prepareRequest = prepareRequest;
            _pathBase = context.ServerAddress.PathBase;
            if (ReuseStreams)
            {
                _requestBody = new FrameRequestStream();
                _responseBody = new FrameResponseStream(this);
                _duplexStream = new FrameDuplexStream(_requestBody, _responseBody);
            }

            FrameControl = this;
            Reset();
        }
예제 #8
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the 
        /// application delegate for as long as the socket is intended to remain open.
        /// The resulting Task from this loop is preserved in a field which is used when the server needs
        /// to drain and close all currently active connections.
        /// </summary>
        public async Task RequestProcessingAsync()
        {
            try
            {
                var terminated = false;
                while (!terminated && !_requestProcessingStopping)
                {
                    while (!terminated && !_requestProcessingStopping && !TakeStartLine(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    if (!terminated && !_requestProcessingStopping)
                    {
                        MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
                        _keepAlive = MessageBody.RequestKeepAlive;
                        RequestBody = new FrameRequestStream(MessageBody);
                        ResponseBody = new FrameResponseStream(this);
                        DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);

                        try
                        {
                            await Application.Invoke(this).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            ReportApplicationError(ex);
                        }
                        finally
                        {
                            // Trigger OnStarting if it hasn't been called yet and the app hasn't
                            // already failed. If an OnStarting callback throws we can go through
                            // our normal error handling in ProduceEnd.
                            // https://github.com/aspnet/KestrelHttpServer/issues/43
                            if (!_responseStarted && _applicationException == null)
                            {
                                await FireOnStarting();
                            }

                            await FireOnCompleted();

                            await ProduceEnd();

                            while (await RequestBody.ReadAsync(_nullBuffer, 0, _nullBuffer.Length) != 0)
                            {
                                // Finish reading the request body in case the app did not.
                            }
                        }

                        terminated = !_keepAlive;
                    }

                    Reset();
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning("Connection processing ended abnormally", ex);
            }
            finally
            {
                try
                {
                    // Inform client no more data will ever arrive
                    ConnectionControl.End(ProduceEndType.SocketShutdownSend);

                    // Wait for client to either disconnect or send unexpected data
                    await SocketInput;

                    // Dispose socket
                    ConnectionControl.End(ProduceEndType.SocketDisconnect);
                }
                catch (Exception ex)
                {
                    Log.LogWarning("Connection shutdown abnormally", ex);
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
        /// application delegate for as long as the socket is intended to remain open.
        /// The resulting Task from this loop is preserved in a field which is used when the server needs
        /// to drain and close all currently active connections.
        /// </summary>
        public async Task RequestProcessingAsync()
        {
            try
            {
                var terminated = false;
                while (!terminated && !_requestProcessingStopping)
                {
                    while (!terminated && !_requestProcessingStopping && !TakeStartLine(SocketInput))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
                    {
                        terminated = SocketInput.RemoteIntakeFin;
                        if (!terminated)
                        {
                            await SocketInput;
                        }
                    }

                    if (!terminated && !_requestProcessingStopping)
                    {
                        MessageBody  = MessageBody.For(HttpVersion, _requestHeaders, this);
                        _keepAlive   = MessageBody.RequestKeepAlive;
                        RequestBody  = new FrameRequestStream(MessageBody);
                        ResponseBody = new FrameResponseStream(this);
                        DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);

                        try
                        {
                            await Application.Invoke(this).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            ReportApplicationError(ex);
                        }
                        finally
                        {
                            // Trigger OnStarting if it hasn't been called yet and the app hasn't
                            // already failed. If an OnStarting callback throws we can go through
                            // our normal error handling in ProduceEnd.
                            // https://github.com/aspnet/KestrelHttpServer/issues/43
                            if (!_responseStarted && _applicationException == null)
                            {
                                await FireOnStarting();
                            }

                            await FireOnCompleted();

                            await ProduceEnd();

                            while (await RequestBody.ReadAsync(_nullBuffer, 0, _nullBuffer.Length) != 0)
                            {
                                // Finish reading the request body in case the app did not.
                            }
                        }

                        terminated = !_keepAlive;
                    }

                    Reset();
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning("Connection processing ended abnormally", ex);
            }
            finally
            {
                try
                {
                    // Inform client no more data will ever arrive
                    ConnectionControl.End(ProduceEndType.SocketShutdownSend);

                    // Wait for client to either disconnect or send unexpected data
                    await SocketInput;

                    // Dispose socket
                    ConnectionControl.End(ProduceEndType.SocketDisconnect);
                }
                catch (Exception ex)
                {
                    Log.LogWarning("Connection shutdown abnormally", ex);
                }
            }
        }