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); }
void Reset() { _rewindCount = 0; _tokenStart = _reader.Position; }
public Script Slice(SequencePosition start, SequencePosition end) => new Script(_script.Sequence.Slice(start, end));
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)); } }
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); }
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); }