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); }
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(); }
/// <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); } } }
/// <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); } } }
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(); }
/// <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); } } }