// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.Network; using Microsoft.Extensions.Logging; /// /// Factory which creates an depending on command line arguments. /// public static class IpAddressResolverFactory { private const string ResolveParameterPrefix = "-resolveIP:"; private const string PublicIpResolve = "-resolveIP:public"; private const string LocalIpResolve = "-resolveIP:local"; private const string LoopbackIpResolve = "-resolveIP:loopback"; /// /// Determines the ip resolver based on command line arguments. /// /// The arguments. /// The configuration, if available. /// The logger factory. /// The determined resolver. public static IIpAddressResolver CreateIpResolver(string[] args, (IpResolverType, string?)? configuration, ILoggerFactory loggerFactory) { var (resolver, source) = DetermineBestFittingResolverWithSource(args, configuration); var allowRuntimeReconfiguration = source is not ResolverSource.StartParameter and not ResolverSource.EnvironmentVariable; return new ConfigurableIpResolver(resolver.Type, resolver.Parameter, loggerFactory, allowRuntimeReconfiguration); } /// /// Determines the best fitting ip resolver. /// /// The arguments. /// The configuration. /// The resolver type with its parameter. public static (IpResolverType Type, string? Parameter) DetermineBestFittingResolver(string[] args, (IpResolverType Type, string? Parameter)? configuration = default) { var (resolver, _) = DetermineBestFittingResolverWithSource(args, configuration); return resolver; } private static (IpResolverType Type, string? Parameter)? DetermineIpResolverByParameters(string[] args) { var parameter = GetParameter(args)?.Trim(); if (string.IsNullOrWhiteSpace(parameter)) { return default; } return parameter! switch { { } when parameter.Equals(LoopbackIpResolve, StringComparison.InvariantCultureIgnoreCase) => (IpResolverType.Loopback, null), { } when parameter.Equals(PublicIpResolve, StringComparison.InvariantCultureIgnoreCase) => (IpResolverType.Public, null), { } when parameter.Equals(LocalIpResolve, StringComparison.InvariantCultureIgnoreCase) => ((IpResolverType, string?)?)(IpResolverType.Local, null), _ => (IpResolverType.Custom, ExtractIpFromParameter(parameter)), }; } private static (IpResolverType Type, string? Parameter)? DetermineResolverByEnvironmentVariable(string variableName = "RESOLVE_IP") { if (Environment.GetEnvironmentVariable(variableName) is { } resolveIp && !string.IsNullOrWhiteSpace(resolveIp)) { return resolveIp switch { "local" => (IpResolverType.Local, null), "public" => (IpResolverType.Public, null), "loopback" => (IpResolverType.Loopback, null), _ => (IpResolverType.Custom, resolveIp), }; } return default; } private static (IpResolverType Type, string? Parameter) DetermineResolverByEnvironment() { var isDevelopmentEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"; if (isDevelopmentEnvironment) { // During development, we use a loopback IP (127.127.127.127). return (IpResolverType.Loopback, null); } // In production our systems should expose itself with their corresponding public IPs. return (IpResolverType.Public, null); } private static string ExtractIpFromParameter(string parameter) => parameter.Substring(parameter.IndexOf(':') + 1); private static string? GetParameter(string[] args) => args.FirstOrDefault(a => a.StartsWith(ResolveParameterPrefix, StringComparison.InvariantCultureIgnoreCase)); private static ((IpResolverType Type, string? Parameter) Resolver, ResolverSource Source) DetermineBestFittingResolverWithSource(string[] args, (IpResolverType Type, string? Parameter)? configuration = default) { if (DetermineIpResolverByParameters(args) is { } byParameters) { return (byParameters, ResolverSource.StartParameter); } if (DetermineResolverByEnvironmentVariable() is { } byEnvironmentVariable) { return (byEnvironmentVariable, ResolverSource.EnvironmentVariable); } if (configuration is { } byConfiguration) { return (byConfiguration, ResolverSource.Configuration); } return (DetermineResolverByEnvironment(), ResolverSource.Environment); } private enum ResolverSource { StartParameter, EnvironmentVariable, Configuration, Environment, } }