1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-11 15:52:25 -05:00

support custom master url

refactor api instatation to allow custom master url in config
This commit is contained in:
RaidMax
2020-06-30 16:39:32 -05:00
parent ff502cb376
commit 9b9c1bd851
14 changed files with 262 additions and 269 deletions

View File

@ -1,72 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using RestEase;
namespace IW4MAdmin.Application.API.Master
{
/// <summary>
/// Defines the heartbeat functionality for IW4MAdmin
/// </summary>
public class Heartbeat
{
/// <summary>
/// Sends heartbeat to master server
/// </summary>
/// <param name="mgr"></param>
/// <param name="firstHeartbeat"></param>
/// <returns></returns>
public static async Task Send(ApplicationManager mgr, bool firstHeartbeat = false)
{
var api = Endpoint.Get();
if (firstHeartbeat)
{
var token = await api.Authenticate(new AuthenticationId()
{
Id = mgr.GetApplicationSettings().Configuration().Id
});
api.AuthorizationToken = $"Bearer {token.AccessToken}";
}
var instance = new ApiInstance()
{
Id = mgr.GetApplicationSettings().Configuration().Id,
Uptime = (int)(DateTime.UtcNow - mgr.StartTime).TotalSeconds,
Version = Program.Version,
Servers = mgr.Servers.Select(s =>
new ApiServer()
{
ClientNum = s.ClientNum,
Game = s.GameName.ToString(),
Version = s.Version,
Gametype = s.Gametype,
Hostname = s.Hostname,
Map = s.CurrentMap.Name,
MaxClientNum = s.MaxClients,
Id = s.EndPoint,
Port = (short)s.Port,
IPAddress = s.IP
}).ToList()
};
Response<ResultMessage> response = null;
if (firstHeartbeat)
{
response = await api.AddInstance(instance);
}
else
{
response = await api.UpdateInstance(instance.Id, instance);
}
if (response.ResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
{
mgr.Logger.WriteWarning($"Response code from master is {response.ResponseMessage.StatusCode}, message is {response.StringContent}");
}
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using RestEase;
@ -37,16 +35,6 @@ namespace IW4MAdmin.Application.API.Master
public string Message { get; set; }
}
public class Endpoint
{
#if !DEBUG
private static readonly IMasterApi api = RestClient.For<IMasterApi>("http://api.raidmax.org:5000");
#else
private static readonly IMasterApi api = RestClient.For<IMasterApi>("http://127.0.0.1");
#endif
public static IMasterApi Get() => api;
}
/// <summary>
/// Defines the capabilities of the master API
/// </summary>

View File

@ -648,85 +648,7 @@ namespace IW4MAdmin.Application
}
}
private async Task SendHeartbeat()
{
bool connected = false;
while (!_tokenSource.IsCancellationRequested)
{
if (!connected)
{
try
{
await Heartbeat.Send(this, true);
connected = true;
}
catch (Exception e)
{
connected = false;
Logger.WriteWarning($"Could not connect to heartbeat server - {e.Message}");
}
}
else
{
try
{
await Heartbeat.Send(this);
}
catch (System.Net.Http.HttpRequestException e)
{
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
catch (AggregateException e)
{
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
var exceptions = e.InnerExceptions.Where(ex => ex.GetType() == typeof(RestEase.ApiException));
foreach (var ex in exceptions)
{
if (((RestEase.ApiException)ex).StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
connected = false;
}
}
}
catch (RestEase.ApiException e)
{
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
if (e.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
connected = false;
}
}
catch (Exception e)
{
Logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
}
try
{
await Task.Delay(30000, _tokenSource.Token);
}
catch { break; }
}
}
public async Task Start()
{
await Task.WhenAll(new[]
{
SendHeartbeat(),
UpdateServerStates()
});
}
public async Task Start() => await UpdateServerStates();
public void Stop()
{

View File

@ -11,7 +11,7 @@ namespace IW4MAdmin.Application.Localization
{
public class Configure
{
public static ITranslationLookup Initialize(bool useLocalTranslation, string customLocale = null)
public static ITranslationLookup Initialize(bool useLocalTranslation, IMasterApi apiInstance, string customLocale = null)
{
string currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale;
string[] localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json");
@ -20,8 +20,7 @@ namespace IW4MAdmin.Application.Localization
{
try
{
var api = Endpoint.Get();
var localization = api.GetLocalization(currentLocale).Result;
var localization = apiInstance.GetLocalization(currentLocale).Result;
Utilities.CurrentLocalization = localization;
return localization.LocalizationIndex;
}

View File

@ -1,9 +1,11 @@
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.API.Master;
using IW4MAdmin.Application.EventParsers;
using IW4MAdmin.Application.Factories;
using IW4MAdmin.Application.Helpers;
using IW4MAdmin.Application.Migration;
using IW4MAdmin.Application.Misc;
using Microsoft.Extensions.DependencyInjection;
using RestEase;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Exceptions;
@ -23,7 +25,6 @@ namespace IW4MAdmin.Application
public static BuildNumber Version { get; private set; } = BuildNumber.Parse(Utilities.GetVersionAsString());
public static ApplicationManager ServerManager;
private static Task ApplicationTask;
private static readonly BuildNumber _fallbackVersion = BuildNumber.Parse("99.99.99.99");
private static ServiceProvider serviceProvider;
/// <summary>
@ -76,12 +77,13 @@ namespace IW4MAdmin.Application
var services = ConfigureServices(args);
serviceProvider = services.BuildServiceProvider();
var versionChecker = serviceProvider.GetRequiredService<IMasterCommunication>();
ServerManager = (ApplicationManager)serviceProvider.GetRequiredService<IManager>();
translationLookup = serviceProvider.GetRequiredService<ITranslationLookup>();
ServerManager.Logger.WriteInfo(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_VERSION"].FormatExt(Version));
await CheckVersion(translationLookup);
await versionChecker.CheckVersion();
await ServerManager.Init();
}
@ -155,6 +157,7 @@ namespace IW4MAdmin.Application
{
ServerManager.Start(),
webfrontTask,
serviceProvider.GetRequiredService<IMasterCommunication>().RunUploadStatus(ServerManager.CancellationToken)
};
await Task.WhenAll(tasks);
@ -162,68 +165,6 @@ namespace IW4MAdmin.Application
ServerManager.Logger.WriteVerbose(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_SHUTDOWN_SUCCESS"]);
}
/// <summary>
/// checks for latest version of the application
/// notifies user if an update is available
/// </summary>
/// <returns></returns>
private static async Task CheckVersion(ITranslationLookup translationLookup)
{
var api = API.Master.Endpoint.Get();
var loc = translationLookup;
var version = new API.Master.VersionInfo()
{
CurrentVersionStable = _fallbackVersion
};
try
{
version = await api.GetVersion(1);
}
catch (Exception e)
{
ServerManager.Logger.WriteWarning(loc["MANAGER_VERSION_FAIL"]);
while (e.InnerException != null)
{
e = e.InnerException;
}
ServerManager.Logger.WriteDebug(e.Message);
}
if (version.CurrentVersionStable == _fallbackVersion)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(loc["MANAGER_VERSION_FAIL"]);
Console.ForegroundColor = ConsoleColor.Gray;
}
#if !PRERELEASE
else if (version.CurrentVersionStable > Version)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"IW4MAdmin {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionStable.ToString()}]");
Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString()}]"));
Console.ForegroundColor = ConsoleColor.Gray;
}
#else
else if (version.CurrentVersionPrerelease > Version)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"IW4MAdmin-Prerelease {loc["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionPrerelease.ToString()}-pr]");
Console.WriteLine(loc["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Version.ToString()}-pr]"));
Console.ForegroundColor = ConsoleColor.Gray;
}
#endif
else
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(loc["MANAGER_VERSION_SUCCESS"]);
Console.ForegroundColor = ConsoleColor.Gray;
}
}
/// <summary>
/// reads input from the console and executes entered commands on the default server
@ -299,9 +240,12 @@ namespace IW4MAdmin.Application
{
var config = _serviceProvider.GetRequiredService<IConfigurationHandler<ApplicationConfiguration>>().Configuration();
return Localization.Configure.Initialize(useLocalTranslation: config?.UseLocalTranslations ?? false,
apiInstance: _serviceProvider.GetRequiredService<IMasterApi>(),
customLocale: config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US");
})
.AddSingleton<IManager, ApplicationManager>();
.AddSingleton<IManager, ApplicationManager>()
.AddSingleton(_serviceProvider => RestClient.For<IMasterApi>(Utilities.IsDevelopment ? new Uri("http://127.0.0.1:8080") : _serviceProvider.GetRequiredService<ApplicationConfiguration>().MasterUrl))
.AddSingleton<IMasterCommunication, MasterCommunication>();
if (args.Contains("serialevents"))
{

View File

@ -0,0 +1,209 @@
using IW4MAdmin.Application.API.Master;
using RestEase;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace IW4MAdmin.Application.Misc
{
/// <summary>
/// implementation of IMasterCommunication
/// talks to the master server
/// </summary>
class MasterCommunication : IMasterCommunication
{
private readonly ILogger _logger;
private readonly ITranslationLookup _transLookup;
private readonly IMasterApi _apiInstance;
private readonly IManager _manager;
private readonly ApplicationConfiguration _appConfig;
private readonly BuildNumber _fallbackVersion = BuildNumber.Parse("99.99.99.99");
private readonly int _apiVersion = 1;
private bool firstHeartBeat = true;
public MasterCommunication(ILogger logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager)
{
_logger = logger;
_transLookup = translationLookup;
_apiInstance = apiInstance;
_appConfig = appConfig;
_manager = manager;
}
/// <summary>
/// checks for latest version of the application
/// notifies user if an update is available
/// </summary>
/// <returns></returns>
public async Task CheckVersion()
{
var version = new VersionInfo()
{
CurrentVersionStable = _fallbackVersion
};
try
{
version = await _apiInstance.GetVersion(_apiVersion);
}
catch (Exception e)
{
_logger.WriteWarning(_transLookup["MANAGER_VERSION_FAIL"]);
while (e.InnerException != null)
{
e = e.InnerException;
}
_logger.WriteDebug(e.Message);
}
if (version.CurrentVersionStable == _fallbackVersion)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(_transLookup["MANAGER_VERSION_FAIL"]);
Console.ForegroundColor = ConsoleColor.Gray;
}
#if !PRERELEASE
else if (version.CurrentVersionStable > Program.Version)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"IW4MAdmin {_transLookup["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionStable.ToString()}]");
Console.WriteLine(_transLookup["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Program.Version.ToString()}]"));
Console.ForegroundColor = ConsoleColor.Gray;
}
#else
else if (version.CurrentVersionPrerelease > Program.Version)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"IW4MAdmin-Prerelease {_transLookup["MANAGER_VERSION_UPDATE"]} [v{version.CurrentVersionPrerelease.ToString()}-pr]");
Console.WriteLine(_transLookup["MANAGER_VERSION_CURRENT"].FormatExt($"[v{Program.Version.ToString()}-pr]"));
Console.ForegroundColor = ConsoleColor.Gray;
}
#endif
else
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(_transLookup["MANAGER_VERSION_SUCCESS"]);
Console.ForegroundColor = ConsoleColor.Gray;
}
}
public async Task RunUploadStatus(CancellationToken token)
{
// todo: clean up this logic
bool connected;
while (!token.IsCancellationRequested)
{
try
{
await UploadStatus();
}
catch (System.Net.Http.HttpRequestException e)
{
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
catch (AggregateException e)
{
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
var exceptions = e.InnerExceptions.Where(ex => ex.GetType() == typeof(ApiException));
foreach (var ex in exceptions)
{
if (((ApiException)ex).StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
connected = false;
}
}
}
catch (ApiException e)
{
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
if (e.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
connected = false;
}
}
catch (Exception e)
{
_logger.WriteWarning($"Could not send heartbeat - {e.Message}");
}
try
{
await Task.Delay(30000, token);
}
catch
{
break;
}
}
}
private async Task UploadStatus()
{
if (firstHeartBeat)
{
var token = await _apiInstance.Authenticate(new AuthenticationId
{
Id = _appConfig.Id
});
_apiInstance.AuthorizationToken = $"Bearer {token.AccessToken}";
}
var instance = new ApiInstance
{
Id = _appConfig.Id,
Uptime = (int)(DateTime.UtcNow - (_manager as ApplicationManager).StartTime).TotalSeconds,
Version = Program.Version,
Servers = _manager.GetServers().Select(s =>
new ApiServer()
{
ClientNum = s.ClientNum,
Game = s.GameName.ToString(),
Version = s.Version,
Gametype = s.Gametype,
Hostname = s.Hostname,
Map = s.CurrentMap.Name,
MaxClientNum = s.MaxClients,
Id = s.EndPoint,
Port = (short)s.Port,
IPAddress = s.IP
}).ToList()
};
Response<ResultMessage> response = null;
if (firstHeartBeat)
{
response = await _apiInstance.AddInstance(instance);
}
else
{
response = await _apiInstance.UpdateInstance(instance.Id, instance);
firstHeartBeat = false;
}
if (response.ResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.WriteWarning($"Response code from master is {response.ResponseMessage.StatusCode}, message is {response.StringContent}");
}
}
}
}