mirror of
https://github.com/ncblakely/GiantsTools
synced 2024-11-23 06:35:37 +01:00
Fix various issues with multiple servers from a single IP.
This commit is contained in:
parent
eb33ce0bb7
commit
e6747b0d3a
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
public class ServerInfo : DataContract.V1.ServerInfo, IIdentifiable
|
public class ServerInfo : DataContract.V1.ServerInfo, IIdentifiable
|
||||||
{
|
{
|
||||||
public string id => this.HostIpAddress;
|
public string id => $"{this.HostIpAddress}-{this.GameName}-{this.Port}";
|
||||||
|
|
||||||
public string DocumentType => nameof(ServerInfo);
|
public string DocumentType => nameof(ServerInfo);
|
||||||
|
|
||||||
@ -17,6 +17,8 @@
|
|||||||
return obj is ServerInfo info &&
|
return obj is ServerInfo info &&
|
||||||
base.Equals(obj) &&
|
base.Equals(obj) &&
|
||||||
this.HostIpAddress == info.HostIpAddress &&
|
this.HostIpAddress == info.HostIpAddress &&
|
||||||
|
this.Port == info.Port &&
|
||||||
|
this.GameName == info.GameName &&
|
||||||
this.DocumentType == info.DocumentType;
|
this.DocumentType == info.DocumentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
|
|
||||||
public class ServerRegistryService : IServerRegistryService
|
public class ServerRegistryService : IServerRegistryService
|
||||||
{
|
{
|
||||||
private static readonly string[] SupportedGameNames = new[] { "Giants", "Giants Beta" };
|
private static readonly string[] SupportedGameNames = new[] { "Giants", "Giants Beta", "Giants Beta Dedicated", "Giants Dedicated" };
|
||||||
private readonly ILogger<ServerRegistryService> logger;
|
private readonly ILogger<ServerRegistryService> logger;
|
||||||
private readonly IServerRegistryStore registryStore;
|
private readonly IServerRegistryStore registryStore;
|
||||||
private readonly IConfiguration configuration;
|
private readonly IConfiguration configuration;
|
||||||
private readonly int maxServerCount;
|
private readonly int maxServerCount;
|
||||||
private readonly int maxServersPerIpGame;
|
private readonly int maxServersPerIp;
|
||||||
|
|
||||||
public ServerRegistryService(
|
public ServerRegistryService(
|
||||||
ILogger<ServerRegistryService> logger,
|
ILogger<ServerRegistryService> logger,
|
||||||
@ -26,7 +26,7 @@
|
|||||||
this.registryStore = registryStore;
|
this.registryStore = registryStore;
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.maxServerCount = Convert.ToInt32(this.configuration["MaxServerCount"]);
|
this.maxServerCount = Convert.ToInt32(this.configuration["MaxServerCount"]);
|
||||||
this.maxServersPerIpGame = Convert.ToInt32(this.configuration["MaxServersPerIpGame"]);
|
this.maxServersPerIp = Convert.ToInt32(this.configuration["MaxServersPerIp"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddServer(
|
public async Task AddServer(
|
||||||
@ -35,13 +35,15 @@
|
|||||||
ArgumentUtility.CheckForNull(serverInfo, nameof(serverInfo));
|
ArgumentUtility.CheckForNull(serverInfo, nameof(serverInfo));
|
||||||
ArgumentUtility.CheckStringForNullOrEmpty(serverInfo.HostIpAddress, nameof(serverInfo.HostIpAddress));
|
ArgumentUtility.CheckStringForNullOrEmpty(serverInfo.HostIpAddress, nameof(serverInfo.HostIpAddress));
|
||||||
|
|
||||||
|
string gameName = serverInfo.GameName.Replace("Dedicated", string.Empty).Trim();
|
||||||
|
serverInfo.GameName = gameName;
|
||||||
if (!SupportedGameNames.Contains(serverInfo.GameName, StringComparer.OrdinalIgnoreCase))
|
if (!SupportedGameNames.Contains(serverInfo.GameName, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Unsupported game name {serverInfo.GameName}", nameof(serverInfo));
|
throw new ArgumentException($"Unsupported game name {serverInfo.GameName}", nameof(serverInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingServers = await this.registryStore.GetServerInfos(whereExpression: x => x.HostIpAddress == serverInfo.HostIpAddress);
|
var existingServers = await this.registryStore.GetServerInfos(whereExpression: x => x.HostIpAddress == serverInfo.HostIpAddress);
|
||||||
if (existingServers.GroupBy(g => g.GameName).Any(g => g.Count() > this.maxServersPerIpGame))
|
if (existingServers.GroupBy(g => new { g.HostIpAddress }).Any(g => g.Count() > this.maxServersPerIp))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Exceeded maximum servers per IP.");
|
throw new InvalidOperationException("Exceeded maximum servers per IP.");
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,8 @@
|
|||||||
|
|
||||||
if (allServerInfo.ContainsKey(serverInfo.HostIpAddress))
|
if (allServerInfo.ContainsKey(serverInfo.HostIpAddress))
|
||||||
{
|
{
|
||||||
ServerInfo existingServerInfo = FindExistingServerForHostIp(allServerInfo[serverInfo.HostIpAddress], serverInfo);
|
IList<ServerInfo> serverInfoForHostIp = allServerInfo[serverInfo.HostIpAddress];
|
||||||
|
ServerInfo existingServerInfo = FindExistingServerForHostIp(serverInfoForHostIp, serverInfo);
|
||||||
|
|
||||||
// DDOS protection: skip write to Cosmos if parameters have not changed,
|
// DDOS protection: skip write to Cosmos if parameters have not changed,
|
||||||
// or it's not been long enough.
|
// or it's not been long enough.
|
||||||
@ -108,24 +109,35 @@
|
|||||||
this.logger.LogInformation("State for {IPAddress} is unchanged. Skipping write to store.", serverInfo.HostIpAddress);
|
this.logger.LogInformation("State for {IPAddress} is unchanged. Skipping write to store.", serverInfo.HostIpAddress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
this.logger.LogInformation("State for {IPAddress} has changed. Committing update to store.", serverInfo.HostIpAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.logger.LogInformation("State for {IPAddress} has changed. Committing update to store.", serverInfo.HostIpAddress);
|
||||||
await this.client.UpsertItem(
|
await this.client.UpsertItem(
|
||||||
item: serverInfo,
|
item: serverInfo,
|
||||||
partitionKey: new PartitionKey(serverInfo.DocumentType));
|
partitionKey: new PartitionKey(serverInfo.DocumentType));
|
||||||
|
|
||||||
this.logger.LogInformation("Updating cache for request from {IPAddress}.", serverInfo.HostIpAddress);
|
// Update cache
|
||||||
|
if (existingServerInfo != null)
|
||||||
if (allServerInfo.ContainsKey(serverInfo.HostIpAddress))
|
|
||||||
{
|
{
|
||||||
allServerInfo[serverInfo.HostIpAddress].Add(serverInfo);
|
var newServerInfo = serverInfoForHostIp.Where(s => !s.Equals(serverInfo)).ToList();
|
||||||
|
newServerInfo.Add(serverInfo);
|
||||||
|
allServerInfo[serverInfo.HostIpAddress] = newServerInfo;
|
||||||
|
|
||||||
|
this.logger.LogInformation("Updating cache for request from {IPAddress} (replaced existing server).", serverInfo.HostIpAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
allServerInfo[serverInfo.HostIpAddress].Add(serverInfo);
|
||||||
|
this.logger.LogInformation("Updating cache for request from {IPAddress} (added new server).", serverInfo.HostIpAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update cache
|
||||||
|
await this.client.UpsertItem(
|
||||||
|
item: serverInfo,
|
||||||
|
partitionKey: new PartitionKey(serverInfo.DocumentType));
|
||||||
|
|
||||||
|
this.logger.LogInformation("Updating cache for request from {IPAddress} (no existing servers).", serverInfo.HostIpAddress);
|
||||||
allServerInfo.TryAdd(serverInfo.HostIpAddress, new List<ServerInfo>() { serverInfo });
|
allServerInfo.TryAdd(serverInfo.HostIpAddress, new List<ServerInfo>() { serverInfo });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,15 +211,7 @@
|
|||||||
|
|
||||||
private static ServerInfo FindExistingServerForHostIp(IList<ServerInfo> serverInfoForHostIp, ServerInfo candidateServerInfo)
|
private static ServerInfo FindExistingServerForHostIp(IList<ServerInfo> serverInfoForHostIp, ServerInfo candidateServerInfo)
|
||||||
{
|
{
|
||||||
foreach (var existingServerInfo in serverInfoForHostIp)
|
return serverInfoForHostIp.FirstOrDefault(s => s.Equals(candidateServerInfo));
|
||||||
{
|
|
||||||
if (existingServerInfo.Equals(candidateServerInfo))
|
|
||||||
{
|
|
||||||
return existingServerInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
"ServerTimeoutPeriodInMinutes": "7",
|
"ServerTimeoutPeriodInMinutes": "7",
|
||||||
"ServerCleanupIntervalInMinutes": "1",
|
"ServerCleanupIntervalInMinutes": "1",
|
||||||
"MaxServerCount": 1000,
|
"MaxServerCount": 1000,
|
||||||
"MaxServersPerIpGame": 5,
|
"MaxServersPerIp": 5,
|
||||||
"DiscordUri": "https://discord.gg/Avj4azU",
|
"DiscordUri": "https://discord.gg/Avj4azU",
|
||||||
"BlobConnectionString": "",
|
"BlobConnectionString": "",
|
||||||
"CrashBlobContainerName": "crashes"
|
"CrashBlobContainerName": "crashes"
|
||||||
|
Loading…
Reference in New Issue
Block a user