Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add presence server #652

Merged
31 changes: 16 additions & 15 deletions Refresh.GameServer/Middlewares/PresenceAuthenticationMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,24 @@ public PresenceAuthenticationMiddleware(IntegrationConfig config)

public void HandleRequest(ListenerContext context, Lazy<IDatabaseContext> database, Action next)
{
if (context.Uri.AbsolutePath.StartsWith(PresenceEndpointAttribute.BaseRoute))
if (!context.Uri.AbsolutePath.StartsWith(PresenceEndpointAttribute.BaseRoute))
{
// Block presence requests if not enabled
if (!this._config.PresenceEnabled)
{
context.ResponseCode = NotImplemented;
return;
}

// Block presence requests with a bad auth token
if (context.RequestHeaders["Authorization"] != this._config.PresenceSharedSecret)
{
context.ResponseCode = Unauthorized;
return;
}
next();
return;
}

next();
// Block presence requests if not enabled
if (!this._config.PresenceEnabled)
{
context.ResponseCode = NotImplemented;
return;
}

// Block presence requests with a bad auth token
if (context.RequestHeaders["Authorization"] != this._config.PresenceSharedSecret)
{
context.ResponseCode = Unauthorized;
return;
}
}
}
4 changes: 2 additions & 2 deletions Refresh.GameServer/Services/PresenceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public bool PlayLevel(GameUser user, int levelId)
if (!this._config.PresenceEnabled || user.PresenceServerAuthToken == null)
return false;

this.Logger.LogInfo(RefreshContext.Presence, $"Sending live play now for level ID {levelId} to {user}");
this.Logger.LogInfo(RefreshContext.Presence, $"Sending presence request for level ID {levelId} to {user}");

HttpResponseMessage result = this._client.PostAsync($"/api/playLevel/{levelId}", new StringContent(user.PresenceServerAuthToken)).Result;

Expand All @@ -44,7 +44,7 @@ public bool PlayLevel(GameUser user, int levelId)
if(result.StatusCode == NotFound)
return false;

this.Logger.LogWarning(RefreshContext.Presence, "Unknown error {0} trying to communicate with presence server.", result.StatusCode);
this.Logger.LogWarning(RefreshContext.Presence, "Received status code {0} {1} while trying to communicate with the presence server.", (int)result.StatusCode, result.StatusCode);

return false;
}
Expand Down
34 changes: 18 additions & 16 deletions Refresh.PresenceServer/ApiClient/RefreshPresenceApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,47 @@ public RefreshPresenceApiClient(PresenceServerConfig config, Logger logger)
this._config = config;
this._logger = logger;

UriBuilder baseAddress = new(this._config.GameServerUrl)
{
Path = EndpointRoutes.PresenceBaseRoute,
};

this._client = new HttpClient();
this._client.BaseAddress = new Uri(this._config.GameServerUrl);
this._client.BaseAddress = baseAddress.Uri;
this._client.DefaultRequestHeaders.Authorization = AuthenticationHeaderValue.Parse(this._config.SharedSecret);
}

public async Task TestRefreshServer()
{
try
{
HttpResponseMessage result = await this._client.PostAsync(EndpointRoutes.PresenceBaseRoute + "test", new ByteArrayContent([]));
HttpResponseMessage result = await this._client.PostAsync("test", new ByteArrayContent([]));

switch (result.StatusCode)
{
case NotFound:
throw new Exception("Unable to access presence endpoint! Are you sure Refresh is up to date?");
throw new Exception("The presence endpoint wasn't found. This likely means Refresh.GameServer is out of date.");
case NotImplemented:
throw new Exception("Presence integration is not enabled in Refresh!");
throw new Exception("Presence integration is disabled in Refresh.GameServer");
case Unauthorized:
throw new Exception("Presence shared secret does not match!");
throw new Exception("Our shared secret does not match the server's shared secret. Please check the config files in both Refresh.PresenceServer and Refresh.GameServer.");
default:
throw new Exception($"Unexpected status code {result.StatusCode} when accessing presence API!");
throw new Exception($"Unexpected status code {(int)result.StatusCode} {result.StatusCode} when accessing presence API");
case OK:
return;
}
}
catch(Exception)
catch(Exception e)
{
this._logger.LogWarning(PresenceCategory.Startup, "Unable to access Refresh game server! Are you sure it is configured correctly?");
this._logger.LogError(PresenceCategory.Startup, "Unable to access Refresh gameserver: {0}", e);
}
}

public async Task<bool> InformConnection(string token)
{
try
{
HttpResponseMessage result = await this._client.PostAsync(EndpointRoutes.PresenceBaseRoute + "informConnection",
new StringContent(token));
HttpResponseMessage result = await this._client.PostAsync("informConnection", new StringContent(token));

switch (result.StatusCode)
{
Expand All @@ -63,12 +67,12 @@ public async Task<bool> InformConnection(string token)
this._logger.LogWarning(PresenceCategory.Connections, $"Unknown user ({token}) tried to connect to presence server, disconnecting.");
return false;
default:
throw new Exception($"Unexpected status code {result.StatusCode} when accessing presence API!");
throw new Exception($"Unexpected status code {(int)result.StatusCode} {result.StatusCode} when accessing presence API");
}
}
catch (Exception)
{
this._logger.LogWarning(PresenceCategory.Connections, "Unable to connect to Refresh to inform about a connection.");
this._logger.LogError(PresenceCategory.Connections, "Unable to connect to Refresh to inform about a connection.");
return false;
}
}
Expand All @@ -77,13 +81,11 @@ public async Task InformDisconnection(string token)
{
try
{
HttpResponseMessage result = await this._client.PostAsync(EndpointRoutes.PresenceBaseRoute + "informDisconnection",
new StringContent(token));
HttpResponseMessage result = await this._client.PostAsync("informDisconnection", new StringContent(token));

switch (result.StatusCode)
{
case OK:
// this can happen if a `goodbye` request comes to the gameserver before our request makes it to Refresh, or maybe they get banned. Something of the sort.
case NotFound:
return;
default:
Expand All @@ -92,7 +94,7 @@ public async Task InformDisconnection(string token)
}
catch (Exception)
{
this._logger.LogWarning(PresenceCategory.Connections, "Unable to connect to Refresh to inform about a disconnection.");
this._logger.LogError(PresenceCategory.Connections, "Unable to connect to Refresh to inform about a disconnection.");
}
}

Expand Down

This file was deleted.

8 changes: 0 additions & 8 deletions Refresh.PresenceServer/ApiServer/Authentication/Token.cs

This file was deleted.

27 changes: 27 additions & 0 deletions Refresh.PresenceServer/ApiServer/Middlewares/SecretMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Bunkum.Core.Database;
using Bunkum.Core.Endpoints.Middlewares;
using Bunkum.Listener.Request;
using Refresh.PresenceServer.Server.Config;

namespace Refresh.PresenceServer.ApiServer.Middlewares;

public class SecretMiddleware : IMiddleware
Beyley marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly PresenceServerConfig _config;

public SecretMiddleware(PresenceServerConfig config)
{
this._config = config;
}

public void HandleRequest(ListenerContext context, Lazy<IDatabaseContext> database, Action next)
{
if (context.RequestHeaders["Authorization"] != this._config.SharedSecret)
{
context.ResponseCode = Unauthorized;
return;
}

next();
}
}
3 changes: 3 additions & 0 deletions Refresh.PresenceServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using NotEnoughLogs.Behaviour;
using Refresh.PresenceServer.ApiClient;
using Refresh.PresenceServer.ApiServer.Endpoints;
using Refresh.PresenceServer.ApiServer.Middlewares;
using Refresh.PresenceServer.Server.Config;

namespace Refresh.PresenceServer;
Expand Down Expand Up @@ -35,6 +36,8 @@ public static async Task Main()

server.DiscoverEndpointsFromAssembly(typeof(ApiEndpoints).Assembly);
server.AddConfig(config);

server.AddMiddleware(new SecretMiddleware(config));
},
};

Expand Down
4 changes: 2 additions & 2 deletions Refresh.PresenceServer/Server/PresenceServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public async Task Block()
}
catch(Exception ex)
{
this._logger.LogWarning(PresenceCategory.Connections, "Failed to accept client. Reason {0}", ex);
this._logger.LogError(PresenceCategory.Connections, "Failed to accept client. Reason {0}", ex);
}
}

Expand Down Expand Up @@ -160,7 +160,7 @@ public async Task Block()
catch(Exception ex)
{
this._logger.LogWarning(PresenceCategory.Connections,
"Failed to send packet data to {0}, reason {1}", client.IpAddress, ex);
"Failed to send packet data to {0}: {1}", client.IpAddress, ex);

// If we get any error, just disconnect the client
client.TcpClient.Close();
Expand Down
Loading