Added backend and console support for RCON

This commit is contained in:
Pat Hartl 2023-08-17 23:39:07 -05:00
parent da017acab4
commit 1281ebff15
4 changed files with 132 additions and 14 deletions

View file

@ -26,6 +26,7 @@
<PackageReference Include="Blazor-ApexCharts" Version="0.9.18-beta" />
<PackageReference Include="BlazorMonaco" Version="3.0.0" />
<PackageReference Include="ByteSize" Version="2.1.1" />
<PackageReference Include="CoreRCON" Version="5.0.5" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.4" />
<PackageReference Include="Hangfire.Core" Version="1.8.4" />
<PackageReference Include="Hangfire.InMemory" Version="0.5.1" />

View file

@ -1,14 +1,21 @@
@using Microsoft.AspNetCore.SignalR.Client
@using LANCommander.Data.Enums;
@using Microsoft.AspNetCore.SignalR.Client
@using NLog;
@using XtermBlazor
@inject ServerService ServerService
@inject ServerConsoleService ServerConsoleService
@inject ServerProcessService ServerProcessService
@inject NavigationManager NavigationManager
@inject IMessageService MessageService
@implements IAsyncDisposable
<Xterm @ref="Terminal" Options="TerminalOptions" AddonIds="TerminalAddons" />
@if (ServerConsole.Type == ServerConsoleType.RCON)
{
<Input @ref="CommandInput" @bind-Value="Command" BindOnInput OnPressEnter="OnPressEnter" @onkeyup="OnCommandKeyDown" />
}
@code {
[Parameter] public Guid ServerId { get; set; }
[Parameter] public Guid ServerConsoleId { get; set; }
@ -17,6 +24,11 @@
HubConnection? HubConnection;
ServerConsole ServerConsole;
Input<string> CommandInput;
string Command;
string[] History;
int HistoryPosition;
TerminalOptions TerminalOptions = new TerminalOptions
{
CursorBlink = true,
@ -31,18 +43,34 @@
protected override async Task OnInitializedAsync()
{
ServerConsole = await ServerConsoleService.Get(ServerConsoleId);
HubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver"))
.Build();
HubConnection.On<Guid, Guid, string>("Log", (serverId, logId, message) =>
History = new string[50];
HistoryPosition = 0;
if (ServerConsole.Type == ServerConsoleType.LogFile)
{
if (serverId == ServerId && logId == ServerConsoleId)
Terminal.WriteLine(message);
});
HubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver"))
.Build();
await HubConnection.StartAsync();
HubConnection.On<Guid, Guid, string>("Log", (serverId, logId, message) =>
{
if (serverId == ServerId && logId == ServerConsoleId)
Terminal.WriteLine(message);
});
await HubConnection.StartAsync();
}
else if (ServerConsole.Type == ServerConsoleType.RCON)
{
try {
ServerProcessService.RconConnect(ServerConsole);
}
catch (Exception ex)
{
await MessageService.Error($"Could not connect to RCON server: {ex.Message}");
}
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
@ -63,6 +91,52 @@
}
}
public async Task OnPressEnter() {
await ServerProcessService.RconSendCommandAsync(Command, ServerConsole);
Array.Copy(History, 0, History, 1, History.Length - 1);
History[0] = Command;
HistoryPosition = -1;
Command = "";
CommandInput.Value = "";
await Task.Yield();
await CommandInput.ValueChanged.InvokeAsync();
await CommandInput.Focus(FocusBehavior.FocusAndClear);
StateHasChanged();
}
public async Task OnCommandKeyDown(KeyboardEventArgs args)
{
switch (args.Key)
{
case "ArrowUp":
if (HistoryPosition < History.Length && History[HistoryPosition + 1] != null)
HistoryPosition++;
Command = History[HistoryPosition];
StateHasChanged();
break;
case "ArrowDown":
if (HistoryPosition >= 0)
{
HistoryPosition--;
if (HistoryPosition >= 0)
Command = History[HistoryPosition];
else
{
Command = "";
}
}
StateHasChanged();
break;
}
}
public async ValueTask DisposeAsync()
{
if (HubConnection is not null)

View file

@ -1,6 +1,9 @@
using LANCommander.Data;
using CoreRCON;
using LANCommander.Data;
using LANCommander.Data.Enums;
using LANCommander.Data.Models;
using System.Diagnostics;
using System.Net;
namespace LANCommander.Services
{
@ -12,6 +15,9 @@ namespace LANCommander.Services
{
var log = await Get(logId);
if (log.Type != ServerConsoleType.LogFile)
throw new Exception("Invalid console type");
var logPath = Path.Combine(log.Server.WorkingDirectory, log.Path);
return await File.ReadAllLinesAsync(logPath);

View file

@ -1,4 +1,5 @@
using LANCommander.Data.Enums;
using CoreRCON;
using LANCommander.Data.Enums;
using LANCommander.Data.Models;
using LANCommander.Hubs;
using Microsoft.AspNetCore.SignalR;
@ -6,6 +7,7 @@ using Microsoft.EntityFrameworkCore;
using NLog;
using NLog.Fluent;
using System.Diagnostics;
using System.Net;
namespace LANCommander.Services
{
@ -98,12 +100,25 @@ namespace LANCommander.Services
}
}
public class RconConnection
{
public RCON RCON { get; set; }
public LogReceiver LogReceiver { get; set; }
public RconConnection(string host, int port, string password)
{
RCON = new RCON(new IPEndPoint(IPAddress.Parse(host), port), password);
}
}
public class ServerProcessService : BaseService
{
public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>();
public Dictionary<Guid, int> Threads { get; set; } = new Dictionary<Guid, int>();
public Dictionary<Guid, LogFileMonitor> LogFileMonitors { get; set; } = new Dictionary<Guid, LogFileMonitor>();
private Dictionary<Guid, RCON> RconConnections { get; set; } = new Dictionary<Guid, RCON>();
public delegate void OnLogHandler(object sender, ServerLogEventArgs e);
public event OnLogHandler OnLog;
@ -177,14 +192,36 @@ namespace LANCommander.Services
private void StartMonitoringLog(ServerConsole log, Server server)
{
var logPath = Path.Combine(server.WorkingDirectory, log.Path);
if (!LogFileMonitors.ContainsKey(server.Id))
{
LogFileMonitors[server.Id] = new LogFileMonitor(server, log, HubContext);
}
}
public RCON RconConnect(ServerConsole console)
{
if (!RconConnections.ContainsKey(console.Id))
{
var rcon = new RCON(new IPEndPoint(IPAddress.Parse(console.Host), console.Port), console.Password);
RconConnections[console.Id] = rcon;
return rcon;
}
else
return RconConnections[console.Id];
}
public async Task<string> RconSendCommandAsync(string command, ServerConsole console)
{
if (RconConnections.ContainsKey(console.Id))
{
return await RconConnections[console.Id].SendCommandAsync(command);
}
else
return "";
}
public ServerProcessStatus GetStatus(Server server)
{
Process process = null;