Beispiel #1
0
        public async Task ProcessAllRequests()
        {
            Reset();

            while (true)
            {
                var buffer = await _input.ReadAsync();

                var  consumed     = buffer.Start;
                bool needMoreData = true;

                try
                {
                    if (buffer.IsEmpty && _input.Completion.IsCompleted)
                    {
                        // We're done with this connection
                        return;
                    }

                    if (_state == ParsingState.StartLine)
                    {
                        // Find \n
                        var delim = buffer.IndexOf(ref CommonVectors.LF);
                        if (delim == ReadCursor.NotFound)
                        {
                            continue;
                        }

                        // Grab the entire start line
                        var startLine = buffer.Slice(0, delim);

                        // Move the buffer to the rest
                        buffer = buffer.Slice(delim).Slice(1);

                        delim = startLine.IndexOf(ref CommonVectors.Space);
                        if (delim == ReadCursor.NotFound)
                        {
                            throw new Exception();
                        }

                        var method = startLine.Slice(0, delim);
                        Method = method.Preserve();

                        // Skip ' '
                        startLine = startLine.Slice(delim).Slice(1);

                        delim = startLine.IndexOf(ref CommonVectors.Space);
                        if (delim == ReadCursor.NotFound)
                        {
                            throw new Exception();
                        }

                        var path = startLine.Slice(0, delim);
                        Path = path.Preserve();

                        // Skip ' '
                        startLine = startLine.Slice(delim).Slice(1);

                        delim = startLine.IndexOf(ref CommonVectors.CR);
                        if (delim == ReadCursor.NotFound)
                        {
                            throw new Exception();
                        }

                        var httpVersion = startLine.Slice(0, delim);
                        HttpVersion = httpVersion.Preserve();

                        _state   = ParsingState.Headers;
                        consumed = startLine.End;
                    }

                    // Parse headers
                    // key: value\r\n

                    while (!buffer.IsEmpty)
                    {
                        var ch = buffer.Peek();

                        if (ch == -1)
                        {
                            break;
                        }

                        if (ch == '\r')
                        {
                            // Check for final CRLF.
                            buffer = buffer.Slice(1);
                            ch     = buffer.Peek();
                            buffer = buffer.Slice(1);

                            if (ch == -1)
                            {
                                break;
                            }
                            else if (ch == '\n')
                            {
                                consumed     = buffer.Start;
                                needMoreData = false;
                                break;
                            }

                            // Headers don't end in CRLF line.
                            throw new Exception();
                        }

                        var headerName  = default(ReadableBuffer);
                        var headerValue = default(ReadableBuffer);

                        // End of the header
                        // \n
                        var delim = buffer.IndexOf(ref CommonVectors.LF);
                        if (delim == ReadCursor.NotFound)
                        {
                            break;
                        }

                        var headerPair = buffer.Slice(0, delim);
                        buffer = buffer.Slice(delim).Slice(1);

                        // :
                        delim = headerPair.IndexOf(ref CommonVectors.Colon);
                        if (delim == ReadCursor.NotFound)
                        {
                            throw new Exception();
                        }

                        headerName = headerPair.Slice(0, delim).TrimStart();
                        headerPair = headerPair.Slice(delim).Slice(1);

                        // \r
                        delim = headerPair.IndexOf(ref CommonVectors.CR);
                        if (delim == ReadCursor.NotFound)
                        {
                            // Bad request
                            throw new Exception();
                        }

                        headerValue = headerPair.Slice(0, delim).TrimStart();
                        RequestHeaders.SetHeader(ref headerName, ref headerValue);

                        // Move the consumed
                        consumed = buffer.Start;
                    }
                }
                catch (Exception)
                {
                    StatusCode = 400;

                    await EndResponse();

                    return;
                }
                finally
                {
                    buffer.Consumed(consumed);
                }

                if (needMoreData)
                {
                    continue;
                }

                var context = _application.CreateContext(this);

                try
                {
                    await _application.ProcessRequestAsync(context);
                }
                catch (Exception ex)
                {
                    StatusCode = 500;

                    _application.DisposeContext(context, ex);
                }
                finally
                {
                    await EndResponse();
                }

                if (!KeepAlive)
                {
                    break;
                }

                Reset();
            }
        }