async Task EnsureChunkHeaderWasReadAsync(
            CancellationToken cancellationToken)
        {
            while (_currentChunkHeader == null)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // Read
                var bytesRead = await _requestStream.ReadAsync(_readBuffer, 0, _readBuffer.Length);

                HttpPrematureFinishException.ThrowIfZero(bytesRead);

                // Append the data we just read to the header builder.
                // If header is built after this call, we are done here.
                int contentStartIndex;
                if (_chunkHeaderBuilder.AppendBuffer(_readBuffer, 0, bytesRead, out contentStartIndex))
                {
                    // Set current chunk metadata
                    _currentChunkHeader         = _chunkHeaderBuilder.Result;
                    _currentChunkRemainingBytes = _chunkHeaderBuilder.Result.Length;

                    // If we read some bytes from the body, rollback those read.
                    _requestStream.TryRollbackFromIndex(
                        _readBuffer,
                        srcLength: bytesRead,
                        startIndex: contentStartIndex);
                }
            }
        }
        /// <summary>
        /// Called when current chunk has no more data to read,
        /// we'll do some cleaning here.
        /// </summary>
        async Task CompleteReadingCurrentChunkAsync()
        {
            // A chunk always nend with a new line character,
            // let's skip it.
            var bytesRead = await _requestStream.ReadAsync(_readBuffer, 0, _readBuffer.Length);

            HttpPrematureFinishException.ThrowIfZero(bytesRead);
            if (false == _lineBuilder.AppendBuffer(_readBuffer, 0, bytesRead, out int nextLineStartIndex))
            {
                throw new HttpBadRequestException(
                          "Chunk body must end with an empty line"
                          );
            }
            _lineBuilder.Reset();
            _requestStream.TryRollbackFromIndex(_readBuffer, bytesRead, nextLineStartIndex);

            // Prepare to read the next header
            _chunkHeaderBuilder.Reset();

            // Clear the header, so next ReadAsync() operation
            // will attempt to read the next header
            _currentChunkHeader = null;
        }
Exemple #3
0
        public bool AppendBuffer(
            byte[] buffer,
            int start,
            int count,
            out int contentStartIndex)
        {
            Validation.RequireValidBuffer(buffer, start, count);
            RequireNullResult();

            // Early exit if there is no new line in the appended buffer;
            contentStartIndex = default(int);
            int nextLineStartIndex;

            if (false == _lineBuilder.AppendBuffer(buffer, start, count, out nextLineStartIndex))
            {
                return(false);
            }

            // New line found in the supplied buffer!
            // The chunk header ends here
            contentStartIndex = nextLineStartIndex;
            _result           = BuildResult(_lineBuilder.Result);
            return(true);
        }
Exemple #4
0
 public void Reset()
 {
     _lineBuilder.Reset();
     _result = null;
 }