async Task <RequestCommandAndStream> ReceiveRequestBodyOverControlAsync(ListenerCommand.RequestCommand requestCommand) { Stream requestStream = null; if (requestCommand.Body.Value) { // We need to buffer this body stream so we can let go of the listener control connection requestStream = new MemoryStream(BufferSize); using (var cts = new CancellationTokenSource(this.OperationTimeout)) { var buffer = new ArraySegment <byte>(new byte[BufferSize]); var readResult = await WebSocketUtility.ReadMessageAsync(this.controlWebSocket, buffer, requestStream, cts.Token).ConfigureAwait(false); if (readResult.MessageType == WebSocketMessageType.Close) { throw RelayEventSource.Log.ThrowingException(new InvalidOperationException(SR.EntityClosedOrAborted), this); } else if (readResult.MessageType != WebSocketMessageType.Binary) { throw RelayEventSource.Log.ThrowingException( new ProtocolViolationException(SR.GetString(SR.InvalidType, WebSocketMessageType.Binary, readResult.MessageType)), this); } requestStream.Position = 0; } } return(new RequestCommandAndStream(requestCommand, requestStream)); }
void InvokeRequestHandler(RequestCommandAndStream requestAndStream) { ListenerCommand.RequestCommand requestCommand = requestAndStream.RequestCommand; Uri requestUri = new Uri(this.listener.Address, requestCommand.RequestTarget); var listenerContext = new RelayedHttpListenerContext( this.listener, requestUri, requestCommand.Id, requestCommand.Method, requestCommand.RequestHeaders); listenerContext.Request.SetRemoteAddress(requestCommand.RemoteEndpoint); listenerContext.Response.StatusCode = HttpStatusCode.OK; listenerContext.Response.OutputStream = new ResponseStream(this, listenerContext); RelayEventSource.Log.HybridHttpRequestReceived(listenerContext.TrackingContext, requestCommand.Method); Stream requestStream = requestAndStream.Stream; if (requestStream != null) { listenerContext.Request.HasEntityBody = true; listenerContext.Request.InputStream = requestStream; } var requestHandler = this.listener.RequestHandler; if (requestHandler != null) { try { RelayEventSource.Log.HybridHttpInvokingUserRequestHandler(); requestHandler(listenerContext); } catch (Exception userException) when(!Fx.IsFatal(userException)) { RelayEventSource.Log.HandledExceptionAsWarning(this, userException); listenerContext.Response.StatusCode = HttpStatusCode.InternalServerError; listenerContext.Response.StatusDescription = this.TrackingContext.EnsureTrackableMessage(SR.RequestHandlerException); listenerContext.Response.CloseAsync().Fork(this); return; } } else { RelayEventSource.Log.HybridHttpConnectionMissingRequestHandler(); listenerContext.Response.StatusCode = HttpStatusCode.NotImplemented; listenerContext.Response.StatusDescription = this.TrackingContext.EnsureTrackableMessage(SR.RequestHandlerMissing); listenerContext.Response.CloseAsync().Fork(this); } }
void InvokeRequestHandler(RequestCommandAndStream requestAndStream) { ListenerCommand.RequestCommand requestCommand = requestAndStream.RequestCommand; Uri requestUri = new Uri(this.listener.Address, requestCommand.RequestTarget); var listenerContext = new RelayedHttpListenerContext( this.listener, requestUri, requestCommand.Id, requestCommand.Method, requestCommand.RequestHeaders); listenerContext.Request.SetRemoteAddress(requestCommand.RemoteEndpoint); listenerContext.Response.StatusCode = HttpStatusCode.OK; listenerContext.Response.OutputStream = new ResponseStream(this, listenerContext); RelayEventSource.Log.HybridHttpRequestReceived(listenerContext.TrackingContext, requestCommand.Method); Stream requestStream = requestAndStream.Stream; if (requestStream != null) { listenerContext.Request.HasEntityBody = true; listenerContext.Request.InputStream = requestStream; } var requestHandler = this.listener.RequestHandler; if (requestHandler != null) { try { RelayEventSource.Log.HybridHttpInvokingUserRequestHandler(); requestHandler(listenerContext); } catch (Exception userException) when(!Fx.IsFatal(userException)) { RelayEventSource.Log.Warning( listenerContext, $"The Relayed Listener's custom RequestHandler threw an exception. {listenerContext.TrackingContext}, Exception: {userException}"); return; } } else { RelayEventSource.Log.HandledExceptionAsWarning(this, new InvalidOperationException("RequestHandler is not set.")); } }
public static async Task CreateAsync(HybridConnectionListener listener, ListenerCommand.RequestCommand requestCommand, WebSocket controlWebSocket) { var hybridHttpConnection = new HybridHttpConnection(listener, controlWebSocket, requestCommand.Address); // In this method we're holding up the listener's control connection. // Do only what we need to do (receive any request body from control channel) and then let this Task complete. bool requestOverControlConnection = requestCommand.Body.HasValue; var requestAndStream = new RequestCommandAndStream(requestCommand, null); if (requestOverControlConnection) { requestAndStream = await hybridHttpConnection.ReceiveRequestBodyOverControlAsync(requestCommand).ConfigureAwait(false); } // ProcessFirstRequestAsync runs without blocking the listener control connection: Task.Run(() => hybridHttpConnection.ProcessFirstRequestAsync(requestAndStream)).Fork(hybridHttpConnection); }
public RequestCommandAndStream(ListenerCommand.RequestCommand requestCommand, Stream stream) { this.RequestCommand = requestCommand; this.Stream = stream; }