/// <summary> /// Accept client connection, create <see cref="ProcessingContext" /> and <see cref="ProcessingContext.ClientStream" /> /// and start processing request. /// </summary> /// <param name="clientSocket">Socket opened by the client</param> public void HandleClient(Socket clientSocket) { ContractUtils.Requires <ArgumentNullException>(clientSocket != null, "clientSocket"); var context = new ProcessingContext { ClientSocket = clientSocket, ClientStream = new NetworkStream(clientSocket, true) { ReadTimeout = (int)ClientReadTimeout.TotalMilliseconds, WriteTimeout = (int)ClientWriteTimeout.TotalMilliseconds } }; _pipeline.Start(context); if (context.Exception != null) { var errorMessage = new StringBuilder("Request processing failed.").AppendLine(); if (context.RequestHeader != null) { errorMessage.AppendLine("Request:"); errorMessage.WriteHttpTrace(context.RequestHeader); } if (context.ResponseHeader != null) { errorMessage.AppendLine("Response:"); errorMessage.WriteHttpTrace(context.ResponseHeader); } errorMessage.AppendLine("Exception:"); errorMessage.AppendLine(context.Exception.ToString()); OnLog(LogLevel.Error, errorMessage.ToString()); } }
/// <summary> /// Send respose to <see cref="ProcessingContext.ClientStream" /> containing /// <see cref="ProcessingContext.ResponseHeader" /> /// and rest of<see cref="ProcessingContext.ServerStream" />. /// Expect <see cref="ProcessingContext.ServerStream" />, <see cref="ProcessingContext.ClientStream" /> and /// <see cref="ProcessingContext.ResponseHeader" /> to be defined. /// </summary> /// <param name="context">current request context</param> protected virtual void SendResponse(ProcessingContext context) { ContractUtils.Requires <ArgumentNullException>(context != null, "context"); ContractUtils.Requires <InvalidContextException>(context.ServerStream != null, "ServerStream"); ContractUtils.Requires <InvalidContextException>(context.ResponseHeader != null, "ResponseHeader"); ContractUtils.Requires <InvalidContextException>(context.ClientStream != null, "ClientStream"); ContractUtils.Requires <InvalidContextException>(context.ServerSocket != null, "ServerSocket"); var responseWriter = new HttpResponseWriter(context.ClientStream); try { responseWriter.Write(context.ResponseHeader, context.ServerStream, context.ServerSocket.Available); OnLog(LogLevel.Debug, "Response Sent. {0}", TraceUtils.GetHttpTrace(context.ResponseHeader)); } catch (IOException ex) { if (ex.IsSocketException(SocketError.TimedOut)) { OnLog(LogLevel.Warn, "Request to remote server has timed out. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); responseWriter.WriteGatewayTimeout(); } else if (ex.IsSocketException(SocketError.ConnectionReset, SocketError.ConnectionAborted)) { OnLog(LogLevel.Debug, "Request Aborted. {0}", TraceUtils.GetHttpTrace(context.RequestHeader)); } else { throw; } context.StopProcessing(); } }