diff options
Diffstat (limited to 'lib/Net.Http/src')
-rw-r--r-- | lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs | 5 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs | 4 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/InitDataBuffer.cs (renamed from lib/Net.Http/src/Helpers/InitDataBuffer.cs) | 1 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/Request/HttpInputStream.cs | 20 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/Request/HttpRequestBody.cs | 4 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs | 39 | ||||
-rw-r--r-- | lib/Net.Http/src/Helpers/CoreBufferHelpers.cs | 71 |
7 files changed, 59 insertions, 85 deletions
diff --git a/lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs b/lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs index 25366ad..7da105b 100644 --- a/lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs +++ b/lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs @@ -39,7 +39,7 @@ using VNLib.Utils.Memory; namespace VNLib.Net.Http.Core.Buffering { - internal class ContextLockedBufferManager : IHttpBufferManager + internal sealed class ContextLockedBufferManager : IHttpBufferManager { private readonly HttpBufferConfig Config; private readonly int TotalBufferSize; @@ -125,6 +125,7 @@ namespace VNLib.Net.Http.Core.Buffering } catch { + _segments = default; //Free buffer on error _handle.Dispose(); _handle = null; @@ -136,7 +137,7 @@ namespace VNLib.Net.Http.Core.Buffering public void ZeroAll() { //Zero the buffer completely - MemoryUtil.InitializeBlock(_handle.Memory); + MemoryUtil.InitializeBlock(_handle!.Memory); } ///<inheritdoc/> diff --git a/lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs b/lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs index 0e60cae..b23bc8f 100644 --- a/lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs +++ b/lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs @@ -66,7 +66,7 @@ namespace VNLib.Net.Http.Core.Buffering ///<inheritdoc/> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual Span<byte> GetBinSpan() => MemoryUtil.GetSpan<byte>(Pinned, Size); + public virtual Span<byte> GetBinSpan() => MemoryUtil.GetSpan<byte>(ref Pinned, Size); ///<inheritdoc/> [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -75,7 +75,7 @@ namespace VNLib.Net.Http.Core.Buffering [MethodImpl(MethodImplOptions.AggressiveInlining)] protected virtual Span<byte> GetBinSpan(int maxSize) { - return maxSize > Size ? throw new ArgumentOutOfRangeException(nameof(maxSize)) : MemoryUtil.GetSpan<byte>(Pinned, maxSize); + return maxSize > Size ? throw new ArgumentOutOfRangeException(nameof(maxSize)) : MemoryUtil.GetSpan<byte>(ref Pinned, maxSize); } } } diff --git a/lib/Net.Http/src/Helpers/InitDataBuffer.cs b/lib/Net.Http/src/Core/InitDataBuffer.cs index c191bb0..323208a 100644 --- a/lib/Net.Http/src/Helpers/InitDataBuffer.cs +++ b/lib/Net.Http/src/Core/InitDataBuffer.cs @@ -43,7 +43,6 @@ namespace VNLib.Net.Http.Core readonly int _dataSize; readonly byte[] _buffer; readonly ArrayPool<byte> _pool; - InitDataBuffer(ArrayPool<byte> pool, byte[] buffer, int size) { diff --git a/lib/Net.Http/src/Core/Request/HttpInputStream.cs b/lib/Net.Http/src/Core/Request/HttpInputStream.cs index c591c6d..be479c6 100644 --- a/lib/Net.Http/src/Core/Request/HttpInputStream.cs +++ b/lib/Net.Http/src/Core/Request/HttpInputStream.cs @@ -67,12 +67,12 @@ namespace VNLib.Net.Http.Core } /// <summary> - /// Creates a new input stream object configured to allow reading of the specified content length - /// bytes from the stream and consumes the initial buffer to read data from on initial read calls + /// Prepares the input stream for reading from the transport with the specified content length + /// and initial data buffer /// </summary> /// <param name="contentLength">The number of bytes to allow being read from the transport or initial buffer</param> /// <param name="initial">Entity body data captured on initial read</param> - internal void Prepare(long contentLength, in InitDataBuffer? initial) + internal void Prepare(long contentLength, in InitDataBuffer initial) { ContentLength = contentLength; _initalData = initial; @@ -81,6 +81,20 @@ namespace VNLib.Net.Http.Core InputStream = ContextInfo.GetTransport(); } + /// <summary> + /// Prepares the input stream for reading from the transport with the specified content length + /// amount of data + /// </summary> + /// <param name="contentLength">The number of bytes to allow being read from the transport</param> + internal void Prepare(long contentLength) + { + ContentLength = contentLength; + _initalData = null; + + //Cache transport + InputStream = ContextInfo.GetTransport(); + } + public override void Close() => throw new NotSupportedException("The HTTP input stream should never be closed!"); private long Remaining => Math.Max(ContentLength - _position, 0); public override bool CanRead => true; diff --git a/lib/Net.Http/src/Core/Request/HttpRequestBody.cs b/lib/Net.Http/src/Core/Request/HttpRequestBody.cs index 824ca24..e39a35c 100644 --- a/lib/Net.Http/src/Core/Request/HttpRequestBody.cs +++ b/lib/Net.Http/src/Core/Request/HttpRequestBody.cs @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Vaughn Nugent +* Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: VNLib.Net.Http @@ -41,7 +41,7 @@ namespace VNLib.Net.Http.Core { Uploads = new(1); - //Request/query args should not be request sensitive + //Request/query args should not be case sensitive RequestArgs = new(StringComparer.OrdinalIgnoreCase); QueryArgs = new(StringComparer.OrdinalIgnoreCase); } diff --git a/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs b/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs index f7e17f7..c25cd12 100644 --- a/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs +++ b/lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs @@ -25,6 +25,7 @@ using System; using System.Net; using System.Linq; +using System.Buffers; using System.Collections.Generic; using System.Security.Authentication; using System.Runtime.CompilerServices; @@ -39,6 +40,10 @@ namespace VNLib.Net.Http.Core internal static class Http11ParseExtensions { + /// <summary> + /// An internal HTTP character binary pool for HTTP specific internal buffers + /// </summary> + public static ArrayPool<byte> InputDataBufferPool { get; } = ArrayPool<byte>.Create(); /// <summary> /// Stores the state of an HTTP/1.1 parsing operation @@ -475,6 +480,7 @@ namespace VNLib.Net.Http.Core return 0; } + /// <summary> /// Prepares the entity body for the current HTTP1 request /// </summary> @@ -537,10 +543,35 @@ namespace VNLib.Net.Http.Core //Make sure non-zero cl header was provided else if (parseState.ContentLength > 0) { - //Open a temp buffer to store initial data in - InitDataBuffer? initData = reader.GetReminaingData(parseState.ContentLength); - //Setup the input stream and capture the initial data from the reader, and wrap the transport stream to read data directly - Request.InputStream.Prepare(parseState.ContentLength, in initData); + //clamp max available to max content length + int available = Math.Clamp(reader.Available, 0, (int)parseState.ContentLength); + + /* + * The reader may still have available content data following the headers segment + * that is part of the entity body data. This data must be read and stored in the + * input stream for the request. + * + * If no data is available from the buffer, we can just prepare the input stream + * with null + */ + + if (available > 0) + { + //Creates the new initial data buffer + InitDataBuffer initData = InitDataBuffer.AllocBuffer(InputDataBufferPool, available); + + //Read remaining data into the buffer's data segment + _ = reader.ReadRemaining(initData.DataSegment); + + //Setup the input stream and capture the initial data from the reader, and wrap the transport stream to read data directly + Request.InputStream.Prepare(parseState.ContentLength, initData); + } + else + { + //Empty input stream + Request.InputStream.Prepare(parseState.ContentLength); + } + Request.HasEntityBody = true; } //Success! diff --git a/lib/Net.Http/src/Helpers/CoreBufferHelpers.cs b/lib/Net.Http/src/Helpers/CoreBufferHelpers.cs deleted file mode 100644 index e3e5854..0000000 --- a/lib/Net.Http/src/Helpers/CoreBufferHelpers.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (c) 2023 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Net.Http -* File: CoreBufferHelpers.cs -* -* CoreBufferHelpers.cs is part of VNLib.Net.Http which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Net.Http is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* VNLib.Net.Http is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - - -using System; -using System.Buffers; - -using VNLib.Utils.IO; - -namespace VNLib.Net.Http.Core -{ - - /// <summary> - /// Provides memory pools and an internal heap for allocations. - /// </summary> - internal static class CoreBufferHelpers - { - /// <summary> - /// An internal HTTP character binary pool for HTTP specific internal buffers - /// </summary> - public static ArrayPool<byte> HttpBinBufferPool { get; } = ArrayPool<byte>.Create(); - - /// <summary> - /// Gets the remaining data in the reader buffer and prepares a - /// sliding window buffer to read data from - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="reader"></param> - /// <param name="maxContentLength">Maximum content size to clamp the remaining buffer window to</param> - /// <returns></returns> - public static InitDataBuffer? GetReminaingData<T>(this ref T reader, long maxContentLength) where T: struct, IVnTextReader - { - //clamp max available to max content length - int available = Math.Clamp(reader.Available, 0, (int)maxContentLength); - if (available <= 0) - { - return null; - } - - //Creates the new initial data buffer - InitDataBuffer buf = InitDataBuffer.AllocBuffer(HttpBinBufferPool, available); - - //Read remaining data into the buffer's data segment - _ = reader.ReadRemaining(buf.DataSegment); - - return buf; - } - - } -} |