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