Implemented power state and task streaming over signalr

This commit is contained in:
2024-12-30 01:16:23 +01:00
parent 394d8b05ed
commit 0bd9074494
14 changed files with 436 additions and 4 deletions

View File

@@ -0,0 +1,159 @@
using Microsoft.AspNetCore.SignalR;
using MoonCore.Attributes;
using MoonlightServers.Daemon.Helpers;
using MoonlightServers.Daemon.Http.Hubs;
namespace MoonlightServers.Daemon.Services;
[Singleton]
public class ServerConsoleService
{
private readonly Dictionary<int, ServerConsoleMonitor> Monitors = new();
private readonly Dictionary<string, ServerConsoleConnection> Connections = new();
private readonly ILogger<ServerConsoleService> Logger;
private readonly AccessTokenHelper AccessTokenHelper;
private readonly ServerService ServerService;
private readonly IHubContext<ServerConsoleHub> HubContext;
public ServerConsoleService(
ILogger<ServerConsoleService> logger,
AccessTokenHelper accessTokenHelper,
ServerService serverService, IHubContext<ServerConsoleHub> hubContext)
{
Logger = logger;
AccessTokenHelper = accessTokenHelper;
ServerService = serverService;
HubContext = hubContext;
}
public Task OnClientDisconnected(HubCallerContext context)
{
ServerConsoleConnection? removedConnection;
lock (Connections)
{
removedConnection = Connections.GetValueOrDefault(context.ConnectionId);
if(removedConnection != null)
Connections.Remove(context.ConnectionId);
}
// Client never authenticated themselves, nothing to do
if(removedConnection == null)
return Task.CompletedTask;
Logger.LogDebug("Authenticated client {id} disconnected", context.ConnectionId);
// Count remaining clients requesting the same resource
int count;
lock (Connections)
{
count = Connections
.Values
.Count(x => x.ServerId == removedConnection.ServerId);
}
if(count > 0)
return Task.CompletedTask;
ServerConsoleMonitor? monitor;
lock (Monitors)
monitor = Monitors.GetValueOrDefault(removedConnection.ServerId);
if(monitor == null)
return Task.CompletedTask;
Logger.LogDebug("Destroying console monitor for server {id}", removedConnection.ServerId);
monitor.Destroy();
lock (Monitors)
Monitors.Remove(removedConnection.ServerId);
return Task.CompletedTask;
}
public async Task Authenticate(HubCallerContext context, string accessToken)
{
// Validate access token
if (!AccessTokenHelper.Process(accessToken, out var accessData))
{
Logger.LogDebug("Received invalid or expired access token. Closing connection");
context.Abort();
return;
}
// Validate access token data
if (!accessData.ContainsKey("type") || !accessData.ContainsKey("serverId"))
{
Logger.LogDebug("Received invalid access token: Required parameters are missing. Closing connection");
context.Abort();
return;
}
// Validate access token type
var type = accessData["type"].GetString()!;
if (type != "console")
{
Logger.LogDebug("Received invalid access token: Invalid type '{type}'. Closing connection", type);
context.Abort();
return;
}
var serverId = accessData["serverId"].GetInt32();
var server = ServerService.GetServer(serverId);
if (server == null)
{
Logger.LogDebug("Received invalid access token: No server found with the requested id. Closing connection");
context.Abort();
return;
}
ServerConsoleConnection? connection;
lock (Connections)
{
connection = Connections
.GetValueOrDefault(context.ConnectionId);
}
if (connection == null) // If no existing connection has been found, we create a new one
{
connection = new()
{
ServerId = server.Configuration.Id,
AuthenticatedUntil = DateTime.UtcNow.AddMinutes(10)
};
lock (Connections)
Connections.Add(context.ConnectionId, connection);
Logger.LogDebug("Connection {id} authenticated successfully", context.ConnectionId);
}
else
Logger.LogDebug("Connection {id} re-authenticated successfully", context.ConnectionId);
ServerConsoleMonitor? monitor;
lock (Monitors)
monitor = Monitors.GetValueOrDefault(server.Configuration.Id);
if (monitor == null)
{
Logger.LogDebug("Initializing console monitor for server {id}", server.Configuration.Id);
monitor = new ServerConsoleMonitor(server, HubContext.Clients);
monitor.Initialize();
lock (Monitors)
Monitors.Add(server.Configuration.Id, monitor);
}
await HubContext.Groups.AddToGroupAsync(context.ConnectionId, $"server-{server.Configuration.Id}");
}
}