コード例 #1
0
        private static ParserState ParseHeaderFields(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HeaderFieldState requestHeaderState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            CurrentHeaderFieldStore currentField,
            HttpHeaders headers)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseHeaderFields()|(inputBufferLength - bytesParsed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseHeaderFields()|Headers already read exceeds limit.");

            // Remember where we started.
            int initialBytesParsed = bytesConsumed;
            int segmentStart;

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus = ParserState.DataTooBig;
            int effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : maximumHeaderLength - totalBytesConsumed + initialBytesParsed;
            if (bytesReady < effectiveMax)
            {
                parseStatus = ParserState.NeedMoreData;
                effectiveMax = bytesReady;
            }

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (requestHeaderState)
            {
                case HeaderFieldState.Name:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != ':')
                    {
                        if (buffer[bytesConsumed] == '\r')
                        {
                            if (!currentField.IsEmpty())
                            {
                                parseStatus = ParserState.Invalid;
                                goto quit;
                            }
                            else
                            {
                                // Move past the '\r'
                                requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                                if (++bytesConsumed == effectiveMax)
                                {
                                    goto quit;
                                }

                                goto case HeaderFieldState.AfterCarriageReturn;
                            }
                        }

                        if (++bytesConsumed == effectiveMax)
                        {
                            string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentField.Name.Append(headerFieldName);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Name.Append(headerFieldName);
                    }

                    // Move past the ':'
                    requestHeaderState = HeaderFieldState.Value;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Value;

                case HeaderFieldState.Value:
                    segmentStart = bytesConsumed;
                    while (buffer[bytesConsumed] != '\r')
                    {
                        if (++bytesConsumed == effectiveMax)
                        {
                            string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                            currentField.Value.Append(headerFieldValue);
                            goto quit;
                        }
                    }

                    if (bytesConsumed > segmentStart)
                    {
                        string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Value.Append(headerFieldValue);
                    }

                    // Move past the CR
                    requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.AfterCarriageReturn;

                case HeaderFieldState.AfterCarriageReturn:
                    if (buffer[bytesConsumed] != '\n')
                    {
                        parseStatus = ParserState.Invalid;
                        goto quit;
                    }

                    if (currentField.IsEmpty())
                    {
                        parseStatus = ParserState.Done;
                        bytesConsumed++;
                        goto quit;
                    }

                    requestHeaderState = HeaderFieldState.FoldingLine;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.FoldingLine;

                case HeaderFieldState.FoldingLine:
                    if (buffer[bytesConsumed] != ' ' && buffer[bytesConsumed] != '\t')
                    {
                        currentField.CopyTo(headers);
                        requestHeaderState = HeaderFieldState.Name;
                        if (bytesConsumed == effectiveMax)
                        {
                            goto quit;
                        }

                        goto case HeaderFieldState.Name;
                    }

                    // Unfold line by inserting SP instead
                    currentField.Value.Append(' ');

                    // Continue parsing header field value
                    requestHeaderState = HeaderFieldState.Value;
                    if (++bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Value;
            }

        quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return parseStatus;
        }
コード例 #2
0
        private static ParserState ParseHeaderFields(
            byte[] buffer,
            int bytesReady,
            ref int bytesConsumed,
            ref HeaderFieldState requestHeaderState,
            int maximumHeaderLength,
            ref int totalBytesConsumed,
            CurrentHeaderFieldStore currentField,
            HttpHeaders headers)
        {
            Contract.Assert((bytesReady - bytesConsumed) >= 0, "ParseHeaderFields()|(inputBufferLength - bytesParsed) < 0");
            Contract.Assert(maximumHeaderLength <= 0 || totalBytesConsumed <= maximumHeaderLength, "ParseHeaderFields()|Headers already read exceeds limit.");

            // Remember where we started.
            int initialBytesParsed = bytesConsumed;
            int segmentStart;

            // Set up parsing status with what will happen if we exceed the buffer.
            ParserState parseStatus  = ParserState.DataTooBig;
            int         effectiveMax = maximumHeaderLength <= 0 ? Int32.MaxValue : maximumHeaderLength - totalBytesConsumed + initialBytesParsed;

            if (bytesReady < effectiveMax)
            {
                parseStatus  = ParserState.NeedMoreData;
                effectiveMax = bytesReady;
            }

            Contract.Assert(bytesConsumed < effectiveMax, "We have already consumed more than the max header length.");

            switch (requestHeaderState)
            {
            case HeaderFieldState.Name:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != ':')
                {
                    if (buffer[bytesConsumed] == '\r')
                    {
                        if (!currentField.IsEmpty())
                        {
                            parseStatus = ParserState.Invalid;
                            goto quit;
                        }
                        else
                        {
                            // Move past the '\r'
                            requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                            if (++bytesConsumed == effectiveMax)
                            {
                                goto quit;
                            }

                            goto case HeaderFieldState.AfterCarriageReturn;
                        }
                    }

                    if (++bytesConsumed == effectiveMax)
                    {
                        string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Name.Append(headerFieldName);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string headerFieldName = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentField.Name.Append(headerFieldName);
                }

                // Move past the ':'
                requestHeaderState = HeaderFieldState.Value;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.Value;

            case HeaderFieldState.Value:
                segmentStart = bytesConsumed;
                while (buffer[bytesConsumed] != '\r')
                {
                    if (++bytesConsumed == effectiveMax)
                    {
                        string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                        currentField.Value.Append(headerFieldValue);
                        goto quit;
                    }
                }

                if (bytesConsumed > segmentStart)
                {
                    string headerFieldValue = Encoding.UTF8.GetString(buffer, segmentStart, bytesConsumed - segmentStart);
                    currentField.Value.Append(headerFieldValue);
                }

                // Move past the CR
                requestHeaderState = HeaderFieldState.AfterCarriageReturn;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.AfterCarriageReturn;

            case HeaderFieldState.AfterCarriageReturn:
                if (buffer[bytesConsumed] != '\n')
                {
                    parseStatus = ParserState.Invalid;
                    goto quit;
                }

                if (currentField.IsEmpty())
                {
                    parseStatus = ParserState.Done;
                    bytesConsumed++;
                    goto quit;
                }

                requestHeaderState = HeaderFieldState.FoldingLine;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.FoldingLine;

            case HeaderFieldState.FoldingLine:
                if (buffer[bytesConsumed] != ' ' && buffer[bytesConsumed] != '\t')
                {
                    currentField.CopyTo(headers);
                    requestHeaderState = HeaderFieldState.Name;
                    if (bytesConsumed == effectiveMax)
                    {
                        goto quit;
                    }

                    goto case HeaderFieldState.Name;
                }

                // Unfold line by inserting SP instead
                currentField.Value.Append(' ');

                // Continue parsing header field value
                requestHeaderState = HeaderFieldState.Value;
                if (++bytesConsumed == effectiveMax)
                {
                    goto quit;
                }

                goto case HeaderFieldState.Value;
            }

quit:
            totalBytesConsumed += bytesConsumed - initialBytesParsed;
            return(parseStatus);
        }