public ForChunkedEncoding(bool keepAlive, FrameRequestHeaders headers, Frame context)
     : base(context)
 {
     RequestKeepAlive = keepAlive;
     _requestHeaders  = headers;
 }
Example #2
0
        public bool TakeMessageHeaders(SocketInput input, FrameRequestHeaders requestHeaders)
        {
            var scan     = input.ConsumingStart();
            var consumed = scan;

            try
            {
                int chFirst;
                int chSecond;
                while (!scan.IsEnd)
                {
                    var beginName = scan;
                    if (scan.Seek(ref _vectorColons, ref _vectorCRs) == -1)
                    {
                        return(false);
                    }
                    var endName = scan;

                    chFirst = scan.Take();
                    var beginValue = scan;
                    chSecond = scan.Take();

                    if (chFirst == -1 || chSecond == -1)
                    {
                        return(false);
                    }
                    if (chFirst == '\r')
                    {
                        if (chSecond == '\n')
                        {
                            consumed = scan;
                            return(true);
                        }

                        ReportCorruptedHttpRequest(new BadHttpRequestException("Headers corrupted, invalid header sequence."));
                        // Headers corrupted, parsing headers is complete
                        return(true);
                    }

                    while (
                        chSecond == ' ' ||
                        chSecond == '\t' ||
                        chSecond == '\r' ||
                        chSecond == '\n')
                    {
                        if (chSecond == '\r')
                        {
                            var scanAhead = scan;
                            var chAhead   = scanAhead.Take();
                            if (chAhead == -1)
                            {
                                return(false);
                            }
                            else if (chAhead == '\n')
                            {
                                chAhead = scanAhead.Take();
                                if (chAhead == -1)
                                {
                                    return(false);
                                }
                                else if (chAhead != ' ' && chAhead != '\t')
                                {
                                    // If the "\r\n" isn't part of "linear whitespace",
                                    // then this header has no value.
                                    break;
                                }
                            }
                        }

                        beginValue = scan;
                        chSecond   = scan.Take();

                        if (chSecond == -1)
                        {
                            return(false);
                        }
                    }
                    scan = beginValue;

                    var wrapping = false;
                    while (!scan.IsEnd)
                    {
                        if (scan.Seek(ref _vectorCRs) == -1)
                        {
                            // no "\r" in sight, burn used bytes and go back to await more data
                            return(false);
                        }

                        var endValue = scan;
                        chFirst  = scan.Take(); // expecting: \r
                        chSecond = scan.Take(); // expecting: \n

                        if (chSecond == -1)
                        {
                            return(false);
                        }
                        else if (chSecond != '\n')
                        {
                            // "\r" was all by itself, move just after it and try again
                            scan = endValue;
                            scan.Take();
                            continue;
                        }

                        var chThird = scan.Peek();
                        if (chThird == -1)
                        {
                            return(false);
                        }
                        else if (chThird == ' ' || chThird == '\t')
                        {
                            // special case, "\r\n " or "\r\n\t".
                            // this is considered wrapping"linear whitespace" and is actually part of the header value
                            // continue past this for the next
                            wrapping = true;
                            continue;
                        }

                        var name  = beginName.GetArraySegment(endName);
                        var value = beginValue.GetAsciiString(endValue);
                        if (wrapping)
                        {
                            value = value.Replace("\r\n", " ");
                        }

                        consumed = scan;
                        requestHeaders.Append(name.Array, name.Offset, name.Count, value);
                        break;
                    }
                }
                return(false);
            }
            finally
            {
                input.ConsumingComplete(consumed, scan);
            }
        }