public FrameRequestStream(MessageBody body)
 {
     _body = body;
 }
        /// <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);
                }
            }
        }
        /// <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);
                }
            }
        }
 //int _readLength;
 //bool _readFin;
 //Exception _readError;
 public FrameRequestStream(MessageBody body)
 {
     _body = body;
 }
Exemple #5
0
        /*
         * public bool LocalIntakeFin
         * {
         *  get
         *  {
         *      return _mode == Mode.MessageBody
         *          ? _messageBody.LocalIntakeFin
         *          : _mode == Mode.Terminated;
         *  }
         * }
         */
        public void Consume()
        {
            var input = SocketInput;

            for (; ;)
            {
                switch (_mode)
                {
                case Mode.StartLine:
                    if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
                    {
                        _mode = Mode.Terminated;
                        return;
                    }

                    if (!TakeStartLine(input))
                    {
                        if (input.RemoteIntakeFin)
                        {
                            _mode = Mode.Terminated;
                        }
                        return;
                    }

                    _mode = Mode.MessageHeader;
                    break;

                case Mode.MessageHeader:
                    if (input.Buffer.Count == 0 && input.RemoteIntakeFin)
                    {
                        _mode = Mode.Terminated;
                        return;
                    }

                    var endOfHeaders = false;
                    while (!endOfHeaders)
                    {
                        if (!TakeMessageHeader(input, out endOfHeaders))
                        {
                            if (input.RemoteIntakeFin)
                            {
                                _mode = Mode.Terminated;
                            }
                            return;
                        }
                    }

                    //var resumeBody = HandleExpectContinue(callback);
                    _mode = Mode.MessageBody;
                    Execute();
                    break;

                case Mode.MessageBody:
                    if (MessageBody.LocalIntakeFin)
                    {
                        // NOTE: stop reading and resume on keepalive?
                        return;
                    }
                    MessageBody.Consume();
                    // NOTE: keep looping?
                    return;

                case Mode.Terminated:
                    return;
                }
            }
        }
Exemple #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 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);
                }
            }
        }
 public void StopAcceptingReads()
 {
     // Can't use dispose (or close) as can be disposed too early by user code
     // As exampled in EngineTests.ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes
     _state = FrameStreamState.Closed;
     _body = null;
 }
 public Stream StartAcceptingReads(MessageBody body)
 {
     // Only start if not aborted
     if (_state == FrameStreamState.Closed)
     {
         _state = FrameStreamState.Open;
         _body = body;
     }
     return this;
 }