Skip to content

Commit

Permalink
OK, so this may not work
Browse files Browse the repository at this point in the history
  • Loading branch information
frasermolyneux committed Sep 20, 2024
1 parent 2b97d07 commit d1ead02
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 21 deletions.
59 changes: 48 additions & 11 deletions servers-integration-api.openapi+json.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"openapi": "3.0.1",
"info": {
"title": "servers-integration-api",
"version": "1.0"
"title": "Servers API",
"version": "v1"
},
"paths": {
"/maps/{gameServerId}": {
"/maps/{gameServerId}/host/loaded": {
"get": {
"tags": [
"Maps"
Expand All @@ -23,12 +23,12 @@
],
"responses": {
"200": {
"description": "Success"
"description": "OK"
}
}
}
},
"/maps/{gameServerId}/{mapName}": {
"/maps/{gameServerId}/host/{mapName}": {
"post": {
"tags": [
"Maps"
Expand All @@ -54,7 +54,7 @@
],
"responses": {
"200": {
"description": "Success"
"description": "OK"
}
}
}
Expand All @@ -77,7 +77,7 @@
],
"responses": {
"200": {
"description": "Success"
"description": "OK"
}
}
}
Expand All @@ -100,19 +100,42 @@
],
"responses": {
"200": {
"description": "Success"
"description": "OK"
}
}
}
},
"/rcon/{gameServerId}/maps": {
"get": {
"tags": [
"Rcon"
],
"parameters": [
{
"name": "gameServerId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/": {
"get": {
"tags": [
"servers-webapi"
"servers-integration-webapi"
],
"responses": {
"200": {
"description": "Success",
"description": "OK",
"content": {
"text/plain": {
"schema": {
Expand All @@ -125,5 +148,19 @@
}
}
},
"components": {}
"components": {
"securitySchemes": {
"Bearer": {
"type": "apiKey",
"description": "",
"name": "Authorization",
"in": "header"
}
}
},
"security": [
{
"Bearer": []
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace XtremeIdiots.Portal.ServersApi.Abstractions.Interfaces
{
public interface IMapsApi
{
Task<ApiResponseDto<ServerMapsCollectionDto>> GetServerMaps(Guid gameServerId);
Task<ApiResponseDto> PushServerMap(Guid gameServerId, string mapName);
Task<ApiResponseDto<ServerMapsCollectionDto>> GetLoadedServerMapsFromHost(Guid gameServerId);
Task<ApiResponseDto> PushServerMapToHost(Guid gameServerId, string mapName);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using MxIO.ApiClient.Abstractions;

using XtremeIdiots.Portal.ServersApi.Abstractions.Models;
using XtremeIdiots.Portal.ServersApi.Abstractions.Models.Rcon;

namespace XtremeIdiots.Portal.ServersApi.Abstractions.Interfaces
{
public interface IRconApi
{
Task<ApiResponseDto<ServerRconStatusResponseDto>> GetServerStatus(Guid gameServerId);
Task<ApiResponseDto<RconMapCollectionDto>> GetServerMaps(Guid gameServerId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using MxIO.ApiClient.Abstractions;

namespace XtremeIdiots.Portal.ServersApi.Abstractions.Models.Rcon
{
public class RconMapCollectionDto : CollectionDto<RconMapDto>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace XtremeIdiots.Portal.ServersApi.Abstractions.Models.Rcon
{
public class RconMapDto
{
public RconMapDto(string gameType, string mapName)
{
GameType = gameType;
MapName = mapName;
}

public string GameType { get; set; }
public string MapName { get; set; }
}
}
33 changes: 33 additions & 0 deletions src/servers-integration-webapi/Clients/Quake3RconClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,28 @@ public Task Say(string message)
return Task.CompletedTask;
}

public Task<List<Quake3QueryMap>> GetMaps()
{
var maps = MapRotation();

var mapList = new List<Quake3QueryMap>();
var mapRegex = new Regex(@"gametype\s+([a-zA-Z0-9]+)\s+map\s+([a-zA-Z0-9_]+)");

var matches = mapRegex.Matches(maps);
foreach (Match match in matches)
{
if (match.Groups.Count != 3)
continue;

var gameType = match.Groups[1].ToString();
var mapName = match.Groups[2].ToString();

mapList.Add(new Quake3QueryMap { GameType = gameType, MapName = mapName });
}

return Task.FromResult(mapList);
}

public Task<string> Restart()
{
_logger.LogDebug("[{GameServerId}] Attempting to send restart the server", _serverId);
Expand Down Expand Up @@ -152,6 +174,17 @@ private string PlayerStatus()
return GetStringFromPackets(packets);
}

private string MapRotation()
{
var packets = Policy.Handle<Exception>()
.WaitAndRetry(GetRetryTimeSpans(), (result, timeSpan, retryCount, context) => { _logger.LogWarning("[{serverName}] Failed to execute rcon command - retry count: {count}", _serverId, retryCount); })
.Execute(() => GetCommandPackets("sv_mapRotation"));

_logger.LogDebug("[{GameServerId}] Total status packets retrieved from server: {Count}", _serverId, packets.Count);

return GetStringFromPackets(packets);
}

private string GetStringFromPackets(List<byte[]> packets)
{
var responseText = new StringBuilder();
Expand Down
5 changes: 5 additions & 0 deletions src/servers-integration-webapi/Clients/SourceRconClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public Task Say(string message)
return Task.CompletedTask;
}

public Task<List<Quake3QueryMap>> GetMaps()
{
throw new NotImplementedException();
}

public Task<string> Restart()
{
return Task.FromResult("Not Implemented");
Expand Down
16 changes: 8 additions & 8 deletions src/servers-integration-webapi/Controllers/MapsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ public MapsController(
}

[HttpGet]
[Route("maps/{gameServerId}")]
public async Task<IActionResult> GetServerMaps(Guid gameServerId)
[Route("maps/{gameServerId}/host/loaded")]
public async Task<IActionResult> GetLoadedServerMapsFromHost(Guid gameServerId)
{
var response = await ((IMapsApi)this).GetServerMaps(gameServerId);
var response = await ((IMapsApi)this).GetLoadedServerMapsFromHost(gameServerId);

return response.ToHttpResult();
}

async Task<ApiResponseDto<ServerMapsCollectionDto>> IMapsApi.GetServerMaps(Guid gameServerId)
async Task<ApiResponseDto<ServerMapsCollectionDto>> IMapsApi.GetLoadedServerMapsFromHost(Guid gameServerId)
{
var gameServerApiResponse = await repositoryApiClient.GameServers.GetGameServer(gameServerId);

Expand Down Expand Up @@ -101,15 +101,15 @@ async Task<ApiResponseDto<ServerMapsCollectionDto>> IMapsApi.GetServerMaps(Guid
}

[HttpPost]
[Route("maps/{gameServerId}/{mapName}")]
public async Task<IActionResult> PushServerMap(Guid gameServerId, string mapName)
[Route("maps/{gameServerId}/host/{mapName}")]
public async Task<IActionResult> PushServerMapToHost(Guid gameServerId, string mapName)
{
var response = await ((IMapsApi)this).PushServerMap(gameServerId, mapName);
var response = await ((IMapsApi)this).PushServerMapToHost(gameServerId, mapName);

return response.ToHttpResult();
}

async Task<ApiResponseDto> IMapsApi.PushServerMap(Guid gameServerId, string mapName)
async Task<ApiResponseDto> IMapsApi.PushServerMapToHost(Guid gameServerId, string mapName)
{
var gameServerApiResponse = await repositoryApiClient.GameServers.GetGameServer(gameServerId);

Expand Down
62 changes: 62 additions & 0 deletions src/servers-integration-webapi/Controllers/RconController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using XtremeIdiots.Portal.RepositoryApiClient;
using XtremeIdiots.Portal.ServersApi.Abstractions.Interfaces;
using XtremeIdiots.Portal.ServersApi.Abstractions.Models;
using XtremeIdiots.Portal.ServersApi.Abstractions.Models.Rcon;
using XtremeIdiots.Portal.ServersWebApi.Interfaces;

namespace XtremeIdiots.Portal.ServersWebApi.Controllers
Expand Down Expand Up @@ -99,5 +100,66 @@ async Task<ApiResponseDto<ServerRconStatusResponseDto>> IRconApi.GetServerStatus
telemetryClient.StopOperation(operation);
}
}

[HttpGet]
[Route("rcon/{gameServerId}/maps")]
public async Task<IActionResult> GetServerMaps(Guid gameServerId)
{
var response = await ((IRconApi)this).GetServerMaps(gameServerId);

return response.ToHttpResult();
}

async Task<ApiResponseDto<RconMapCollectionDto>> IRconApi.GetServerMaps(Guid gameServerId)
{
var gameServerApiResponse = await repositoryApiClient.GameServers.GetGameServer(gameServerId);

if (!gameServerApiResponse.IsSuccess || gameServerApiResponse.Result == null)
return new ApiResponseDto<RconMapCollectionDto>(HttpStatusCode.InternalServerError);

if (gameServerApiResponse.IsNotFound)
return new ApiResponseDto<RconMapCollectionDto>(HttpStatusCode.NotFound);

if (string.IsNullOrWhiteSpace(gameServerApiResponse.Result.RconPassword))
return new ApiResponseDto<RconMapCollectionDto>(HttpStatusCode.BadRequest, "The game server does not have an rcon password configured");

var queryClient = rconClientFactory.CreateInstance(gameServerApiResponse.Result.GameType, gameServerApiResponse.Result.GameServerId, gameServerApiResponse.Result.Hostname, gameServerApiResponse.Result.QueryPort, gameServerApiResponse.Result.RconPassword);

var operation = telemetryClient.StartOperation<DependencyTelemetry>("RconMapRotation");
operation.Telemetry.Type = $"{gameServerApiResponse.Result.GameType}Server";
operation.Telemetry.Target = $"{gameServerApiResponse.Result.Hostname}:{gameServerApiResponse.Result.QueryPort}";

try
{
var statusResult = await queryClient.GetMaps();

if (statusResult != null)
{
var result = new RconMapCollectionDto
{
TotalRecords = statusResult.Count,
FilteredRecords = statusResult.Count,
Entries = statusResult.Select(m => new RconMapDto(m.GameType, m.MapName)).ToList()
};

return new ApiResponseDto<RconMapCollectionDto>(HttpStatusCode.OK, result);
}
else
{
return new ApiResponseDto<RconMapCollectionDto>(HttpStatusCode.OK, new RconMapCollectionDto());
}
}
catch (Exception ex)
{
operation.Telemetry.Success = false;
operation.Telemetry.ResultCode = ex.Message;
telemetryClient.TrackException(ex);
throw;
}
finally
{
telemetryClient.StopOperation(operation);
}
}
}
}
2 changes: 2 additions & 0 deletions src/servers-integration-webapi/Interfaces/IRconClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using XtremeIdiots.Portal.RepositoryApi.Abstractions.Constants;
using XtremeIdiots.Portal.ServersWebApi.Models;

namespace XtremeIdiots.Portal.ServersWebApi.Interfaces
{
Expand All @@ -7,6 +8,7 @@ public interface IRconClient
void Configure(GameType gameType, Guid gameServerId, string hostname, int queryPort, string rconPassword);
List<IRconPlayer> GetPlayers();
Task Say(string message);
Task<List<Quake3QueryMap>> GetMaps();
Task<string> Restart();
Task<string> RestartMap();
Task<string> FastRestartMap();
Expand Down
8 changes: 8 additions & 0 deletions src/servers-integration-webapi/Models/Quake3QueryMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace XtremeIdiots.Portal.ServersWebApi.Models
{
public class Quake3QueryMap
{
public string GameType { get; set; }
public string MapName { get; set; }
}
}

0 comments on commit d1ead02

Please sign in to comment.