1
0
mirror of https://github.com/livingcomputermuseum/IFS.git synced 2026-01-31 14:02:04 +00:00
Files
livingcomputermuseum.IFS/PUP/Configuration.cs

249 lines
8.7 KiB
C#

/*
This file is part of IFS.
IFS 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.
IFS 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 IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace IFS
{
public class InvalidConfigurationException : Exception
{
public InvalidConfigurationException(string message) : base(message)
{
}
}
/// <summary>
/// Encapsulates global server configuration information.
/// </summary>
public static class Configuration
{
static Configuration()
{
ReadConfiguration();
//
// Ensure that required values were read from the config file. If not,
// throw so that startup is aborted.
//
if (string.IsNullOrWhiteSpace(FTPRoot) || !Directory.Exists(FTPRoot))
{
throw new InvalidConfigurationException("FTP root path is invalid.");
}
if (string.IsNullOrWhiteSpace(CopyDiskRoot) || !Directory.Exists(CopyDiskRoot))
{
throw new InvalidConfigurationException("CopyDisk root path is invalid.");
}
if (string.IsNullOrWhiteSpace(BootRoot) || !Directory.Exists(BootRoot))
{
throw new InvalidConfigurationException("Boot root path is invalid.");
}
if (string.IsNullOrWhiteSpace(BootRoot) || !Directory.Exists(MailRoot))
{
throw new InvalidConfigurationException("Mail root path is invalid.");
}
if (MaxWorkers < 1)
{
throw new InvalidConfigurationException("MaxWorkers must be >= 1.");
}
if (UDPPort == 0)
{
// Set to default.
UDPPort = 42424;
}
}
/// <summary>
/// The type of interface (UDP or RAW) to communicate over
/// </summary>
public static readonly string InterfaceType;
/// <summary>
/// The name of the network interface to use
/// </summary>
public static readonly string InterfaceName;
/// <summary>
/// The UDP port to use when using a UDP interface.
/// </summary>
public static readonly int UDPPort;
/// <summary>
/// The network that this server lives on
/// </summary>
public static readonly int ServerNetwork;
/// <summary>
/// The host number for this server.
/// </summary>
public static readonly int ServerHost;
/// <summary>
/// The root directory for the FTP file store.
/// </summary>
public static readonly string FTPRoot;
/// <summary>
/// The root directory for the CopyDisk file store.
/// </summary>
public static readonly string CopyDiskRoot;
/// <summary>
/// The root directory for the Boot file store.
/// </summary>
public static readonly string BootRoot;
/// <summary>
/// The root directory for the Mail file store.
/// </summary>
public static readonly string MailRoot;
/// <summary>
/// The maximum number of worker threads for protocol handling.
/// </summary>
public static readonly int MaxWorkers = 256;
/// <summary>
/// The components to display logging messages for.
/// </summary>
public static readonly LogComponent LogComponents;
/// <summary>
/// The type (Verbosity) of messages to log.
/// </summary>
public static readonly LogType LogTypes;
private static void ReadConfiguration()
{
using (StreamReader configStream = new StreamReader(Path.Combine("Conf", "ifs.cfg")))
{
//
// Config file consists of text lines containing name / value pairs:
// <Name>=<Value>
// Whitespace is ignored.
//
int lineNumber = 0;
while (!configStream.EndOfStream)
{
lineNumber++;
string line = configStream.ReadLine().Trim();
if (string.IsNullOrEmpty(line))
{
// Empty line, ignore.
continue;
}
if (line.StartsWith("#"))
{
// Comment to EOL, ignore.
continue;
}
// Find the '=' separating tokens and ensure there are just two.
string[] tokens = line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length < 2)
{
Log.Write(LogType.Warning, LogComponent.Configuration,
"ifs.cfg line {0}: Invalid syntax.", lineNumber);
continue;
}
string parameter = tokens[0].Trim();
string value = tokens[1].Trim();
// Reflect over the public, static properties in this class and see if the parameter matches one of them
// If not, it's an error, if it is then we attempt to coerce the value to the correct type.
System.Reflection.FieldInfo[] info = typeof(Configuration).GetFields(BindingFlags.Public | BindingFlags.Static);
bool bMatch = false;
foreach (FieldInfo field in info)
{
// Case-insensitive compare.
if (field.Name.ToLowerInvariant() == parameter.ToLowerInvariant())
{
bMatch = true;
//
// Switch on the type of the field and attempt to convert the value to the appropriate type.
// At this time we support only strings and integers.
//
try
{
switch (field.FieldType.Name)
{
case "Int32":
{
int v = int.Parse(value);
field.SetValue(null, v);
}
break;
case "String":
{
field.SetValue(null, value);
}
break;
case "LogType":
{
field.SetValue(null, Enum.Parse(typeof(LogType), value, true));
}
break;
case "LogComponent":
{
field.SetValue(null, Enum.Parse(typeof(LogComponent), value, true));
}
break;
}
}
catch
{
Log.Write(LogType.Warning, LogComponent.Configuration,
"ifs.cfg line {0}: Value '{1}' is invalid for parameter '{2}'.", lineNumber, value, parameter);
}
}
}
if (!bMatch)
{
Log.Write(LogType.Warning, LogComponent.Configuration,
"ifs.cfg line {0}: Unknown configuration parameter '{1}'.", lineNumber, parameter);
}
}
}
}
}
}