// Author: Simon Gockner // Created: 2020-02-08 // Copyright(c) 2020 SimonG. All Rights Reserved. using System; using System.IO; using System.Net; using System.Threading.Tasks; using GBase.Logging; using GBase.Server.Exceptions; using GBase.Server.Interfaces; namespace GBase.Server { public class GBaseServerSettings : IGBaseServerSettings { public const string ENDPOINT_STARTUP_CONFIGURATION_PREFIX = "--endpoint"; private const string PROTOCOL_ARGUMENT_PREFIX = "-pr"; private const string IP_ADDRESS_ARGUMENT_PREFIX = "-ip"; private const string PORT_ARGUMENT_PREFIX = "-p"; private const string ENDPOINT_ARGUMENT_PREFIX = "-e"; private const string LOG_FILE_PATH_ARGUMENT_PREFIX = "-lp"; private const string LOG_FILE_NAME_ARGUMENT_PREFIX = "-ln"; private const string HELP_ARGUMENT_PREFIX = "-help"; private readonly string _defaultLogFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "GBase", "Server", "Logs"); private readonly string _defaultLogFileName = $"GBaseServer_Log_{DateTime.Now:yyyy_MM_dd}_{DateTime.Now:hh_mm_ss}.txt"; private bool _protocolInitialized; private bool _ipAddressInitialized; private bool _portInitialized; private bool _endpointInitialized; private bool _logFilePathInitialized; private bool _logFileNameInitialized; public ServerProtocol Protocol { get; private set; } public IPAddress IpAddress { get; private set; } public int Port { get; private set; } public string Endpoint { get; private set; } public string LogFilePath { get; private set; } public string LogFileName { get; private set; } public async Task ParseArguments(string[] args) { for (int index = 0; index < args.Length; index++) { if (args[index] == PROTOCOL_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); Protocol = ServerProtocolExtensions.GetServerProtocolFromString(args[index]); _protocolInitialized = true; } else if (args[index] == IP_ADDRESS_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); IpAddress = ParseIpAddress(args[index]); _ipAddressInitialized = true; } else if (args[index] == PORT_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); Port = Convert.ToInt32(args[index]); _portInitialized = true; } else if (args[index] == ENDPOINT_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); Endpoint = args[index]; _endpointInitialized = true; } else if (args[index] == LOG_FILE_PATH_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); LogFilePath = args[index]; _logFilePathInitialized = true; } else if (args[index] == LOG_FILE_NAME_ARGUMENT_PREFIX) { index++; await VerifyArgsLength(index, args.Length); LogFileName = args[index]; _logFileNameInitialized = true; } else { await PrintHelp(); throw new ArgumentOutOfRangeException(nameof(args), args[index], "Invalid argument."); } } if (!await VerifySettings()) throw new IncompleteArgumentsException($"Not all mandatory arguments were passed. Check {HELP_ARGUMENT_PREFIX} to find out which arguments are mandatory."); } private async Task VerifyArgsLength(int index, int length) { if (length > index) return; await PrintHelp(); throw new MissingArgumentException(PROTOCOL_ARGUMENT_PREFIX); } private async Task VerifySettings() { //optional settings if (!_logFilePathInitialized) LogFilePath = _defaultLogFilePath; if (!_logFileNameInitialized) LogFileName = _defaultLogFileName; //mandatory settings if (_protocolInitialized && _ipAddressInitialized && _portInitialized && _endpointInitialized) return true; await PrintHelp(); return false; } private IPAddress ParseIpAddress(string ipAddressString) { string[] ipStringArray = ipAddressString.Split('.'); byte[] ipByteArray = new byte[ipStringArray.Length]; for (var i = 0; i < ipStringArray.Length; i++) { string @string = ipStringArray[i]; ipByteArray[i] = Convert.ToByte(@string); } return new IPAddress(ipByteArray); } private async Task PrintHelp() { await Log.Write("Mandatory Arguments:"); await Log.Write($"{PROTOCOL_ARGUMENT_PREFIX}: The used protocol (e.g 'http' or 'https')"); await Log.Write($"{IP_ADDRESS_ARGUMENT_PREFIX}: The used ip address"); await Log.Write($"{PORT_ARGUMENT_PREFIX}: The used port"); await Log.Write($"{ENDPOINT_ARGUMENT_PREFIX}: The used endpoint"); await Log.Write(""); await Log.Write("Optional Arguments:"); await Log.Write($"{LOG_FILE_PATH_ARGUMENT_PREFIX}: The path to the server log file (default: '{_defaultLogFilePath}')"); await Log.Write($"{LOG_FILE_NAME_ARGUMENT_PREFIX}: The name of the server log file (default: 'GBaseServer_Log_$day_$time.txt')"); } } }