public IEnumerable <object> BeginRequestInternal(ISocket socket) { var bufferHeaders = new ContinuationState <LinkedList <ArraySegment <byte> > >(socket.BufferHeaders()); yield return(bufferHeaders); var headerBuffers = bufferHeaders.Result; Dictionary <string, object> env = new Dictionary <string, object>(); var bodyDataReadWithHeaders = headerBuffers.Last.Value; headerBuffers.RemoveLast(); var headersString = headerBuffers.GetString(); var reader = new StringReader(headersString); var requestLine = reader.ReadRequestLine(); var headers = reader.ReadHeaders(); env["Owin.RequestMethod"] = requestLine.Verb; env["Owin.RequestUri"] = requestLine.RequestUri; env["Owin.RequestHeaders"] = headers; env["Owin.BaseUri"] = ""; env["Owin.RemoteEndPoint"] = socket.RemoteEndPoint; env["Owin.RequestBody"] = CreateReadBody(socket, bodyDataReadWithHeaders); // TODO provide better values env["Owin.ServerName"] = ""; env["Owin.ServerPort"] = 0; env["Owin.UriScheme"] = "http"; yield return(env); }
public IEnumerable<object> BeginRequestInternal(ISocket socket) { var bufferHeaders = new ContinuationState<LinkedList<ArraySegment<byte>>>(socket.BufferHeaders()); yield return bufferHeaders; var headerBuffers = bufferHeaders.Result; Dictionary<string, object> env = new Dictionary<string, object>(); var bodyDataReadWithHeaders = headerBuffers.Last.Value; headerBuffers.RemoveLast(); var headersString = headerBuffers.GetString(); var reader = new StringReader(headersString); var requestLine = reader.ReadRequestLine(); var headers = reader.ReadHeaders(); env["Owin.RequestMethod"] = requestLine.Verb; env["Owin.RequestUri"] = requestLine.RequestUri; env["Owin.RequestHeaders"] = headers; env["Owin.BaseUri"] = ""; env["Owin.RemoteEndPoint"] = socket.RemoteEndPoint; env["Owin.RequestBody"] = CreateReadBody(socket, bodyDataReadWithHeaders); // TODO provide better values env["Owin.ServerName"] = ""; env["Owin.ServerPort"] = 0; env["Owin.UriScheme"] = "http"; yield return env; }
static IEnumerable<object> ProcessSocketInternal(this ISocket socket, IHttpSupport http, OwinApplication application) { var beginRequest = http.BeginRequest(socket); yield return beginRequest; var request = beginRequest.Result; var invoke = new ContinuationState<Tuple<string, IDictionary<string, IList<string>>, IEnumerable<object>>> ((r, e) => application(request, (s,h,b) => r(new Tuple<string,IDictionary<string,IList<string>>,IEnumerable<object>>(s, h, b)), e)); yield return invoke; var response = invoke.Result; yield return http.BeginResponse(socket, response.Item1, response.Item2); foreach (var obj in response.Item3) { var objectToWrite = obj; if (obj is Action<Action<object>, Action<Exception>>) { var cs = new ContinuationState<object>(obj as Action<Action<object>, Action<Exception>>); yield return cs; objectToWrite = cs.Result; } if (objectToWrite is FileInfo) { yield return new ContinuationState(socket.WriteFile((objectToWrite as FileInfo).Name)); continue; } var chunk = default(ArraySegment<byte>); if (obj is ArraySegment<byte>) chunk = (ArraySegment<byte>)obj; else if (obj is byte[]) chunk = new ArraySegment<byte>(obj as byte[]); else continue; //throw new ArgumentException("Invalid object of type " + obj.GetType() + " '" + obj.ToString() + "'"); var write = socket.WriteChunk(chunk); yield return write; // TODO enumerate to completion if (write.Exception != null) throw write.Exception; } socket.Dispose(); }
// this is horribly inefficient right now. static IEnumerable <object> BufferHeadersInternal(ISocket socket) { LinkedList <ArraySegment <byte> > result = new LinkedList <ArraySegment <byte> >(); int bufferPosition = 0, totalBytesRead = 0; byte[] buffer = null; while (true) { if (buffer == null || bufferPosition > BufferSize / 2) { buffer = new byte[BufferSize]; bufferPosition = 0; } int bytesRead = 0; //Trace.Write("About to read header chunk."); var read = new ContinuationState <int>(socket.Read(buffer, bufferPosition, buffer.Length - bufferPosition)); yield return(read); bytesRead = read.Result; //Trace.Write("Read {0} bytes.", bytesRead); result.AddLast(new ArraySegment <byte>(buffer, bufferPosition, bytesRead)); if (bytesRead == 0) { break; } bufferPosition += bytesRead; totalBytesRead += bytesRead; // TODO: would be nice to have a state machine and only parse once. for now // let's just hope to catch it on the first go-round. var bodyDataPosition = IndexOfAfterCRLFCRLF(result); if (bodyDataPosition != -1) { var last = result.Last.Value; result.RemoveLast(); var overlapLength = totalBytesRead - bodyDataPosition; result.AddLast(new ArraySegment <byte>(last.Array, last.Offset, last.Count - overlapLength)); result.AddLast(new ArraySegment <byte>(last.Array, last.Offset + last.Count - overlapLength, overlapLength)); break; } // TODO test this if (totalBytesRead > MaxHeaderLength) { throw new Exception("Request headers data exceeds max header length."); } } yield return(result); }
public BuildingState(ContinuationState state) { State = state; CurrentPropertyId = null; Properties = null; Types = null; Positions = null; }
IEnumerable <object> Nest_ResultStateTrampoline(IDisposable disposable) { using (disposable) { var state = new ContinuationState <object>((r, e) => r("result")); yield return(state); yield return(state.Result); } }
public BuildingState(ContinuationState state) { State = state; MaxPropertyId = 0; CurrentProperty = null; Properties = null; Types = null; Positions = null; FirstWrite = 0; }
IEnumerable <object> Nest_ExceptionStateTrampoline(IDisposable disposable) { using (disposable) { var state = new ContinuationState <object>((r, e) => e(new Exception("Nest_ExceptionState Exception"))); yield return(state); yield return(state.Result); } }
static IEnumerable<object> HostInternal(this IKayakServer server, OwinApplication application, Action<Action> trampoline) { while (true) { var accept = new ContinuationState<ISocket>((r, e) => server.GetConnection()(r)); yield return accept; if (accept.Result == null) break; accept.Result.ProcessSocket(new HttpSupport(), application, trampoline); } }
static IEnumerable <object> WriteChunkInternal(this ISocket socket, ArraySegment <byte> chunk) { int bytesWritten = 0; while (bytesWritten < chunk.Count) { var write = new ContinuationState <int>(socket.Write(chunk.Array, chunk.Offset + bytesWritten, chunk.Count - bytesWritten)); yield return(write); bytesWritten += write.Result; } yield return(default(Unit)); }
static IEnumerable<object> WriteChunkInternal(this ISocket socket, ArraySegment<byte> chunk) { int bytesWritten = 0; while (bytesWritten < chunk.Count) { var write = new ContinuationState<int>(socket.Write(chunk.Array, chunk.Offset + bytesWritten, chunk.Count - bytesWritten)); yield return write; bytesWritten += write.Result; } yield return default(Unit); }
static IEnumerable <object> HostInternal(this IKayakServer server, OwinApplication application, Action <Action> trampoline) { while (true) { var accept = new ContinuationState <ISocket>((r, e) => server.GetConnection()(r)); yield return(accept); if (accept.Result == null) { break; } accept.Result.ProcessSocket(new HttpSupport(), application, trampoline); } }
internal void AddContinuation( ITestOperationState first, ContinuationState continuation) { first.BuildDescription(this); switch (continuation) { case ContinuationState.Available available: available.State.BuildDescription(this); break; case ContinuationState.NotAvailable notAvailable: this.AddStatus(notAvailable.CreationStatus, "..."); break; } }
private static void AsyncReplyComplete(IAsyncResult result, ContinuationState state) { try { state.Request.EndReply(result); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } try { state.Reply.Close(); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } try { state.ChannelHandler.HandleErrorContinuation(state.Exception, state.Request, state.Channel, ref state.FaultInfo, true); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } state.ChannelHandler.EnsurePump(); }
static IEnumerable<object> ProcessSocketInternal(this ISocket socket, IHttpSupport http, OwinApplication application) { var beginRequest = http.BeginRequest(socket); yield return beginRequest; var request = beginRequest.Result; var invoke = new ContinuationState<Tuple<string, IDictionary<string, IEnumerable<string>>, IEnumerable<object>>> ((r, e) => application(request, r, e)); yield return invoke; var response = invoke.Result; yield return http.BeginResponse(socket, response.Item1, response.Item2); foreach (var obj in response.Item3) { var objectToWrite = obj; if (obj is Action<Action<object>, Action<Exception>>) { var cs = new ContinuationState<object>(obj as Action<Action<object>, Action<Exception>>); yield return cs; objectToWrite = cs.Result; } if (objectToWrite is FileInfo) { yield return new ContinuationState(socket.WriteFile((objectToWrite as FileInfo).Name)); } var write = socket.WriteFileOrData(objectToWrite); yield return write; if (write.Exception != null) throw write.Exception; } // HTTP/1.1 support might only close the connection if client wants to //Trace.Write("Closed connection."); socket.Dispose(); }
IEnumerable<object> Nest_ExceptionStateTrampoline(IDisposable disposable) { using (disposable) { var state = new ContinuationState<object>((r, e) => e(new Exception("Nest_ExceptionState Exception"))); yield return state; yield return state.Result; } }
private void ProvideFaultAndReplyFailure(RequestContext request, Exception exception, ref ErrorHandlerFaultInfo faultInfo, out bool replied, out bool replySentAsync) { replied = false; replySentAsync = false; bool requestMessageIsFault = false; try { requestMessageIsFault = request.RequestMessage.IsFault; } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // do not propagate non-fatal exceptions } bool enableFaults = false; if (_listener != null) { enableFaults = _listener.ChannelDispatcher.EnableFaults; } else if (_channel != null && _channel.IsClient) { enableFaults = _channel.ClientRuntime.EnableFaults; } if ((!requestMessageIsFault) && enableFaults) { this.ProvideFault(exception, ref faultInfo); if (faultInfo.Fault != null) { Message reply = faultInfo.Fault; try { try { if (this.PrepareReply(request, reply)) { if (_sendAsynchronously) { var state = new ContinuationState { ChannelHandler = this, Channel = _channel, Exception = exception, FaultInfo = faultInfo, Request = request, Reply = reply }; var result = request.BeginReply(reply, ChannelHandler.s_onAsyncReplyComplete, state); if (result.CompletedSynchronously) { ChannelHandler.AsyncReplyComplete(result, state); replied = true; } else { replySentAsync = true; } } else { request.Reply(reply); replied = true; } } } finally { if (!replySentAsync) { reply.Close(); } } } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { if (Fx.IsFatal(e)) { throw; } this.HandleError(e); } } } }
static void AsyncReplyComplete(IAsyncResult result, ContinuationState state) { try { state.Request.EndReply(result); } catch (Exception e) { DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error); if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } try { state.Reply.Close(); } catch (Exception e) { DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error); if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } try { state.ChannelHandler.HandleErrorContinuation(state.Exception, state.Request, state.Channel, ref state.FaultInfo, true); } catch (Exception e) { DiagnosticUtility.TraceHandledException(e, System.Diagnostics.TraceEventType.Error); if (Fx.IsFatal(e)) { throw; } state.ChannelHandler.HandleError(e); } state.ChannelHandler.EnsurePump(); }
void ProvideFaultAndReplyFailure(RequestContext request, Exception exception, ref ErrorHandlerFaultInfo faultInfo, out bool replied, out bool replySentAsync) { replied = false; replySentAsync = false; bool requestMessageIsFault = false; try { requestMessageIsFault = request.RequestMessage.IsFault; } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { if (Fx.IsFatal(e)) { throw; } // ---- it } bool enableFaults = false; if (this.listener != null) { enableFaults = this.listener.ChannelDispatcher.EnableFaults; } else if (this.channel != null && this.channel.IsClient) { enableFaults = this.channel.ClientRuntime.EnableFaults; } if ((!requestMessageIsFault) && enableFaults) { this.ProvideFault(exception, ref faultInfo); if (faultInfo.Fault != null) { Message reply = faultInfo.Fault; try { try { if (this.PrepareReply(request, reply)) { if (this.sendAsynchronously) { var state = new ContinuationState { ChannelHandler = this, Channel = channel, Exception = exception, FaultInfo = faultInfo, Request = request, Reply = reply }; var result = request.BeginReply(reply, ChannelHandler.onAsyncReplyComplete, state); if (result.CompletedSynchronously) { ChannelHandler.AsyncReplyComplete(result, state); replied = true; } else { replySentAsync = true; } } else { request.Reply(reply); replied = true; } } } finally { if (!replySentAsync) { reply.Close(); } } } #pragma warning suppress 56500 // covered by FxCOP catch (Exception e) { if (Fx.IsFatal(e)) { throw; } this.HandleError(e); } } } }
static IEnumerable <object> ProcessSocketInternal(this ISocket socket, IHttpSupport http, OwinApplication application) { var beginRequest = http.BeginRequest(socket); yield return(beginRequest); var request = beginRequest.Result; var invoke = new ContinuationState <Tuple <string, IDictionary <string, IList <string> >, IEnumerable <object> > > ((r, e) => application(request, (s, h, b) => r(new Tuple <string, IDictionary <string, IList <string> >, IEnumerable <object> >(s, h, b)), e)); yield return(invoke); var response = invoke.Result; yield return(http.BeginResponse(socket, response.Item1, response.Item2)); foreach (var obj in response.Item3) { var objectToWrite = obj; if (obj is Action <Action <object>, Action <Exception> > ) { var cs = new ContinuationState <object>(obj as Action <Action <object>, Action <Exception> >); yield return(cs); objectToWrite = cs.Result; } if (objectToWrite is FileInfo) { yield return(new ContinuationState(socket.WriteFile((objectToWrite as FileInfo).Name))); continue; } var chunk = default(ArraySegment <byte>); if (objectToWrite is ArraySegment <byte> ) { chunk = (ArraySegment <byte>)objectToWrite; } else if (objectToWrite is byte[]) { chunk = new ArraySegment <byte>(objectToWrite as byte[]); } else { continue; } //throw new ArgumentException("Invalid object of type " + obj.GetType() + " '" + obj.ToString() + "'"); var write = socket.WriteChunk(chunk); yield return(write); // TODO enumerate to completion if (write.Exception != null) { throw write.Exception; } } socket.Dispose(); }
IEnumerable<object> Nest_ResultStateTrampoline(IDisposable disposable) { using (disposable) { var state = new ContinuationState<object>((r, e) => r("result")); yield return state; yield return state.Result; } }
private void ThrowIllegalStateException(ContinuationState state, string realOperation) { throw new InvalidOperationException($"Cannot perform {realOperation} when encountered the {state} state"); }
// this is horribly inefficient right now. static IEnumerable<object> BufferHeadersInternal(ISocket socket) { LinkedList<ArraySegment<byte>> result = new LinkedList<ArraySegment<byte>>(); int bufferPosition = 0, totalBytesRead = 0; byte[] buffer = null; while (true) { if (buffer == null || bufferPosition > BufferSize / 2) { buffer = new byte[BufferSize]; bufferPosition = 0; } int bytesRead = 0; //Trace.Write("About to read header chunk."); var read = new ContinuationState<int>(socket.Read(buffer, bufferPosition, buffer.Length - bufferPosition)); yield return read; bytesRead = read.Result; //Trace.Write("Read {0} bytes.", bytesRead); result.AddLast(new ArraySegment<byte>(buffer, bufferPosition, bytesRead)); if (bytesRead == 0) break; bufferPosition += bytesRead; totalBytesRead += bytesRead; // TODO: would be nice to have a state machine and only parse once. for now // let's just hope to catch it on the first go-round. var bodyDataPosition = IndexOfAfterCRLFCRLF(result); if (bodyDataPosition != -1) { var last = result.Last.Value; result.RemoveLast(); var overlapLength = totalBytesRead - bodyDataPosition; result.AddLast(new ArraySegment<byte>(last.Array, last.Offset, last.Count - overlapLength)); result.AddLast(new ArraySegment<byte>(last.Array, last.Offset + last.Count - overlapLength, overlapLength)); break; } // TODO test this if (totalBytesRead > MaxHeaderLength) throw new Exception("Request headers data exceeds max header length."); } yield return result; }
static ContinuationState <int> ReadAsync(this Stream stream, byte[] buffer, int offset, int count) { return(ContinuationState.FromAsync <int>( (cb, s) => stream.BeginRead(buffer, offset, count, cb, s), stream.EndRead)); }