support hostnames for server config
This commit is contained in:
parent
5ef00d6dae
commit
e2ea5c6ce0
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System.Text;
|
||||
using Integrations.Cod;
|
||||
@ -26,21 +27,15 @@ namespace IW4MAdmin.Application.Factories
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// creates a new rcon connection instance
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">ip address of the server</param>
|
||||
/// <param name="port">port of the server</param>
|
||||
/// <param name="password">rcon password of the server</param>
|
||||
/// <returns></returns>
|
||||
public IRConConnection CreateConnection(string ipAddress, int port, string password, string rconEngine)
|
||||
/// <inheritdoc/>
|
||||
public IRConConnection CreateConnection(IPEndPoint ipEndpoint, string password, string rconEngine)
|
||||
{
|
||||
return rconEngine switch
|
||||
{
|
||||
"COD" => new CodRConConnection(ipAddress, port, password,
|
||||
"COD" => new CodRConConnection(ipEndpoint, password,
|
||||
_serviceProvider.GetRequiredService<ILogger<CodRConConnection>>(), GameEncoding),
|
||||
"Source" => new SourceRConConnection(_serviceProvider.GetRequiredService<ILogger<SourceRConConnection>>(),
|
||||
_serviceProvider.GetRequiredService<IRConClientFactory>(), ipAddress, port, password),
|
||||
_serviceProvider.GetRequiredService<IRConClientFactory>(), ipEndpoint, password),
|
||||
_ => throw new ArgumentException($"No supported RCon engine available for '{rconEngine}'")
|
||||
};
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
@ -1059,6 +1060,16 @@ namespace IW4MAdmin
|
||||
|
||||
public async Task Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
ResolvedIpEndPoint = new IPEndPoint((await Dns.GetHostAddressesAsync(IP)).First(), Port);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServerLogger.LogWarning(ex, "Could not resolve hostname or IP for RCon connection {IP}:{Port}", IP, Port);
|
||||
ResolvedIpEndPoint = new IPEndPoint(IPAddress.Parse(IP), Port);
|
||||
}
|
||||
|
||||
RconParser = Manager.AdditionalRConParsers
|
||||
.FirstOrDefault(_parser => _parser.Version == ServerConfig.RConParserVersion);
|
||||
|
||||
@ -1068,7 +1079,7 @@ namespace IW4MAdmin
|
||||
RconParser ??= Manager.AdditionalRConParsers[0];
|
||||
EventParser ??= Manager.AdditionalEventParsers[0];
|
||||
|
||||
RemoteConnection = RConConnectionFactory.CreateConnection(IP, Port, Password, RconParser.RConEngine);
|
||||
RemoteConnection = RConConnectionFactory.CreateConnection(ResolvedIpEndPoint, Password, RconParser.RConEngine);
|
||||
RemoteConnection.SetConfiguration(RconParser);
|
||||
|
||||
var version = await this.GetMappedDvarValueOrDefaultAsync<string>("version");
|
||||
|
@ -32,12 +32,12 @@ namespace Integrations.Cod
|
||||
private readonly ILogger _log;
|
||||
private readonly Encoding _gameEncoding;
|
||||
|
||||
public CodRConConnection(string ipAddress, int port, string password, ILogger<CodRConConnection> log, Encoding gameEncoding)
|
||||
public CodRConConnection(IPEndPoint ipEndpoint, string password, ILogger<CodRConConnection> log, Encoding gameEncoding)
|
||||
{
|
||||
Endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
|
||||
_gameEncoding = gameEncoding;
|
||||
RConPassword = password;
|
||||
_gameEncoding = gameEncoding;
|
||||
_log = log;
|
||||
Endpoint = ipEndpoint;
|
||||
}
|
||||
|
||||
public void SetConfiguration(IRConParser parser)
|
||||
|
@ -1,9 +1,10 @@
|
||||
using RconSharp;
|
||||
using System.Net;
|
||||
using RconSharp;
|
||||
|
||||
namespace Integrations.Source.Interfaces
|
||||
{
|
||||
public interface IRConClientFactory
|
||||
{
|
||||
RconClient CreateClient(string hostname, int port);
|
||||
RconClient CreateClient(IPEndPoint ipEndPoint);
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
using Integrations.Source.Interfaces;
|
||||
using System.Net;
|
||||
using Integrations.Source.Interfaces;
|
||||
using RconSharp;
|
||||
|
||||
namespace Integrations.Source
|
||||
{
|
||||
public class RConClientFactory : IRConClientFactory
|
||||
{
|
||||
public RconClient CreateClient(string hostname, int port)
|
||||
public RconClient CreateClient(IPEndPoint ipEndPoint)
|
||||
{
|
||||
return RconClient.Create(hostname, port);
|
||||
return RconClient.Create(ipEndPoint.Address.ToString(), ipEndPoint.Port);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -20,8 +21,7 @@ namespace Integrations.Source
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _password;
|
||||
private readonly string _hostname;
|
||||
private readonly int _port;
|
||||
private readonly IPEndPoint _ipEndPoint;
|
||||
private readonly IRConClientFactory _rconClientFactory;
|
||||
private readonly SemaphoreSlim _activeQuery;
|
||||
|
||||
@ -34,13 +34,12 @@ namespace Integrations.Source
|
||||
private bool _needNewSocket = true;
|
||||
|
||||
public SourceRConConnection(ILogger<SourceRConConnection> logger, IRConClientFactory rconClientFactory,
|
||||
string hostname, int port, string password)
|
||||
IPEndPoint ipEndPoint, string password)
|
||||
{
|
||||
_rconClientFactory = rconClientFactory;
|
||||
_password = password;
|
||||
_hostname = hostname;
|
||||
_port = port;
|
||||
_logger = logger;
|
||||
_ipEndPoint = ipEndPoint;
|
||||
_activeQuery = new SemaphoreSlim(1, 1);
|
||||
}
|
||||
|
||||
@ -67,12 +66,12 @@ namespace Integrations.Source
|
||||
// ignored
|
||||
}
|
||||
|
||||
_rconClient = _rconClientFactory.CreateClient(_hostname, _port);
|
||||
_rconClient = _rconClientFactory.CreateClient(_ipEndPoint);
|
||||
_authenticated = false;
|
||||
_needNewSocket = false;
|
||||
}
|
||||
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogDebug("Connecting to RCon socket");
|
||||
}
|
||||
@ -90,7 +89,7 @@ namespace Integrations.Source
|
||||
parameters = parameters.ReplaceUnfriendlyCharacters();
|
||||
parameters = parameters.StripColors();
|
||||
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogDebug("Sending query {Type} with parameters \"{Parameters}\"", type, parameters);
|
||||
}
|
||||
@ -98,7 +97,7 @@ namespace Integrations.Source
|
||||
var response = await _rconClient.ExecuteCommandAsync(parameters, multiPacket)
|
||||
.WithTimeout(ConnectionTimeout);
|
||||
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", $"{_ipEndPoint}"))
|
||||
{
|
||||
_logger.LogDebug("Received RCon response {Response}", response);
|
||||
}
|
||||
@ -115,7 +114,7 @@ namespace Integrations.Source
|
||||
|
||||
catch (SocketException ex)
|
||||
{
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogError(ex, "Socket exception encountered while attempting to communicate with server");
|
||||
}
|
||||
@ -128,7 +127,7 @@ namespace Integrations.Source
|
||||
catch (Exception ex) when (ex.GetType() != typeof(NetworkException) &&
|
||||
ex.GetType() != typeof(ServerException))
|
||||
{
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogError(ex, "Could not execute RCon query {Parameters}", parameters);
|
||||
}
|
||||
@ -160,7 +159,7 @@ namespace Integrations.Source
|
||||
{
|
||||
if (!_authenticated)
|
||||
{
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogDebug("Authenticating to RCon socket");
|
||||
}
|
||||
@ -170,7 +169,7 @@ namespace Integrations.Source
|
||||
|
||||
if (!_authenticated)
|
||||
{
|
||||
using (LogContext.PushProperty("Server", $"{_hostname}:{_port}"))
|
||||
using (LogContext.PushProperty("Server", _ipEndPoint.ToString()))
|
||||
{
|
||||
_logger.LogError("Could not login to server");
|
||||
}
|
||||
|
@ -87,12 +87,8 @@ namespace SharedLibraryCore.Configuration
|
||||
|
||||
while (string.IsNullOrEmpty(IPAddress))
|
||||
{
|
||||
string input = Utilities.PromptString(loc["SETUP_SERVER_IP"]);
|
||||
|
||||
if (System.Net.IPAddress.TryParse(input, out System.Net.IPAddress ip))
|
||||
{
|
||||
IPAddress = input;
|
||||
}
|
||||
var input = Utilities.PromptString(loc["SETUP_SERVER_IP"]);
|
||||
IPAddress = input;
|
||||
}
|
||||
|
||||
Port = Utilities.PromptInt(loc["SETUP_SERVER_PORT"], null, 1, ushort.MaxValue);
|
||||
|
@ -10,10 +10,6 @@ namespace SharedLibraryCore.Configuration.Validation
|
||||
{
|
||||
public ServerConfigurationValidator()
|
||||
{
|
||||
RuleFor(_server => _server.IPAddress)
|
||||
.NotEmpty()
|
||||
.Must(_address => IPAddress.TryParse(_address, out _));
|
||||
|
||||
RuleFor(_server => _server.Port)
|
||||
.InclusiveBetween(1, ushort.MaxValue);
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
using System.Net;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// defines the capabilities of an RCon connection factory
|
||||
@ -8,11 +10,10 @@
|
||||
/// <summary>
|
||||
/// creates an rcon connection instance
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">ip address of the server</param>
|
||||
/// <param name="port">port of the server</param>
|
||||
/// <param name="ipEndpoint">ip address and port of the server</param>
|
||||
/// <param name="password"> password of the server</param>
|
||||
/// <param name="rconEngine">engine to create the rcon connection to</param>
|
||||
/// <returns>instance of rcon connection</returns>
|
||||
IRConConnection CreateConnection(string ipAddress, int port, string password, string rconEngine);
|
||||
IRConConnection CreateConnection(IPEndPoint ipEndpoint, string password, string rconEngine);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -58,7 +59,9 @@ namespace SharedLibraryCore
|
||||
InitializeAutoMessages();
|
||||
}
|
||||
|
||||
public long EndPoint => Convert.ToInt64($"{IP.Replace(".", "")}{Port}");
|
||||
public long EndPoint => IPAddress.TryParse(IP, out _)
|
||||
? Convert.ToInt64($"{IP.Replace(".", "")}{Port}")
|
||||
: $"{IP.Replace(".", "")}{Port}".GetStableHashCode();
|
||||
|
||||
/// <summary>
|
||||
/// Returns list of all current players
|
||||
@ -303,7 +306,7 @@ namespace SharedLibraryCore
|
||||
{
|
||||
get
|
||||
{
|
||||
return Clients.Where(p => p != null/* && !p.IsBot*/).Count();
|
||||
return Clients.Count(p => p != null && !p.IsBot);
|
||||
}
|
||||
}
|
||||
public int MaxClients { get; protected set; }
|
||||
@ -320,7 +323,11 @@ namespace SharedLibraryCore
|
||||
public SemaphoreSlim EventProcessing { get; private set; }
|
||||
|
||||
// Internal
|
||||
/// <summary>
|
||||
/// this is actually the hostname now
|
||||
/// </summary>
|
||||
public string IP { get; protected set; }
|
||||
public IPEndPoint ResolvedIpEndPoint { get; protected set; }
|
||||
public string Version { get; protected set; }
|
||||
public bool IsInitialized { get; set; }
|
||||
protected readonly ILogger ServerLogger;
|
||||
|
@ -12,7 +12,7 @@ namespace WebfrontCore.ViewComponents
|
||||
{
|
||||
public IViewComponentResult Invoke(Game? game)
|
||||
{
|
||||
var servers = Program.Manager.GetServers().Where(_server => !game.HasValue ? true : _server.GameName == game);
|
||||
var servers = Program.Manager.GetServers().Where(_server => !game.HasValue || _server.GameName == game);
|
||||
|
||||
var serverInfo = servers.Select(s => new ServerInfo()
|
||||
{
|
||||
@ -36,8 +36,8 @@ namespace WebfrontCore.ViewComponents
|
||||
}).ToList(),
|
||||
ChatHistory = s.ChatHistory.ToList(),
|
||||
Online = !s.Throttled,
|
||||
IPAddress = $"{(IPAddress.Parse(s.IP).IsInternal() ? Program.Manager.ExternalIPAddress : s.IP)}:{s.Port}",
|
||||
ConnectProtocolUrl = s.EventParser.URLProtocolFormat.FormatExt(IPAddress.Parse(s.IP).IsInternal() ? Program.Manager.ExternalIPAddress : s.IP, s.Port)
|
||||
IPAddress = $"{(s.ResolvedIpEndPoint.Address.IsInternal() ? Program.Manager.ExternalIPAddress : s.IP)}:{s.Port}",
|
||||
ConnectProtocolUrl = s.EventParser.URLProtocolFormat.FormatExt(s.ResolvedIpEndPoint.Address.IsInternal() ? Program.Manager.ExternalIPAddress : s.IP, s.Port)
|
||||
}).ToList();
|
||||
return View("_List", serverInfo);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@
|
||||
: null;
|
||||
|
||||
var headShots = allPerServer.Any()
|
||||
? allPerServer.Where(hit => hit.MeansOfDeath?.Name == headshotKey || hit.MeansOfDeath?.Name == headshotKey2).Sum(hit => hit.HitCount)
|
||||
? allPerServer.Where(hit => hit.MeansOfDeath?.Name == headshotKey || hit.HitLocation?.Name == headshotKey2).Sum(hit => hit.HitCount)
|
||||
: (int?) null; // want to default to -- in ui instead of 0
|
||||
|
||||
var meleeKills = allPerServer.Any()
|
||||
|
Loading…
Reference in New Issue
Block a user