Skip to content

Commit

Permalink
- do not override minimum CSP version if version in server_cfg is hig…
Browse files Browse the repository at this point in the history
…her than extra_cfg

- always print file path on config file parsing errors
- improve exception messages
  • Loading branch information
compujuckel committed Jan 21, 2024
1 parent 794da7c commit 4d1018b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 44 deletions.
34 changes: 26 additions & 8 deletions AssettoServer/ExceptionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,33 @@ or another Discord server.
public static void PrintExceptionHelp(Exception ex, bool isContentManager, string? crashReportPath)
{
string? helpLink = null;
string? configPath = null;

while (ex is DependencyResolutionException && ex.InnerException != null)
{
ex = ex.InnerException;
}

if (ex is ConfigurationParsingException cfgEx)
{
configPath = cfgEx.Path;
if (ex.InnerException != null)
{
ex = ex.InnerException;
}
}

Console.WriteLine();
switch (ex)
{
case YamlException yamlException:
WrapText(YamlExceptionHelp(yamlException), isContentManager);
WrapText(YamlExceptionHelp(yamlException, configPath), isContentManager);
break;
case ParsingException when ex.InnerException is FileNotFoundException fnfException:
WrapText(fnfException.Message, isContentManager);
break;
case ParsingException iniException:
WrapText(IniExceptionHelp(iniException), isContentManager);
WrapText(IniExceptionHelp(iniException, configPath), isContentManager);
break;
case IOException { InnerException: AddressInUseException } or SocketException { ErrorCode: 10048 }:
WrapText(AddressInUseExceptionHelp(), isContentManager);
Expand All @@ -72,6 +82,11 @@ public static void PrintExceptionHelp(Exception ex, bool isContentManager, strin
{
Console.WriteLine("Press I to get more info on this error");
}

if (configPath != null)
{
Console.WriteLine("Press F to show the faulty configuration file");
}
if (crashReportPath != null)
{
Console.WriteLine("Press C to show the crash report");
Expand All @@ -97,7 +112,11 @@ public static void PrintExceptionHelp(Exception ex, bool isContentManager, strin
}
else if (crashReportPath != null && key.Key == ConsoleKey.C)
{
Process.Start("explorer.exe", $"/select, \"{crashReportPath}\"");
ProcessHelper.ShowInExplorer(crashReportPath);
}
else if (configPath != null && key.Key == ConsoleKey.F)
{
ProcessHelper.ShowInExplorer(configPath);
}
}

Expand Down Expand Up @@ -127,19 +146,18 @@ private static void WrapText(string text, bool isContentManager)
Console.ForegroundColor = old;
}

private static string YamlExceptionHelp(YamlException ex)
private static string YamlExceptionHelp(YamlException ex, string? path = null)
{
return $"""
YAML error. Check your extra_cfg.yml around line {ex.Start.Line}.
When copying plugin configuration, make sure to copy EVERYTHING, including the "---".
YAML error in {path ?? "unknown file"} around line {ex.Start.Line}.
{ex.Message}
""";
}

private static string IniExceptionHelp(ParsingException ex)
private static string IniExceptionHelp(ParsingException ex, string? path = null)
{
return $"""
INI error. Check your server_cfg.ini or entry_list.ini around line {ex.LineNumber}.
INI error in {path ?? "unknown file"} around line {ex.LineNumber}.
{ex.Message}
""";
}
Expand Down
106 changes: 70 additions & 36 deletions AssettoServer/Server/Configuration/ACServerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public ACServerConfiguration(string? preset, ConfigurationLocations locations, b
$"AssettoServer {ThisAssembly.AssemblyInformationalVersion}");

var parsedTrackOptions = CSPTrackOptions = CSPTrackOptions.Parse(Server.Track);
if (Extra.MinimumCSPVersion.HasValue)
if (Extra.MinimumCSPVersion.HasValue
&& (!CSPTrackOptions.MinimumCSPVersion.HasValue || Extra.MinimumCSPVersion.Value > CSPTrackOptions.MinimumCSPVersion.Value))
{
CSPTrackOptions = new CSPTrackOptions
{
Expand All @@ -95,27 +96,45 @@ public ACServerConfiguration(string? preset, ConfigurationLocations locations, b
private ServerConfiguration LoadServerConfiguration(string path)
{
Log.Debug("Loading server_cfg.ini from {Path}", path);
if (!File.Exists(path))
try
{
if (!File.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
using var serverCfg = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("AssettoServer.Assets.server_cfg.ini")!;
using var outFile = File.Create(path);
serverCfg.CopyTo(outFile);
}

return ServerConfiguration.FromFile(path);
}
catch (Exception ex)
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
using var serverCfg = Assembly.GetExecutingAssembly().GetManifestResourceStream("AssettoServer.Assets.server_cfg.ini")!;
using var outFile = File.Create(path);
serverCfg.CopyTo(outFile);
throw new ConfigurationParsingException(path, ex);
}
return ServerConfiguration.FromFile(path);
}

private EntryList LoadEntryList(string path)
{
Log.Debug("Loading entry_list.ini from {Path}", path);
if (!File.Exists(path))
try
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
using var entryList = Assembly.GetExecutingAssembly().GetManifestResourceStream("AssettoServer.Assets.entry_list.ini")!;
using var outFile = File.Create(path);
entryList.CopyTo(outFile);
if (!File.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
using var entryList = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("AssettoServer.Assets.entry_list.ini")!;
using var outFile = File.Create(path);
entryList.CopyTo(outFile);
}

return EntryList.FromFile(path);
}
catch (Exception ex)
{
throw new ConfigurationParsingException(path, ex);
}
return EntryList.FromFile(path);
}

private string LoadWelcomeMessage()
Expand Down Expand Up @@ -213,26 +232,34 @@ internal void LoadPluginConfiguration(ACPluginLoader loader, ContainerBuilder bu
{
if (!plugin.HasConfiguration) continue;

var schemaPath = ConfigurationSchemaGenerator.WritePluginConfigurationSchema(plugin);
ReferenceConfigurationHelper.WriteReferenceConfiguration(plugin.ReferenceConfigurationFileName, schemaPath, plugin.ReferenceConfiguration, plugin.Name);

var configPath = Path.Join(BaseFolder, plugin.ConfigurationFileName);
if (File.Exists(configPath))
try
{
var deserializer = new DeserializerBuilder().Build();
using var file = File.OpenText(configPath);
var configObj = deserializer.Deserialize(file, plugin.ConfigurationType)!;
var schemaPath = ConfigurationSchemaGenerator.WritePluginConfigurationSchema(plugin);
ReferenceConfigurationHelper.WriteReferenceConfiguration(plugin.ReferenceConfigurationFileName,
schemaPath, plugin.ReferenceConfiguration, plugin.Name);

if (File.Exists(configPath))
{
var deserializer = new DeserializerBuilder().Build();
using var file = File.OpenText(configPath);
var configObj = deserializer.Deserialize(file, plugin.ConfigurationType)!;

ValidatePluginConfiguration(plugin, configObj);
builder.RegisterInstance(configObj).AsSelf();
ValidatePluginConfiguration(plugin, configObj);
builder.RegisterInstance(configObj).AsSelf();
}
else
{
var serializer = new SerializerBuilder().Build();
using var file = File.CreateText(configPath);
ConfigurationSchemaGenerator.WriteModeLine(file, BaseFolder, schemaPath);
var configObj = Activator.CreateInstance(plugin.ConfigurationType)!;
serializer.Serialize(file, configObj, plugin.ConfigurationType);
}
}
else
catch (Exception ex)
{
var serializer = new SerializerBuilder().Build();
using var file = File.CreateText(configPath);
ConfigurationSchemaGenerator.WriteModeLine(file, BaseFolder, schemaPath);
var configObj = Activator.CreateInstance(plugin.ConfigurationType)!;
serializer.Serialize(file, configObj, plugin.ConfigurationType);
throw new ConfigurationParsingException(configPath, ex);
}
}

Expand Down Expand Up @@ -263,17 +290,24 @@ private static void ValidatePluginConfiguration(LoadedPlugin plugin, object conf

private void LoadExtraConfig(string path, string schemaPath) {
Log.Debug("Loading extra_cfg.yml from {Path}", path);
if (!File.Exists(path))

try
{
using var file = File.CreateText(path);
ConfigurationSchemaGenerator.WriteModeLine(file, BaseFolder, schemaPath);
new ACExtraConfiguration().ToStream(file);
if (!File.Exists(path))
{
using var file = File.CreateText(path);
ConfigurationSchemaGenerator.WriteModeLine(file, BaseFolder, schemaPath);
new ACExtraConfiguration().ToStream(file);
}

Extra = ACExtraConfiguration.FromFile(path);
}
catch (Exception ex)
{
throw new ConfigurationParsingException(path, ex);
}

Extra = ACExtraConfiguration.FromFile(path);

if (Regex.IsMatch(Server.Name, @"x:\w+$"))
if (Regex.IsMatch(Server.Name, @"x:\w+$")) // TODO remove
{
const string errorMsg =
"Server details are configured via ID in server name. This interferes with native AssettoServer server details. More info: https://assettoserver.org/docs/common-configuration-errors#wrong-server-details";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace AssettoServer.Server.Configuration;

public class ConfigurationParsingException : Exception
{
public string? Path { get; }

public ConfigurationParsingException()
{
}

public ConfigurationParsingException(string? path, Exception? inner = null)
: base($"Error parsing configuration file {path}", inner)
{
Path = path;
}
}
5 changes: 5 additions & 0 deletions AssettoServer/Utils/ProcessHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ public static void OpenURL(string url)
url = url.Replace("&", "^&");
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
}

public static void ShowInExplorer(string path)
{
Process.Start("explorer.exe", $"/select, \"{path}\"");
}
}

0 comments on commit 4d1018b

Please sign in to comment.