aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-05-22 17:42:58 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-05-22 17:42:58 -0400
commitc97e49c4ae19feaea289b0c31ff99aa57bcc512d (patch)
tree80957a797a506279de137452fa2901c9c42cb3f5
parentbf885833a2031c238e19ac3578a8d81ad35e08b0 (diff)
Http buffer update polish
-rw-r--r--lib/Net.Http/src/Core/Buffering/ContextLockedBufferManager.cs5
-rw-r--r--lib/Net.Http/src/Core/Buffering/HttpBufferElement.cs4
-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.cs20
-rw-r--r--lib/Net.Http/src/Core/Request/HttpRequestBody.cs4
-rw-r--r--lib/Net.Http/src/Core/RequestParse/Http11ParseExtensions.cs39
-rw-r--r--lib/Net.Http/src/Helpers/CoreBufferHelpers.cs71
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs11
8 files changed, 70 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;
- }
-
- }
-}
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index c4cbc2f..26adf85 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -709,6 +709,17 @@ namespace VNLib.Utils.Memory
/// <summary>
/// Gets a <see cref="Span{T}"/> over the block of memory pointed to by the supplied handle.
+ /// reference
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="handle"></param>
+ /// <param name="size">The size of the span (the size of the block)</param>
+ /// <returns>A span over the block of memory pointed to by the handle of the specified size</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> GetSpan<T>(ref MemoryHandle handle, int size) => new(handle.Pointer, size);
+
+ /// <summary>
+ /// Gets a <see cref="Span{T}"/> over the block of memory pointed to by the supplied handle.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="handle"></param>