Пример #1
0
        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);
        }
Пример #2
0
        // 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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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();
        }