aboutsummaryrefslogtreecommitdiff
path: root/apps/VNLib.WebServer/src/Config
diff options
context:
space:
mode:
Diffstat (limited to 'apps/VNLib.WebServer/src/Config')
-rw-r--r--apps/VNLib.WebServer/src/Config/IServerConfig.cs34
-rw-r--r--apps/VNLib.WebServer/src/Config/JsonConfigOptions.cs42
-rw-r--r--apps/VNLib.WebServer/src/Config/JsonServerConfig.cs156
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/BenchmarkConfig.cs43
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/CorsSecurityConfig.cs41
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/ErrorFileConfig.cs37
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/HttpCompressorConfig.cs47
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/HttpGlobalConfig.cs137
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/LogConfig.cs52
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/ServerPluginConfig.cs46
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/TcpConfigJson.cs73
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/TransportInterface.cs137
-rw-r--r--apps/VNLib.WebServer/src/Config/Model/VirtualHostServerConfig.cs98
-rw-r--r--apps/VNLib.WebServer/src/Config/ServerConfigurationException.cs40
-rw-r--r--apps/VNLib.WebServer/src/Config/Validate.cs113
15 files changed, 1096 insertions, 0 deletions
diff --git a/apps/VNLib.WebServer/src/Config/IServerConfig.cs b/apps/VNLib.WebServer/src/Config/IServerConfig.cs
new file mode 100644
index 0000000..b0b06ba
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/IServerConfig.cs
@@ -0,0 +1,34 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: IServerConfig.cs
+*
+* IServerConfig.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json;
+
+
+namespace VNLib.WebServer.Config
+{
+ internal interface IServerConfig
+ {
+ JsonElement GetDocumentRoot();
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/JsonConfigOptions.cs b/apps/VNLib.WebServer/src/Config/JsonConfigOptions.cs
new file mode 100644
index 0000000..a48b4e9
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/JsonConfigOptions.cs
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: JsonConfigOptions.cs
+*
+* JsonConfigOptions.cs is part of VNLib.WebServer which is part of
+* the larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json;
+
+namespace VNLib.WebServer.Config
+{
+ internal static class JsonConfigOptions
+ {
+ private static readonly JsonSerializerOptions _ops = new()
+ {
+ AllowTrailingCommas = true,
+ ReadCommentHandling = JsonCommentHandling.Skip,
+ };
+
+ public static T? DeserializeElement<T>(this JsonElement el)
+ {
+ return el.Deserialize<T>(_ops);
+ }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/JsonServerConfig.cs b/apps/VNLib.WebServer/src/Config/JsonServerConfig.cs
new file mode 100644
index 0000000..ada9902
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/JsonServerConfig.cs
@@ -0,0 +1,156 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: JsonServerConfig.cs
+*
+* JsonServerConfig.cs is part of VNLib.WebServer which is part
+* of the larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.IO;
+using System.Text.Json;
+
+using YamlDotNet.Core.Events;
+using YamlDotNet.Serialization;
+
+using VNLib.Utils.IO;
+
+namespace VNLib.WebServer.Config
+{
+ internal sealed class JsonServerConfig(JsonDocument doc) : IServerConfig
+ {
+ public JsonElement GetDocumentRoot() => doc.RootElement;
+
+ public static JsonServerConfig? FromFile(string filename)
+ {
+ string nameOnly = Path.GetFileName(filename);
+ Console.WriteLine("Loading configuration file from {0}", nameOnly);
+
+ if (filename.EndsWith(".json"))
+ {
+ return FromJson(filename);
+ }
+ else if (filename.EndsWith(".yaml") || filename.EndsWith(".yml"))
+ {
+ return FromYaml(filename);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Reads a server configuration from the specified JSON document
+ /// </summary>
+ /// <param name="configPath">The file path of the json cofiguration file</param>
+ /// <returns>A new <see cref="JsonServerConfig"/> wrapping the server config</returns>
+ public static JsonServerConfig? FromJson(string fileName)
+ {
+ if (!FileOperations.FileExists(fileName))
+ {
+ return null;
+ }
+
+ //Open the config file
+ using FileStream fs = File.OpenRead(fileName);
+
+ //Allow comments
+ JsonDocumentOptions jdo = new()
+ {
+ CommentHandling = JsonCommentHandling.Skip,
+ AllowTrailingCommas = true,
+ };
+
+ return new JsonServerConfig(JsonDocument.Parse(fs, jdo));
+ }
+
+ public static JsonServerConfig? FromYaml(string fileName)
+ {
+ if (!FileOperations.FileExists(fileName))
+ {
+ return null;
+ }
+
+ /*
+ * The following code reads the configuration as a yaml
+ * object and then serializes it over to json.
+ */
+
+ using StreamReader reader = OpenFileRead(fileName);
+
+ object? yamlObject = new DeserializerBuilder()
+ .WithNodeTypeResolver(new NumberTypeResolver())
+ .Build()
+ .Deserialize(reader);
+
+ ISerializer serializer = new SerializerBuilder()
+ .JsonCompatible()
+ .Build();
+
+ using VnMemoryStream ms = new();
+ using (StreamWriter sw = new(ms, leaveOpen: true))
+ {
+ serializer.Serialize(sw, yamlObject);
+ }
+
+ ms.Seek(0, SeekOrigin.Begin);
+
+ return new JsonServerConfig(JsonDocument.Parse(ms));
+ }
+
+ private static StreamReader OpenFileRead(string fileName)
+ {
+ return new StreamReader(
+ stream: File.OpenRead(fileName),
+ encoding: System.Text.Encoding.UTF8,
+ detectEncodingFromByteOrderMarks: false,
+ leaveOpen: false
+ );
+ }
+
+ public class NumberTypeResolver : INodeTypeResolver
+ {
+ public bool Resolve(NodeEvent? nodeEvent, ref Type currentType)
+ {
+ if (nodeEvent is Scalar scalar)
+ {
+ if(long.TryParse(scalar.Value, out _))
+ {
+ currentType = typeof(int);
+ return true;
+ }
+
+ if (double.TryParse(scalar.Value, out _))
+ {
+ currentType = typeof(double);
+ return true;
+ }
+
+ if (bool.TryParse(scalar.Value, out _))
+ {
+ currentType = typeof(bool);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/BenchmarkConfig.cs b/apps/VNLib.WebServer/src/Config/Model/BenchmarkConfig.cs
new file mode 100644
index 0000000..1b0f157
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/BenchmarkConfig.cs
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: BenchmarkConfig.cs
+*
+* BenchmarkConfig.cs is part of VNLib.WebServer which is part of the
+* larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+
+ internal sealed class BenchmarkConfig
+ {
+
+ [JsonPropertyName("enabled")]
+ public bool Enabled { get; set; }
+
+ [JsonPropertyName("size")]
+ public int Size { get; set; }
+
+ [JsonPropertyName("random")]
+ public bool Random { get; set; }
+
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/CorsSecurityConfig.cs b/apps/VNLib.WebServer/src/Config/Model/CorsSecurityConfig.cs
new file mode 100644
index 0000000..2f95697
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/CorsSecurityConfig.cs
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: CorsSecurityConfig.cs
+*
+* CorsSecurityConfig.cs is part of VNLib.WebServer which is part of the
+* larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal class CorsSecurityConfig
+ {
+ [JsonPropertyName("enabled")]
+ public bool Enabled { get; set; } = false;
+
+ [JsonPropertyName("deny_cors_connections")]
+ public bool DenyCorsCons { get; set; } = false;
+
+ [JsonPropertyName("allowed_authority")]
+ public string[] AllowedCorsAuthority { get; set; } = Array.Empty<string>();
+ }
+} \ No newline at end of file
diff --git a/apps/VNLib.WebServer/src/Config/Model/ErrorFileConfig.cs b/apps/VNLib.WebServer/src/Config/Model/ErrorFileConfig.cs
new file mode 100644
index 0000000..c4355d6
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/ErrorFileConfig.cs
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: ErrorFileConfig.cs
+*
+* ErrorFileConfig.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal sealed class ErrorFileConfig
+ {
+ [JsonPropertyName("code")]
+ public int Code { get; set; }
+
+ [JsonPropertyName("path")]
+ public string? Path { get; set; }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/HttpCompressorConfig.cs b/apps/VNLib.WebServer/src/Config/Model/HttpCompressorConfig.cs
new file mode 100644
index 0000000..eb8e68c
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/HttpCompressorConfig.cs
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: HttpCompressorConfig.cs
+*
+* HttpCompressorConfig.cs is part of VNLib.WebServer which is part of
+* the larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal sealed class HttpCompressorConfig
+ {
+ [JsonPropertyName("assembly")]
+ public string? AssemblyPath { get; set; }
+
+ /// <summary>
+ /// If this compressor is enabled. The default is true, to use built-in
+ /// compressors.
+ /// </summary>
+ [JsonPropertyName("enabled")]
+ public bool Enabled { get; set; } = true;
+
+ [JsonPropertyName("max_size")]
+ public long CompressionMax { get; set; } = 104857600; //100MB
+
+ [JsonPropertyName("min_size")]
+ public int CompressionMin { get; set; } = 256;
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/HttpGlobalConfig.cs b/apps/VNLib.WebServer/src/Config/Model/HttpGlobalConfig.cs
new file mode 100644
index 0000000..22bfe75
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/HttpGlobalConfig.cs
@@ -0,0 +1,137 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: HttpGlobalConfig.cs
+*
+* HttpGlobalConfig.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal class HttpGlobalConfig
+ {
+
+ [JsonPropertyName("default_version")]
+ public string DefaultHttpVersion { get; set; } = "HTTP/1.1";
+
+ /// <summary>
+ /// The maximum size of a request entity that can be sent to the server.
+ /// </summary>
+ [JsonPropertyName("max_entity_size")]
+ public long MaxEntitySize { get; set; } = long.MaxValue;
+
+ /// <summary>
+ /// The maximum size of a multipart form data upload.
+ /// </summary>
+ [JsonPropertyName("multipart_max_size")]
+ public int MultipartMaxSize { get; set; } = 1048576; //1MB
+
+ /// <summary>
+ /// The time in milliseconds for an HTTP/1.1 connection to remain open
+ /// before the server closes it.
+ /// </summary>
+ [JsonPropertyName("keepalive_ms")]
+ public int KeepAliveMs { get; set; } = 60000; //60 seconds
+
+ /// <summary>
+ /// The time in milliseconds to wait for data on an active connection.
+ /// IE: A connection that has been established and has signaled that
+ /// it is ready to transfer data.
+ /// </summary>
+ [JsonPropertyName("recv_timeout_ms")]
+ public int RecvTimeoutMs { get; set; } = 5000; //5 seconds
+
+ /// <summary>
+ /// The time in milliseconds to wait for data to be sent on a connection.
+ /// </summary>
+ [JsonPropertyName("send_timeout_ms")]
+ public int SendTimeoutMs { get; set; } = 60000; //60 seconds
+
+ /// <summary>
+ /// The maximum number of headers that can be sent in a request.
+ /// </summary>
+ [JsonPropertyName("max_request_header_count")]
+ public int MaxRequestHeaderCount { get; set; } = 32;
+
+ /// <summary>
+ /// The maximum number of open connections that can be made to the server, before
+ /// the server starts rejecting new connections.
+ /// </summary>
+ [JsonPropertyName("max_connections")]
+ public int MaxConnections { get; set; } = int.MaxValue;
+
+ /// <summary>
+ /// The maximum number of uploads that can be made in a single request. If
+ /// this value is exceeded, the request will be rejected.
+ /// </summary>
+ [JsonPropertyName("max_uploads_per_request")]
+ public ushort MaxUploadsPerRequest { get; set; } = 10;
+
+ /// <summary>
+ /// The size of the buffer used to store request headers.
+ /// </summary>
+ [JsonPropertyName("header_buf_size")]
+ public int HeaderBufSize { get; set; }
+
+ /// <summary>
+ /// The size of the buffer used to store response headers.
+ /// </summary>
+ [JsonPropertyName("response_header_buf_size")]
+ public int ResponseHeaderBufSize { get; set; }
+
+ /// <summary>
+ /// The size of the buffer used to store form data.
+ /// </summary>
+ [JsonPropertyName("multipart_max_buf_size")]
+ public int MultipartMaxBufSize { get; set; }
+
+ /// <summary>
+ /// The configuration for the HTTP compression settings.
+ /// </summary>
+ [JsonPropertyName("compression")]
+ public HttpCompressorConfig? Compression { get; set; } = new();
+
+ public void ValidateConfig()
+ {
+ Validate.EnsureNotNull(DefaultHttpVersion, "Default HTTP version is required");
+
+ Validate.EnsureRange(MaxEntitySize, 0, long.MaxValue);
+ Validate.EnsureRange(MultipartMaxSize, -1, int.MaxValue);
+ Validate.EnsureRange(KeepAliveMs, -1, int.MaxValue);
+
+ //Timeouts may be disabled by setting 0 or -1. Both are allowed for readability
+ Validate.EnsureRange(RecvTimeoutMs, -2, int.MaxValue);
+ Validate.EnsureRange(SendTimeoutMs, -2, int.MaxValue);
+
+ Validate.EnsureRange(MaxRequestHeaderCount, 0, 1024);
+ Validate.EnsureRange(MaxConnections, 0, int.MaxValue);
+ Validate.EnsureRange(MaxUploadsPerRequest, 0, 1024);
+ Validate.EnsureRange(HeaderBufSize, 0, int.MaxValue);
+ Validate.EnsureRange(ResponseHeaderBufSize, 0, int.MaxValue);
+ Validate.EnsureRange(MultipartMaxBufSize, 0, int.MaxValue);
+
+ //Validate compression config
+ Validate.EnsureNotNull(Compression, "Compression configuration should not be set to null. Comment to enable defaults");
+ Validate.EnsureRange(Compression.CompressionMax, -1, long.MaxValue);
+ Validate.EnsureRange(Compression.CompressionMin, -1, int.MaxValue);
+ }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/LogConfig.cs b/apps/VNLib.WebServer/src/Config/Model/LogConfig.cs
new file mode 100644
index 0000000..fafd630
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/LogConfig.cs
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: LogConfig.cs
+*
+* LogConfig.cs is part of VNLib.WebServer which is part of the
+* larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal sealed class LogConfig
+ {
+ [JsonPropertyName("enabled")]
+ public bool Enabled { get; set; } = false;
+
+ [JsonPropertyName("path")]
+ public string? Path { get; set; }
+
+ [JsonPropertyName("template")]
+ public string? Template { get; set; }
+
+ [JsonPropertyName("flush_sec")]
+ public int FlushIntervalSeconds { get; set; } = 10;
+
+ [JsonPropertyName("retained_files")]
+ public int RetainedFiles { get; set; } = 31;
+
+ [JsonPropertyName("file_size_limit")]
+ public int FileSizeLimit { get; set; } = 500 * 1000 * 1024;
+
+ [JsonPropertyName("interval")]
+ public string Interval { get; set; } = "infinite";
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/ServerPluginConfig.cs b/apps/VNLib.WebServer/src/Config/Model/ServerPluginConfig.cs
new file mode 100644
index 0000000..42b91b1
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/ServerPluginConfig.cs
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: ServerPluginConfig.cs
+*
+* ServerPluginConfig.cs is part of VNLib.WebServer which is part of
+* the larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal class ServerPluginConfig
+ {
+ [JsonPropertyName("enabled")]
+ public bool Enabled { get; set; } = true; //default to true if config is defined, then it can be assumed we want to load plugins unless explicitly disabled
+
+ [JsonPropertyName("path")]
+ public string? Path { get; set; }
+
+ [JsonPropertyName("config_dir")]
+ public string? ConfigDir { get; set; }
+
+ [JsonPropertyName("hot_reload")]
+ public bool HotReload { get; set; }
+
+ [JsonPropertyName("reload_delay_sec")]
+ public int ReloadDelaySec { get; set; } = 2;
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/TcpConfigJson.cs b/apps/VNLib.WebServer/src/Config/Model/TcpConfigJson.cs
new file mode 100644
index 0000000..5bd2b94
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/TcpConfigJson.cs
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: TcpServerLoader.cs
+*
+* TcpServerLoader.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal sealed class TcpConfigJson
+ {
+ [JsonPropertyName("keepalive_sec")]
+ public int TcpKeepAliveTime { get; set; } = 4;
+
+ [JsonPropertyName("keepalive_interval_sec")]
+ public int KeepaliveInterval { get; set; } = 4;
+
+ [JsonPropertyName("max_recv_buffer")]
+ public int MaxRecvBufferData { get; set; } = 10 * 64 * 1024;
+
+ [JsonPropertyName("backlog")]
+ public int BackLog { get; set; } = 1000;
+
+ [JsonPropertyName("max_connections")]
+ public long MaxConnections { get; set; } = long.MaxValue;
+
+ [JsonPropertyName("no_delay")]
+ public bool NoDelay { get; set; } = false;
+
+ /*
+ * Buffer sizes are a pain, this is a good default size for medium bandwith connections (100mbps)
+ * using the BDP calculations
+ *
+ * BDP = Bandwidth * RTT
+ */
+
+ [JsonPropertyName("tx_buffer")]
+ public int TcpSendBufferSize { get; set; } = 625 * 1024;
+
+ [JsonPropertyName("rx_buffer")]
+ public int TcpRecvBufferSize { get; set; } = 625 * 1024;
+
+
+ public void ValidateConfig()
+ {
+ Validate.EnsureRange(TcpKeepAliveTime, 0, 60);
+ Validate.EnsureRange(KeepaliveInterval, 0, 60);
+ Validate.EnsureRange(BackLog, 0, 10000);
+ Validate.EnsureRange(MaxConnections, 0, long.MaxValue);
+ Validate.EnsureRange(MaxRecvBufferData, 0, 10 * 1024 * 1024); //10MB
+ Validate.EnsureRange(TcpSendBufferSize, 0, 10 * 1024 * 1024); //10MB
+ }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/TransportInterface.cs b/apps/VNLib.WebServer/src/Config/Model/TransportInterface.cs
new file mode 100644
index 0000000..e0e2551
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/TransportInterface.cs
@@ -0,0 +1,137 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: TransportInterface.cs
+*
+* TransportInterface.cs is part of VNLib.WebServer which is part of
+* the larger VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.IO;
+using System.Net;
+using System.Security.Cryptography.X509Certificates;
+using System.Text.Json.Serialization;
+
+using VNLib.Utils.Memory;
+using VNLib.Utils.Resources;
+
+namespace VNLib.WebServer.Config.Model
+{
+ /// <summary>
+ /// Represents a transport interface configuration element for a virtual host
+ /// </summary>
+ internal class TransportInterface
+ {
+ [JsonPropertyName("port")]
+ public int Port { get; set; }
+
+ [JsonPropertyName("address")]
+ public string? Address { get; set; }
+
+ [JsonPropertyName("certificate")]
+ public string? Cert { get; set; }
+
+ [JsonPropertyName("private_key")]
+ public string? PrivKey { get; set; }
+
+ [JsonPropertyName("ssl")]
+ public bool Ssl { get; set; }
+
+ [JsonPropertyName("client_cert_required")]
+ public bool ClientCertRequired { get; set; }
+
+ [JsonPropertyName("password")]
+ public string? PrivKeyPassword { get; set; }
+
+ [JsonPropertyName("use_os_ciphers")]
+ public bool UseOsCiphers { get; set; }
+
+ public IPEndPoint GetEndpoint()
+ {
+ IPAddress addr = string.IsNullOrEmpty(Address) ? IPAddress.Any : IPAddress.Parse(Address);
+ return new IPEndPoint(addr, Port);
+ }
+
+ public X509Certificate? LoadCertificate()
+ {
+ if (!Ssl)
+ {
+ return null;
+ }
+
+ Validate.EnsureNotNull(Cert, "TLS Certificate is required when ssl is enabled");
+ Validate.FileExists(Cert);
+
+ X509Certificate? cert = null;
+
+ /*
+ * Default to use a PEM encoded certificate and private key file. Unless the file
+ * is a pfx file, then we will use the private key from the pfx file.
+ */
+
+ if (Path.GetExtension(Cert).EndsWith("pfx", StringComparison.OrdinalIgnoreCase))
+ {
+ //Create from pfx file including private key
+ cert = X509Certificate.CreateFromCertFile(Cert);
+ }
+ else
+ {
+ Validate.EnsureNotNull(PrivKey, "TLS Private Key is required ssl is enabled");
+ Validate.FileExists(PrivKey);
+
+ /*
+ * Attempt to capture the private key password. This will wrap the
+ * string in a private string instance, and setting the value to true
+ * will ensure the password memory is wiped when this function returns
+ */
+ using PrivateString? password = PrivateString.ToPrivateString(PrivKeyPassword, true);
+
+ //Load the cert and decrypt with password if set
+ using X509Certificate2 cert2 = password == null ? X509Certificate2.CreateFromPemFile(Cert, PrivKey)
+ : X509Certificate2.CreateFromEncryptedPemFile(Cert, password.ToReadOnlySpan(), PrivKey);
+
+ /*
+ * Workaround for a silly Windows SecureChannel module bug for parsing
+ * X509Certificate2 from pem cert and private key files.
+ *
+ * Must export into pkcs12 format then create a new X509Certificate2 from the
+ * exported bytes.
+ */
+
+ //Copy the cert in pkcs12 format
+ byte[] pkcs = cert2.Export(X509ContentType.Pkcs12);
+ cert = new X509Certificate2(pkcs);
+ MemoryUtil.InitializeBlock(pkcs);
+ }
+
+ return cert;
+ }
+
+ /// <summary>
+ /// Builds a deterministic hash-code base on the configuration state.
+ /// </summary>
+ /// <returns>The hash-code that represents the current instance</returns>
+ public override int GetHashCode() => HashCode.Combine(Address, Port);
+
+ public override bool Equals(object? obj) => obj is TransportInterface iface && GetHashCode() == iface.GetHashCode();
+
+ public override string ToString() => $"[{Address}:{Port}]";
+
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Model/VirtualHostServerConfig.cs b/apps/VNLib.WebServer/src/Config/Model/VirtualHostServerConfig.cs
new file mode 100644
index 0000000..5734bd3
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Model/VirtualHostServerConfig.cs
@@ -0,0 +1,98 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: VirtualHostServerConfig.cs
+*
+* VirtualHostServerConfig.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace VNLib.WebServer.Config.Model
+{
+ internal sealed class VirtualHostServerConfig
+ {
+ [JsonPropertyName("trace")]
+ public bool RequestTrace { get; set; } = false;
+
+ [JsonPropertyName("force_port_check")]
+ public bool ForcePortCheck { get; set; } = false;
+
+ [JsonPropertyName("benchmark")]
+ public BenchmarkConfig? Benchmark { get; set; }
+
+ [JsonPropertyName("interfaces")]
+ public TransportInterface[] Interfaces { get; set; } = Array.Empty<TransportInterface>();
+
+ [JsonPropertyName("hostnames")]
+ public string[]? Hostnames { get; set; } = Array.Empty<string>();
+
+ [JsonPropertyName("hostname")]
+ public string? Hostname
+ {
+ get => Hostnames?.FirstOrDefault();
+ set
+ {
+ if (value != null)
+ {
+ Hostnames = [value];
+ }
+ }
+ }
+
+ [JsonPropertyName("path")]
+ public string? DirPath { get; set; } = string.Empty;
+
+ [JsonPropertyName("downstream_servers")]
+ public string[] DownstreamServers { get; set; } = Array.Empty<string>();
+
+ [JsonPropertyName("whitelist")]
+ public string[]? Whitelist { get; set; }
+
+ [JsonPropertyName("blacklist")]
+ public string[]? Blacklist { get; set; }
+
+ [JsonPropertyName("deny_extensions")]
+ public string[]? DenyExtensions { get; set; }
+
+ [JsonPropertyName("default_files")]
+ public string[]? DefaultFiles { get; set; }
+
+ [JsonPropertyName("headers")]
+ public Dictionary<string, string> Headers { get; set; } = [];
+
+ [JsonPropertyName("cors")]
+ public CorsSecurityConfig Cors { get; set; } = new();
+
+ [JsonPropertyName("error_files")]
+ public ErrorFileConfig[] ErrorFiles { get; set; } = Array.Empty<ErrorFileConfig>();
+
+ [JsonPropertyName("cache_default_sec")]
+ public int CacheDefaultTimeSeconds { get; set; } = 0;
+
+ [JsonPropertyName("path_filter")]
+ public string? PathFilter { get; set; }
+
+ [JsonPropertyName("max_execution_time_ms")]
+ public int MaxExecutionTimeMs { get; set; } = 20000;
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/ServerConfigurationException.cs b/apps/VNLib.WebServer/src/Config/ServerConfigurationException.cs
new file mode 100644
index 0000000..39c18e5
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/ServerConfigurationException.cs
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: ServerConfigurationException.cs
+*
+* ServerConfigurationException.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+
+namespace VNLib.WebServer.Config
+{
+ public class ServerConfigurationException : Exception
+ {
+ public ServerConfigurationException()
+ { }
+
+ public ServerConfigurationException(string? message) : base(message)
+ { }
+
+ public ServerConfigurationException(string? message, Exception? innerException) : base(message, innerException)
+ { }
+ }
+}
diff --git a/apps/VNLib.WebServer/src/Config/Validate.cs b/apps/VNLib.WebServer/src/Config/Validate.cs
new file mode 100644
index 0000000..773d787
--- /dev/null
+++ b/apps/VNLib.WebServer/src/Config/Validate.cs
@@ -0,0 +1,113 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.WebServer
+* File: Validate.cs
+*
+* Validate.cs is part of VNLib.WebServer which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.WebServer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.WebServer 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
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.WebServer. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System;
+using System.Net;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+using VNLib.Utils.IO;
+
+namespace VNLib.WebServer.Config
+{
+ internal static class Validate
+ {
+ [DoesNotReturn]
+ public static void EnsureNotNull<T>(T? obj, string message) where T : class
+ {
+ if (obj is null)
+ {
+ throw new ServerConfigurationException(message);
+ }
+
+ if (obj is string s && string.IsNullOrWhiteSpace(s))
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void Assert([DoesNotReturnIf(false)] bool condition, string message)
+ {
+ if (!condition)
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void EnsureValidIp(string? address, string message)
+ {
+ if (!IPAddress.TryParse(address, out _))
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void EnsureNotEqual<T>(T a, T b, string message)
+ {
+ if (a is null || b is null)
+ {
+ throw new ServerConfigurationException(message);
+ }
+
+ if (a.Equals(b))
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void EnsureRangeEx(ulong value, ulong min, ulong max, string message)
+ {
+ if (value < min || value > max)
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void EnsureRangeEx(long value, long min, long max, string message)
+ {
+ if (value < min || value > max)
+ {
+ throw new ServerConfigurationException(message);
+ }
+ }
+
+ public static void EnsureRange(ulong value, ulong min, ulong max, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ EnsureRangeEx(value, min, max, $"Value for {paramName} must be between {min} and {max}. Value: {value}");
+ }
+
+ public static void EnsureRange(long value, long min, long max, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ EnsureRangeEx(value, min, max, $"Value for {paramName} must be between {min} and {max}. Value: {value}");
+ }
+
+ public static void FileExists(string path)
+ {
+ if (!FileOperations.FileExists(path))
+ {
+ throw new ServerConfigurationException($"Required file: {path} not found");
+ }
+ }
+ }
+}