aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-03-10 16:03:08 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-03-10 16:03:08 -0400
commitdd0f384ec3b2fd86ec03aa0fb42387091b5430a7 (patch)
tree23f6e1c99fe2c0d1c0c12b0a40dba2d7f35e90c6
parentb679ddd4e647ac915febd0d5a5e488a1e8e48842 (diff)
Squashed commit of the following:
commit df1fed9e668d9e629354b209fd9dba18301db5d7 Author: vnugent <public@vaughnnugent.com> Date: Sun Mar 10 16:01:29 2024 -0400 refactor: primary constructor for HttpRequest commit 795e7d307b5aa90321f9867d3b6b2630e3d8f29b Author: vnugent <public@vaughnnugent.com> Date: Sat Mar 9 16:30:43 2024 -0500 package updates commit c826c9f99d9ccd43e056bc7b7283146868733e85 Author: vnugent <public@vaughnnugent.com> Date: Sat Mar 9 14:58:58 2024 -0500 feat: Some docs, and updated clr string erasure functionality commit cefe2c38d9093bff553aa46c2fcf08380c6e2aed Author: vnugent <public@vaughnnugent.com> Date: Wed Mar 6 21:37:59 2024 -0500 chore: removed bad oauth token function, abstracted HttpServer commit d2ef0e78b27c68fb83d183d50beeeb7a5ba7cba8 Author: vnugent <public@vaughnnugent.com> Date: Wed Mar 6 19:49:55 2024 -0500 chore: pluginbase logging, consitent proj files, some outdated readmes commit b7537cd283431f684b16d3008d3b45f8b063d489 Author: vnugent <public@vaughnnugent.com> Date: Sat Mar 2 15:12:48 2024 -0500 feat: session handle, endpoints, and helper functions
-rw-r--r--lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj9
-rw-r--r--lib/Net.Compression/VNLib.Net.Compression/VNLib.Net.Compression.csproj8
-rw-r--r--lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj6
-rw-r--r--lib/Net.Http/src/AlternateProtocolBase.cs2
-rw-r--r--lib/Net.Http/src/Core/AlternateProtocolTransportStreamWrapper.cs (renamed from lib/Net.Http/src/Helpers/AlternateProtocolTransportStreamWrapper.cs)14
-rw-r--r--lib/Net.Http/src/Core/HttpEvent.cs2
-rw-r--r--lib/Net.Http/src/Core/HttpServerProcessing.cs14
-rw-r--r--lib/Net.Http/src/Core/Request/HttpRequest.cs55
-rw-r--r--lib/Net.Http/src/IHttpEvent.cs2
-rw-r--r--lib/Net.Http/src/VNLib.Net.Http.csproj12
-rw-r--r--lib/Net.Messaging.FBM/README.md10
-rw-r--r--lib/Net.Messaging.FBM/src/Client/FBMClient.cs9
-rw-r--r--lib/Net.Messaging.FBM/src/Client/FBMClientFactory.cs13
-rw-r--r--lib/Net.Messaging.FBM/src/Client/FBMFallbackClientWsFactory.cs19
-rw-r--r--lib/Net.Messaging.FBM/src/Client/FBMRequest.cs33
-rw-r--r--lib/Net.Messaging.FBM/src/Client/README.md122
-rw-r--r--lib/Net.Messaging.FBM/src/Server/readme.md17
-rw-r--r--lib/Net.Messaging.FBM/src/SharedHeapFBMMemoryManager.cs (renamed from lib/Net.Messaging.FBM/src/FallbackFBMMemoryManager.cs)33
-rw-r--r--lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj8
-rw-r--r--lib/Net.Transport.SimpleTCP/src/VNLib.Net.Transport.SimpleTCP.csproj8
-rw-r--r--lib/Plugins.Essentials.ServiceStack/README.md6
-rw-r--r--lib/Plugins.Essentials.ServiceStack/src/VNLib.Plugins.Essentials.ServiceStack.csproj13
-rw-r--r--lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs34
-rw-r--r--lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs8
-rw-r--r--lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs20
-rw-r--r--lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs29
-rw-r--r--lib/Plugins.Essentials/src/HttpEntity.cs2
-rw-r--r--lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs8
-rw-r--r--lib/Plugins.Essentials/src/Sessions/SessionHandle.cs50
-rw-r--r--lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj7
-rw-r--r--lib/Plugins.PluginBase/src/PluginBase.cs28
-rw-r--r--lib/Plugins.PluginBase/src/VNLib.Plugins.PluginBase.csproj10
-rw-r--r--lib/Plugins.Runtime/src/VNLib.Plugins.Runtime.csproj7
-rw-r--r--lib/Utils.Cryptography/monocypher/readme.md30
-rw-r--r--lib/Utils.Cryptography/readme.md17
-rw-r--r--lib/Utils/src/IO/VnMemoryStream.cs3
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs21
-rw-r--r--lib/Utils/src/Memory/PrivateStringManager.cs16
-rw-r--r--lib/Utils/src/VNLib.Utils.csproj13
-rw-r--r--lib/Utils/tests/VNLib.UtilsTests.csproj6
40 files changed, 312 insertions, 412 deletions
diff --git a/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj
index e61aa95..db95906 100644
--- a/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj
+++ b/lib/Hashing.Portable/tests/VNLib.Hashing.PortableTests.csproj
@@ -15,9 +15,12 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
- <PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
- <PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
- <PackageReference Include="coverlet.collector" Version="6.0.0" />
+ <PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
+ <PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
+ <PackageReference Include="coverlet.collector" Version="6.0.1">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
</ItemGroup>
<ItemGroup>
diff --git a/lib/Net.Compression/VNLib.Net.Compression/VNLib.Net.Compression.csproj b/lib/Net.Compression/VNLib.Net.Compression/VNLib.Net.Compression.csproj
index 36082f1..14672ae 100644
--- a/lib/Net.Compression/VNLib.Net.Compression/VNLib.Net.Compression.csproj
+++ b/lib/Net.Compression/VNLib.Net.Compression/VNLib.Net.Compression.csproj
@@ -10,11 +10,8 @@
<AnalysisLevel>latest-all</AnalysisLevel>
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
- <!--Enable dynamic loading for debugging-->
+ <!--Enable dynamic loading because it's dynamically loaded by servers-->
<EnableDynamicLoading>true</EnableDynamicLoading>
- <PackageReadmeFile>readme.md</PackageReadmeFile>
- <PackageLicenseFile>LICENSE</PackageLicenseFile>
- <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
<PropertyGroup>
@@ -26,6 +23,9 @@
<Description>.NET/8.0 dynamically loadable managed wrapper library for loading vnlib_compress native library. It provides an implementation of the IHttpCompressorManager interface for use with the VNLib.Net.Http library and servers wishing to support dynamic response compression.</Description>
<PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Core</PackageProjectUrl>
<RepositoryUrl>https://github.com/VnUgE/VNLib.Core/tree/main/lib/Net.Compression</RepositoryUrl>
+ <PackageReadmeFile>readme.md</PackageReadmeFile>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
<ItemGroup>
diff --git a/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj b/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj
index bf1c1a1..fb462d1 100644
--- a/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj
+++ b/lib/Net.Compression/VNLib.Net.CompressionTests/VNLib.Net.CompressionTests.csproj
@@ -9,9 +9,9 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
- <PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
- <PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
- <PackageReference Include="coverlet.collector" Version="6.0.0">
+ <PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
+ <PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
+ <PackageReference Include="coverlet.collector" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
diff --git a/lib/Net.Http/src/AlternateProtocolBase.cs b/lib/Net.Http/src/AlternateProtocolBase.cs
index 929bc33..e7b9a61 100644
--- a/lib/Net.Http/src/AlternateProtocolBase.cs
+++ b/lib/Net.Http/src/AlternateProtocolBase.cs
@@ -58,7 +58,7 @@ namespace VNLib.Net.Http
try
{
//Call child initialize method
- await RunAsync(new AlternateProtocolTransportStreamWrapper(transport));
+ await RunAsync(transport);
CancelSource.Cancel();
}
finally
diff --git a/lib/Net.Http/src/Helpers/AlternateProtocolTransportStreamWrapper.cs b/lib/Net.Http/src/Core/AlternateProtocolTransportStreamWrapper.cs
index d81b7eb..8661e15 100644
--- a/lib/Net.Http/src/Helpers/AlternateProtocolTransportStreamWrapper.cs
+++ b/lib/Net.Http/src/Core/AlternateProtocolTransportStreamWrapper.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -34,19 +34,15 @@ namespace VNLib.Net.Http.Core
{
internal sealed class AlternateProtocolTransportStreamWrapper : BackingStream<Stream>
{
- public AlternateProtocolTransportStreamWrapper(Stream transport)
- {
- this.BaseStream = transport;
- }
+ public AlternateProtocolTransportStreamWrapper(Stream transport) => BaseStream = transport;
//Do not allow the caller to dispose the transport stream
protected override void Dispose(bool disposing)
{ }
- public override ValueTask DisposeAsync()
- {
- return ValueTask.CompletedTask;
- }
+
+ public override ValueTask DisposeAsync() => ValueTask.CompletedTask;
+
public override void Close()
{}
}
diff --git a/lib/Net.Http/src/Core/HttpEvent.cs b/lib/Net.Http/src/Core/HttpEvent.cs
index e6f3b5b..8867a12 100644
--- a/lib/Net.Http/src/Core/HttpEvent.cs
+++ b/lib/Net.Http/src/Core/HttpEvent.cs
@@ -50,7 +50,7 @@ namespace VNLib.Net.Http
IConnectionInfo IHttpEvent.Server => _ci;
///<inheritdoc/>
- HttpServer IHttpEvent.OriginServer => Context.ParentServer;
+ IHttpServer IHttpEvent.OriginServer => Context.ParentServer;
///<inheritdoc/>
IReadOnlyDictionary<string, string> IHttpEvent.QueryArgs => Context.Request.QueryArgs;
diff --git a/lib/Net.Http/src/Core/HttpServerProcessing.cs b/lib/Net.Http/src/Core/HttpServerProcessing.cs
index 4595f3e..8a9ca07 100644
--- a/lib/Net.Http/src/Core/HttpServerProcessing.cs
+++ b/lib/Net.Http/src/Core/HttpServerProcessing.cs
@@ -101,8 +101,18 @@ namespace VNLib.Net.Http
stream.ReadTimeout = Timeout.Infinite;
stream.WriteTimeout = Timeout.Infinite;
+ /*
+ * Create a transport wrapper so callers cannot take control of the transport
+ * hooks such as disposing. Timeouts are allowed to be changed, not exactly
+ * our problem.
+ */
+
+#pragma warning disable CA2000 // Dispose objects before losing scope
+ AlternateProtocolTransportStreamWrapper apWrapper = new(transport:stream);
+#pragma warning restore CA2000 // Dispose objects before losing scope
+
//Listen on the alternate protocol
- await ap.RunAsync(stream, StopToken!.Token).ConfigureAwait(false);
+ await ap.RunAsync(apWrapper, StopToken!.Token).ConfigureAwait(false);
}
}
//Catch wrapped socket exceptions
@@ -131,7 +141,7 @@ namespace VNLib.Net.Http
//Dec open connection count
Interlocked.Decrement(ref OpenConnectionCount);
- //Return the context for normal operation
+ //Return the context for normal operation (alternate protocol will return before now so it will be null)
if(context != null)
{
//Return context to store
diff --git a/lib/Net.Http/src/Core/Request/HttpRequest.cs b/lib/Net.Http/src/Core/Request/HttpRequest.cs
index 43b3e5f..ce8257f 100644
--- a/lib/Net.Http/src/Core/Request/HttpRequest.cs
+++ b/lib/Net.Http/src/Core/Request/HttpRequest.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Http
@@ -32,24 +32,23 @@ using VNLib.Utils.Extensions;
namespace VNLib.Net.Http.Core
{
-
- internal sealed class HttpRequest : IHttpLifeCycle
+ internal sealed class HttpRequest(IHttpContextInformation contextInfo, ushort maxUploads) : IHttpLifeCycle
#if DEBUG
,IStringSerializeable
#endif
{
- public readonly VnWebHeaderCollection Headers;
- public readonly List<string> Accept;
- public readonly List<string> AcceptLanguage;
- public readonly Dictionary<string, string> Cookies;
- public readonly Dictionary<string, string> RequestArgs;
- public readonly Dictionary<string, string> QueryArgs;
+ public readonly VnWebHeaderCollection Headers = new();
+ public readonly List<string> Accept = new(8);
+ public readonly List<string> AcceptLanguage = new(8);
+ public readonly Dictionary<string, string> Cookies = new(5, StringComparer.OrdinalIgnoreCase);
+ public readonly Dictionary<string, string> RequestArgs = new(StringComparer.OrdinalIgnoreCase);
+ public readonly Dictionary<string, string> QueryArgs = new(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// A transport stream wrapper that is positioned for reading
/// the entity body from the input stream
/// </summary>
- public readonly HttpInputStream InputStream;
+ public readonly HttpInputStream InputStream = new(contextInfo);
/*
* Evil mutable structure that stores the http request state.
@@ -63,7 +62,7 @@ namespace VNLib.Net.Http.Core
* null/default values and easy reset.
*/
private HttpRequestState _state;
- private readonly FileUpload[] _uploads;
+ private readonly FileUpload[] _uploads = new FileUpload[maxUploads];
/// <summary>
/// Gets a mutable structure ref only used to initalize the request
@@ -77,20 +76,6 @@ namespace VNLib.Net.Http.Core
/// </summary>
internal ref readonly HttpRequestState State => ref _state;
- public HttpRequest(IHttpContextInformation contextInfo, ushort maxUploads)
- {
- //Create new collection for headers
- _uploads = new FileUpload[maxUploads];
- Headers = new();
- Cookies = new(5, StringComparer.OrdinalIgnoreCase);
- RequestArgs = new(StringComparer.OrdinalIgnoreCase);
- QueryArgs = new(StringComparer.OrdinalIgnoreCase);
- Accept = new(8);
- AcceptLanguage = new(8);
- //New reusable input stream
- InputStream = new(contextInfo);
- }
-
void IHttpLifeCycle.OnPrepare()
{ }
@@ -147,10 +132,22 @@ namespace VNLib.Net.Http.Core
}
}
+ /// <summary>
+ /// Checks if another upload can be added to the request
+ /// </summary>
+ /// <returns>A value indicating if another file upload can be added to the array</returns>
+ public bool CanAddUpload() => _state.UploadCount < _uploads.Length;
+
+ /// <summary>
+ /// Attempts to add a file upload to the request if there
+ /// is room for it. If there is no room, it will be ignored.
+ /// See <see cref="CanAddUpload"/> to check if another upload can be added.
+ /// </summary>
+ /// <param name="upload">The file upload structure to add to the list</param>
public void AddFileUpload(in FileUpload upload)
{
//See if there is room for another upload
- if (_state.UploadCount < _uploads.Length)
+ if (CanAddUpload())
{
//Add file to upload array and increment upload count
_uploads[_state.UploadCount++] = upload;
@@ -158,12 +155,6 @@ namespace VNLib.Net.Http.Core
}
/// <summary>
- /// Checks if another upload can be added to the request
- /// </summary>
- /// <returns>A value indicating if another file upload can be added to the array</returns>
- public bool CanAddUpload() => _state.UploadCount < _uploads.Length;
-
- /// <summary>
/// Creates a new array and copies the uploads to it.
/// </summary>
/// <returns>The array clone of the file uploads</returns>
diff --git a/lib/Net.Http/src/IHttpEvent.cs b/lib/Net.Http/src/IHttpEvent.cs
index 917f959..ce7f6ff 100644
--- a/lib/Net.Http/src/IHttpEvent.cs
+++ b/lib/Net.Http/src/IHttpEvent.cs
@@ -42,7 +42,7 @@ namespace VNLib.Net.Http
/// <summary>
/// The <see cref="HttpServer"/> that this connection originated from
/// </summary>
- HttpServer OriginServer { get; }
+ IHttpServer OriginServer { get; }
/// <summary>
/// If the request has query arguments they are stored in key value format
diff --git a/lib/Net.Http/src/VNLib.Net.Http.csproj b/lib/Net.Http/src/VNLib.Net.Http.csproj
index 43224fe..b491cc1 100644
--- a/lib/Net.Http/src/VNLib.Net.Http.csproj
+++ b/lib/Net.Http/src/VNLib.Net.Http.csproj
@@ -25,18 +25,6 @@
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'">
- <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
<PrivateAssets>all</PrivateAssets>
diff --git a/lib/Net.Messaging.FBM/README.md b/lib/Net.Messaging.FBM/README.md
index 3b7713e..022ef51 100644
--- a/lib/Net.Messaging.FBM/README.md
+++ b/lib/Net.Messaging.FBM/README.md
@@ -1,18 +1,18 @@
# VNLib.Net.Messaging.FBM
-High performance structured web-socket based asynchronous request/response messaging library for .NET.
+*High performance structured websocket based asynchronous request/response messaging library for .NET.*
-[**Client Lib**](src/Client/#) - FBM Fixed Buffer Messaging client library
-[**Server Lib**](src/Server/#) - FBM Fixed Buffer Messaging server/listener helper library
+The protocol specification and library usage is on my website at the docs link below.
## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file.
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).
## Docs and Guides
Documentation, specifications, and setup guides are available on my website.
[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_VNLib.Net.Messaging.FBM)
[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core)
+[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
## License
-The software in this repository is licensed under the GNU Affero General Public License (or any later version). See the [LICENSE](LICENSE.txt) file for more information. \ No newline at end of file
+The software for this library is licensed under the GNU Affero General Public License (or any later version). See the [LICENSE](LICENSE.txt) file for more information. \ No newline at end of file
diff --git a/lib/Net.Messaging.FBM/src/Client/FBMClient.cs b/lib/Net.Messaging.FBM/src/Client/FBMClient.cs
index d3b6b55..fb9e3b4 100644
--- a/lib/Net.Messaging.FBM/src/Client/FBMClient.cs
+++ b/lib/Net.Messaging.FBM/src/Client/FBMClient.cs
@@ -106,11 +106,11 @@ namespace VNLib.Net.Messaging.FBM.Client
/// </summary>
/// <param name="config">The client config</param>
/// <param name="websocket">The websocket instance used to comunicate with an FBMServer</param>
- public FBMClient(in FBMClientConfig config, IFbmClientWebsocket websocket)
+ public FBMClient(ref readonly FBMClientConfig config, IFbmClientWebsocket websocket)
:this(in config, websocket, null)
{ }
- internal FBMClient(in FBMClientConfig config, IFbmClientWebsocket websocket, IObjectRental<FBMRequest>? requestRental)
+ internal FBMClient(ref readonly FBMClientConfig config, IFbmClientWebsocket websocket, IObjectRental<FBMRequest>? requestRental)
{
ArgumentNullException.ThrowIfNull(websocket);
ArgumentNullException.ThrowIfNull(config.MemoryManager, nameof(config.MemoryManager));
@@ -118,7 +118,7 @@ namespace VNLib.Net.Messaging.FBM.Client
_config = config;
_socket = websocket;
- //Create new request rental if none supplied
+ //Create new request rental if none supplied, it will have to be disposed when the client exits
if(requestRental is null)
{
_ownsObjectRenal = true;
@@ -129,7 +129,7 @@ namespace VNLib.Net.Messaging.FBM.Client
_requestRental = requestRental;
}
- Headers = new();
+ Headers = [];
SendLock = new(1);
ConnectionStatusHandle = new(true);
ActiveRequests = new(Environment.ProcessorCount, 100);
@@ -232,6 +232,7 @@ namespace VNLib.Net.Messaging.FBM.Client
/// </param>
/// <returns>When awaited, yields the server response</returns>
/// <exception cref="ArgumentException"></exception>
+ /// <exception cref="TimeoutException"></exception>
/// <exception cref="ObjectDisposedException"></exception>
/// <exception cref="InvalidOperationException"></exception>
/// <exception cref="FBMInvalidRequestException"></exception>
diff --git a/lib/Net.Messaging.FBM/src/Client/FBMClientFactory.cs b/lib/Net.Messaging.FBM/src/Client/FBMClientFactory.cs
index 51d3768..25c8cd8 100644
--- a/lib/Net.Messaging.FBM/src/Client/FBMClientFactory.cs
+++ b/lib/Net.Messaging.FBM/src/Client/FBMClientFactory.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Messaging.FBM
@@ -43,13 +43,16 @@ namespace VNLib.Net.Messaging.FBM.Client
/// </summary>
/// <param name="config">The configuration state</param>
/// <param name="webSocketManager">The client websocket factory</param>
+ /// <param name="maxClients">The maximum number of clients expected to be connected concurrently</param>
/// <exception cref="ArgumentNullException"></exception>
- public FBMClientFactory(in FBMClientConfig config, IFbmWebsocketFactory webSocketManager)
+ public FBMClientFactory(ref readonly FBMClientConfig config, IFbmWebsocketFactory webSocketManager, int maxClients)
{
+ ArgumentNullException.ThrowIfNull(config.MemoryManager, nameof(config.MemoryManager));
+ ArgumentNullException.ThrowIfNull(webSocketManager);
+
_config = config;
- _ = config.MemoryManager ?? throw new ArgumentException("The client memory manager must not be null", nameof(config));
- _socketMan = webSocketManager ?? throw new ArgumentNullException(nameof(webSocketManager));
- _internalRequestPool = ObjectRental.CreateReusable(ReuseableRequestConstructor, 1000);
+ _socketMan = webSocketManager;
+ _internalRequestPool = ObjectRental.CreateReusable(ReuseableRequestConstructor, maxClients);
}
/// <summary>
diff --git a/lib/Net.Messaging.FBM/src/Client/FBMFallbackClientWsFactory.cs b/lib/Net.Messaging.FBM/src/Client/FBMFallbackClientWsFactory.cs
index 5ee4142..a6cfbbd 100644
--- a/lib/Net.Messaging.FBM/src/Client/FBMFallbackClientWsFactory.cs
+++ b/lib/Net.Messaging.FBM/src/Client/FBMFallbackClientWsFactory.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Messaging.FBM
@@ -36,17 +36,12 @@ namespace VNLib.Net.Messaging.FBM.Client
/// Creates a new <see cref="IFbmWebsocketFactory"/> that builds new client websockets
/// on demand using the <see cref="ClientWebSocket"/> .NET default implementation
/// </summary>
- public class FBMFallbackClientWsFactory : IFbmWebsocketFactory
+ /// <remarks>
+ /// Initalizes a new <see cref="FBMFallbackClientWsFactory"/> instance
+ /// </remarks>
+ /// <param name="onConfigureSocket">A callback function that allows users to configure sockets when created</param>
+ public class FBMFallbackClientWsFactory(Action<ClientWebSocketOptions>? onConfigureSocket = null) : IFbmWebsocketFactory
{
- private readonly Action<ClientWebSocketOptions>? _onConfigure;
-
- /// <summary>
- /// Initalizes a new <see cref="FBMFallbackClientWsFactory"/> instance
- /// </summary>
- /// <param name="onConfigureSocket">A callback function that allows users to configure sockets when created</param>
- public FBMFallbackClientWsFactory(Action<ClientWebSocketOptions>? onConfigureSocket = null)
- => _onConfigure = onConfigureSocket;
-
///<inheritdoc/>
public IFbmClientWebsocket CreateWebsocket(in FBMClientConfig clientConfig)
{
@@ -65,7 +60,7 @@ namespace VNLib.Net.Messaging.FBM.Client
}
//invoke client configuration user callback
- _onConfigure?.Invoke(socket.Options);
+ onConfigureSocket?.Invoke(socket.Options);
return new FBMWebsocket(socket, poolBuffer);
}
diff --git a/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs b/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
index 1787941..f16a490 100644
--- a/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
+++ b/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
@@ -40,6 +40,7 @@ using VNLib.Utils.Memory.Caching;
namespace VNLib.Net.Messaging.FBM.Client
{
+
/// <summary>
/// <para>
/// A reusable Fixed Buffer Message request container. This class is not thread-safe
@@ -50,6 +51,28 @@ namespace VNLib.Net.Messaging.FBM.Client
/// </summary>
public sealed class FBMRequest : VnDisposeable, IReusable, IFBMMessage, IStringSerializeable
{
+ /*
+ * Important impl notes.
+ *
+ * In order to conserve memory and types, the FBMRequest stores all state information
+ * and memory required for an FBM transaction. That is, the request headers, the
+ * message waiting state (the wait handles for async/await), and the response message
+ * headers and body.
+ *
+ * Okay, the buffer is used for 3 purposes.
+ * - Store request headers
+ * - Store request body if not streaming
+ * - Store response headers once message has been sent
+ *
+ * Since a request is no longer needed when a response is received, it's buffer is used
+ * to store response header data. (it becomes tri-use).
+ *
+ * During response header parsing, FBMMessageHeader structures are stored in the
+ * ResponseHeaderList field that are simply pointers to consecutive memory locations
+ * in the buffer. This is done to avoid allocating multiple memory segments for each
+ * header key-value pair, and internal copy overhead.
+ */
+
#pragma warning disable CA2213 // Disposable fields should be disposed
private readonly FBMBuffer Buffer;
#pragma warning restore CA2213 // Disposable fields should be disposed
@@ -62,7 +85,7 @@ namespace VNLib.Net.Messaging.FBM.Client
* in the reused buffer (in response "mode") cast to a
* character buffer.
*/
- private readonly List<FBMMessageHeader> ResponseHeaderList = new();
+ private readonly List<FBMMessageHeader> ResponseHeaderList = [];
/// <summary>
@@ -88,7 +111,7 @@ namespace VNLib.Net.Messaging.FBM.Client
/// and a random messageid
/// </summary>
/// <param name="config">The fbm client config storing required config variables</param>
- public FBMRequest(in FBMClientConfig config) : this(Helpers.RandomMessageId, in config)
+ public FBMRequest(ref readonly FBMClientConfig config) : this(Helpers.RandomMessageId, in config)
{ }
/// <summary>
@@ -96,7 +119,7 @@ namespace VNLib.Net.Messaging.FBM.Client
/// </summary>
/// <param name="messageId">The custom message id</param>
/// <param name="config">The fbm client config storing required config variables</param>
- public FBMRequest(int messageId, in FBMClientConfig config)
+ public FBMRequest(int messageId, ref readonly FBMClientConfig config)
:this(messageId, config.MemoryManager, config.MessageBufferSize, config.HeaderEncoding)
{ }
@@ -358,7 +381,7 @@ namespace VNLib.Net.Messaging.FBM.Client
if (cancellation.CanBeCanceled)
{
//Register cancellation
- _token = cancellation.Register(OnCancelled, this, false);
+ _token = cancellation.Register(OnCancelled, null, false);
}
}
@@ -366,7 +389,7 @@ namespace VNLib.Net.Messaging.FBM.Client
}
///<inheritdoc/>
- public void ManualCancellation() => OnCancelled(this);
+ public void ManualCancellation() => OnCancelled(null);
//Set cancelled state if exists, the task may have already completed
private void OnCancelled(object? state) => _tcs?.TrySetCanceled();
diff --git a/lib/Net.Messaging.FBM/src/Client/README.md b/lib/Net.Messaging.FBM/src/Client/README.md
deleted file mode 100644
index ea76a46..0000000
--- a/lib/Net.Messaging.FBM/src/Client/README.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# VNLib.Net.Messaging.FBM.Client
-
-Fixed Buffer Messaging Protocol client library. High performance stateful messaging protocol built on top of HTTP web-sockets. Low/no allocation, completely asynchronous while providing a TPL API. This library provides a simple asynchronous request/response architecture to web-sockets. This was initially designed to provide an alternative to complete HTTP request/response overhead, but allow a simple control flow for work across a network.
-
-The base of the library relies on creating message objects that allocate fixed size buffers are configured when the IFBMMessageis constructed. All data is written to the internal buffer adhering to the [FBM protocol](../../#)
-
-This client library allows for messages to be streamed to the server, however this library is optimized for fixed buffers, so streaming will not be the most efficient, and will likely cause slow-downs in message transmission. However, since FBM relies on a streaming protocol,
-so it was silly not to provide it. Streams add overhead of additional buffer allocation, additional copy, and message fragmentation (multiple writes to the web-socket). Since frames written to the web-socket must be synchronized, a mutex is held during transmission, which means the more message overhead, the longer the blocking period on new messages. Mutex acquisition will wait asynchronously when necessary.
-
-## Fundamentals
-The main implementation is the FBMClient class. This class provides the means for creating the stateful connection to the remote server. It also provides an internal FBMRequest message rental (object cache) that created initialized FBMRequest messages. This class may be derived to provide additional functionality, such as handling control frames that may dynamically alter the state of the connection (negotiation etc). A mechanism to do so is provided.
-
-### FBMClient layout
-
-``` C#
- public class FBMClient : VnDisposeable, IStatefulConnection, ICacheHolder
- {
- //Raised when an error occurs during receiving or parsing
- public event EventHandler<FMBClientErrorEventArgs>? ConnectionClosedOnError;
-
- //Raised when connection is closed, regardless of the cause
- public event EventHandler? ConnectionClosed;
-
- //Connects to the remote server at the specified websocket address (ws:// or wss://)
- public Task ConnectAsync(Uri address, CancellationToken cancellation = default);
-
- //When connected, sends the specified message to the remote server, with the default timeout
- public Task<FBMResponse> SendAsync(FBMRequest request, CancellationToken cancellationToken = default);
-
- //When connected, sends the specified message to the remote server, with the specified timeout, -1 or 0 to disable timeout
- public Task<FBMResponse> SendAsync(FBMRequest request, TimeSpan timeout, CancellationToken cancellationToken = default);
-
- //When connected, streams a message to the remote server, * the message payload must not be configured *
- public Task<FBMResponse> StreamDataAsync(FBMRequest request, Stream payload, ContentType ct, CancellationToken cancellationToken = default);
-
- //Disconnects from the remote server
- public async Task DisconnectAsync(CancellationToken cancellationToken = default);
-
- //Releases all held resourses
- public void Dispose(); //Inherrited from VnDisposeable
-
- ICacheHolder.CacheClear(); //Inherited member, clears cached FBMRequest objects
- ICacheHolder.CacheHardClear(); //Inherited member, clears cached FBMRequest objects
- }
-```
-
-### Example usage
-``` C#
-
- FBMClientConfig config = new()
- {
- //The unmanaged heap the allocate buffers from
- BufferHeap = MemoryUtil.Shared,
- //The absolute maximum message size to buffer from the server
- MaxMessageSize = 10 * 1024 * 1024, //10KiB,
- //The size of the buffer used for buffering incoming messages server messages
- RecvBufferSize = maxExtra,
- //The FBMRequest internal buffer size, should be max message + headers
- MessageBufferSize = (int)Helpers.ToNearestKb(maxMessageSize + MAX_FBM_MESSAGE_HEADER_SIZE),
- //The space reserved in the FBM request buffer used for header storage
- MaxHeaderBufferSize = 1024,
- //Set the web-socket subprotocol
- SubProtocol = "object-cache",
- //Use the default encoding (UTF-8)
- HeaderEncoding = Helpers.DefaultEncoding,
- //How frequently to send web-socket keepalive messages
- KeepAliveInterval = TimeSpan.FromSeconds(30),
- //The default request message timeout
- RequestTimeout = TimeSpan.FromSeconds(10),
- //optional debug log, write message debug information if set
- DebugLog = null
- };
-
- //Create client from the config
- using (FBMClient client = new(config))
- {
- //Usually set some type of authentication headers before connecting
-
- /*
- client.ClientSocket.SetHeader("Authorization", "Authorization token");
- */
-
- //Connect to server
- Uri address = new Uri("wss://localhost:8080/some/fbm/endpoint");
- await client.ConnectAsync(address, CancellationToken.None);
-
- do
- {
- //Rent request message
- FBMRequest request = client.RentRequest();
- //Some arbitrary header value (or preconfigured header)
- request.WriteHeader(0x10, "Hello");
- //Some arbitrary payload
- request.WriteBody(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }, ContentType.Binary);
- //Send request message
- using (FBMResponse response = await client.SendAsync(request, CancellationToken.None))
- {
- //Extension method to raise exception if an invalid response was received (also use the response.IsSet flag)
- response.ThrowIfNotSet();
-
- //Check header parse status
- //response.StatusFlags
-
- //Check headers (using Linq to get first header)
- string header1 = response.Headers.First().Value.ToString();
-
- //Get payload, data is valid until the response is disposed
- ReadOnlySpan<byte> body = response.ResponseBody;
- }
- //Return request
- client.ReturnRequest(request);
- //request.Dispose(); //Alternativly dispose message
-
- await Task.Delay(1000);
- }
- while(true);
- //You should probably cleanup by asynchronously closing the connection before disposing
- }
-```
-
-## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my [website](https://www.vaughnnugent.com/resources/software). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file. \ No newline at end of file
diff --git a/lib/Net.Messaging.FBM/src/Server/readme.md b/lib/Net.Messaging.FBM/src/Server/readme.md
deleted file mode 100644
index cd6f53e..0000000
--- a/lib/Net.Messaging.FBM/src/Server/readme.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# VNLib.Net.Messaging.FBM.Server
-
-Please see [FBM Protocol spec](../../#) for architecture details
-
-## Usage
-This library exports a main type called `FBMListener` it is the "entry point" so to speak for your server development. It listens on an active web-socket session that has been accepted an negotiated by your http server and passed to the `FBMListener.ListenAsync()` method. This call only returns once the connection is disconnected, has an error, or the session is closed. The listener listens for FBM messages on the web-socket, buffers them, and when message has been pre-processed, calls your request handler delegate if the message is valid. If the message exceeds the maximum size, the socket is gracefully closed and the method returns.
-
-Your `RequestHandler` delegate method accepts a type `FBMContext` that holds the request instance, and the `FBMResponseMessage` instance you will use to respond to the client. **Context instances are pooled, so you may not save them or any of their properties once your request handler returns.** Response objects implement the `IFBMMessage` interface, for your consumption. You may also use the "streaming" api, to reduce buffering and copying, implementing your own `IAsyncMessageBody` objects which allows reading data into a buffer asynchronously. Keep in mind a mutex is held while this streaming process occurs, and can cause performance issues, you should generally write a copy of your data to the internal response buffer.
-
-A `FBMListenerSessionParams` structure must be passed on every call `ListenAsync()` to define the buffer sizes and limits per-session.
-
-The `FBMListenerBase` is an abstract type that provides some scaffolding for implementing your own message handler, by handling some plumbing and giving you an abstract method to process incoming messages.
-
-Calls to your `RequestHandler` method are invoked on a background queuing task, to avoid blocking, or delaying the receive task. However it is still task, not a background thread, so you should try **not** to synchronously block in your request handling routine to avoid blocking a threadpool thread.
-
-## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my [website](https://www.vaughnnugent.com/resources/software). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file. \ No newline at end of file
diff --git a/lib/Net.Messaging.FBM/src/FallbackFBMMemoryManager.cs b/lib/Net.Messaging.FBM/src/SharedHeapFBMMemoryManager.cs
index 260cbd6..f32c084 100644
--- a/lib/Net.Messaging.FBM/src/FallbackFBMMemoryManager.cs
+++ b/lib/Net.Messaging.FBM/src/SharedHeapFBMMemoryManager.cs
@@ -1,12 +1,12 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Net.Messaging.FBM
-* File: FallbackFBMMemoryManager.cs
+* File: SharedHeapFBMMemoryManager.cs
*
-* FallbackFBMMemoryManager.cs is part of VNLib.Net.Messaging.FBM which is part of the larger
-* VNLib collection of libraries and utilities.
+* SharedHeapFBMMemoryManager.cs is part of VNLib.Net.Messaging.FBM which
+* is part of the larger VNLib collection of libraries and utilities.
*
* VNLib.Net.Messaging.FBM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -35,29 +35,27 @@ namespace VNLib.Net.Messaging.FBM
/// A default/fallback implementation of a <see cref="IFBMMemoryManager"/> that
/// uses an <see cref="IUnmangedHeap"/> to allocate buffers from
/// </summary>
- public sealed class FallbackFBMMemoryManager : IFBMMemoryManager
+ /// <remarks>
+ /// Initializes a new instance of <see cref="SharedHeapFBMMemoryManager"/> allocating
+ /// memory from the specified <see cref="IUnmangedHeap"/>
+ /// </remarks>
+ /// <param name="heap">The heap to allocate memory from</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public sealed class SharedHeapFBMMemoryManager(IUnmangedHeap heap) : IFBMMemoryManager
{
- private readonly IUnmangedHeap _heap;
-
- /// <summary>
- /// Initializes a new instance of <see cref="FallbackFBMMemoryManager"/> allocationg
- /// memory from the specified <see cref="IUnmangedHeap"/>
- /// </summary>
- /// <param name="heap">The heap to allocate memory from</param>
- /// <exception cref="ArgumentNullException"></exception>
- public FallbackFBMMemoryManager(IUnmangedHeap heap) => _heap = heap ?? throw new ArgumentNullException(nameof(heap));
+ private readonly IUnmangedHeap _heap = heap ?? throw new ArgumentNullException(nameof(heap));
///<inheritdoc/>
public void AllocBuffer(IFBMSpanOnlyMemoryHandle state, int size)
{
- _ = state ?? throw new ArgumentNullException(nameof(state));
+ ArgumentNullException.ThrowIfNull(state);
(state as IFBMBufferHolder)!.AllocBuffer(size);
}
///<inheritdoc/>
public void FreeBuffer(IFBMSpanOnlyMemoryHandle state)
{
- _ = state ?? throw new ArgumentNullException(nameof(state));
+ ArgumentNullException.ThrowIfNull(state);
(state as IFBMBufferHolder)!.FreeBuffer();
}
@@ -84,7 +82,7 @@ namespace VNLib.Net.Messaging.FBM
private sealed record class FBMMemHandle(IUnmangedHeap Heap) : IFBMMemoryHandle, IFBMBufferHolder
{
private MemoryHandle<byte>? _handle;
- private IMemoryOwner<byte>? _memHandle;
+ private MemoryManager<byte>? _memHandle;
///<inheritdoc/>
public Memory<byte> GetMemory()
@@ -112,7 +110,6 @@ namespace VNLib.Net.Messaging.FBM
public void FreeBuffer()
{
_handle?.Dispose();
- _memHandle?.Dispose();
_handle = null;
_memHandle = null;
diff --git a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
index c431fdd..c7a4151 100644
--- a/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
+++ b/lib/Net.Rest.Client/src/VNLib.Net.Rest.Client.csproj
@@ -23,14 +23,6 @@
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
<PrivateAssets>all</PrivateAssets>
diff --git a/lib/Net.Transport.SimpleTCP/src/VNLib.Net.Transport.SimpleTCP.csproj b/lib/Net.Transport.SimpleTCP/src/VNLib.Net.Transport.SimpleTCP.csproj
index e8c28f1..e999072 100644
--- a/lib/Net.Transport.SimpleTCP/src/VNLib.Net.Transport.SimpleTCP.csproj
+++ b/lib/Net.Transport.SimpleTCP/src/VNLib.Net.Transport.SimpleTCP.csproj
@@ -8,19 +8,21 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<AnalysisLevel>latest-all</AnalysisLevel>
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
- <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
- <PackageReadmeFile>README.md</PackageReadmeFile>
- <PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup>
+ <PackageId>VNLib.Net.Transport.SimpleTCP</PackageId>
<Product>VNLib Simple Transport Library</Product>
+ <PackageTags>vnlib, tcp, transport, simpletcp, networking</PackageTags>
<Description>Provides a library for single process asynchronous, event driven, TCP socket listening and supporting structures to implement simple high performance TCP servers with or without TLS security.</Description>
<Authors>Vaughn Nugent</Authors>
<Company>Vaughn Nugent</Company>
<Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
<PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Core</PackageProjectUrl>
<RepositoryUrl>https://github.com/VnUgE/VNLib.Core/tree/main/lib/Net.Transport.SimpleTCP</RepositoryUrl>
+ <PackageReadmeFile>README.md</PackageReadmeFile>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
<ItemGroup>
diff --git a/lib/Plugins.Essentials.ServiceStack/README.md b/lib/Plugins.Essentials.ServiceStack/README.md
index 240b5fc..e16044f 100644
--- a/lib/Plugins.Essentials.ServiceStack/README.md
+++ b/lib/Plugins.Essentials.ServiceStack/README.md
@@ -3,13 +3,15 @@
*A toolkit library for building full http stacks with the Plugins.Essentials framework into your application with hardware being the only limitation*
## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated .sha384 appended checksum of the desired download file.
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below).
## Docs and Guides
Documentation, specifications, and setup guides are available on my website.
[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_VNLib.Plugins.Essentials.ServiceStack)
[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core)
+[Nuget Feeds](https://www.vaughnnugent.com/resources/software/modules)
+
## License
-The software in this repository is licensed under the GNU Affero General Public License (or any later version). See the LICENSE files for more information. \ No newline at end of file
+The software for this library is licensed under the GNU Affero General Public License (or any later version). See the LICENSE files for more information.
diff --git a/lib/Plugins.Essentials.ServiceStack/src/VNLib.Plugins.Essentials.ServiceStack.csproj b/lib/Plugins.Essentials.ServiceStack/src/VNLib.Plugins.Essentials.ServiceStack.csproj
index 792b168..7dc12b6 100644
--- a/lib/Plugins.Essentials.ServiceStack/src/VNLib.Plugins.Essentials.ServiceStack.csproj
+++ b/lib/Plugins.Essentials.ServiceStack/src/VNLib.Plugins.Essentials.ServiceStack.csproj
@@ -16,24 +16,13 @@
<Company>Vaughn Nugent</Company>
<PackageId>VNLib.Plugins.Essentials.ServiceStack</PackageId>
<Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
- <Description>
- Provides data structures for building a dynamic HTTP servicing stack with runtime plugin loading,
- dynamic endpoint routing, middleware* configuration, and multi-server managment.
- </Description>
+ <Description>Provides data structures for building a dynamic HTTP servicing stack with runtime plugin loading, dynamic endpoint routing, middleware* configuration, and multi-server managment.</Description>
<PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Core</PackageProjectUrl>
<RepositoryUrl>https://github.com/VnUgE/VNLib.Core/tree/main/lib/Plugins.Essentials.ServiceStack</RepositoryUrl>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>
diff --git a/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs b/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs
index 7c72bc4..048c543 100644
--- a/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs
+++ b/lib/Plugins.Essentials/src/Endpoints/ResourceEndpointBase.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -42,6 +42,7 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// </summary>
public abstract class ResourceEndpointBase : VirtualEndpoint<HttpEntity>
{
+
/// <summary>
/// Default protection settings. Protection settings are the most
/// secure by default, should be loosened an necessary
@@ -288,6 +289,11 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// <returns>The results of the processing</returns>
protected virtual VfReturnType AlternateMethod(HttpEntity entity, HttpMethod method) => VirtualClose(entity, HttpStatusCode.MethodNotAllowed);
+ /// <summary>
+ /// This method gets invoked when an incoming OPTIONS request to the endpoint has been requested.
+ /// </summary>
+ /// <param name="entity">The entity to be processed</param>
+ /// <returns>The result of the operation to return to the file processor</returns>
protected virtual VfReturnType Options(HttpEntity entity) => VfReturnType.Forbidden;
/// <summary>
@@ -328,7 +334,8 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// <param name="entity">The entity to close the connection for</param>
/// <param name="jsonValue">A object that will be serialized and returned to the client as JSON</param>
/// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns>
- public static VfReturnType VirtualOkJson<T>(HttpEntity entity, T jsonValue) => VirtualCloseJson(entity, jsonValue, HttpStatusCode.OK);
+ public static VfReturnType VirtualOkJson<T>(HttpEntity entity, T jsonValue)
+ => VirtualCloseJson(entity, jsonValue, HttpStatusCode.OK);
/// <summary>
/// Shortcut helper methods to a virtual skip response with a 200 OK status code
@@ -338,7 +345,8 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// <param name="webm">The <see cref="WebMessage"/> json response</param>
/// <param name="code">The status code to return to the client</param>
/// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns>
- public static VfReturnType VirtualClose<T>(HttpEntity entity, T webm, HttpStatusCode code) where T: WebMessage => VirtualCloseJson(entity, webm, code);
+ public static VfReturnType VirtualClose<T>(HttpEntity entity, T webm, HttpStatusCode code) where T: WebMessage
+ => VirtualCloseJson(entity, webm, code);
/// <summary>
/// Shortcut helper methods to a virtual skip response with a given status code
@@ -391,11 +399,10 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// <param name="code">The status code to return to the client</param>
/// <param name="ct">The response content type</param>
/// <param name="response">The stream response to return to the user</param>
- /// <param name="length">The explicit length of the stream</param>
/// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns>
public static VfReturnType VirtualClose(HttpEntity entity, HttpStatusCode code, ContentType ct, Stream response)
{
- ArgumentNullException.ThrowIfNull(response, nameof(response));
+ ArgumentNullException.ThrowIfNull(response);
if (!response.CanSeek)
{
throw new IOException("The stream must be seekable when using implicit length");
@@ -405,6 +412,23 @@ namespace VNLib.Plugins.Essentials.Endpoints
}
/// <summary>
+ /// Shortcut helper methods to a virtual skip response with a given status code,
+ /// and memory content to return to the client
+ /// </summary>
+ /// <param name="entity">The entity to close the connection for</param>
+ /// <param name="code">The status code to return to the client</param>
+ /// <param name="ct">The response content type</param>
+ /// <param name="response">The stream response to return to the user</param>
+ /// <param name="length">The length of the response data to send to the clien</param>
+ /// <returns>The <see cref="VfReturnType.VirtualSkip"/> operation result</returns>
+ public static VfReturnType VirtualClose(HttpEntity entity, HttpStatusCode code, ContentType ct, IHttpStreamResponse response, long length)
+ {
+ ArgumentNullException.ThrowIfNull(response);
+ entity.CloseResponse(code, ct, response, length);
+ return VfReturnType.VirtualSkip;
+ }
+
+ /// <summary>
/// Shortcut helper methods to a virtual skip response with a given status code, and
/// a json payload to return to the client
/// </summary>
diff --git a/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs b/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs
index 7a4364b..0d3623b 100644
--- a/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs
+++ b/lib/Plugins.Essentials/src/Endpoints/UnprotectedWebEndpoint.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -33,9 +33,7 @@ namespace VNLib.Plugins.Essentials.Endpoints
public abstract class UnprotectedWebEndpoint : ResourceEndpointBase
{
///<inheritdoc/>
- protected override ERRNO PreProccess(HttpEntity entity)
- {
- return base.PreProccess(entity) && entity.Session.IsSet && entity.Session.SessionType == Sessions.SessionType.Web;
- }
+ protected override ERRNO PreProccess(HttpEntity entity)
+ => base.PreProccess(entity) && entity.Session.IsSet && entity.Session.SessionType == Sessions.SessionType.Web;
}
} \ No newline at end of file
diff --git a/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs b/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs
index 4ffe288..6d42ca7 100644
--- a/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs
+++ b/lib/Plugins.Essentials/src/Endpoints/VirtualEndpoint.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -47,19 +47,21 @@ namespace VNLib.Plugins.Essentials.Endpoints
/// <summary>
/// Sets the log and path and checks the values
/// </summary>
- /// <param name="Path">The path this instance represents</param>
+ /// <param name="path">The path this instance represents</param>
/// <param name="log">The log provider that will be used</param>
/// <exception cref="ArgumentException"></exception>
- protected void InitPathAndLog(string Path, ILogProvider log)
+ protected void InitPathAndLog(string path, ILogProvider log)
{
- if (string.IsNullOrWhiteSpace(Path) || Path[0] != '/')
+ ArgumentException.ThrowIfNullOrWhiteSpace(path);
+ ArgumentNullException.ThrowIfNull(log);
+
+ if (path[0] != '/')
{
- throw new ArgumentException("Path must begin with a '/' character", nameof(Path));
+ throw new ArgumentException("Path must begin with a '/' character", nameof(path));
}
- //Store path
- this.Path = Path;
- //Store log
- Log = log ?? throw new ArgumentNullException(nameof(log));
+
+ Path = path;
+ Log = log;
}
///<inheritdoc/>
diff --git a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
index 5f59346..8adf883 100644
--- a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
+++ b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
@@ -29,7 +29,6 @@ using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using VNLib.Net.Http;
@@ -46,8 +45,7 @@ namespace VNLib.Plugins.Essentials.Extensions
/// </summary>
public static class EssentialHttpEventExtensions
{
- public const string BEARER_STRING = "Bearer";
- private static readonly int BEARER_LEN = BEARER_STRING.Length;
+
/*
* Pooled/tlocal serializers
@@ -798,31 +796,6 @@ namespace VNLib.Plugins.Essentials.Extensions
//Parse the file using the specified parser
return parser(file.FileData, file.ContentTypeString());
}
-
- /// <summary>
- /// Gets the bearer token from an authorization header
- /// </summary>
- /// <param name="ci"></param>
- /// <param name="token">The token stored in the user's authorization header</param>
- /// <returns>True if the authorization header was set, has a Bearer token value</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool HasAuthorization(this IConnectionInfo ci, [NotNullWhen(true)] out string? token)
- {
- ArgumentNullException.ThrowIfNull(ci);
-
- //Get auth header value
- string? authorization = ci.Headers[HttpRequestHeader.Authorization];
- //Check if its set
- if (!string.IsNullOrWhiteSpace(authorization))
- {
- int bearerIndex = authorization.IndexOf(BEARER_STRING, StringComparison.OrdinalIgnoreCase);
- //Calc token offset, get token, and trim any whitespace
- token = authorization.AsSpan(bearerIndex + BEARER_LEN).Trim().ToString();
- return true;
- }
- token = null;
- return false;
- }
/// <summary>
/// Get a <see cref="DirectoryInfo"/> instance that points to the current sites filesystem root.
diff --git a/lib/Plugins.Essentials/src/HttpEntity.cs b/lib/Plugins.Essentials/src/HttpEntity.cs
index efdb2cd..2a24982 100644
--- a/lib/Plugins.Essentials/src/HttpEntity.cs
+++ b/lib/Plugins.Essentials/src/HttpEntity.cs
@@ -183,7 +183,7 @@ namespace VNLib.Plugins.Essentials
public IReadOnlyList<FileUpload> Files => Entity.Files;
///<inheritdoc/>
- HttpServer IHttpEvent.OriginServer => Entity.OriginServer;
+ IHttpServer IHttpEvent.OriginServer => Entity.OriginServer;
/// <summary>
/// Complete the session and respond to user
diff --git a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
index 3bce1f6..e65c26d 100644
--- a/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
+++ b/lib/Plugins.Essentials/src/Oauth/OauthHttpExtensions.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -68,7 +68,7 @@ namespace VNLib.Plugins.Essentials.Oauth
/// <summary>
/// The request could not be processed at this time
/// </summary>
- TemporarilyUnabavailable
+ TemporarilyUnavailable
}
public static class OauthHttpExtensions
@@ -114,7 +114,7 @@ namespace VNLib.Plugins.Essentials.Oauth
case ErrorType.ServerError:
writer.Append("server_error");
break;
- case ErrorType.TemporarilyUnabavailable:
+ case ErrorType.TemporarilyUnavailable:
writer.Append("temporarily_unavailable");
break;
default:
@@ -139,7 +139,7 @@ namespace VNLib.Plugins.Essentials.Oauth
ErrorType.UnsupportedResponseType => "Bearer error=\"unsupported_response_type\"",
ErrorType.InvalidScope => "Bearer error=\"invalid_scope\"",
ErrorType.ServerError => "Bearer error=\"server_error\"",
- ErrorType.TemporarilyUnabavailable => "Bearer error=\"temporarily_unavailable\"",
+ ErrorType.TemporarilyUnavailable => "Bearer error=\"temporarily_unavailable\"",
ErrorType.InvalidClient => "Bearer error=\"invalid_client\"",
ErrorType.InvalidToken => "Bearer error=\"invalid_token\"",
_ => "Bearer error=\"error\"",
diff --git a/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs b/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs
index 823012e..d41350d 100644
--- a/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs
+++ b/lib/Plugins.Essentials/src/Sessions/SessionHandle.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials
@@ -22,7 +22,9 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
+using System;
using System.Threading.Tasks;
+using System.Diagnostics.CodeAnalysis;
using VNLib.Net.Http;
@@ -35,59 +37,63 @@ namespace VNLib.Plugins.Essentials.Sessions
/// <param name="event">The connection the session is attached to</param>
/// <returns>A value task that resolves when the session has been released from the connection</returns>
public delegate ValueTask SessionReleaseCallback(ISession session, IHttpEvent @event);
-
+
/// <summary>
/// A handle that holds exclusive access to a <see cref="ISession"/>
/// session object
/// </summary>
- public readonly record struct SessionHandle
+ /// <param name="sessionData">The session data instance</param>
+ /// <param name="callback">A callback that is invoked when the handle is released</param>
+ /// <param name="entityStatus"></param>
+ public readonly struct SessionHandle(ISession? sessionData, FileProcessArgs entityStatus, SessionReleaseCallback? callback) : IEquatable<SessionHandle>
{
/// <summary>
/// An empty <see cref="SessionHandle"/> instance. (A handle without a session object)
/// </summary>
public static readonly SessionHandle Empty = new(null, FileProcessArgs.Continue, null);
- private readonly SessionReleaseCallback? ReleaseCb;
-
/// <summary>
/// True when a valid session is held by the current handle
/// </summary>
- internal readonly bool IsSet => SessionData != null;
+ internal readonly bool IsSet { get; } = sessionData != null;
/// <summary>
/// The session data object associated with the current session
/// </summary>
- public readonly ISession? SessionData { get; }
+ public readonly ISession? SessionData => sessionData;
/// <summary>
/// A value indicating if the connection is valid and should continue to be processed
/// </summary>
- public readonly FileProcessArgs EntityStatus { get; }
+ public readonly FileProcessArgs EntityStatus => entityStatus;
/// <summary>
/// Initializes a new <see cref="SessionHandle"/>
/// </summary>
/// <param name="sessionData">The session data instance</param>
/// <param name="callback">A callback that is invoked when the handle is released</param>
- /// <param name="entityStatus"></param>
- public SessionHandle(ISession? sessionData, FileProcessArgs entityStatus, SessionReleaseCallback? callback)
- {
- SessionData = sessionData;
- ReleaseCb = callback;
- EntityStatus = entityStatus;
- }
- /// <summary>
- /// Initializes a new <see cref="SessionHandle"/>
- /// </summary>
- /// <param name="sessionData">The session data instance</param>
- /// <param name="callback">A callback that is invoked when the handle is released</param>
- public SessionHandle(ISession sessionData, SessionReleaseCallback callback):this(sessionData, FileProcessArgs.Continue, callback)
+ public SessionHandle(ISession sessionData, SessionReleaseCallback callback) : this(sessionData, FileProcessArgs.Continue, callback)
{}
/// <summary>
/// Releases the session from use
/// </summary>
/// <param name="event">The current connection event object</param>
- public readonly ValueTask ReleaseAsync(IHttpEvent @event) => ReleaseCb?.Invoke(SessionData!, @event) ?? ValueTask.CompletedTask;
+ public readonly ValueTask ReleaseAsync(IHttpEvent @event) => callback?.Invoke(SessionData!, @event) ?? ValueTask.CompletedTask;
+
+ ///<inheritdoc/>
+ public override bool Equals([NotNullWhen(true)] object? obj) => obj is SessionHandle handle && Equals(handle);
+
+ ///<inheritdoc/>
+ public bool Equals(SessionHandle other) => GetHashCode() == other.GetHashCode();
+
+ ///<inheritdoc/>
+ public override int GetHashCode() => HashCode.Combine(SessionData, EntityStatus, callback);
+
+ ///<inheritdoc/>
+ public static bool operator ==(SessionHandle left, SessionHandle right) => left.Equals(right);
+
+ ///<inheritdoc/>
+ public static bool operator !=(SessionHandle left, SessionHandle right) => !(left == right);
}
}
diff --git a/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj b/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj
index 9b8abb7..4da640a 100644
--- a/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj
+++ b/lib/Plugins.Essentials/src/VNLib.Plugins.Essentials.csproj
@@ -25,13 +25,6 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
diff --git a/lib/Plugins.PluginBase/src/PluginBase.cs b/lib/Plugins.PluginBase/src/PluginBase.cs
index d8b0973..0609e86 100644
--- a/lib/Plugins.PluginBase/src/PluginBase.cs
+++ b/lib/Plugins.PluginBase/src/PluginBase.cs
@@ -188,9 +188,20 @@ namespace VNLib.Plugins
int fileSizeLimit = 500 * 1000 * 1024;
RollingInterval interval = RollingInterval.Infinite;
- //try to get the host's app_log config object, if it does not exist, do not write logs to file
- if (HostConfig.TryGetProperty("app_log", out JsonElement logEl))
+ /*
+ * Try to get login configuration from the plugin configuration, otherwise fall
+ * back to the application logger
+ */
+ if (PluginConfig.TryGetProperty("log", out JsonElement logEl) ||
+ HostConfig.TryGetProperty("app_log", out logEl)
+ )
{
+ //User may want to disable plugin logging
+ if (logEl.TryGetProperty("disabled", out JsonElement disEl) && disEl.GetBoolean())
+ {
+ return;
+ }
+
IReadOnlyDictionary<string, JsonElement> conf = logEl.EnumerateObject().ToDictionary(static s => s.Name, static s => s.Value);
filePath = conf.GetPropString("path");
@@ -216,12 +227,14 @@ namespace VNLib.Plugins
interval = Enum.Parse<RollingInterval>(intervalEl.GetString()!, true);
}
+ /*
+ * If the user specified a log file path, replace the name of the log file with the
+ * plugin name, leave the directory and file extension the same
+ */
if(filePath != null)
- {
- //Get the file name to replace with the plugin name
+ {
string appLogName = Path.GetFileNameWithoutExtension(filePath);
-
- //Replace the file name
+
filePath = filePath.Replace(appLogName, PluginName, StringComparison.Ordinal);
}
@@ -237,7 +250,8 @@ namespace VNLib.Plugins
fileSizeLimitBytes: fileSizeLimit,
rollingInterval: interval,
outputTemplate: template,
- flushToDiskInterval: flushInterval);
+ flushToDiskInterval: flushInterval
+ );
}
}
diff --git a/lib/Plugins.PluginBase/src/VNLib.Plugins.PluginBase.csproj b/lib/Plugins.PluginBase/src/VNLib.Plugins.PluginBase.csproj
index 2b8eccd..7be9124 100644
--- a/lib/Plugins.PluginBase/src/VNLib.Plugins.PluginBase.csproj
+++ b/lib/Plugins.PluginBase/src/VNLib.Plugins.PluginBase.csproj
@@ -21,16 +21,6 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
- <ItemGroup>
- <None Include="..\.editorconfig" Link=".editorconfig" />
- </ItemGroup>
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
diff --git a/lib/Plugins.Runtime/src/VNLib.Plugins.Runtime.csproj b/lib/Plugins.Runtime/src/VNLib.Plugins.Runtime.csproj
index 30f2106..f95a95f 100644
--- a/lib/Plugins.Runtime/src/VNLib.Plugins.Runtime.csproj
+++ b/lib/Plugins.Runtime/src/VNLib.Plugins.Runtime.csproj
@@ -23,13 +23,6 @@
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
<PrivateAssets>all</PrivateAssets>
diff --git a/lib/Utils.Cryptography/monocypher/readme.md b/lib/Utils.Cryptography/monocypher/readme.md
index 940c95f..7c73d80 100644
--- a/lib/Utils.Cryptography/monocypher/readme.md
+++ b/lib/Utils.Cryptography/monocypher/readme.md
@@ -1,11 +1,12 @@
-# VNLib.Utils.Cryptography
-Contains vendored packages that are (optionally)used with VNLib applications such as Argon2 and MonoCypher, as well as build files for compiling the projects cross-platform using CMake and Taskfile.dev.
+# vnlib_monocypher
+A native shared/dynamic library for transforming exporting Monocypher library functions for use with my .NET managed libraries. A vendored version of Monocypher is included in this directory, that I maintain.
-Pre-build Windows binaries are available on my website (link below).
+
+Pre-built Windows binaries are available on my website (link below).
Source code blobs are also packaged and ready for building. See the docs link below for building instructions.
## Builds
-Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated checksum and PGP signature of the desired download file.
+C libraries are packaged in source code (to compile locally) or Windows amd64 dll binaries and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated checksum and PGP signature of the desired download file.
## Docs and Guides
Documentation, specifications, and setup guides are available on my website.
@@ -14,4 +15,23 @@ Documentation, specifications, and setup guides are available on my website.
[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core)
## License
-Code is individually licensed. See the `LICENSE` file in each subdirectory for more information. \ No newline at end of file
+Code is individually licensed. See the `LICENSE` file in each subdirectory for more information.
+
+## Notes
+
+### Building from source
+> This guide may become out-of-date, use the docs link above for the most recent information.
+
+This project uses the [CMake](https://cmake.org) build system for cross-platform compilation. My CMakelist.txt might not be perfect for your platform, so feel free to make a new issue or send me an email if you run into problems compiling on your platform.
+
+Download the package [source code src.tgz](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core?p=vnlib_monocypher) archive from my builds page.
+
+```bash
+tar -xzf src.tgz
+cmake -B./build/ -DCMAKE_BUILD_TYPE=Release
+cmake --build ./build/ --config Release
+```
+
+On **Windows**, you should navigate to build/Release to see your `vnlib_monocypher.dll` file.
+
+On **Linux**, you should navigate to build/ to see your `libvn_monocypher.so` file. \ No newline at end of file
diff --git a/lib/Utils.Cryptography/readme.md b/lib/Utils.Cryptography/readme.md
new file mode 100644
index 0000000..05d1e20
--- /dev/null
+++ b/lib/Utils.Cryptography/readme.md
@@ -0,0 +1,17 @@
+# VNLib.Utils.Cryptography
+Contains vendored packages that are (optionally)used with VNLib applications such as Argon2 and MonoCypher, as well as build files for compiling the projects cross-platform using CMake and Taskfile.dev.
+
+Pre-built Windows binaries are available on my website (link below).
+Source code blobs are also packaged and ready for building. See the docs link below for building instructions.
+
+## Builds
+Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated checksum and PGP signature of the desired download file.
+
+## Docs and Guides
+Documentation, specifications, and setup guides are available on my website.
+
+[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_vnlib.utils.cryptography)
+[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core)
+
+## License
+Code is individually licensed. See the `LICENSE` file in each subdirectory for more information. \ No newline at end of file
diff --git a/lib/Utils/src/IO/VnMemoryStream.cs b/lib/Utils/src/IO/VnMemoryStream.cs
index ada2c64..f4bf970 100644
--- a/lib/Utils/src/IO/VnMemoryStream.cs
+++ b/lib/Utils/src/IO/VnMemoryStream.cs
@@ -58,7 +58,8 @@ namespace VNLib.Utils.IO
/// <param name="readOnly">Should the stream be readonly?</param>
/// <exception cref="ArgumentException"></exception>
/// <returns>A <see cref="VnMemoryStream"/> wrapper to access the handle data</returns>
- public static VnMemoryStream ConsumeHandle(IResizeableMemoryHandle<byte> handle, nint length, bool readOnly) => FromHandle(handle, true, length, readOnly);
+ public static VnMemoryStream ConsumeHandle(IResizeableMemoryHandle<byte> handle, nint length, bool readOnly)
+ => FromHandle(handle, true, length, readOnly);
/// <summary>
/// Creates a new <see cref="VnMemoryStream"/> from the supplied memory handle
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index ba25104..6efd5ba 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -356,14 +356,31 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void InitializeBlock<T>(ref T block, int itemCount) where T : struct
{
+ if (itemCount <= 0)
+ {
+ return;
+ }
+
+ InitializeBlock(ref block, (uint)itemCount);
+ }
+
+ /// <summary>
+ /// Zeroes a block of memory of the given unmanaged type
+ /// </summary>
+ /// <typeparam name="T">The unmanaged type to zero</typeparam>
+ /// <param name="block">A pointer to the block of memory to zero</param>
+ /// <param name="itemCount">The number of elements in the block to zero</param>
+ [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+ public static void InitializeBlock<T>(ref T block, uint itemCount) where T : struct
+ {
ThrowIfNullRef(in block, nameof(block));
- if (itemCount <= 0)
+ if (itemCount == 0)
{
return;
}
- ZeroByRef(ref block, (uint)itemCount);
+ ZeroByRef(ref block, itemCount);
}
/// <summary>
diff --git a/lib/Utils/src/Memory/PrivateStringManager.cs b/lib/Utils/src/Memory/PrivateStringManager.cs
index 073ee9e..2bc825c 100644
--- a/lib/Utils/src/Memory/PrivateStringManager.cs
+++ b/lib/Utils/src/Memory/PrivateStringManager.cs
@@ -65,9 +65,7 @@ namespace VNLib.Utils.Memory
strRef.Erase();
//Set the new value and determine if it is interned
- ProtectedElements[index] = value is null ?
- new StringRef(null, false)
- : new StringRef(value, string.IsInterned(value) != null);
+ ProtectedElements[index] = StringRef.Create(value);
}
/// <summary>
@@ -105,6 +103,14 @@ namespace VNLib.Utils.Memory
///<inheritdoc/>
protected override void Free() => Array.ForEach(ProtectedElements, static p => p.Erase());
+ /// <summary>
+ /// Erases the contents of the supplied string if it
+ /// is safe to do so. If the string is interned, it will
+ /// not be erased, nor will a null string
+ /// </summary>
+ /// <param name="str">The reference to the string to zero</param>
+ public static void EraseString(string? str) => StringRef.Create(str).Erase();
+
private readonly record struct StringRef(string? Value, bool IsInterned)
{
public readonly void Erase()
@@ -118,6 +124,10 @@ namespace VNLib.Utils.Memory
MemoryUtil.UnsafeZeroMemory<char>(Value);
}
}
+
+ internal static StringRef Create(string? str) => str is null ?
+ new(null, false)
+ : new(str, string.IsInterned(str) != null);
}
}
}
diff --git a/lib/Utils/src/VNLib.Utils.csproj b/lib/Utils/src/VNLib.Utils.csproj
index 54199e0..bda2164 100644
--- a/lib/Utils/src/VNLib.Utils.csproj
+++ b/lib/Utils/src/VNLib.Utils.csproj
@@ -17,6 +17,7 @@
<Company>Vaughn Nugent</Company>
<Product>VNLib Utilities Library</Product>
<Copyright>Copyright © 2024 Vaughn Nugent</Copyright>
+ <PackageTags>vnlib,utils,utilities,vnlib utils,utility</PackageTags>
<Description>.NET/8.0 Utilities library for high-performance common operations. Utilities and abstractions for building and diagnosing native memory implementations. Dyanmic native library loading, IO, extensions, data encoding, resource access, and asynchronous cooperation primitives.</Description>
<PackageProjectUrl>https://www.vaughnnugent.com/resources/software/modules/VNLib.Core</PackageProjectUrl>
<RepositoryUrl>https://github.com/VnUgE/VNLib.Core/tree/main/lib/Utils</RepositoryUrl>
@@ -36,18 +37,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
-
- <PropertyGroup Condition="'$(Configuration)'=='Debug'">
- <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
diff --git a/lib/Utils/tests/VNLib.UtilsTests.csproj b/lib/Utils/tests/VNLib.UtilsTests.csproj
index 75093f8..9a8891e 100644
--- a/lib/Utils/tests/VNLib.UtilsTests.csproj
+++ b/lib/Utils/tests/VNLib.UtilsTests.csproj
@@ -17,9 +17,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
- <PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
- <PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
- <PackageReference Include="coverlet.collector" Version="6.0.0">
+ <PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
+ <PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
+ <PackageReference Include="coverlet.collector" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>