Пример #1
0
        protected override int ProcessData(byte[] data, bool writeExcess)
        {
            ThrowIfEnded();
            bool run = true; int i = 0;

            for (; i < data.Length && run; i++)
            {
                char c = (char)data[i];
                switch (State)
                {
                case RequestParserState.Method:
                    if (c != WHITESPACE)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        Incoming.Method = StringQueue.Next();
                        StringQueue.New();
                        State = RequestParserState.Query;
                    }
                    break;

                case RequestParserState.Query:
                    if (c != WHITESPACE)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        if (!Query.TryParse(StringQueue.Next(), out Query result))
                        {
                            End();
                            return(-1);
                        }
                        Incoming.Query = result;
                        StringQueue.New();
                        State = RequestParserState.Version;
                    }
                    break;

                case RequestParserState.Version:
                    if (c != CR)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        if (!HttpVersion.TryParse(StringQueue.Next(), out HttpVersion result))
                        {
                            End();
                            return(-1);
                        }
                        Incoming.Version = result;
                        StringQueue.New();
                        State = RequestParserState.FirstLf;
                    }
                    break;

                case RequestParserState.FirstLf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    State = RequestParserState.HeaderName;
                    break;

                case RequestParserState.HeaderName:
                    if (c == CR)
                    {
                        State = RequestParserState.Lf;
                    }
                    else if (c != COLON)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        StringQueue.New();
                        State = RequestParserState.HeaderValue;
                    }
                    break;

                case RequestParserState.HeaderValue:
                    if (c != CR)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        Incoming.Headers.Set(StringQueue.Next(), StringQueue.Next().Trim());
                        State = RequestParserState.HeaderLf;
                    }
                    break;

                case RequestParserState.HeaderLf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    else
                    {
                        StringQueue.New();
                        State = RequestParserState.HeaderName;
                    }
                    break;

                case RequestParserState.Lf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    run = false;
                    PushIncoming();
                    State = RequestParserState.Method;
                    break;
                }
            }
            if (writeExcess)
            {
                int    len    = data.Length - i;
                byte[] sliced = new byte[len];
                System.Buffer.BlockCopy(data, i, sliced, 0, len);
                Bwrite(sliced);
            }
            return(i);
        }
Пример #2
0
        private int ProcessData(byte[] data, bool writeExcess)
        {
            ThrowIfEnded();
            if (!IsSet)
            {
                throw new InvalidOperationException("Not set");
            }
            int i = 0, len; char c; byte[] sliced;

            for (; i < data.Length;)
            {
                switch (State)
                {
                case BodyParserState.RawRead:
                    len    = ContentLength == -1 ? data.Length - i : Math.Min(data.Length - i, ContentLength - CurrentReadBytes);
                    sliced = new byte[len];
                    Buffer.BlockCopy(data, i, sliced, 0, len);
                    i += len;
                    CurrentReadBytes += len;
                    ContentTransform.Write(data);
                    if (ContentTransform.Buffered > 0)
                    {
                        Readable.Write(ContentTransform.Read());
                    }
                    if (CurrentReadBytes == ContentLength)
                    {
                        State = BodyParserState.Dormant;
                        OnEnd?.Invoke();
                        break;
                    }
                    break;

                case BodyParserState.Chunked_Length:
                    c = (char)data[i++];
                    if (c != CR)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        if (!int.TryParse(StringQueue.Next(), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out int result))
                        {
                            End(); return(-1);
                        }
                        chunkLen = result;
                        State    = BodyParserState.Chunked_LenLf;
                    }
                    break;

                case BodyParserState.Chunked_LenLf:
                    c = (char)data[i++];
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    if (chunkLen == 0)
                    {
                        State = BodyParserState.Chunked_Trailer;
                    }
                    else
                    {
                        State = BodyParserState.Chunked_ChunkData;
                    }
                    break;

                case BodyParserState.Chunked_ChunkData:
                    len    = Math.Min(data.Length - i, chunkLen - chunkIndex);
                    sliced = new byte[len];
                    Buffer.BlockCopy(data, i, sliced, 0, len);
                    i += len;
                    CurrentReadBytes += len;
                    chunkIndex       += len;
                    ContentTransform.Write(sliced);
                    Readable.Write(ContentTransform.Read());
                    if (chunkLen == chunkIndex)
                    {
                        State = BodyParserState.Chunked_ChunkCr;
                    }
                    break;

                case BodyParserState.Chunked_ChunkCr:
                    c = (char)data[i++];
                    if (c != CR)
                    {
                        End(); return(-1);
                    }
                    State = BodyParserState.Chunked_ChunkLf;
                    break;

                case BodyParserState.Chunked_ChunkLf:
                    c = (char)data[i++];
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    State    = BodyParserState.Chunked_Length;
                    chunkLen = chunkIndex = 0;
                    StringQueue.New();
                    break;

                case BodyParserState.Chunked_Trailer:
                    c = (char)data[i++];
                    if (c != CR)
                    {
                        chunkIndex++;
                    }
                    else
                    {
                        if (chunkIndex == 0)
                        {
                            State = BodyParserState.Chunked_Lf;
                        }
                        else
                        {
                            chunkIndex = -1;      // LF will be added
                        }
                    }
                    break;

                case BodyParserState.Chunked_Lf:
                    c = (char)data[i++];
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    State = BodyParserState.Dormant;
                    OnEnd?.Invoke();
                    ContentLength = CurrentReadBytes;
                    break;

                default: throw new InvalidOperationException("ProcessData cannot execute on Dormant state");
                }
            }
            if (writeExcess)
            {
                len    = data.Length - i;
                sliced = new byte[len];
                Buffer.BlockCopy(data, i, sliced, 0, len);
                Writable.Write(sliced);
            }
            return(i);
        }