/* * Copyright (c) 2023 Vaughn Nugent * * Library: VNLib * Package: ObjectCacheServer * File: NodeConfig.cs * * NodeConfig.cs is part of ObjectCacheServer which is part of the larger * VNLib collection of libraries and utilities. * * ObjectCacheServer 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. * * ObjectCacheServer 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.Linq; using System.Text.Json; using VNLib.Plugins; using VNLib.Utils.Logging; using VNLib.Utils.Extensions; using VNLib.Plugins.Extensions.Loading; using VNLib.Data.Caching.ObjectCache.Server.Endpoints; using VNLib.Data.Caching.Extensions.Clustering; namespace VNLib.Data.Caching.ObjectCache.Server { [ConfigurationName("cluster")] internal sealed class NodeConfig { const string CacheConfigTemplate = @" Cluster Configuration: Node Id: {id} TlsEndabled: {tls} Cache Endpoint: {ep} Discovery Endpoint: {dep} Discovery Interval: {di} Max Peers: {mpc} "; public CacheNodeConfiguration Config { get; } public CacheAuthKeyStore KeyStore { get; } public TimeSpan DiscoveryInterval { get; } /// /// The maximum number of peer connections to allow /// public uint MaxPeerConnections { get; } = 10; public NodeConfig(PluginBase plugin, IConfigScope config) { Config = new(); //Get the port of the primary webserver int port; bool usingTls; { //Get the port number of the first virtual host JsonElement firstHost = plugin.HostConfig.GetProperty("virtual_hosts") .EnumerateArray() .First(); port = firstHost.GetProperty("interface") .GetProperty("port") .GetInt32(); //If the ssl element is present, ssl is enabled for the server usingTls = firstHost.TryGetProperty("ssl", out _); } string hostname = Dns.GetHostName(); //Server id is just dns name for now string nodeId = $"{hostname}:{port}"; //The endpoint to advertise to cache clients that allows cache connections Uri cacheEndpoint = GetEndpointUri(plugin, usingTls, port, hostname); //Init key store KeyStore = new(plugin); //Setup cache node config Config.WithCacheEndpoint(cacheEndpoint) .WithNodeId(nodeId) .WithAuthenticator(KeyStore) .WithTls(usingTls); //Check if advertising is enabled if(plugin.HasConfigForType()) { //Get the the broadcast endpoint Uri discoveryEndpoint = GetEndpointUri(plugin, usingTls, port, hostname); //Enable advertising Config.EnableAdvertisment(discoveryEndpoint); } DiscoveryInterval = config["discovery_interval_sec"].GetTimeSpan(TimeParseType.Seconds); //Get the max peer connections if(config.TryGetValue("max_peers", out JsonElement maxPeerEl)) { MaxPeerConnections = maxPeerEl.GetUInt32(); } //log the config plugin.Log.Information(CacheConfigTemplate, nodeId, usingTls, cacheEndpoint, Config.DiscoveryEndpoint, DiscoveryInterval, MaxPeerConnections ); } private static Uri GetEndpointUri(PluginBase plugin, bool usingTls, int port, string hostName) where T: IEndpoint { //Get the cache endpoint config IConfigScope cacheEpConfig = plugin.GetConfigForType(); //The endpoint to advertise to cache clients that allows cache connections return new UriBuilder(usingTls ? Uri.UriSchemeHttps : Uri.UriSchemeHttp, hostName, port, cacheEpConfig["path"].GetString()).Uri; } } }