diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 368b51689..3c67255a2 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -835,6 +835,7 @@ namespace IW4MAdmin Logger.WriteDebug(e.GetExceptionInfo()); } + Logger.WriteError(e.Message); return false; } @@ -876,6 +877,13 @@ namespace IW4MAdmin Version = RconParser.Version; } + var svRunning = await this.GetDvarAsync("sv_running"); + + if (svRunning.Value == 0) + { + throw new ServerException(loc["SERVER_ERROR_NOT_RUNNING"]); + } + var infoResponse = RconParser.Configuration.CommandPrefixes.RConGetInfo != null ? await this.GetInfoAsync() : null; // this is normally slow, but I'm only doing it because different games have different prefixes var hostname = infoResponse == null ? diff --git a/Application/Main.cs b/Application/Main.cs index d94358b8c..eda7c6fbc 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -130,7 +130,6 @@ namespace IW4MAdmin.Application }; await Task.WhenAll(tasks); - inputThread.Abort(); ServerManager.Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]); } diff --git a/Application/RconParsers/BaseRConParser.cs b/Application/RconParsers/BaseRConParser.cs index e7b72801a..381b0e38d 100644 --- a/Application/RconParsers/BaseRConParser.cs +++ b/Application/RconParsers/BaseRConParser.cs @@ -36,6 +36,7 @@ namespace IW4MAdmin.Application.RconParsers RConGetInfo = "ÿÿÿÿgetinfo", RConResponse = "ÿÿÿÿprint", }, + ServerNotRunningResponse = "Server is not running." }; Configuration.Status.Pattern = @"^ *([0-9]+) +-?([0-9]+) +((?:[A-Z]+|[0-9]+)) +((?:[a-z]|[0-9]){8,32}|(?:[a-z]|[0-9]){8,32}|bot[0-9]+|(?:[0-9]+)) *(.{0,32}) +([0-9]+) +(\d+\.\d+\.\d+.\d+\:-*\d{1,5}|0+.0+:-*\d{1,5}|loopback|unknown) +(-*[0-9]+) +([0-9]+) *$"; @@ -141,7 +142,7 @@ namespace IW4MAdmin.Application.RconParsers if (Status.Length < 4) { - throw new ServerException("Unexpected status response received"); + throw new ServerException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNEXPECTED_STATUS"]); } int validMatches = 0; @@ -208,7 +209,7 @@ namespace IW4MAdmin.Application.RconParsers // this happens if status is requested while map is rotating if (Status.Length > 5 && validMatches == 0) { - throw new ServerException("Server is rotating map"); + throw new ServerException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_ROTATING_MAP"]); } return StatusPlayers; diff --git a/Application/RconParsers/DynamicRConParserConfiguration.cs b/Application/RconParsers/DynamicRConParserConfiguration.cs index 012f3386e..3d92c2f13 100644 --- a/Application/RconParsers/DynamicRConParserConfiguration.cs +++ b/Application/RconParsers/DynamicRConParserConfiguration.cs @@ -1,5 +1,4 @@ -using SharedLibraryCore; -using SharedLibraryCore.Interfaces; +using SharedLibraryCore.Interfaces; using SharedLibraryCore.RCon; namespace IW4MAdmin.Application.RconParsers @@ -14,6 +13,7 @@ namespace IW4MAdmin.Application.RconParsers public ParserRegex Status { get; set; } = new ParserRegex(); public ParserRegex MapStatus { get; set; } = new ParserRegex(); public ParserRegex Dvar { get; set; } = new ParserRegex(); + public string ServerNotRunningResponse { get; set; } public bool WaitForResponse { get; set; } = true; } } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index 27ad276ca..bf60abf70 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -257,13 +257,16 @@ namespace SharedLibraryCore { processed = await Task.Run(() => _eventFinishedWaiter.WaitOne(timeSpan), token); } - catch { } + catch (TaskCanceledException) + { + processed = true; + } if (!processed) { #if DEBUG - //throw new Exception(); + throw new Exception(); #endif Owner?.Logger.WriteError("Waiting for event to complete timed out"); Owner?.Logger.WriteDebug($"{Id}, {Type}, {Data}, {Extra}, {FailReason.ToString()}, {Message}, {Origin}, {Target}"); diff --git a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs index dd75e377f..9c15cdecf 100644 --- a/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs +++ b/SharedLibraryCore/Interfaces/IRConParserConfiguration.cs @@ -24,6 +24,11 @@ namespace SharedLibraryCore.Interfaces /// ParserRegex Dvar { get; set; } + /// + /// Specifies the expected response message from rcon when the server is not running + /// + string ServerNotRunningResponse { get; set; } + /// /// indicates if the application should wait for response from server /// when executing a command diff --git a/SharedLibraryCore/RCon/Connection.cs b/SharedLibraryCore/RCon/Connection.cs index 4987735ec..904e36e03 100644 --- a/SharedLibraryCore/RCon/Connection.cs +++ b/SharedLibraryCore/RCon/Connection.cs @@ -184,16 +184,22 @@ namespace SharedLibraryCore.RCon string responseString = defaultEncoding.GetString(response, 0, response.Length) + '\n'; + // note: not all games respond if the pasword is wrong or not set if (responseString.Contains("Invalid password") || responseString.Contains("rconpassword")) { throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_INVALID"]); } - if (responseString.ToString().Contains("rcon_password")) + if (responseString.Contains("rcon_password")) { throw new NetworkException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_RCON_NOTSET"]); } + if (responseString.Contains(Config.ServerNotRunningResponse)) + { + throw new ServerException(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_NOT_RUNNING"].FormatExt(Endpoint.ToString())); + } + string[] splitResponse = responseString.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(line => line.Trim()) .ToArray();