aboutsummaryrefslogtreecommitdiff
path: root/Libs
diff options
context:
space:
mode:
Diffstat (limited to 'Libs')
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs194
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs55
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/IOauthSessionIdFactory.cs63
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2AuthenticationPluginEntry.cs60
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2SessionProviderEntry.cs124
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2Session.cs131
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionIdProvider.cs132
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionProvider.cs228
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2TokenResult.cs37
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OauthTokenResponseMessage.cs44
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/TokenAndSessionIdResult.cs44
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.OAuth/VNLib.Plugins.Essentials.Sessions.OAuth.csproj48
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.Runtime/IRuntimeSessionProvider.cs49
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.Runtime/ISessionIdFactory.cs41
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.Runtime/VNLib.Plugins.Essentials.Sessions.Runtime.csproj29
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/IWebSessionIdFactory.cs50
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/VNLib.Plugins.Essentials.Sessions.VNCache.csproj43
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSession.cs124
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionIdFactoryImpl.cs120
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProvider.cs137
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProviderEntry.cs82
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/MemorySession.cs130
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionConfig.cs58
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionEntrypoint.cs93
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs168
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/SessionIdFactory.cs84
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.csproj56
-rw-r--r--Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.xml78
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/MessageTooLargeException.cs51
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionStatusException.cs46
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionUpdateFailedException.cs41
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/GlobalCacheStore.cs64
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/IRemoteCacheStore.cs48
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/RemoteSession.cs188
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/SessionCacheClient.cs242
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.csproj48
-rw-r--r--Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.xml72
37 files changed, 0 insertions, 3302 deletions
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs
deleted file mode 100644
index d968398..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: AccessTokenEndpoint.cs
-*
-* AccessTokenEndpoint.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Net;
-using System.Text.Json;
-
-using VNLib.Utils.Memory;
-using VNLib.Hashing.IdentityUtility;
-using VNLib.Plugins.Essentials.Oauth;
-using VNLib.Plugins.Essentials.Endpoints;
-using VNLib.Plugins.Essentials.Oauth.Tokens;
-using VNLib.Plugins.Essentials.Oauth.Applications;
-using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Extensions.Loading.Sql;
-using VNLib.Plugins.Extensions.Validation;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth.Endpoints
-{
- delegate Task<IOAuth2TokenResult?> CreateTokenImpl(HttpEntity ev, UserApplication application, CancellationToken cancellation = default);
-
- /// <summary>
- /// Grants authorization to OAuth2 clients to protected resources
- /// with access tokens
- /// </summary>
- internal sealed class AccessTokenEndpoint : ResourceEndpointBase
- {
-
- private readonly CreateTokenImpl CreateToken;
- private readonly ApplicationStore Applications;
-
- private readonly Task<JsonDocument?> JWTVerificationKey;
-
- //override protection settings to allow most connections to authenticate
- protected override ProtectionSettings EndpointProtectionSettings { get; } = new()
- {
- DisableBrowsersOnly = true,
- DisableSessionsRequired = true,
- DisableVerifySessionCors = true
- };
-
- public AccessTokenEndpoint(string path, PluginBase pbase, CreateTokenImpl tokenStore, Task<JsonDocument?> verificationKey)
- {
- InitPathAndLog(path, pbase.Log);
- CreateToken = tokenStore;
- Applications = new(pbase.GetContextOptions(), pbase.GetPasswords());
- JWTVerificationKey = verificationKey;
- }
-
-
- protected override async ValueTask<VfReturnType> PostAsync(HttpEntity entity)
- {
- //Check for refresh token
- if (entity.RequestArgs.IsArgumentSet("grant_type", "refresh_token"))
- {
- //process a refresh token
- }
-
- //See if we have an application authorized with JWT
- else if (entity.RequestArgs.IsArgumentSet("grant_type", "application"))
- {
- if(entity.RequestArgs.TryGetNonEmptyValue("token", out string? appJwt))
- {
- //Try to get and verify the app
- UserApplication? app = GetApplicationFromJwt(appJwt);
-
- //generate token
- return await GenerateTokenAsync(entity, app);
- }
- }
-
- //Check for grant_type parameter from the request body
- else if (entity.RequestArgs.IsArgumentSet("grant_type", "client_credentials"))
- {
- //Get client id and secret (and make sure theyre not empty
- if (entity.RequestArgs.TryGetNonEmptyValue("client_id", out string? clientId) &&
- entity.RequestArgs.TryGetNonEmptyValue("client_secret", out string? secret))
- {
-
- if (!ValidatorExtensions.OnlyAlphaNumRegx.IsMatch(clientId))
- {
- //respond with error message
- entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidRequest, "Invalid client_id");
- return VfReturnType.VirtualSkip;
- }
- if (!ValidatorExtensions.OnlyAlphaNumRegx.IsMatch(secret))
- {
- //respond with error message
- entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidRequest, "Invalid client_secret");
- return VfReturnType.VirtualSkip;
- }
-
- //Convert the clientid and secret to lowercase
- clientId = clientId.ToLower();
- secret = secret.ToLower();
-
- //Convert secret to private string that is unreferrenced
- using PrivateString secretPv = new(secret, false);
-
- //Get the application from apps store
- UserApplication? app = await Applications.VerifyAppAsync(clientId, secretPv);
-
- return await GenerateTokenAsync(entity, app);
- }
- }
-
- entity.CloseResponseError(HttpStatusCode.BadRequest, ErrorType.InvalidClient, "Invalid grant type");
- //Default to bad request
- return VfReturnType.VirtualSkip;
- }
-
- private UserApplication? GetApplicationFromJwt(string jwtData)
- {
- //Not enabled
- if (JWTVerificationKey?.Result == null)
- {
- return null;
- }
-
- //Parse application token
- using JsonWebToken jwt = JsonWebToken.Parse(jwtData);
-
- //verify the application jwt
- if (!jwt.VerifyFromJwk(JWTVerificationKey.Result.RootElement))
- {
- return null;
- }
-
- using JsonDocument doc = jwt.GetPayload();
-
- //Get expiration time
- DateTimeOffset exp = doc.RootElement.GetProperty("exp").GetDateTimeOffset();
-
- //Check if token is expired
- return exp < DateTimeOffset.UtcNow ? null : UserApplication.FromJwtDoc(doc.RootElement);
- }
-
-
- private async Task<VfReturnType> GenerateTokenAsync(HttpEntity entity, UserApplication? app)
- {
- if (app == null)
- {
- //App was not found or the credentials do not match
- entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidClient, "The credentials are invalid or do not exist");
- return VfReturnType.VirtualSkip;
- }
-
- IOAuth2TokenResult? result = await CreateToken(entity, app, entity.EventCancellation);
-
- if (result == null)
- {
- entity.CloseResponseError(HttpStatusCode.TooManyRequests, ErrorType.TemporarilyUnabavailable, "You have reached the maximum number of valid tokens for this application");
- return VfReturnType.VirtualSkip;
- }
-
- //Create the new response message
- OauthTokenResponseMessage tokenMessage = new()
- {
- AccessToken = result.AccessToken,
- IdToken = result.IdentityToken,
- //set expired as seconds in int form
- Expires = result.ExpiresSeconds,
- RefreshToken = result.RefreshToken,
- TokenType = result.TokenType
- };
-
- //Respond with the token message
- entity.CloseResponseJson(HttpStatusCode.OK, tokenMessage);
- return VfReturnType.VirtualSkip;
- }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs
deleted file mode 100644
index d981f69..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: RevocationEndpoint.cs
-*
-* RevocationEndpoint.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Text.Json;
-
-using VNLib.Plugins.Essentials.Oauth;
-using VNLib.Plugins.Extensions.Loading;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth.Endpoints
-{
- /// <summary>
- /// An OAuth2 authorized endpoint for revoking the access token
- /// held by the current connection
- /// </summary>
- [ConfigurationName("o2_revocation_endpoint")]
- internal class RevocationEndpoint : O2EndpointBase
- {
-
- public RevocationEndpoint(PluginBase pbase, IReadOnlyDictionary<string, JsonElement> config)
- {
- string? path = config["path"].GetString();
- InitPathAndLog(path, pbase.Log);
- }
-
- protected override VfReturnType Post(HttpEntity entity)
- {
- //Revoke the access token, by invalidating it
- entity.Session.Invalidate();
- entity.CloseResponse(System.Net.HttpStatusCode.OK);
- return VfReturnType.VirtualSkip;
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/IOauthSessionIdFactory.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/IOauthSessionIdFactory.cs
deleted file mode 100644
index 4878804..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/IOauthSessionIdFactory.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: IOauthSessionIdFactory.cs
-*
-* IOauthSessionIdFactory.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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 VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Oauth.Applications;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-using VNLib.Plugins.Sessions.Cache.Client;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- public interface IOauthSessionIdFactory : ISessionIdFactory
- {
- /// <summary>
- /// The maxium number of tokens allowed to be created per OAuth application
- /// </summary>
- int MaxTokensPerApp { get; }
- /// <summary>
- /// Allows for custom configuration of the newly created session and
- /// the <see cref="IHttpEvent"/> its attached to
- /// </summary>
- /// <param name="session">The newly created session</param>
- /// <param name="app">The application associated with the session</param>
- /// <param name="entity">The http event that generated the new session</param>
- void InitNewSession(RemoteSession session, UserApplication app, IHttpEvent entity);
- /// <summary>
- /// The time a session is valid for
- /// </summary>
- TimeSpan SessionValidFor { get; }
- /// <summary>
- /// Called when the session provider wishes to generate a new session
- /// and required credential information to generate the new session
- /// </summary>
- /// <returns>The information genreated for the news ession</returns>
- TokenAndSessionIdResult GenerateTokensAndId();
- /// <summary>
- /// The type of token this session provider generates
- /// </summary>
- string TokenType { get; }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2AuthenticationPluginEntry.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2AuthenticationPluginEntry.cs
deleted file mode 100644
index 4a48f8b..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2AuthenticationPluginEntry.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: O2AuthenticationPluginEntry.cs
-*
-* O2AuthenticationPluginEntry.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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 VNLib.Utils.Logging;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-
-
-namespace VNLib.Plugins.Essentials.Sessions.Oauth
-{
- public sealed class O2AuthenticationPluginEntry : PluginBase
- {
- public override string PluginName => "Essentials.Oauth.Authentication";
-
- private readonly O2SessionProviderEntry SessionProvider = new();
-
- protected override void OnLoad()
- {
- try
- {
- //Load the session provider, that will only load the endpoints
- (SessionProvider as IRuntimeSessionProvider).Load(this, Log);
- }
- catch(KeyNotFoundException kne)
- {
- Log.Error("Missing required configuration keys {err}", kne.Message);
- }
- }
-
- protected override void OnUnLoad()
- {
- Log.Information("Plugin unloaded");
- }
-
- protected override void ProcessHostCommand(string cmd)
- {
- throw new NotImplementedException();
- }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2SessionProviderEntry.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2SessionProviderEntry.cs
deleted file mode 100644
index 7e72714..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/O2SessionProviderEntry.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: O2SessionProviderEntry.cs
-*
-* O2SessionProviderEntry.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Text.Json;
-
-using VNLib.Net.Http;
-using VNLib.Utils.Logging;
-using VNLib.Utils.Extensions;
-using VNLib.Data.Caching;
-using VNLib.Plugins.Sessions.Cache.Client;
-using VNLib.Plugins.Essentials.Oauth.Tokens;
-using VNLib.Plugins.Essentials.Oauth.Applications;
-using VNLib.Plugins.Essentials.Sessions.OAuth;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-using VNLib.Plugins.Essentials.Sessions.OAuth.Endpoints;
-using VNLib.Plugins.Extensions.VNCache;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Extensions.Loading.Routing;
-using VNLib.Plugins.Extensions.Loading.Sql;
-using VNLib.Plugins.Extensions.Loading.Events;
-
-
-namespace VNLib.Plugins.Essentials.Sessions.Oauth
-{
-
- public sealed class O2SessionProviderEntry : IRuntimeSessionProvider
- {
- const string OAUTH2_CONFIG_KEY = "oauth2";
-
- private OAuth2SessionProvider? _sessions;
-
- bool IRuntimeSessionProvider.CanProcess(IHttpEvent entity)
- {
- //If authorization header is set try to process as oauth2 session
- return _sessions != null && entity.Server.Headers.HeaderSet(System.Net.HttpRequestHeader.Authorization);
- }
-
- ValueTask<SessionHandle> ISessionProvider.GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- return _sessions!.GetSessionAsync(entity, cancellationToken);
- }
-
-
- void IRuntimeSessionProvider.Load(PluginBase plugin, ILogProvider localized)
- {
- IReadOnlyDictionary<string, JsonElement> oauth2Config = plugin.GetConfigForType<OAuth2SessionProvider>();
-
- //Optional application jwt token
- Task<JsonDocument?> jwtTokenSecret = plugin.TryGetSecretAsync("application_token_key")
- .ContinueWith(static t => t.Result?.GetJsonDocument(), TaskScheduler.Default);
-
- //Access token endpoint is optional
- if (oauth2Config.TryGetValue("token_path", out JsonElement el))
- {
- //Init auth endpoint
- AccessTokenEndpoint authEp = new(el.GetString()!, plugin, CreateTokenDelegateAsync, jwtTokenSecret);
-
- //route auth endpoint
- plugin.Route(authEp);
- }
-
- //Optional revocation endpoint
- if (plugin.HasConfigForType<RevocationEndpoint>())
- {
- //Route revocation endpoint
- plugin.Route<RevocationEndpoint>();
- }
-
- int cacheLimit = oauth2Config["cache_size"].GetInt32();
- int maxTokensPerApp = oauth2Config["max_tokens_per_app"].GetInt32();
- int sessionIdSize = (int)oauth2Config["access_token_size"].GetUInt32();
- TimeSpan tokenValidFor = oauth2Config["token_valid_for_sec"].GetTimeSpan(TimeParseType.Seconds);
- TimeSpan cleanupInterval = oauth2Config["gc_interval_sec"].GetTimeSpan(TimeParseType.Seconds);
- string sessionIdPrefix = oauth2Config["cache_prefix"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'cache_prefix' in '{OAUTH2_CONFIG_KEY}' config");
-
- //init the id provider
- OAuth2SessionIdProvider idProv = new(sessionIdPrefix, maxTokensPerApp, sessionIdSize, tokenValidFor);
-
- //Get shared global-cache
- IGlobalCacheProvider globalCache = plugin.GetGlobalCache();
-
- //Create cache store from global cache
- GlobalCacheStore cacheStore = new(globalCache);
-
- //Init session provider now that client is loaded
- _sessions = new(cacheStore, cacheLimit, 100, idProv, plugin.GetContextOptions());
-
- //Schedule cleanup interval with the plugin scheduler
- plugin.ScheduleInterval(_sessions, cleanupInterval);
-
- //Wait and cleanup expired sessions
- _ = plugin.DeferTask(() => _sessions.CleanupExpiredSessionsAsync(localized, plugin.UnloadToken), 1000);
-
- localized.Information("Session provider loaded");
-
- }
-
- private async Task<IOAuth2TokenResult?> CreateTokenDelegateAsync(HttpEntity entity, UserApplication app, CancellationToken cancellation)
- {
- return await _sessions!.CreateAccessTokenAsync(entity, app, cancellation).ConfigureAwait(false);
- }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2Session.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2Session.cs
deleted file mode 100644
index e9a69cd..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2Session.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: OAuth2Session.cs
-*
-* OAuth2Session.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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 VNLib.Net.Http;
-using VNLib.Plugins.Sessions.Cache.Client;
-using VNLib.Plugins.Sessions.Cache.Client.Exceptions;
-
-using static VNLib.Plugins.Essentials.Sessions.ISessionExtensions;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- /// <summary>
- /// The implementation of the OAuth2 session container for HTTP sessions
- /// </summary>
- internal sealed class OAuth2Session : RemoteSession
- {
- private readonly Action<OAuth2Session> InvalidateCache;
-
- /// <summary>
- /// Initalizes a new <see cref="OAuth2Session"/>
- /// </summary>
- /// <param name="sessionId">The session id (or token)</param>
- /// <param name="client">The <see cref="IRemoteCacheStore"/> used as the backing cache provider</param>
- /// <param name="backgroundTimeOut">The ammount of time to wait for a background operation (delete, update, get)</param>
- /// <param name="invalidCache">Called when the session has been marked as invalid and the close even hook is being executed</param>
- public OAuth2Session(string sessionId, IRemoteCacheStore client, TimeSpan backgroundTimeOut, Action<OAuth2Session> invalidCache)
- : base(sessionId, client, backgroundTimeOut)
- {
- InvalidateCache = invalidCache;
- IsInvalid = false;
- }
-
- public bool IsInvalid { get; private set; }
-
-
- ///<inheritdoc/>
- ///<exception cref="NotSupportedException"></exception>
- public override string Token
- {
- get => throw new NotSupportedException("Token property is not supported for OAuth2 sessions");
- set => throw new NotSupportedException("Token property is not supported for OAuth2 sessions");
- }
-
- ///<inheritdoc/>
- protected override void IndexerSet(string key, string value)
- {
- //Guard protected entires
- switch (key)
- {
- case TOKEN_ENTRY:
- case LOGIN_TOKEN_ENTRY:
- throw new InvalidOperationException("Token entry may not be changed!");
- }
- base.IndexerSet(key, value);
- }
- ///<inheritdoc/>
- ///<exception cref="SessionStatusException"></exception>
- public override async Task WaitAndLoadAsync(IHttpEvent entity, CancellationToken token = default)
- {
- //Wait to enter lock
- await base.WaitAndLoadAsync(entity, token);
- if (IsInvalid)
- {
- //Release lock
- MainLock.Release();
- throw new SessionStatusException("The session has been invalidated");
- }
- //Set session type
- if (IsNew)
- {
- SessionType = SessionType.OAuth2;
- }
- }
- ///<inheritdoc/>
- protected override async ValueTask<Task?> UpdateResource(bool isAsync, IHttpEvent state)
- {
- Task? result = null;
- //Invalid flag is set, so exit
- if (IsInvalid)
- {
- result = Task.CompletedTask;
- }
- //Check flags in priority level, Invalid is highest state priority
- else if (Flags.IsSet(INVALID_MSK))
- {
- //Clear all stored values
- DataStore!.Clear();
- //Delete the entity syncronously
- await ProcessDeleteAsync();
- //Set invalid flag
- IsInvalid = true;
- //Invlidate cache
- InvalidateCache(this);
- result = Task.CompletedTask;
- }
- else if (Flags.IsSet(MODIFIED_MSK))
- {
- //Send update to server
- result = Task.Run(ProcessUpdateAsync);
- }
-
- //Clear all flags
- Flags.ClearAll();
-
- return result;
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionIdProvider.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionIdProvider.cs
deleted file mode 100644
index e1cfc7f..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionIdProvider.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: OAuth2SessionIdProvider.cs
-*
-* OAuth2SessionIdProvider.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Diagnostics.CodeAnalysis;
-
-using VNLib.Utils.Memory;
-using VNLib.Utils.Extensions;
-using VNLib.Hashing;
-using VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-using VNLib.Plugins.Essentials.Oauth.Applications;
-using VNLib.Plugins.Sessions.Cache.Client;
-using static VNLib.Plugins.Essentials.Oauth.OauthSessionExtensions;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- /// <summary>
- /// Generates secure OAuth2 session tokens and initalizes new OAuth2 sessions
- /// </summary>
- internal class OAuth2SessionIdProvider : IOauthSessionIdFactory
- {
- private readonly string SessionIdPrefix;
- private readonly int _bufferSize;
- private readonly int _tokenSize;
-
- ///<inheritdoc/>
- public int MaxTokensPerApp { get; }
- ///<inheritdoc/>
- public TimeSpan SessionValidFor { get; }
- ///<inheritdoc/>
- string IOauthSessionIdFactory.TokenType => "Bearer";
-
- public OAuth2SessionIdProvider(string sessionIdPrefix, int maxTokensPerApp, int tokenSize, TimeSpan validFor)
- {
- SessionIdPrefix = sessionIdPrefix;
- MaxTokensPerApp = maxTokensPerApp;
- SessionValidFor = validFor;
- _tokenSize = tokenSize;
- _bufferSize = tokenSize * 2;
- }
-
- ///<inheritdoc/>
- bool ISessionIdFactory.TryGetSessionId(IHttpEvent entity, [NotNullWhen(true)] out string? sessionId)
- {
- //Get authorization token and make sure its not too large to cause a buffer overflow
- if (entity.Server.HasAuthorization(out string? token) && (token.Length + SessionIdPrefix.Length) <= _bufferSize)
- {
- //Compute session id from token
- sessionId = ComputeSessionIdFromToken(token);
-
- return true;
- }
- else
- {
- sessionId = null;
- }
-
- return false;
- }
-
- private string ComputeSessionIdFromToken(string token)
- {
- //Buffer to copy data to
- using UnsafeMemoryHandle<char> buffer = Memory.UnsafeAlloc<char>(_bufferSize, true);
-
- //Writer to accumulate data
- ForwardOnlyWriter<char> writer = new(buffer.Span);
-
- //Append session id prefix and token
- writer.Append(SessionIdPrefix);
- writer.Append(token);
-
- //Compute base64 hash of token and
- return ManagedHash.ComputeBase64Hash(writer.AsSpan(), HashAlg.SHA256);
- }
-
- ///<inheritdoc/>
- TokenAndSessionIdResult IOauthSessionIdFactory.GenerateTokensAndId()
- {
- //Alloc buffer for random data
- using UnsafeMemoryHandle<byte> mem = Memory.UnsafeAlloc<byte>(_tokenSize, true);
-
- //Generate token from random cng bytes
- RandomHash.GetRandomBytes(mem);
-
- //Token is the raw value
- string token = Convert.ToBase64String(mem.Span);
-
- //The session id is the HMAC of the token
- string sessionId = ComputeSessionIdFromToken(token);
-
- //Clear buffer
- Memory.InitializeBlock(mem.Span);
-
- //Return sessid result
- return new(sessionId, token, null);
- }
-
- ///<inheritdoc/>
- void IOauthSessionIdFactory.InitNewSession(RemoteSession session, UserApplication app, IHttpEvent entity)
- {
- //Store session variables
- session[APP_ID_ENTRY] = app.Id;
- session[TOKEN_TYPE_ENTRY] = "client_credential,bearer";
- session[SCOPES_ENTRY] = app.Permissions;
- session.UserID = app.UserId;
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionProvider.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionProvider.cs
deleted file mode 100644
index dca7909..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2SessionProvider.cs
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: OAuth2SessionProvider.cs
-*
-* OAuth2SessionProvider.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Net;
-
-using Microsoft.EntityFrameworkCore;
-
-using VNLib.Net.Http;
-using VNLib.Utils;
-using VNLib.Utils.Logging;
-using VNLib.Data.Caching.Exceptions;
-using VNLib.Plugins.Sessions.Cache.Client;
-using VNLib.Plugins.Essentials.Oauth;
-using VNLib.Plugins.Essentials.Oauth.Tokens;
-using VNLib.Plugins.Essentials.Oauth.Applications;
-using VNLib.Plugins.Extensions.Loading.Events;
-using VNLib.Plugins.Extensions.Loading;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
-
- /// <summary>
- /// Provides OAuth2 session management
- /// </summary>
- [ConfigurationName("oauth2")]
- internal sealed class OAuth2SessionProvider : SessionCacheClient, ITokenManager, IIntervalScheduleable
- {
-
- private static readonly SessionHandle NotFoundHandle = new(null, FileProcessArgs.NotFound, null);
-
- private static readonly TimeSpan BackgroundTimeout = TimeSpan.FromSeconds(10);
-
-
- private readonly IOauthSessionIdFactory factory;
- private readonly TokenStore TokenStore;
- private readonly uint MaxConnections;
-
- public OAuth2SessionProvider(IRemoteCacheStore client, int maxCacheItems, uint maxConnections, IOauthSessionIdFactory idFactory, DbContextOptions dbCtx)
- : base(client, maxCacheItems)
- {
- factory = idFactory;
- TokenStore = new(dbCtx);
- MaxConnections = maxConnections;
- }
-
- ///<inheritdoc/>
- protected override RemoteSession SessionCtor(string sessionId) => new OAuth2Session(sessionId, Store, BackgroundTimeout, InvalidatateCache);
-
- private void InvalidatateCache(OAuth2Session session)
- {
- lock (CacheLock)
- {
- _ = CacheTable.Remove(session.SessionID);
- }
- }
-
- ///<inheritdoc/>
- public async ValueTask<SessionHandle> GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- //Callback to close the session when the handle is closeed
- static ValueTask HandleClosedAsync(ISession session, IHttpEvent entity)
- {
- return ((SessionBase)session).UpdateAndRelease(true, entity);
- }
- try
- {
- //Get session id
- if (!factory.TryGetSessionId(entity, out string? sessionId))
- {
- //Id not allowed/found, so do not attach a session
- return SessionHandle.Empty;
- }
-
- //Limit max number of waiting clients
- if (WaitingConnections > MaxConnections)
- {
- //Set 503 for temporary unavail
- entity.CloseResponse(HttpStatusCode.ServiceUnavailable);
- return new SessionHandle(null, FileProcessArgs.VirtualSkip, null);
- }
-
- //Recover the session
- RemoteSession session = await base.GetSessionAsync(entity, sessionId, cancellationToken);
-
- //Session should not be new
- if (session.IsNew)
- {
- //Invalidate the session, so it is deleted
- session.Invalidate();
- await session.UpdateAndRelease(true, entity);
- return SessionHandle.Empty;
- }
- //Make sure session is still valid
- if (session.Created.Add(factory.SessionValidFor) < DateTimeOffset.UtcNow)
- {
- //Invalidate the handle
- session.Invalidate();
- //Flush changes
- await session.UpdateAndRelease(false, entity);
- //Remove the token from the db backing store
- await TokenStore.RevokeTokenAsync(sessionId, cancellationToken);
- //close entity
- entity.CloseResponseError(HttpStatusCode.Unauthorized, ErrorType.InvalidToken, "The token has expired");
- //return a completed handle
- return NotFoundHandle;
- }
-
- return new SessionHandle(session, HandleClosedAsync);
- }
- //Pass session exceptions
- catch (SessionException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw new SessionException("Exception raised while retreiving or loading OAuth2 session", ex);
- }
- }
- ///<inheritdoc/>
- public async Task<IOAuth2TokenResult?> CreateAccessTokenAsync(IHttpEvent ev, UserApplication app, CancellationToken cancellation)
- {
- //Get a new session for the current connection
- TokenAndSessionIdResult ids = factory.GenerateTokensAndId();
- //try to insert token into the store, may fail if max has been reached
- if (await TokenStore.InsertTokenAsync(ids.SessionId, app.Id!, ids.RefreshToken, factory.MaxTokensPerApp, cancellation) != ERRNO.SUCCESS)
- {
- return null;
- }
- //Create new session from the session id
- RemoteSession session = SessionCtor(ids.SessionId);
- await session.WaitAndLoadAsync(ev, cancellation);
- try
- {
- //Init new session
- factory.InitNewSession(session, app, ev);
- }
- finally
- {
- await session.UpdateAndRelease(false, ev);
- }
- //Init new token result to pass to client
- return new OAuth2TokenResult()
- {
- ExpiresSeconds = (int)factory.SessionValidFor.TotalSeconds,
- TokenType = factory.TokenType,
- //Return token and refresh token
- AccessToken = ids.AccessToken,
- RefreshToken = ids.RefreshToken,
- };
- }
- ///<inheritdoc/>
- Task ITokenManager.RevokeTokensAsync(IReadOnlyCollection<string> tokens, CancellationToken cancellation)
- {
- return TokenStore.RevokeTokensAsync(tokens, cancellation);
- }
- ///<inheritdoc/>
- Task ITokenManager.RevokeTokensForAppAsync(string appId, CancellationToken cancellation)
- {
- return TokenStore.RevokeTokenAsync(appId, cancellation);
- }
-
-
- /*
- * Interval for removing expired tokens
- */
-
- ///<inheritdoc/>
- async Task IIntervalScheduleable.OnIntervalAsync(ILogProvider log, CancellationToken cancellationToken)
- {
- //Calculate valid token time
- DateTime validAfter = DateTime.UtcNow.Subtract(factory.SessionValidFor);
- //Remove tokens from db store
- IReadOnlyCollection<ActiveToken> revoked = await TokenStore.CleanupExpiredTokensAsync(validAfter, cancellationToken);
- //exception list
- List<Exception>? errors = null;
- //Remove all sessions from the store
- foreach (ActiveToken token in revoked)
- {
- try
- {
- //Remove tokens by thier object id from cache
- await base.Store.DeleteObjectAsync(token.Id, cancellationToken);
- }
- //Ignore if the object has already been removed
- catch (ObjectNotFoundException)
- {}
- catch (Exception ex)
- {
- errors = new()
- {
- ex
- };
- }
- }
- if (errors?.Count > 0)
- {
- throw new AggregateException(errors);
- }
- if(revoked.Count > 0)
- {
- log.Debug("Cleaned up {0} expired tokens", revoked.Count);
- }
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2TokenResult.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2TokenResult.cs
deleted file mode 100644
index 5517192..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OAuth2TokenResult.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: OAuth2TokenResult.cs
-*
-* OAuth2TokenResult.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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 VNLib.Plugins.Essentials.Oauth.Tokens;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- internal class OAuth2TokenResult : IOAuth2TokenResult
- {
- public string? IdentityToken { get; }
- public string? AccessToken { get; set; }
- public string? RefreshToken { get; set; }
- public string? TokenType { get; set; }
- public int ExpiresSeconds { get; set; }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OauthTokenResponseMessage.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OauthTokenResponseMessage.cs
deleted file mode 100644
index 1088373..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/OauthTokenResponseMessage.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: OauthTokenResponseMessage.cs
-*
-* OauthTokenResponseMessage.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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.Text.Json.Serialization;
-
-#nullable enable
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- public sealed class OauthTokenResponseMessage
- {
- [JsonPropertyName("access_token")]
- public string? AccessToken { get; set; }
- [JsonPropertyName("refresh_token")]
- public string? RefreshToken { get; set; }
- [JsonPropertyName("token_type")]
- public string? TokenType { get; set; }
- [JsonPropertyName("expires_in")]
- public int Expires { get; set; }
- [JsonPropertyName("id_token")]
- public string? IdToken { get; set; }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/TokenAndSessionIdResult.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/TokenAndSessionIdResult.cs
deleted file mode 100644
index ceb3cb5..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/TokenAndSessionIdResult.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: TokenAndSessionIdResult.cs
-*
-* TokenAndSessionIdResult.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.OAuth 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.Plugins.Essentials.Sessions.OAuth 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/.
-*/
-
-#nullable enable
-
-using VNLib;
-
-namespace VNLib.Plugins.Essentials.Sessions.OAuth
-{
- public readonly struct TokenAndSessionIdResult
- {
- public readonly string SessionId;
- public readonly string AccessToken;
- public readonly string? RefreshToken;
-
- public TokenAndSessionIdResult(string sessionId, string token, string? refreshToken)
- {
- SessionId = sessionId;
- AccessToken = token;
- RefreshToken = refreshToken;
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/VNLib.Plugins.Essentials.Sessions.OAuth.csproj b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/VNLib.Plugins.Essentials.Sessions.OAuth.csproj
deleted file mode 100644
index d6775c8..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/VNLib.Plugins.Essentials.Sessions.OAuth.csproj
+++ /dev/null
@@ -1,48 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <ImplicitUsings>enable</ImplicitUsings>
- <Nullable>enable</Nullable>
- <GenerateDocumentationFile>True</GenerateDocumentationFile>
- <Authors>Vaughn Nugent</Authors>
- <Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
-
- <EnableDynamicLoading>true</EnableDynamicLoading>
- <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
- <Version>1.0.1.1</Version>
- <PackageProjectUrl>https://www.vaughnugent.com</PackageProjectUrl>
- <AnalysisLevel>latest-all</AnalysisLevel>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>\\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <Target Name="PostBuild" AfterTargets="PostBuildEvent">
- <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
- </Target>
- <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
- <Exec Command="erase &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /q &gt; nul" />
- </Target>
- <ItemGroup>
- <ProjectReference Include="..\..\..\..\VNLib\Http\src\VNLib.Net.Http.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Plugins\src\VNLib.Plugins.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Utils\src\VNLib.Utils.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading.Sql\VNLib.Plugins.Extensions.Loading.Sql.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading\VNLib.Plugins.Extensions.Loading.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Validation\VNLib.Plugins.Extensions.Validation.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.VNCache\VNLib.Plugins.Extensions.VNCache.csproj" />
- <ProjectReference Include="..\..\..\Oauth\Libs\VNLib.Plugins.Essentials.Oauth\VNLib.Plugins.Essentials.Oauth.csproj" />
- <ProjectReference Include="..\..\..\PluginBase\VNLib.Plugins.PluginBase.csproj" />
- <ProjectReference Include="..\VNLib.Plugins.Essentials.Sessions.Runtime\VNLib.Plugins.Essentials.Sessions.Runtime.csproj" />
- <ProjectReference Include="..\VNLib.Plugins.Sessions.Cache.Client\VNLib.Plugins.Sessions.Cache.Client.csproj" />
- </ItemGroup>
-
-</Project>
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/IRuntimeSessionProvider.cs b/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/IRuntimeSessionProvider.cs
deleted file mode 100644
index 5d4de0a..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/IRuntimeSessionProvider.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Runtime
-* File: IRuntimeSessionProvider.cs
-*
-* IRuntimeSessionProvider.cs is part of VNLib.Plugins.Essentials.Sessions.Runtime which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Runtime 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.Plugins.Essentials.Sessions.Runtime 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 VNLib.Net.Http;
-using VNLib.Utils.Logging;
-
-namespace VNLib.Plugins.Essentials.Sessions.Runtime
-{
- /// <summary>
- /// Represents a dynamically loadable type that an provide sessions to http connections
- /// </summary>
- public interface IRuntimeSessionProvider : ISessionProvider
- {
- /// <summary>
- /// Called immediatly after the plugin is loaded into the appdomain
- /// </summary>
- /// <param name="plugin">The plugin instance that is loading the module</param>
- /// <param name="localizedLog">The localized log provider for the provider</param>
- void Load(PluginBase plugin, ILogProvider localizedLog);
-
- /// <summary>
- /// Determines if the provider can return a session for the connection
- /// </summary>
- /// <param name="entity">The entity to process</param>
- /// <returns>A value indicating if this provider should be called to load a session for</returns>
- bool CanProcess(IHttpEvent entity);
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/ISessionIdFactory.cs b/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/ISessionIdFactory.cs
deleted file mode 100644
index c9df924..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/ISessionIdFactory.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Runtime
-* File: ISessionIdFactory.cs
-*
-* ISessionIdFactory.cs is part of VNLib.Plugins.Essentials.Sessions.Runtime which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Runtime 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.Plugins.Essentials.Sessions.Runtime 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.Diagnostics.CodeAnalysis;
-
-using VNLib.Net.Http;
-
-namespace VNLib.Plugins.Essentials.Sessions.Runtime
-{
- public interface ISessionIdFactory
- {
- /// <summary>
- /// Attempts to recover a session-id from the connection
- /// </summary>
- /// <param name="entity">The connection to process</param>
- /// <param name="sessionId"></param>
- /// <returns></returns>
- bool TryGetSessionId(IHttpEvent entity, [NotNullWhen(true)] out string? sessionId);
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/VNLib.Plugins.Essentials.Sessions.Runtime.csproj b/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/VNLib.Plugins.Essentials.Sessions.Runtime.csproj
deleted file mode 100644
index 87c29e8..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.Runtime/VNLib.Plugins.Essentials.Sessions.Runtime.csproj
+++ /dev/null
@@ -1,29 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <ImplicitUsings>enable</ImplicitUsings>
- <Nullable>enable</Nullable>
- <Authors>Vaughn Nugent</Authors>
- <Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
- <Version>1.0.1.2</Version>
- <SignAssembly>False</SignAssembly>
- <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
- <AnalysisLevel>latest-all</AnalysisLevel>
- <GenerateDocumentationFile>True</GenerateDocumentationFile>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>\\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" />
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'" />
-
- <ItemGroup>
- <ProjectReference Include="..\..\..\..\VNLib\Essentials\src\VNLib.Plugins.Essentials.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Http\src\VNLib.Net.Http.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading\VNLib.Plugins.Extensions.Loading.csproj" />
- <ProjectReference Include="..\..\..\PluginBase\VNLib.Plugins.PluginBase.csproj" />
- </ItemGroup>
-
-</Project>
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/IWebSessionIdFactory.cs b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/IWebSessionIdFactory.cs
deleted file mode 100644
index f1fdf39..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/IWebSessionIdFactory.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.VNCache
-* File: IWebSessionIdFactory.cs
-*
-* IWebSessionIdFactory.cs is part of VNLib.Plugins.Essentials.Sessions.VNCache which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.VNCache 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.Plugins.Essentials.Sessions.VNCache 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 VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-
-namespace VNLib.Plugins.Essentials.Sessions.VNCache
-{
- /// <summary>
- /// Id factory for <see cref="WebSessionProvider"/>
- /// </summary>
- internal interface IWebSessionIdFactory: ISessionIdFactory
- {
- /// <summary>
- /// The maxium amount of time a session is valid for. Sessions will be invalidated
- /// after this time
- /// </summary>
- TimeSpan ValidFor { get; }
-
- /// <summary>
- /// Gets a new session-id for the connection and manipulates the entity as necessary
- /// </summary>
- /// <param name="entity">The connection to generate the new session for</param>
- /// <returns>The new session-id</returns>
- string GenerateSessionId(IHttpEvent entity);
- }
-
-
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/VNLib.Plugins.Essentials.Sessions.VNCache.csproj b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/VNLib.Plugins.Essentials.Sessions.VNCache.csproj
deleted file mode 100644
index 9895eea..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/VNLib.Plugins.Essentials.Sessions.VNCache.csproj
+++ /dev/null
@@ -1,43 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <ImplicitUsings>enable</ImplicitUsings>
- <Nullable>enable</Nullable>
- <Authors>Vaughn Nugent</Authors>
- <Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
- <Version>1.0.1.1</Version>
- <SignAssembly>False</SignAssembly>
- <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
-
- <EnableDynamicLoading>true</EnableDynamicLoading>
- <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
- <GenerateDocumentationFile>True</GenerateDocumentationFile>
- <AnalysisLevel>latest-all</AnalysisLevel>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>\\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
-
- <ItemGroup>
- <Folder Include="Endpoints\" />
- </ItemGroup>
-
- <ItemGroup>
- <ProjectReference Include="..\..\..\..\VNLib\Http\src\VNLib.Net.Http.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Utils\src\VNLib.Utils.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading\VNLib.Plugins.Extensions.Loading.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.VNCache\VNLib.Plugins.Extensions.VNCache.csproj" />
- <ProjectReference Include="..\..\..\PluginBase\VNLib.Plugins.PluginBase.csproj" />
- <ProjectReference Include="..\VNLib.Plugins.Essentials.Sessions.Runtime\VNLib.Plugins.Essentials.Sessions.Runtime.csproj" />
- <ProjectReference Include="..\VNLib.Plugins.Sessions.Cache.Client\VNLib.Plugins.Sessions.Cache.Client.csproj" />
- </ItemGroup>
-
- <Target Name="PostBuild" AfterTargets="PostBuildEvent">
- <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
- </Target>
-
- <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
- <Exec Command="erase &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /q &gt; nul" />
- </Target>
-
-</Project>
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSession.cs b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSession.cs
deleted file mode 100644
index 87e08e7..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSession.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.VNCache
-* File: WebSession.cs
-*
-* WebSession.cs is part of VNLib.Plugins.Essentials.Sessions.VNCache which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.VNCache 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.Plugins.Essentials.Sessions.VNCache 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 VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Plugins.Sessions.Cache.Client;
-using static VNLib.Plugins.Essentials.Sessions.ISessionExtensions;
-
-namespace VNLib.Plugins.Essentials.Sessions.VNCache
-{
- internal class WebSession : RemoteSession
- {
- protected const ulong UPGRADE_MSK = 0b0000000000010000UL;
-
- protected readonly Func<IHttpEvent, string, string> UpdateId;
- private string? _oldId;
-
- public WebSession(string sessionId, IRemoteCacheStore client, TimeSpan backgroundTimeOut, Func<IHttpEvent, string, string> UpdateId)
- : base(sessionId, client, backgroundTimeOut)
- {
- this.UpdateId = UpdateId;
- }
-
- protected override void IndexerSet(string key, string value)
- {
- //Set value
- base.IndexerSet(key, value);
- switch (key)
- {
- //Set the upgrade flag when token data is modified
- case LOGIN_TOKEN_ENTRY:
- case TOKEN_ENTRY:
- Flags.Set(UPGRADE_MSK);
- break;
- }
- }
-
- public override async Task WaitAndLoadAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- //Wait for the session to load
- await base.WaitAndLoadAsync(entity, cancellationToken);
- //If the session is new, set to web mode
- if (IsNew)
- {
- SessionType = SessionType.Web;
- }
- }
-
- private async Task ProcessUpgradeAsync()
- {
- //Setup timeout cancellation for the update, to cancel it
- using CancellationTokenSource cts = new(UpdateTimeout);
- await Client.AddOrUpdateObjectAsync(_oldId!, SessionID, DataStore, cts.Token);
- _oldId = null;
- }
-
- protected override ValueTask<Task?> UpdateResource(bool isAsync, IHttpEvent state)
- {
- Task? result = null;
- //Check flags in priority level, Invalid is highest state priority
- if (Flags.IsSet(INVALID_MSK))
- {
- //Clear all stored values
- DataStore!.Clear();
- //Reset ip-address
- UserIP = state.Server.GetTrustedIp();
- //Update created time
- Created = DateTimeOffset.UtcNow;
- //Init the new session-data
- this.InitNewSession(state.Server);
- //Restore session type
- SessionType = SessionType.Web;
- //generate new session-id and update the record in the store
- _oldId = SessionID;
- //Update the session-id
- SessionID = UpdateId(state, _oldId);
- //write update to server
- result = Task.Run(ProcessUpgradeAsync);
- }
- else if (Flags.IsSet(UPGRADE_MSK | REGEN_ID_MSK))
- {
- //generate new session-id and update the record in the store
- _oldId = SessionID;
- //Update the session-id
- SessionID = UpdateId(state, _oldId);
- //Update created time
- Created = DateTimeOffset.UtcNow;
- //write update to server
- result = Task.Run(ProcessUpgradeAsync);
- }
- else if (Flags.IsSet(MODIFIED_MSK))
- {
- //Send update to server
- result = Task.Run(ProcessUpdateAsync);
- }
-
- //Clear all flags
- Flags.ClearAll();
-
- return ValueTask.FromResult<Task?>(null);
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionIdFactoryImpl.cs b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionIdFactoryImpl.cs
deleted file mode 100644
index 8dfda77..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionIdFactoryImpl.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.VNCache
-* File: WebSessionIdFactoryImpl.cs
-*
-* WebSessionIdFactoryImpl.cs is part of VNLib.Plugins.Essentials.Sessions.VNCache which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.VNCache 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.Plugins.Essentials.Sessions.VNCache 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.Diagnostics.CodeAnalysis;
-
-using VNLib.Hashing;
-using VNLib.Utils.Memory;
-using VNLib.Utils.Extensions;
-using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-
-namespace VNLib.Plugins.Essentials.Sessions.VNCache
-{
- /// <summary>
- /// <see cref="IWebSessionIdFactory"/> implementation, using
- /// http cookies as session id storage
- /// </summary>
- internal sealed class WebSessionIdFactoryImpl : IWebSessionIdFactory
- {
- public TimeSpan ValidFor { get; }
-
- public string GenerateSessionId(IHttpEvent entity)
- {
- //Random hex hash
- string cookie = RandomHash.GetRandomBase32(_tokenSize);
-
- //Set the session id cookie
- entity.Server.SetCookie(SessionCookieName, cookie, ValidFor, secure: true, httpOnly: true);
-
- //return session-id value from cookie value
- return ComputeSessionIdFromCookie(cookie);
- }
-
- bool ISessionIdFactory.TryGetSessionId(IHttpEvent entity, [NotNullWhen(true)] out string? sessionId)
- {
- //Get authorization token and make sure its not too large to cause a buffer overflow
- if (entity.Server.GetCookie(SessionCookieName, out string? cookie) && (cookie.Length + SessionIdPrefix.Length) <= _bufferSize)
- {
- //Compute session id from token
- sessionId = ComputeSessionIdFromCookie(cookie);
-
- return true;
- }
- //Only add sessions for user-agents
- else if(entity.Server.IsBrowser())
- {
- //Get a new session id
- sessionId = GenerateSessionId(entity);
-
- return true;
- }
- else
- {
- sessionId = null;
- return false;
- }
- }
-
- private readonly string SessionCookieName;
- private readonly string SessionIdPrefix;
- private readonly int _bufferSize;
- private readonly int _tokenSize;
-
- /// <summary>
- /// Initialzies a new web session Id factory
- /// </summary>
- /// <param name="cookieSize">The size of the cookie in bytes</param>
- /// <param name="sessionCookieName">The name of the session cookie</param>
- /// <param name="sessionIdPrefix">The session-id internal prefix</param>
- /// <param name="validFor">The time the session cookie is valid for</param>
- public WebSessionIdFactoryImpl(uint cookieSize, string sessionCookieName, string sessionIdPrefix, TimeSpan validFor)
- {
- ValidFor = validFor;
- SessionCookieName = sessionCookieName;
- SessionIdPrefix = sessionIdPrefix;
- _tokenSize = (int)cookieSize;
- //Calc buffer size
- _bufferSize = Math.Max(32, ((int)cookieSize * 3) + sessionIdPrefix.Length);
- }
-
-
- private string ComputeSessionIdFromCookie(string sessionId)
- {
- //Buffer to copy data to
- using UnsafeMemoryHandle<char> buffer = Memory.UnsafeAlloc<char>(_bufferSize, true);
-
- //Writer to accumulate data
- ForwardOnlyWriter<char> writer = new(buffer.Span);
-
- //Append prefix and session id
- writer.Append(SessionIdPrefix);
- writer.Append(sessionId);
-
- //Compute base64 hash of token and
- return ManagedHash.ComputeBase64Hash(writer.AsSpan(), HashAlg.SHA256);
- }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProvider.cs b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProvider.cs
deleted file mode 100644
index ebc3c3d..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProvider.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.VNCache
-* File: WebSessionProvider.cs
-*
-* WebSessionProvider.cs is part of VNLib.Plugins.Essentials.Sessions.VNCache which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.VNCache 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.Plugins.Essentials.Sessions.VNCache 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 VNLib.Net.Http;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Sessions.Cache.Client;
-
-namespace VNLib.Plugins.Essentials.Sessions.VNCache
-{
- /// <summary>
- /// The implementation of a VNCache web based session
- /// </summary>
- [ConfigurationName("web")]
- internal sealed class WebSessionProvider : SessionCacheClient, ISessionProvider
- {
- static readonly TimeSpan BackgroundUpdateTimeout = TimeSpan.FromSeconds(10);
-
- private readonly IWebSessionIdFactory factory;
- private readonly uint MaxConnections;
-
- /// <summary>
- /// Initializes a new <see cref="WebSessionProvider"/>
- /// </summary>
- /// <param name="client">The cache client to make cache operations against</param>
- /// <param name="maxCacheItems">The max number of items to store in cache</param>
- /// <param name="maxWaiting">The maxium number of waiting session events before 503s are sent</param>
- /// <param name="factory">The session-id factory</param>
- public WebSessionProvider(IRemoteCacheStore client, int maxCacheItems, uint maxWaiting, IWebSessionIdFactory factory) : base(client, maxCacheItems)
- {
- this.factory = factory;
- MaxConnections = maxWaiting;
- }
-
- private string UpdateSessionId(IHttpEvent entity, string oldId)
- {
- //Generate and set a new sessionid
- string newid = factory.GenerateSessionId(entity);
- //Aquire lock on cache
- lock (CacheLock)
- {
- //Change the cache lookup id
- if (CacheTable.Remove(oldId, out RemoteSession? session))
- {
- CacheTable.Add(newid, session);
- }
- }
- return newid;
- }
-
- protected override RemoteSession SessionCtor(string sessionId) => new WebSession(sessionId, Store, BackgroundUpdateTimeout, UpdateSessionId);
-
- public async ValueTask<SessionHandle> GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- //Callback to close the session when the handle is closeed
- static ValueTask HandleClosedAsync(ISession session, IHttpEvent entity)
- {
- return (session as SessionBase)!.UpdateAndRelease(true, entity);
- }
-
- try
- {
- //Get session id
- if (!factory.TryGetSessionId(entity, out string? sessionId))
- {
- //Id not allowed/found, so do not attach a session
- return SessionHandle.Empty;
- }
-
- //Limit max number of waiting clients
- if (WaitingConnections > MaxConnections)
- {
- //Set 503 for temporary unavail
- entity.CloseResponse(System.Net.HttpStatusCode.ServiceUnavailable);
- return new SessionHandle(null, FileProcessArgs.VirtualSkip, null);
- }
-
- //Get session
- RemoteSession session = await GetSessionAsync(entity, sessionId, cancellationToken);
-
- //If the session is new (not in cache), then overwrite the session id with a new one as user may have specified their own
- if (session.IsNew)
- {
- session.RegenID();
- }
-
- //Make sure the session has not expired yet
- if (session.Created.Add(factory.ValidFor) < DateTimeOffset.UtcNow)
- {
- //Invalidate the session, so its technically valid for this request, but will be cleared on this handle close cycle
- session.Invalidate();
- //Clear basic login status
- session.Token = null;
- session.UserID = null;
- session.Privilages = 0;
- session.SetLoginToken(null);
- }
-
- return new SessionHandle(session, HandleClosedAsync);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (SessionException)
- {
- throw;
- }
- catch (Exception ex)
- {
- throw new SessionException("Exception raised while retreiving or loading Web session", ex);
- }
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProviderEntry.cs b/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProviderEntry.cs
deleted file mode 100644
index 309db47..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions.VNCache/WebSessionProviderEntry.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.VNCache
-* File: WebSessionProviderEntry.cs
-*
-* WebSessionProviderEntry.cs is part of VNLib.Plugins.Essentials.Sessions.VNCache which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.VNCache 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.Plugins.Essentials.Sessions.VNCache 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.Text.Json;
-
-using VNLib.Net.Http;
-using VNLib.Utils.Logging;
-using VNLib.Utils.Extensions;
-using VNLib.Data.Caching;
-using VNLib.Plugins.Sessions.Cache.Client;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Extensions.VNCache;
-
-namespace VNLib.Plugins.Essentials.Sessions.VNCache
-{
- public sealed class WebSessionProviderEntry : IRuntimeSessionProvider
- {
- const string WEB_SESSION_CONFIG = "web";
-
- private WebSessionProvider? _sessions;
-
- //Web sessions can always be provided so long as cache is loaded
- bool IRuntimeSessionProvider.CanProcess(IHttpEvent entity) => _sessions != null;
-
- ValueTask<SessionHandle> ISessionProvider.GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- return _sessions!.GetSessionAsync(entity, cancellationToken);
- }
-
- void IRuntimeSessionProvider.Load(PluginBase plugin, ILogProvider localized)
- {
- //Try get vncache config element
- IReadOnlyDictionary<string, JsonElement> webSessionConfig = plugin.GetConfigForType<WebSessionProvider>();
-
- uint cookieSize = webSessionConfig["cookie_size"].GetUInt32();
- string cookieName = webSessionConfig["cookie_name"].GetString() ?? throw new KeyNotFoundException($"Missing required element 'cookie_name' for config '{WEB_SESSION_CONFIG}'");
- string cachePrefix = webSessionConfig["cache_prefix"].GetString() ?? throw new KeyNotFoundException($"Missing required element 'cache_prefix' for config '{WEB_SESSION_CONFIG}'");
- int cacheLimit = (int)webSessionConfig["cache_size"].GetUInt32();
- uint maxConnections = webSessionConfig["max_waiting_connections"].GetUInt32();
- TimeSpan validFor = webSessionConfig["valid_for_sec"].GetTimeSpan(TimeParseType.Seconds);
-
- //Init id factory
- WebSessionIdFactoryImpl idFactory = new(cookieSize, cookieName, cachePrefix, validFor);
-
- //Get shared global-cache
- IGlobalCacheProvider globalCache = plugin.GetGlobalCache();
-
- //Create cache store from global cache
- GlobalCacheStore cacheStore = new(globalCache);
-
- //Init provider
- _sessions = new(cacheStore, cacheLimit, maxConnections, idFactory);
-
- //Load and run cached sessions on deferred task lib
- _ = plugin.DeferTask(() => _sessions.CleanupExpiredSessionsAsync(localized, plugin.UnloadToken), 1000);
-
- localized.Information("Session provider loaded");
- }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySession.cs b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySession.cs
deleted file mode 100644
index d365cd2..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySession.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Memory
-* File: MemorySession.cs
-*
-* MemorySession.cs is part of VNLib.Plugins.Essentials.Sessions.Memory which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Memory 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.Plugins.Essentials.Sessions.Memory 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.Net;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-using VNLib.Plugins.Essentials.Extensions;
-
-using VNLib.Utils.Async;
-using VNLib.Net.Http;
-using VNLib.Utils.Memory.Caching;
-using static VNLib.Plugins.Essentials.Sessions.ISessionExtensions;
-
-#nullable enable
-
-namespace VNLib.Plugins.Essentials.Sessions.Memory
-{
- internal class MemorySession : SessionBase, ICacheable
- {
- private readonly Dictionary<string, string> DataStorage;
-
- private readonly Func<IHttpEvent, string, string> OnSessionUpdate;
- private readonly AsyncQueue<MemorySession> ExpiredTable;
-
- public MemorySession(string sessionId, IPAddress ipAddress, Func<IHttpEvent, string, string> onSessionUpdate, AsyncQueue<MemorySession> expired)
- {
- //Set the initial is-new flag
- DataStorage = new Dictionary<string, string>(10);
- ExpiredTable = expired;
-
- OnSessionUpdate = onSessionUpdate;
- //Get new session id
- SessionID = sessionId;
- UserIP = ipAddress;
- SessionType = SessionType.Web;
- Created = DateTimeOffset.UtcNow;
- //Init
- IsNew = true;
- }
- //Store in memory directly
- public override IPAddress UserIP { get; protected set; }
-
- //Session type has no backing store, so safe to hard-code it's always web
-
- public override SessionType SessionType => SessionType.Web;
-
- protected override ValueTask<Task?> UpdateResource(bool isAsync, IHttpEvent state)
- {
- //if invalid is set, invalide the current session
- if (Flags.IsSet(INVALID_MSK))
- {
- //Clear storage, and regenerate the sessionid
- DataStorage.Clear();
- //store new sessionid
- SessionID = OnSessionUpdate(state, SessionID);
- //Reset ip-address
- UserIP = state.Server.GetTrustedIp();
- //Update created-time
- Created = DateTimeOffset.UtcNow;
- //Re-initialize the session to the state of the current connection
- this.InitNewSession(state.Server);
- //Modified flag doesnt matter since there is no write-back
-
- }
- else if (Flags.IsSet(REGEN_ID_MSK))
- {
- //Regen id without modifying the data store
- SessionID = OnSessionUpdate(state, SessionID);
- }
- //Clear flags
- Flags.ClearAll();
- //Memory session always completes
- return ValueTask.FromResult<Task?>(null);
- }
-
- protected override string IndexerGet(string key)
- {
- return DataStorage.GetValueOrDefault(key, string.Empty);
- }
-
- protected override void IndexerSet(string key, string value)
- {
- //Check for special keys
- switch (key)
- {
- //For tokens/login hashes, we can set the upgrade flag
- case TOKEN_ENTRY:
- case LOGIN_TOKEN_ENTRY:
- Flags.Set(REGEN_ID_MSK);
- break;
- }
- DataStorage[key] = value;
- }
-
-
- DateTime ICacheable.Expires { get; set; }
-
- void ICacheable.Evicted()
- {
- DataStorage.Clear();
- //Enque cleanup
- _ = ExpiredTable.TryEnque(this);
- }
-
- bool IEquatable<ICacheable>.Equals(ICacheable? other) => other is ISession ses && SessionID.Equals(ses.SessionID, StringComparison.Ordinal);
-
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionConfig.cs b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionConfig.cs
deleted file mode 100644
index 74199e6..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionConfig.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Memory
-* File: MemorySessionConfig.cs
-*
-* MemorySessionConfig.cs is part of VNLib.Plugins.Essentials.Sessions.Memory which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Memory 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.Plugins.Essentials.Sessions.Memory 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 VNLib.Utils.Logging;
-
-namespace VNLib.Plugins.Essentials.Sessions.Memory
-{
- /// <summary>
- /// Represents configration variables used to create and operate http sessions.
- /// </summary>
- public readonly struct MemorySessionConfig
- {
- /// <summary>
- /// The name of the cookie to use for matching sessions
- /// </summary>
- public string SessionCookieID { get; init; }
- /// <summary>
- /// The size (in bytes) of the genreated SessionIds
- /// </summary>
- public uint SessionIdSizeBytes { get; init; }
- /// <summary>
- /// The amount of time a session is valid (within the backing store)
- /// </summary>
- public TimeSpan SessionTimeout { get; init; }
- /// <summary>
- /// The log for which all errors within the <see cref="SessionProvider"/> instance will be written to.
- /// </summary>
- public ILogProvider SessionLog { get; init; }
- /// <summary>
- /// The maximum number of sessions allowed to be cached in memory. If this value is exceed requests to this
- /// server will be denied with a 503 error code
- /// </summary>
- public int MaxAllowedSessions { get; init; }
- }
-} \ No newline at end of file
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionEntrypoint.cs b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionEntrypoint.cs
deleted file mode 100644
index 07ae04b..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionEntrypoint.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Memory
-* File: MemorySessionEntrypoint.cs
-*
-* MemorySessionEntrypoint.cs is part of VNLib.Plugins.Essentials.Sessions.Memory which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Memory 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.Plugins.Essentials.Sessions.Memory 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.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-
-using VNLib.Net.Http;
-using VNLib.Utils.Logging;
-using VNLib.Utils.Extensions;
-using VNLib.Plugins.Extensions.Loading.Events;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-
-#nullable enable
-
-namespace VNLib.Plugins.Essentials.Sessions.Memory
-{
- public sealed class MemorySessionEntrypoint : IRuntimeSessionProvider, IIntervalScheduleable
- {
- const string WEB_SESSION_CONFIG = "web";
-
- private MemorySessionStore? _sessions;
-
- bool IRuntimeSessionProvider.CanProcess(IHttpEvent entity)
- {
- //Web sessions can always be provided
- return _sessions != null;
- }
-
- public ValueTask<SessionHandle> GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- return _sessions!.GetSessionAsync(entity, cancellationToken);
- }
-
- void IRuntimeSessionProvider.Load(PluginBase plugin, ILogProvider localized)
- {
- //Get websessions config element
-
- IReadOnlyDictionary<string, JsonElement> webSessionConfig = plugin.GetConfig(WEB_SESSION_CONFIG);
-
- MemorySessionConfig config = new()
- {
- SessionLog = localized,
- MaxAllowedSessions = webSessionConfig["cache_size"].GetInt32(),
- SessionIdSizeBytes = webSessionConfig["cookie_size"].GetUInt32(),
- SessionTimeout = webSessionConfig["valid_for_sec"].GetTimeSpan(TimeParseType.Seconds),
- SessionCookieID = webSessionConfig["cookie_name"].GetString() ?? throw new KeyNotFoundException($"Missing required element 'cookie_name' for config '{WEB_SESSION_CONFIG}'"),
- };
-
- _sessions = new(config);
-
- //Begin listening for expired records
- _ = plugin.DeferTask(() => _sessions.CleanupExiredAsync(localized, plugin.UnloadToken));
-
- //Schedule garbage collector
- plugin.ScheduleInterval(this, TimeSpan.FromMinutes(1));
-
- //Call cleanup on exit
- _ = plugin.RegisterForUnload(_sessions.Cleanup);
- }
-
- Task IIntervalScheduleable.OnIntervalAsync(ILogProvider log, CancellationToken cancellationToken)
- {
- //Cleanup expired sessions on interval
- _sessions?.GC();
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs b/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
deleted file mode 100644
index 1af885e..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/MemorySessionStore.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Memory
-* File: MemorySessionStore.cs
-*
-* MemorySessionStore.cs is part of VNLib.Plugins.Essentials.Sessions.Memory which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Memory 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.Plugins.Essentials.Sessions.Memory 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.Threading;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-
-using VNLib.Net.Http;
-using VNLib.Net.Http.Core;
-using VNLib.Utils;
-using VNLib.Utils.Async;
-using VNLib.Utils.Logging;
-using VNLib.Utils.Extensions;
-using VNLib.Plugins.Essentials.Extensions;
-
-#nullable enable
-
-namespace VNLib.Plugins.Essentials.Sessions.Memory
-{
- /// <summary>
- /// An <see cref="ISessionProvider"/> for in-process-memory backed sessions
- /// </summary>
- internal sealed class MemorySessionStore : ISessionProvider
- {
- private readonly Dictionary<string, MemorySession> SessionsStore;
-
- internal readonly MemorySessionConfig Config;
- internal readonly SessionIdFactory IdFactory;
- internal readonly AsyncQueue<MemorySession> ExpiredSessions;
-
- public MemorySessionStore(MemorySessionConfig config)
- {
- Config = config;
- SessionsStore = new(config.MaxAllowedSessions, StringComparer.Ordinal);
- IdFactory = new(config.SessionIdSizeBytes, config.SessionCookieID, config.SessionTimeout);
- ExpiredSessions = new(false, true);
- }
-
- ///<inheritdoc/>
- public async ValueTask<SessionHandle> GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
-
- static ValueTask SessionHandleClosedAsync(ISession session, IHttpEvent ev)
- {
- return (session as MemorySession)!.UpdateAndRelease(true, ev);
- }
-
- //Try to get the id for the session
- if (IdFactory.TryGetSessionId(entity, out string? sessionId))
- {
- //Try to get the old record or evict it
- ERRNO result = SessionsStore.TryGetOrEvictRecord(sessionId, out MemorySession? session);
- if(result > 0)
- {
- //Valid, now wait for exclusive access
- await session.WaitOneAsync(cancellationToken);
- return new (session, SessionHandleClosedAsync);
- }
- else
- {
- //try to cleanup expired records
- GC();
- //Make sure there is enough room to add a new session
- if (SessionsStore.Count >= Config.MaxAllowedSessions)
- {
- entity.Server.SetNoCache();
- //Set 503 when full
- entity.CloseResponse(System.Net.HttpStatusCode.ServiceUnavailable);
- //Cannot service new session
- return new(null, FileProcessArgs.VirtualSkip, null);
- }
- //Initialze a new session
- session = new(sessionId, entity.Server.GetTrustedIp(), UpdateSessionId, ExpiredSessions);
- //Increment the semaphore
- (session as IWaitHandle).WaitOne();
- //store the session in cache while holding semaphore, and set its expiration
- SessionsStore.StoreRecord(session.SessionID, session, Config.SessionTimeout);
- //Init new session handle
- return new (session, SessionHandleClosedAsync);
- }
- }
- else
- {
- return SessionHandle.Empty;
- }
- }
-
- public async Task CleanupExiredAsync(ILogProvider log, CancellationToken token)
- {
- while (true)
- {
- try
- {
- //Wait for expired session and dispose it
- using MemorySession session = await ExpiredSessions.DequeueAsync(token);
-
- //Obtain lock on session
- await session.WaitOneAsync(CancellationToken.None);
-
- log.Verbose("Removed expired session {id}", session.SessionID);
- }
- catch (OperationCanceledException)
- {
- break;
- }
- catch (Exception ex)
- {
- log.Error(ex);
- }
- }
- }
-
- private string UpdateSessionId(IHttpEvent entity, string oldId)
- {
- //Generate and set a new sessionid
- string newid = IdFactory.GenerateSessionId(entity);
- //Aquire lock on cache
- lock (SessionsStore)
- {
- //Change the cache lookup id
- if (SessionsStore.Remove(oldId, out MemorySession? session))
- {
- SessionsStore.Add(newid, session);
- }
- }
- return newid;
- }
-
- /// <summary>
- /// Evicts all sessions from the current store
- /// </summary>
- public void Cleanup()
- {
- //Expire all old records to cleanup all entires
- this.SessionsStore.CollectRecords(DateTime.MaxValue);
- }
- /// <summary>
- /// Collects all expired records from the current store
- /// </summary>
- public void GC()
- {
- //collect expired records
- this.SessionsStore.CollectRecords();
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/SessionIdFactory.cs b/Libs/VNLib.Plugins.Essentials.Sessions/SessionIdFactory.cs
deleted file mode 100644
index c221617..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/SessionIdFactory.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.Memory
-* File: SessionIdFactory.cs
-*
-* SessionIdFactory.cs is part of VNLib.Plugins.Essentials.Sessions.Memory which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Essentials.Sessions.Memory 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.Plugins.Essentials.Sessions.Memory 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.Diagnostics.CodeAnalysis;
-
-using VNLib.Hashing;
-using VNLib.Net.Http;
-using VNLib.Plugins.Essentials.Extensions;
-using VNLib.Plugins.Essentials.Sessions.Runtime;
-
-#nullable enable
-
-namespace VNLib.Plugins.Essentials.Sessions.Memory
-{
- internal sealed class SessionIdFactory : ISessionIdFactory
- {
- private readonly int IdSize;
- private readonly string cookieName;
- private readonly TimeSpan ValidFor;
-
- public SessionIdFactory(uint idSize, string cookieName, TimeSpan validFor)
- {
- IdSize = (int)idSize;
- this.cookieName = cookieName;
- ValidFor = validFor;
- }
-
- public string GenerateSessionId(IHttpEvent entity)
- {
- //Random hex hash
- string cookie = RandomHash.GetRandomBase32(IdSize);
-
- //Set the session id cookie
- entity.Server.SetCookie(cookieName, cookie, ValidFor, secure: true, httpOnly: true);
-
- //return session-id value from cookie value
- return cookie;
- }
-
- public bool TryGetSessionId(IHttpEvent entity, [NotNullWhen(true)] out string? sessionId)
- {
- //Get authorization token and make sure its not too large to cause a buffer overflow
- if (entity.Server.GetCookie(cookieName, out sessionId))
- {
- return true;
- }
- //Only add sessions for user-agents
- else if (entity.Server.IsBrowser())
- {
- //Get a new session id
- sessionId = GenerateSessionId(entity);
-
- return true;
- }
- else
- {
- sessionId = null;
- return false;
- }
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.csproj b/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.csproj
deleted file mode 100644
index 78fe298..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.csproj
+++ /dev/null
@@ -1,56 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
- <AssemblyName>VNLib.Plugins.Essentials.Sessions.Memory</AssemblyName>
- <RootNamespace>VNLib.Plugins.Essentials.Sessions.Memory</RootNamespace>
- <Authors>Vaughn Nugent</Authors>
- <Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
- <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>\\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
-
- <!-- Resolve nuget dll files and store them in the output dir -->
- <PropertyGroup>
- <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
- <EnableDynamicLoading>true</EnableDynamicLoading>
- <GenerateDocumentationFile>True</GenerateDocumentationFile>
- <AnalysisLevel>latest-all</AnalysisLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <Deterministic>False</Deterministic>
- </PropertyGroup>
-
- <ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
- <ItemGroup>
- <PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
- <PrivateAssets>all</PrivateAssets>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
- <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2">
- <PrivateAssets>all</PrivateAssets>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\..\..\VNLib\Essentials\src\VNLib.Plugins.Essentials.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Http\src\VNLib.Net.Http.csproj" />
- <ProjectReference Include="..\..\..\Extensions\VNLib.Plugins.Extensions.Loading\VNLib.Plugins.Extensions.Loading.csproj" />
- <ProjectReference Include="..\..\..\PluginBase\VNLib.Plugins.PluginBase.csproj" />
- <ProjectReference Include="..\VNLib.Plugins.Essentials.Sessions.Runtime\VNLib.Plugins.Essentials.Sessions.Runtime.csproj" />
- </ItemGroup>
-
- <Target Name="PostBuild" AfterTargets="PostBuildEvent">
- <Exec Command="start xcopy &quot;$(TargetDir)&quot; &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /E /Y /R" />
- </Target>
- <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
- <Exec Command="erase &quot;F:\Programming\Web Plugins\DevPlugins\RuntimeAssets\$(TargetName)&quot; /q &gt; nul" />
- </Target>
-
-
-</Project>
diff --git a/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.xml b/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.xml
deleted file mode 100644
index 0821935..0000000
--- a/Libs/VNLib.Plugins.Essentials.Sessions/VNLib.Plugins.Essentials.Sessions.Memory.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0"?>
-<!--
-Copyright (c) 2022 Vaughn Nugent
--->
-<doc>
- <assembly>
- <name>VNLib.Plugins.Essentials.Sessions.Memory</name>
- </assembly>
- <members>
- <member name="T:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore">
- <summary>
- An <see cref="T:VNLib.Plugins.Essentials.Sessions.ISessionProvider"/> for in-process-memory backed sessions
- </summary>
- </member>
- <member name="M:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore.GetSessionAsync(VNLib.Net.Http.HttpEvent,System.Threading.CancellationToken)">
- <inheritdoc/>
- </member>
- <member name="P:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore.NewSessionID">
- <summary>
- Gets a new unique sessionid for sessions
- </summary>
- </member>
- <member name="M:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore.SetSessionCookie(VNLib.Net.Http.HttpEvent,VNLib.Plugins.Essentials.Sessions.Memory.MemorySession)">
- <summary>
- Sets a standard session cookie for an entity/connection
- </summary>
- <param name="entity">The entity to set the cookie on</param>
- <param name="session">The session attached to the </param>
- </member>
- <member name="M:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore.Cleanup">
- <summary>
- Evicts all sessions from the current store
- </summary>
- </member>
- <member name="M:VNLib.Plugins.Essentials.Sessions.Memory.MemorySessionStore.GC">
- <summary>
- Collects all expired records from the current store
- </summary>
- </member>
- <member name="T:VNLib.Plugins.Essentials.Sessions.Memory.MemSessionHandle">
- <summary>
- Provides a one-time-use handle (similar to asyncReleaser, or openHandle)
- that holds exclusive access to a session until it is released
- </summary>
- </member>
- <member name="T:VNLib.Net.Sessions.MemorySessionConfig">
- <summary>
- Represents configration variables used to create and operate http sessions.
- </summary>
- </member>
- <member name="P:VNLib.Net.Sessions.MemorySessionConfig.SessionCookieID">
- <summary>
- The name of the cookie to use for matching sessions
- </summary>
- </member>
- <member name="P:VNLib.Net.Sessions.MemorySessionConfig.SessionIdSizeBytes">
- <summary>
- The size (in bytes) of the genreated SessionIds
- </summary>
- </member>
- <member name="P:VNLib.Net.Sessions.MemorySessionConfig.SessionTimeout">
- <summary>
- The amount of time a session is valid (within the backing store)
- </summary>
- </member>
- <member name="P:VNLib.Net.Sessions.MemorySessionConfig.SessionLog">
- <summary>
- The log for which all errors within the <see cref="!:SessionProvider"/> instance will be written to.
- </summary>
- </member>
- <member name="P:VNLib.Net.Sessions.MemorySessionConfig.MaxAllowedSessions">
- <summary>
- The maximum number of sessions allowed to be cached in memory. If this value is exceed requests to this
- server will be denied with a 503 error code
- </summary>
- </member>
- </members>
-</doc>
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/MessageTooLargeException.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/MessageTooLargeException.cs
deleted file mode 100644
index 5a096a6..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/MessageTooLargeException.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: MessageTooLargeException.cs
-*
-* MessageTooLargeException.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Runtime.Serialization;
-
-using VNLib.Net.Messaging.FBM;
-
-namespace VNLib.Plugins.Sessions.Cache.Client.Exceptions
-{
- /// <summary>
- /// Raised when a request message is too large to send to
- /// the server and the server may close the connection.
- /// </summary>
- public class MessageTooLargeException : FBMException
- {
- ///<inheritdoc/>
- public MessageTooLargeException()
- { }
- ///<inheritdoc/>
- public MessageTooLargeException(string message) : base(message)
- { }
- ///<inheritdoc/>
- public MessageTooLargeException(string message, Exception innerException) : base(message, innerException)
- { }
- ///<inheritdoc/>
- protected MessageTooLargeException(SerializationInfo info, StreamingContext context) : base(info, context)
- { }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionStatusException.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionStatusException.cs
deleted file mode 100644
index bc6b217..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionStatusException.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: SessionStatusException.cs
-*
-* SessionStatusException.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Runtime.Serialization;
-
-using VNLib.Plugins.Essentials.Sessions;
-
-namespace VNLib.Plugins.Sessions.Cache.Client.Exceptions
-{
- /// <summary>
- /// Raised when the status of the session is invalid and cannot be used
- /// </summary>
- public class SessionStatusException : SessionException
- {
- public SessionStatusException()
- { }
- public SessionStatusException(string message) : base(message)
- { }
- public SessionStatusException(string message, Exception innerException) : base(message, innerException)
- { }
- protected SessionStatusException(SerializationInfo info, StreamingContext context) : base(info, context)
- { }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionUpdateFailedException.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionUpdateFailedException.cs
deleted file mode 100644
index 6d572aa..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/Exceptions/SessionUpdateFailedException.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: SessionUpdateFailedException.cs
-*
-* SessionUpdateFailedException.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Runtime.Serialization;
-
-namespace VNLib.Plugins.Sessions.Cache.Client.Exceptions
-{
- public class SessionUpdateFailedException : SessionStatusException
- {
- public SessionUpdateFailedException()
- { }
- public SessionUpdateFailedException(string message) : base(message)
- { }
- public SessionUpdateFailedException(string message, Exception innerException) : base(message, innerException)
- { }
- protected SessionUpdateFailedException(SerializationInfo info, StreamingContext context) : base(info, context)
- { }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/GlobalCacheStore.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/GlobalCacheStore.cs
deleted file mode 100644
index df3c564..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/GlobalCacheStore.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: GlobalCacheStore.cs
-*
-* GlobalCacheStore.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Threading;
-using System.Threading.Tasks;
-
-using VNLib.Data.Caching;
-
-namespace VNLib.Plugins.Sessions.Cache.Client
-{
- /// <summary>
- /// A wrapper class to provide a <see cref="IRemoteCacheStore"/> from
- /// a <see cref="IGlobalCacheProvider"/> client instance
- /// </summary>
- public sealed class GlobalCacheStore : IRemoteCacheStore
- {
- private readonly IGlobalCacheProvider _cache;
-
- public GlobalCacheStore(IGlobalCacheProvider globalCache)
- {
- _cache = globalCache ?? throw new ArgumentNullException(nameof(globalCache));
- }
-
- ///<inheritdoc/>
- public Task AddOrUpdateObjectAsync<T>(string objectId, string? newId, T obj, CancellationToken cancellationToken = default)
- {
- return _cache.AddOrUpdateAsync(objectId, newId, obj, cancellationToken);
- }
-
- ///<inheritdoc/>
- public Task DeleteObjectAsync(string objectId, CancellationToken cancellationToken = default)
- {
- return _cache.DeleteAsync(objectId, cancellationToken);
- }
-
- ///<inheritdoc/>
- public Task<T?> GetObjectAsync<T>(string objectId, CancellationToken cancellationToken = default)
- {
- return _cache.GetAsync<T>(objectId, cancellationToken);
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/IRemoteCacheStore.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/IRemoteCacheStore.cs
deleted file mode 100644
index 2a8bd49..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/IRemoteCacheStore.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: IRemoteCacheStore.cs
-*
-* IRemoteCacheStore.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Threading;
-using System.Threading.Tasks;
-
-namespace VNLib.Plugins.Sessions.Cache.Client
-{
- /// <summary>
- /// Represents an asynchronous interface to a remote cache store
- /// </summary>
- public interface IRemoteCacheStore
- {
- /// <summary>
- /// Gets an object from the cache provider by key
- /// </summary>
- /// <typeparam name="T">The data type</typeparam>
- /// <param name="objectId">The key/id of the object to recover</param>
- /// <param name="cancellationToken">A token to cancel the operation</param>
- /// <returns>A task that resolves the found object or null otherwise</returns>
- Task<T?> GetObjectAsync<T>(string objectId, CancellationToken cancellationToken = default);
-
- Task AddOrUpdateObjectAsync<T>(string objectId, string? newId, T obj, CancellationToken cancellationToken = default);
-
- Task DeleteObjectAsync(string objectId, CancellationToken cancellationToken = default);
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/RemoteSession.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/RemoteSession.cs
deleted file mode 100644
index af2c969..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/RemoteSession.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: RemoteSession.cs
-*
-* RemoteSession.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Threading;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-
-using Microsoft.VisualStudio.Threading;
-
-using VNLib.Net.Http;
-using VNLib.Data.Caching.Exceptions;
-using VNLib.Utils.Extensions;
-using VNLib.Plugins.Essentials.Sessions;
-using VNLib.Plugins.Essentials.Extensions;
-
-namespace VNLib.Plugins.Sessions.Cache.Client
-{
- /// <summary>
- /// Base class for cacheable lazy initialized session entires
- /// that exist in a remote caching server
- /// </summary>
- public abstract class RemoteSession : SessionBase
- {
- protected const string CREATED_TIME_ENTRY = "__.i.ctime";
-
- protected IRemoteCacheStore Client { get; }
- protected TimeSpan UpdateTimeout { get; }
-
- private readonly AsyncLazyInitializer Initializer;
-
- /// <summary>
- /// The lazy loaded data-store
- /// </summary>
- protected Dictionary<string, string>? DataStore;
-
- protected RemoteSession(string sessionId, IRemoteCacheStore client, TimeSpan backgroundTimeOut)
- {
- SessionID = sessionId;
- UpdateTimeout = backgroundTimeOut;
- Client = client;
- Initializer = new(InitializeAsync, null);
- }
-
- /// <summary>
- /// The data initializer, loads the data store from the connected cache server
- /// </summary>
- /// <returns>A task that completes when the get operation completes</returns>
- protected virtual async Task InitializeAsync()
- {
- //Setup timeout cancellation for the get, to cancel it
- using CancellationTokenSource cts = new(UpdateTimeout);
- //get or create a new session
- DataStore = await Client.GetObjectAsync<Dictionary<string, string>>(SessionID, cancellationToken: cts.Token);
- }
- /// <summary>
- /// Updates the current sessin agaisnt the cache store
- /// </summary>
- /// <returns>A task that complets when the update has completed</returns>
- protected virtual async Task ProcessUpdateAsync()
- {
- //Setup timeout cancellation for the update, to cancel it
- using CancellationTokenSource cts = new(UpdateTimeout);
- await Client.AddOrUpdateObjectAsync(SessionID, null, DataStore, cts.Token);
- }
- /// <summary>
- /// Delets the current session in the remote store
- /// </summary>
- /// <returns>A task that completes when instance has been deleted</returns>
- protected virtual async Task ProcessDeleteAsync()
- {
- //Setup timeout cancellation for the update, to cancel it
- using CancellationTokenSource cts = new(UpdateTimeout);
- try
- {
- await Client.DeleteObjectAsync(SessionID, cts.Token);
- }
- catch (ObjectNotFoundException)
- {
- //This is fine, if the object does not exist, nothing to invalidate
- }
- }
-
- ///<inheritdoc/>
- public override DateTimeOffset Created
- {
- get
- {
- //Deserialze the base32 ms
- long unixMs = this.GetValueType<string, long>(CREATED_TIME_ENTRY);
- //set created time from ms
- return DateTimeOffset.FromUnixTimeMilliseconds(unixMs);
- }
-
- protected set => this.SetValueType(CREATED_TIME_ENTRY, value.ToUnixTimeMilliseconds());
- }
-
-
- ///<inheritdoc/>
- protected override string IndexerGet(string key)
- {
- //Get the value at the key or an empty string as a default
- return DataStore!.GetValueOrDefault(key, string.Empty);
- }
- ///<inheritdoc/>
- protected override void IndexerSet(string key, string value)
- {
- //If the value is null, remove the key from the store
- if (value == null)
- {
- //Set modified flag
- IsModified |= DataStore!.Remove(key);
- }
- else
- {
- //Store the value at the specified key
- DataStore![key] = value;
- IsModified = true;
- }
- }
-
-
- /*
- * If the data-store is not found it means the session does not
- * exist in cache, so its technically not dangerous to reuse,
- * so the new mask needs to be set, but the old ID is going
- * to be reused
- */
-
- /// <summary>
- /// Waits for exclusive access to the session, and initializes
- /// session data (loads it from the remote store)
- /// </summary>
- /// <param name="entity">The event to attach a session to</param>
- /// <param name="cancellationToken">A token to cancel the operaion</param>
- /// <returns></returns>
- public virtual async Task WaitAndLoadAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- //Wait for exclusive access
- await base.WaitOneAsync(cancellationToken);
- try
- {
- //Lazily initalize the current instance
- await Initializer.InitializeAsync(cancellationToken);
- //See if data-store is null (new session was created
- if (DataStore == null)
- {
- //New session was created
- DataStore = new(10);
- //Set is-new flag
- Flags.Set(IS_NEW_MSK);
- //Set created time
- Created = DateTimeOffset.UtcNow;
- //Init ipaddress
- UserIP = entity.Server.GetTrustedIp();
- //Set modified flag so session will be updated
- IsModified = true;
- }
- }
- catch
- {
- MainLock.Release();
- throw;
- }
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/SessionCacheClient.cs b/Libs/VNLib.Plugins.Sessions.Cache.Client/SessionCacheClient.cs
deleted file mode 100644
index 800ad66..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/SessionCacheClient.cs
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Sessions.Cache.Client
-* File: SessionCacheClient.cs
-*
-* SessionCacheClient.cs is part of VNLib.Plugins.Sessions.Cache.Client which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Plugins.Sessions.Cache.Client 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.Plugins.Sessions.Cache.Client 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.Threading;
-using System.Threading.Tasks;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-
-using VNLib.Net.Http;
-using VNLib.Utils.Async;
-using VNLib.Utils.Logging;
-using VNLib.Utils.Memory.Caching;
-using VNLib.Plugins.Essentials.Sessions;
-
-namespace VNLib.Plugins.Sessions.Cache.Client
-{
-
- /// <summary>
- /// A client that allows access to sessions located on external servers
- /// </summary>
- public abstract class SessionCacheClient : ICacheHolder
- {
- public class LRUSessionStore<T> : LRUCache<string, T>, ICacheHolder where T : ISession
- {
- internal AsyncQueue<T> ExpiredSessions { get; }
-
- ///<inheritdoc/>
- public override bool IsReadOnly => false;
- ///<inheritdoc/>
- protected override int MaxCapacity { get; }
-
-
- public LRUSessionStore(int maxCapacity) : base(StringComparer.Ordinal)
- {
- MaxCapacity = maxCapacity;
- ExpiredSessions = new (true, true);
- }
-
- ///<inheritdoc/>
- protected override bool CacheMiss(string key, [NotNullWhen(true)] out T? value)
- {
- value = default;
- return false;
- }
-
- ///<inheritdoc/>
- protected override void Evicted(KeyValuePair<string, T> evicted)
- {
- //add to queue, the list lock should be held during this operatio
- _ = ExpiredSessions.TryEnque(evicted.Value);
- }
-
- ///<inheritdoc/>
- public void CacheClear()
- {
- foreach (KeyValuePair<string, T> value in List)
- {
- Evicted(value);
- }
- Clear();
- }
-
- ///<inheritdoc/>
- public void CacheHardClear()
- {
- CacheClear();
- }
- }
-
- protected readonly LRUSessionStore<RemoteSession> CacheTable;
- protected readonly object CacheLock;
- protected readonly int MaxLoadedEntires;
-
- /// <summary>
- /// The client used to communicate with the cache server
- /// </summary>
- protected IRemoteCacheStore Store { get; }
-
- /// <summary>
- /// Initializes a new <see cref="SessionCacheClient"/>
- /// </summary>
- /// <param name="client"></param>
- /// <param name="maxCacheItems">The maximum number of sessions to keep in memory</param>
- protected SessionCacheClient(IRemoteCacheStore client, int maxCacheItems)
- {
- MaxLoadedEntires = maxCacheItems;
- CacheLock = new();
- CacheTable = new(maxCacheItems);
- Store = client;
- }
-
- private ulong _waitingCount;
-
- /// <summary>
- /// The number of pending connections waiting for results from the cache server
- /// </summary>
- public ulong WaitingConnections => _waitingCount;
-
- /// <summary>
- /// Attempts to get a session from the cache identified by its sessionId asynchronously
- /// </summary>
- /// <param name="entity">The connection/request to attach the session to</param>
- /// <param name="sessionId">The ID of the session to retrieve</param>
- /// <param name="cancellationToken">A token to cancel the operation</param>
- /// <returns>A <see cref="ValueTask"/> that resolves the remote session</returns>
- /// <exception cref="SessionException"></exception>
- public virtual async ValueTask<RemoteSession> GetSessionAsync(IHttpEvent entity, string sessionId, CancellationToken cancellationToken)
- {
- try
- {
- RemoteSession? session;
- //Aquire lock on cache
- lock (CacheLock)
- {
- //See if session is loaded into cache
- if (!CacheTable.TryGetValue(sessionId, out session))
- {
- //Init new record
- session = SessionCtor(sessionId);
- //Add to cache
- CacheTable.Add(session.SessionID, session);
- }
- //Valid entry found in cache
- }
-
- //Inc waiting count
- Interlocked.Increment(ref _waitingCount);
-
- try
- {
- //Load session-data
- await session.WaitAndLoadAsync(entity, cancellationToken);
- return session;
- }
- catch
- {
- //Remove the invalid cached session
- lock (CacheLock)
- {
- _ = CacheTable.Remove(sessionId);
- }
- throw;
- }
- finally
- {
- //Dec waiting count
- Interlocked.Decrement(ref _waitingCount);
- }
- }
- catch (SessionException)
- {
- throw;
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- //Wrap exceptions
- catch (Exception ex)
- {
- throw new SessionException("An unhandled exception was raised", ex);
- }
- }
-
- /// <summary>
- /// Gets a new <see cref="RemoteSession"/> instances for the given sessionId,
- /// and places it a the head of internal cache
- /// </summary>
- /// <param name="sessionId">The session identifier</param>
- /// <returns>The new session for the given ID</returns>
- protected abstract RemoteSession SessionCtor(string sessionId);
-
- /// <summary>
- /// Begins waiting for expired sessions to be evicted from the cache table that
- /// may have pending synchronization operations
- /// </summary>
- /// <param name="log"></param>
- /// <param name="token"></param>
- /// <returns></returns>
- public async Task CleanupExpiredSessionsAsync(ILogProvider log, CancellationToken token)
- {
- while (true)
- {
- try
- {
- //Wait for expired session and dispose it
- using RemoteSession session = await CacheTable.ExpiredSessions.DequeueAsync(token);
-
- //Obtain lock on session
- await session.WaitOneAsync(CancellationToken.None);
-
- log.Verbose("Removed expired session {id}", session.SessionID);
- }
- catch (OperationCanceledException)
- {
- break;
- }
- catch(Exception ex)
- {
- log.Error(ex);
- }
- }
- }
-
- ///<inheritdoc/>
- public void CacheClear()
- {
-
- }
- ///<inheritdoc/>
- public void CacheHardClear()
- {
- //Cleanup cache when disconnected
- lock (CacheLock)
- {
- CacheTable.CacheHardClear();
- }
- }
- }
-}
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.csproj b/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.csproj
deleted file mode 100644
index 8271ed2..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.csproj
+++ /dev/null
@@ -1,48 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <Authors>Vaughn Nugent</Authors>
- <Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
- <Version>1.0.1.1</Version>
- <SignAssembly>True</SignAssembly>
- <AssemblyOriginatorKeyFile>\\vaughnnugent.com\Internal\Folder Redirection\vman\Documents\Programming\Software\StrongNameingKey.snk</AssemblyOriginatorKeyFile>
- </PropertyGroup>
-
- <PropertyGroup>
- <DocumentationFile></DocumentationFile>
- <GenerateDocumentationFile>True</GenerateDocumentationFile>
- <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
- <AnalysisLevel>latest-all</AnalysisLevel>
- <Nullable>enable</Nullable>
- </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>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
- <PackageReference Include="ErrorProne.NET.Structs" Version="0.1.2">
- <PrivateAssets>all</PrivateAssets>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
- <PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.4.27" />
- <PackageReference Include="RestSharp" Version="108.0.2" />
- </ItemGroup>
-
- <ItemGroup>
- <ProjectReference Include="..\..\..\..\VNLib\Essentials\src\VNLib.Plugins.Essentials.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Http\src\VNLib.Net.Http.csproj" />
- <ProjectReference Include="..\..\..\..\VNLib\Utils\src\VNLib.Utils.csproj" />
- <ProjectReference Include="..\..\..\DataCaching\VNLib.Data.Caching\VNLib.Data.Caching.csproj" />
- </ItemGroup>
-
-</Project>
diff --git a/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.xml b/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.xml
deleted file mode 100644
index c96515b..0000000
--- a/Libs/VNLib.Plugins.Sessions.Cache.Client/VNLib.Plugins.Sessions.Cache.Client.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0"?>
-<!--
-Copyright (c) 2022 Vaughn Nugent
--->
-<doc>
- <assembly>
- <name>VNLib.Plugins.Sessions.Cache.Client</name>
- </assembly>
- <members>
- <member name="T:VNLib.Plugins.Sessions.Cache.Client.MessageTooLargeException">
- <summary>
- Raised when a request message is too large to send to
- the server and the server may close the connection.
- </summary>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.MessageTooLargeException.#ctor">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.MessageTooLargeException.#ctor(System.String)">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.MessageTooLargeException.#ctor(System.String,System.Exception)">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.MessageTooLargeException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
- <inheritdoc/>
- </member>
- <member name="T:VNLib.Plugins.Sessions.Cache.Client.SessionClient">
- <summary>
- A client that allows access to sessions located on external servers
- </summary>
- </member>
- <member name="P:VNLib.Plugins.Sessions.Cache.Client.SessionClient.GetSessionId">
- <summary>
- A callback that produces a session-id from the connection (or a new id if needed)
- </summary>
- </member>
- <member name="P:VNLib.Plugins.Sessions.Cache.Client.SessionClient.NewSessionId">
- <summary>
- A callback that produces a new session-id for the connection (and updates the client if necessary)
- </summary>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.#ctor(System.Int32,System.Int32,System.Int32,VNLib.Utils.Logging.ILogProvider,VNLib.Utils.Memory.PrivateHeap)">
- <summary>
- Initializes a new <see cref="T:VNLib.Plugins.Sessions.Cache.Client.SessionClient"/>
- </summary>
- <param name="maxMessageSize">The maxium message size (in bytes) the client will allow receiving (maximum data size for sessions)</param>
- <param name="recvBufferSize">The size (in bytes) of the client message receive buffer</param>
- <param name="maxCacheItems">The maximum number of sessions to keep in memory</param>
- <param name="log">A <see cref="T:VNLib.Utils.Logging.ILogProvider"/> to write log events to</param>
- <param name="heap">The <see cref="T:VNLib.Utils.Memory.PrivateHeap"/> to allocate buffers from</param>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.GetSessionAsync(VNLib.Net.Http.HttpEvent,System.Threading.CancellationToken)">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.CacheClear">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.CacheHardClear">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.OnConnected">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.OnError(VNLib.Net.Messaging.FBM.Client.FMBClientErrorEventArgs)">
- <inheritdoc/>
- </member>
- <member name="M:VNLib.Plugins.Sessions.Cache.Client.SessionClient.OnDisconnected">
- <inheritdoc/>
- </member>
- </members>
-</doc>