private void ParseChunkedPrefix(ReadOnlySequence <byte> buffer, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = buffer.Start;
            examined = buffer.Start;
            var reader = new SequenceReader <byte>(buffer);

            if (!reader.TryRead(out var ch1) || !reader.TryRead(out var ch2))
            {
                examined = reader.Position;
                return;
            }

            // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedPrefix.
            examined = reader.Position;

            var chunkSize = CalculateChunkSize(ch1, 0);

            ch1 = ch2;

            while (reader.Consumed < MaxChunkPrefixBytes)
            {
                if (ch1 == ';')
                {
                    consumed = reader.Position;
                    examined = reader.Position;

                    AddAndCheckConsumedBytes(reader.Consumed);
                    _inputLength = chunkSize;
                    _mode        = Mode.Extension;
                    return;
                }

                if (!reader.TryRead(out ch2))
                {
                    examined = reader.Position;
                    return;
                }

                // Advance examined before possibly throwing, so we don't risk examining less than the previous call to ParseChunkedPrefix.
                examined = reader.Position;

                if (ch1 == '\r' && ch2 == '\n')
                {
                    consumed = reader.Position;

                    AddAndCheckConsumedBytes(reader.Consumed);
                    _inputLength = chunkSize;
                    _mode        = chunkSize > 0 ? Mode.Data : Mode.Trailer;
                    return;
                }

                chunkSize = CalculateChunkSize(ch1, chunkSize);
                ch1       = ch2;
            }

            // At this point, 10 bytes have been consumed which is enough to parse the max value "7FFFFFFF\r\n".
            BadProtoRequestException.Throw(RequestRejectionReason.BadChunkSizeData);
        }
 public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
 {
 }
        protected bool Read(ReadOnlySequence <byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = default;
            examined = default;

            while (_mode < Mode.Trailer)
            {
                if (_mode == Mode.Prefix)
                {
                    ParseChunkedPrefix(readableBuffer, out consumed, out examined);

                    if (_mode == Mode.Prefix)
                    {
                        return(false);
                    }

                    readableBuffer = readableBuffer.Slice(consumed);
                }

                if (_mode == Mode.Extension)
                {
                    ParseExtension(readableBuffer, out consumed, out examined);

                    if (_mode == Mode.Extension)
                    {
                        return(false);
                    }

                    readableBuffer = readableBuffer.Slice(consumed);
                }

                if (_mode == Mode.Data)
                {
                    ReadChunkedData(readableBuffer, writableBuffer, out consumed, out examined);

                    if (_mode == Mode.Data)
                    {
                        return(false);
                    }

                    readableBuffer = readableBuffer.Slice(consumed);
                }

                if (_mode == Mode.Suffix)
                {
                    ParseChunkedSuffix(readableBuffer, out consumed, out examined);

                    if (_mode == Mode.Suffix)
                    {
                        return(false);
                    }

                    readableBuffer = readableBuffer.Slice(consumed);
                }
            }

            // Chunks finished, parse trailers
            if (_mode == Mode.Trailer)
            {
                ParseChunkedTrailer(readableBuffer, out consumed, out examined);

                if (_mode == Mode.Trailer)
                {
                    return(false);
                }

                readableBuffer = readableBuffer.Slice(consumed);
            }

            // _consumedBytes aren't tracked for trailer headers, since headers have separate limits.
            if (_mode == Mode.TrailerHeaders)
            {
                if (_context.TakeMessageHeaders(readableBuffer, out consumed, out examined))
                {
                    _mode = Mode.Complete;
                }
            }

            return(_mode == Mode.Complete);
        }
Beispiel #4
0
 void Reset()
 {
     _rewindCount = 0;
     _tokenStart  = _reader.Position;
 }
Beispiel #5
0
 public Script Slice(SequencePosition start, SequencePosition end) => new Script(_script.Sequence.Slice(start, end));
Beispiel #6
0
        private bool ReaderBuffer(ref ReadOnlySequence <byte> buffer, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = buffer.Start;
            examined = buffer.End;

            var bytesConsumedTotal = 0L;

            var maxPackageLength = Options.MaxPackageLength;

            var seqReader = new SequenceReader <byte>(buffer);

            while (true)
            {
                var currentPipelineFilter = _pipelineFilter;

                var packageInfo = currentPipelineFilter.Filter(ref seqReader);

                var nextFilter = currentPipelineFilter.NextFilter;

                if (nextFilter != null)
                {
                    nextFilter.Context = currentPipelineFilter.Context; // pass through the context
                    _pipelineFilter    = nextFilter;
                }

                var bytesConsumed = seqReader.Consumed;
                bytesConsumedTotal += bytesConsumed;

                var len = bytesConsumed;

                // nothing has been consumed, need more data
                if (len == 0)
                {
                    len = seqReader.Length;
                }

                if (maxPackageLength > 0 && len > maxPackageLength)
                {
                    OnError($"Package cannot be larger than {maxPackageLength}.");
                    // close the the connection directly
                    Close();
                    return(false);
                }

                // continue receive...
                if (packageInfo == null)
                {
                    consumed = buffer.GetPosition(bytesConsumedTotal);
                    return(true);
                }

                currentPipelineFilter.Reset();

                _packagePipe.Write(packageInfo);

                if (seqReader.End) // no more data
                {
                    examined = consumed = buffer.End;
                    return(true);
                }

                seqReader = new SequenceReader <byte>(seqReader.Sequence.Slice(bytesConsumed));
            }
        }
Beispiel #7
0
        private bool ParseHttpRequest(ref ReadOnlySequence <byte> buffer, bool isCompleted, out SequencePosition examined)
        {
            examined = buffer.End;

            var consumed = buffer.Start;
            var state    = _state;

            if (!buffer.IsEmpty)
            {
                if (state == State.StartLine)
                {
                    if (Parser.ParseRequestLine(new ParsingAdapter(this), buffer, out consumed, out examined))
                    {
                        state = State.Headers;
                    }

                    buffer = buffer.Slice(consumed);
                }

                if (state == State.Headers)
                {
                    var reader  = new SequenceReader <byte>(buffer);
                    var success = Parser.ParseHeaders(new ParsingAdapter(this), ref reader);

                    consumed = reader.Position;
                    if (success)
                    {
                        examined = consumed;
                        state    = State.Body;
                    }
                    else
                    {
                        examined = buffer.End;
                    }

                    buffer = buffer.Slice(consumed);
                }

                if (state != State.Body && isCompleted)
                {
                    ThrowUnexpectedEndOfData();
                }
            }
            else if (isCompleted)
            {
                return(false);
            }

            _state = state;
            return(true);
        }
Beispiel #8
0
 public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
 {
     throw new NotImplementedException();
 }
 void IDuplexMessageStream.AdvanceReaderTo(SequencePosition consumed) => reader.AdvanceTo(consumed);
 public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
 {
     OnAdvance(_readResult, consumed, examined);
     _requestBodyPipe.Reader.AdvanceTo(consumed, examined);
 }
        public void AdvanceWithoutReadingWithValidSequencePosition()
        {
            var sequencePosition = new SequencePosition(new BufferSegment(), 5);

            Assert.Throws <InvalidOperationException>(() => Reader.AdvanceTo(sequencePosition));
        }
        public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
        {
            ValidateState();

            _body !.AdvanceTo(consumed, examined);
        }