Esempio n. 1
0
        private void StoreBody(Stream output, long contentLength)
        {
            // argument checks
            Debug.Assert(output != null);
            Debug.Assert(output.CanWrite);
            Debug.Assert(0 <= contentLength);

            // state checks
            HeaderBuffer headerBuffer = this.headerBuffer;

            Debug.Assert(headerBuffer != null);

            // write body bytes in the header buffer to the output
            int bodyBytesInHeaderBufferLength = headerBuffer.Limit - headerBuffer.Next;

            if (bodyBytesInHeaderBufferLength <= contentLength)
            {
                WriteTo(headerBuffer, output, headerBuffer.Next, bodyBytesInHeaderBufferLength);
            }
            else
            {
                // there is data of the next message
                bodyBytesInHeaderBufferLength = (int)contentLength;
                WriteTo(headerBuffer, output, headerBuffer.Next, bodyBytesInHeaderBufferLength);
                headerBuffer.SetPrefetchedBytes(headerBuffer.Next + bodyBytesInHeaderBufferLength);
            }

            // write rest of body bytes to the output
            // the memoryBlock is used as just intermediate buffer instead of storing media
            byte[] memoryBlock = EnsureMemoryBlockAllocated();
            long   remaining   = contentLength - bodyBytesInHeaderBufferLength;

            while (0 < remaining)
            {
                long count     = Math.Min(remaining, memoryBlock.Length);
                int  readCount = ReadBytes(memoryBlock, 0, (int)count);
                Debug.Assert(0 < readCount);                    // ReadBytes() throws an exception on end of stream
                output.Write(memoryBlock, 0, readCount);
                remaining -= readCount;
            }

            return;
        }
Esempio n. 2
0
        public void SkipBody(long contentLength)
        {
            // argument checks
            if (contentLength < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(contentLength));
            }

            // state checks
            HeaderBuffer headerBuffer = this.headerBuffer;

            if (headerBuffer == null)
            {
                throw new InvalidOperationException();
            }
            if (this.bodyLength != 0)
            {
                throw new InvalidOperationException("This buffer has already handled a message body.");
            }
            Debug.Assert(this.bodyStream == null);

            // skip the body storing its bytes
            // The media to store body depends on its length and the current margin.
            Stream bodyStream = null;

            try {
                // Note that the some body bytes may be read into the header buffer.
                // Unread bytes in the header buffer at this point are body bytes.
                // That is, range [headerBuffer.Next - headerBuffer.Limit).
                int  bodyBytesInHeaderBufferLength = headerBuffer.Limit - headerBuffer.Next;
                long restLen = contentLength - bodyBytesInHeaderBufferLength;
                if (restLen <= headerBuffer.Margin)
                {
                    // The body is to be stored in the rest of header buffer. (tiny body)

                    // read body bytes into the rest of the header buffer
                    if (0 <= restLen)
                    {
                        Debug.Assert(restLen <= int.MaxValue);
                        FillBuffer(headerBuffer, (int)restLen);
                        Debug.Assert(contentLength == headerBuffer.Limit - headerBuffer.Next);
                        Debug.Assert(this.MemoryBlock == null);
                    }
                    else
                    {
                        // there is data of the next message
                        Debug.Assert(contentLength <= int.MaxValue);
                        int offset = headerBuffer.Next + (int)contentLength;
                        headerBuffer.SetPrefetchedBytes(offset);
                    }
                }
                else
                {
                    byte[] memoryBlock = EnsureMemoryBlockAllocated();
                    if (contentLength <= memoryBlock.Length)
                    {
                        // The body is to be stored in a memory block. (small body)

                        // copy body bytes in the header buffer to this buffer
                        CopyFrom(headerBuffer, headerBuffer.Next, bodyBytesInHeaderBufferLength);

                        // read rest of body bytes
                        Debug.Assert(restLen <= int.MaxValue);
                        FillBuffer((int)restLen);
                        Debug.Assert(contentLength == (this.Limit - this.Next));
                    }
                    else
                    {
                        // The body is to be stored in a stream.

                        // determine which medium is used to store body, memory or file
                        if (contentLength <= BodyStreamThreshold)
                        {
                            // use memory stream (medium body)
                            Debug.Assert(contentLength <= int.MaxValue);
                            bodyStream = new MemoryStream((int)contentLength);
                        }
                        else
                        {
                            // use temp file stream (large body)
                            bodyStream = Util.CreateTempFileStream();
                        }

                        StoreBody(bodyStream, contentLength);
                    }
                }

                // update state
                this.bodyLength = contentLength;
                this.bodyStream = bodyStream;
            } catch {
                DisposableUtil.DisposeSuppressingErrors(bodyStream);
                throw;
            }

            return;
        }