1
0
mirror of https://github.com/chylex/Minecraft-Phantom-Panel.git synced 2024-11-25 16:42:54 +01:00

Compare commits

..

5 Commits

179 changed files with 679 additions and 494 deletions

View File

@ -1,9 +1,9 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Server + Agent x3" type="CompoundRunConfigurationType"> <configuration default="false" name="Controller + Agent x3" type="CompoundRunConfigurationType">
<toRun name="Agent 1" type="DotNetProject" /> <toRun name="Agent 1" type="DotNetProject" />
<toRun name="Agent 2" type="DotNetProject" /> <toRun name="Agent 2" type="DotNetProject" />
<toRun name="Agent 3" type="DotNetProject" /> <toRun name="Agent 3" type="DotNetProject" />
<toRun name="Server" type="DotNetProject" /> <toRun name="Controller" type="DotNetProject" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>

View File

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Controller + Agent" type="CompoundRunConfigurationType">
<toRun name="Agent 1" type="DotNetProject" />
<toRun name="Controller" type="DotNetProject" />
<method v="2" />
</configuration>
</component>

View File

@ -1,7 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Server + Agent" type="CompoundRunConfigurationType">
<toRun name="Agent 1" type="DotNetProject" />
<toRun name="Server" type="DotNetProject" />
<method v="2" />
</configuration>
</component>

View File

@ -1,4 +1,4 @@
namespace Phantom.Agent.Minecraft.Command; namespace Phantom.Agent.Minecraft.Command;
public static class MinecraftCommand { public static class MinecraftCommand {
public const string SaveOn = "save-on"; public const string SaveOn = "save-on";

View File

@ -1,7 +1,7 @@
using Phantom.Utils.Collections; using Phantom.Utils.Collections;
using Phantom.Utils.Processes; using Phantom.Utils.Processes;
namespace Phantom.Agent.Minecraft.Instance; namespace Phantom.Agent.Minecraft.Instance;
public sealed class InstanceProcess : IDisposable { public sealed class InstanceProcess : IDisposable {
public InstanceProperties InstanceProperties { get; } public InstanceProperties InstanceProperties { get; }

View File

@ -1,6 +1,6 @@
using Phantom.Common.Data.Java; using Phantom.Common.Data.Java;
namespace Phantom.Agent.Minecraft.Java; namespace Phantom.Agent.Minecraft.Java;
public sealed class JavaRuntimeExecutable { public sealed class JavaRuntimeExecutable {
internal string ExecutablePath { get; } internal string ExecutablePath { get; }

View File

@ -1,6 +1,6 @@
using Phantom.Agent.Minecraft.Java; using Phantom.Agent.Minecraft.Java;
using Phantom.Agent.Minecraft.Server; using Phantom.Agent.Minecraft.Server;
namespace Phantom.Agent.Minecraft.Launcher; namespace Phantom.Agent.Minecraft.Launcher;
public sealed record LaunchServices(MinecraftServerExecutables ServerExecutables, JavaRuntimeRepository JavaRuntimeRepository); public sealed record LaunchServices(MinecraftServerExecutables ServerExecutables, JavaRuntimeRepository JavaRuntimeRepository);

View File

@ -3,7 +3,7 @@ using Phantom.Agent.Minecraft.Instance;
using Phantom.Utils.IO; using Phantom.Utils.IO;
using Serilog; using Serilog;
namespace Phantom.Agent.Minecraft.Launcher.Types; namespace Phantom.Agent.Minecraft.Launcher.Types;
public sealed class FabricLauncher : BaseLauncher { public sealed class FabricLauncher : BaseLauncher {
public FabricLauncher(InstanceProperties instanceProperties) : base(instanceProperties) {} public FabricLauncher(InstanceProperties instanceProperties) : base(instanceProperties) {}

View File

@ -1,7 +1,7 @@
using Phantom.Agent.Minecraft.Server; using Phantom.Agent.Minecraft.Server;
using Serilog; using Serilog;
namespace Phantom.Agent.Minecraft.Launcher.Types; namespace Phantom.Agent.Minecraft.Launcher.Types;
public sealed class InvalidLauncher : IServerLauncher { public sealed class InvalidLauncher : IServerLauncher {
public static InvalidLauncher Instance { get; } = new (); public static InvalidLauncher Instance { get; } = new ();

View File

@ -1,6 +1,6 @@
using Phantom.Agent.Minecraft.Instance; using Phantom.Agent.Minecraft.Instance;
namespace Phantom.Agent.Minecraft.Launcher.Types; namespace Phantom.Agent.Minecraft.Launcher.Types;
public sealed class VanillaLauncher : BaseLauncher { public sealed class VanillaLauncher : BaseLauncher {
public VanillaLauncher(InstanceProperties instanceProperties) : base(instanceProperties) {} public VanillaLauncher(InstanceProperties instanceProperties) : base(instanceProperties) {}

View File

@ -1,6 +1,6 @@
using Phantom.Agent.Minecraft.Java; using Phantom.Agent.Minecraft.Java;
namespace Phantom.Agent.Minecraft.Properties; namespace Phantom.Agent.Minecraft.Properties;
abstract class MinecraftServerProperty<T> { abstract class MinecraftServerProperty<T> {
private readonly string key; private readonly string key;

View File

@ -1,4 +1,4 @@
namespace Phantom.Agent.Minecraft.Server; namespace Phantom.Agent.Minecraft.Server;
public sealed class DownloadProgressEventArgs : EventArgs { public sealed class DownloadProgressEventArgs : EventArgs {
public ulong DownloadedBytes { get; } public ulong DownloadedBytes { get; }

View File

@ -1,3 +1,3 @@
namespace Phantom.Agent.Minecraft.Server; namespace Phantom.Agent.Minecraft.Server;
sealed record MinecraftServerExecutableDownloadListener(EventHandler<DownloadProgressEventArgs> DownloadProgressEventHandler, CancellationToken CancellationToken); sealed record MinecraftServerExecutableDownloadListener(EventHandler<DownloadProgressEventArgs> DownloadProgressEventHandler, CancellationToken CancellationToken);

View File

@ -6,7 +6,7 @@ using System.Text;
using Phantom.Common.Logging; using Phantom.Common.Logging;
using Serilog; using Serilog;
namespace Phantom.Agent.Minecraft.Server; namespace Phantom.Agent.Minecraft.Server;
public sealed class ServerStatusProtocol { public sealed class ServerStatusProtocol {
private readonly ILogger logger; private readonly ILogger logger;

View File

@ -0,0 +1,43 @@
using NetMQ;
using NetMQ.Sockets;
using Phantom.Common.Data.Agent;
using Phantom.Common.Messages.Agent;
using Phantom.Common.Messages.Agent.ToController;
using Phantom.Utils.Rpc;
using Phantom.Utils.Tasks;
namespace Phantom.Agent.Rpc;
public sealed class RpcClientRuntime : RpcClientRuntime<IMessageToAgentListener, IMessageToControllerListener, RegisterAgentMessage> {
public static Task Launch(RpcConfiguration config, AuthToken authToken, AgentInfo agentInfo, Func<RpcConnectionToServer<IMessageToControllerListener>, IMessageToAgentListener> listenerFactory, SemaphoreSlim disconnectSemaphore, CancellationToken receiveCancellationToken) {
return new RpcClientRuntime(config, agentInfo.Guid, listenerFactory, new RegisterAgentMessage(authToken, agentInfo), disconnectSemaphore, receiveCancellationToken).Launch();
}
private readonly RpcConfiguration config;
private readonly Guid agentGuid;
private RpcClientRuntime(RpcConfiguration config, Guid agentGuid, Func<RpcConnectionToServer<IMessageToControllerListener>, IMessageToAgentListener> messageListenerFactory, RegisterAgentMessage registerAgentMessage, SemaphoreSlim disconnectSemaphore, CancellationToken receiveCancellationToken) : base(config, AgentMessageRegistries.Definitions, messageListenerFactory, registerAgentMessage, disconnectSemaphore, receiveCancellationToken) {
this.config = config;
this.agentGuid = agentGuid;
}
protected override void RunWithConnection(ClientSocket socket, RpcConnectionToServer<IMessageToControllerListener> connection, TaskManager taskManager) {
ServerMessaging.SetCurrentConnection(connection);
var keepAliveLoop = new KeepAliveLoop(connection);
try {
base.RunWithConnection(socket, connection, taskManager);
} finally {
keepAliveLoop.Cancel();
}
}
protected override async Task Disconnect(ClientSocket socket) {
var unregisterMessageBytes = AgentMessageRegistries.ToController.Write(new UnregisterAgentMessage(agentGuid)).ToArray();
try {
await socket.SendAsync(unregisterMessageBytes).AsTask().WaitAsync(TimeSpan.FromSeconds(5), CancellationToken.None);
} catch (TimeoutException) {
config.RuntimeLogger.Error("Timed out communicating agent shutdown with the controller.");
}
}
}

View File

@ -1,107 +0,0 @@
using NetMQ;
using NetMQ.Sockets;
using Phantom.Common.Data.Agent;
using Phantom.Common.Messages.Agent;
using Phantom.Common.Messages.Agent.BiDirectional;
using Phantom.Common.Messages.Agent.ToController;
using Phantom.Utils.Rpc;
using Phantom.Utils.Rpc.Message;
using Phantom.Utils.Tasks;
using Serilog;
using Serilog.Events;
namespace Phantom.Agent.Rpc;
public sealed class RpcLauncher : RpcRuntime<ClientSocket> {
public static Task Launch(RpcConfiguration config, AuthToken authToken, AgentInfo agentInfo, Func<RpcConnectionToServer<IMessageToControllerListener>, IMessageToAgentListener> listenerFactory, SemaphoreSlim disconnectSemaphore, CancellationToken receiveCancellationToken) {
var socket = new ClientSocket();
var options = socket.Options;
options.CurveServerCertificate = config.ServerCertificate;
options.CurveCertificate = new NetMQCertificate();
options.HelloMessage = AgentMessageRegistries.ToController.Write(new RegisterAgentMessage(authToken, agentInfo)).ToArray();
return new RpcLauncher(config, socket, agentInfo.Guid, listenerFactory, disconnectSemaphore, receiveCancellationToken).Launch();
}
private readonly RpcConfiguration config;
private readonly Guid agentGuid;
private readonly Func<RpcConnectionToServer<IMessageToControllerListener>, IMessageToAgentListener> messageListenerFactory;
private readonly SemaphoreSlim disconnectSemaphore;
private readonly CancellationToken receiveCancellationToken;
private RpcLauncher(RpcConfiguration config, ClientSocket socket, Guid agentGuid, Func<RpcConnectionToServer<IMessageToControllerListener>, IMessageToAgentListener> messageListenerFactory, SemaphoreSlim disconnectSemaphore, CancellationToken receiveCancellationToken) : base(config, socket) {
this.config = config;
this.agentGuid = agentGuid;
this.messageListenerFactory = messageListenerFactory;
this.disconnectSemaphore = disconnectSemaphore;
this.receiveCancellationToken = receiveCancellationToken;
}
protected override void Connect(ClientSocket socket) {
var logger = config.RuntimeLogger;
var url = config.TcpUrl;
logger.Information("Starting ZeroMQ client and connecting to {Url}...", url);
socket.Connect(url);
logger.Information("ZeroMQ client ready.");
}
protected override void Run(ClientSocket socket, MessageReplyTracker replyTracker, TaskManager taskManager) {
var connection = new RpcConnectionToServer<IMessageToControllerListener>(socket, AgentMessageRegistries.ToController, replyTracker);
ServerMessaging.SetCurrentConnection(connection);
var logger = config.RuntimeLogger;
var handler = new MessageToAgentHandler(messageListenerFactory(connection), logger, taskManager, receiveCancellationToken);
var keepAliveLoop = new KeepAliveLoop(connection);
try {
while (!receiveCancellationToken.IsCancellationRequested) {
var data = socket.Receive(receiveCancellationToken);
LogMessageType(logger, data);
if (data.Length > 0) {
AgentMessageRegistries.ToAgent.Handle(data, handler);
}
}
} catch (OperationCanceledException) {
// Ignore.
} finally {
logger.Debug("ZeroMQ client stopped receiving messages.");
disconnectSemaphore.Wait(CancellationToken.None);
keepAliveLoop.Cancel();
}
}
private static void LogMessageType(ILogger logger, ReadOnlyMemory<byte> data) {
if (!logger.IsEnabled(LogEventLevel.Verbose)) {
return;
}
if (data.Length > 0 && AgentMessageRegistries.ToAgent.TryGetType(data, out var type)) {
logger.Verbose("Received {MessageType} ({Bytes} B) from controller.", type.Name, data.Length);
}
else {
logger.Verbose("Received {Bytes} B message from controller.", data.Length);
}
}
protected override async Task Disconnect() {
var unregisterTimeoutTask = Task.Delay(TimeSpan.FromSeconds(5), CancellationToken.None);
var finishedTask = await Task.WhenAny(ServerMessaging.Send(new UnregisterAgentMessage(agentGuid)), unregisterTimeoutTask);
if (finishedTask == unregisterTimeoutTask) {
config.RuntimeLogger.Error("Timed out communicating agent shutdown with the controller.");
}
}
private sealed class MessageToAgentHandler : MessageHandler<IMessageToAgentListener> {
public MessageToAgentHandler(IMessageToAgentListener listener, ILogger logger, TaskManager taskManager, CancellationToken cancellationToken) : base(listener, logger, taskManager, cancellationToken) {}
protected override Task SendReply(uint sequenceId, byte[] serializedReply) {
return ServerMessaging.Send(new ReplyMessage(sequenceId, serializedReply));
}
}
}

View File

@ -1,3 +1,3 @@
namespace Phantom.Agent.Services; namespace Phantom.Agent.Services;
public readonly record struct AgentServiceConfiguration(int MaxConcurrentCompressionTasks); public readonly record struct AgentServiceConfiguration(int MaxConcurrentCompressionTasks);

View File

@ -7,7 +7,7 @@ using Phantom.Common.Logging;
using Phantom.Utils.IO; using Phantom.Utils.IO;
using Serilog; using Serilog;
namespace Phantom.Agent.Services.Backups; namespace Phantom.Agent.Services.Backups;
sealed class BackupArchiver { sealed class BackupArchiver {
private readonly string destinationBasePath; private readonly string destinationBasePath;

View File

@ -2,7 +2,7 @@
using Phantom.Utils.Processes; using Phantom.Utils.Processes;
using Serilog; using Serilog;
namespace Phantom.Agent.Services.Backups; namespace Phantom.Agent.Services.Backups;
static class BackupCompressor { static class BackupCompressor {
private static ILogger Logger { get; } = PhantomLogger.Create(nameof(BackupCompressor)); private static ILogger Logger { get; } = PhantomLogger.Create(nameof(BackupCompressor));

View File

@ -23,7 +23,7 @@ sealed class BackupScheduler : CancellableBackgroundTask {
private readonly ServerStatusProtocol serverStatusProtocol; private readonly ServerStatusProtocol serverStatusProtocol;
private readonly ManualResetEventSlim serverOutputWhileWaitingForOnlinePlayers = new (); private readonly ManualResetEventSlim serverOutputWhileWaitingForOnlinePlayers = new ();
public event EventHandler<BackupCreationResult>? BackupCompleted; public event EventHandler<BackupCreationResult>? BackupCompleted;
public BackupScheduler(TaskManager taskManager, BackupManager backupManager, InstanceProcess process, IInstanceContext context, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName), taskManager, "Backup scheduler for " + context.ShortName) { public BackupScheduler(TaskManager taskManager, BackupManager backupManager, InstanceProcess process, IInstanceContext context, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName), taskManager, "Backup scheduler for " + context.ShortName) {
this.backupManager = backupManager; this.backupManager = backupManager;

View File

@ -3,7 +3,7 @@ using Phantom.Agent.Services.Instances.States;
using Phantom.Common.Data.Instance; using Phantom.Common.Data.Instance;
using Serilog; using Serilog;
namespace Phantom.Agent.Services.Instances; namespace Phantom.Agent.Services.Instances;
interface IInstanceContext { interface IInstanceContext {
string ShortName { get; } string ShortName { get; }

View File

@ -27,7 +27,7 @@ sealed class Instance : IAsyncDisposable {
private IInstanceState currentState; private IInstanceState currentState;
public bool IsRunning => currentState is not InstanceNotRunningState; public bool IsRunning => currentState is not InstanceNotRunningState;
public event EventHandler? IsRunningChanged; public event EventHandler? IsRunningChanged;
private readonly InstanceProcedureManager procedureManager; private readonly InstanceProcedureManager procedureManager;

View File

@ -2,6 +2,6 @@
using Phantom.Agent.Services.Backups; using Phantom.Agent.Services.Backups;
using Phantom.Utils.Tasks; using Phantom.Utils.Tasks;
namespace Phantom.Agent.Services.Instances; namespace Phantom.Agent.Services.Instances;
sealed record InstanceServices(TaskManager TaskManager, PortManager PortManager, BackupManager BackupManager, LaunchServices LaunchServices); sealed record InstanceServices(TaskManager TaskManager, PortManager PortManager, BackupManager BackupManager, LaunchServices LaunchServices);

View File

@ -1,6 +1,6 @@
using Phantom.Agent.Services.Instances.States; using Phantom.Agent.Services.Instances.States;
namespace Phantom.Agent.Services.Instances.Procedures; namespace Phantom.Agent.Services.Instances.Procedures;
interface IInstanceProcedure { interface IInstanceProcedure {
Task<IInstanceState?> Run(IInstanceContext context, CancellationToken cancellationToken); Task<IInstanceState?> Run(IInstanceContext context, CancellationToken cancellationToken);

View File

@ -1,4 +1,4 @@
namespace Phantom.Agent.Services.Instances.States; namespace Phantom.Agent.Services.Instances.States;
interface IInstanceState { interface IInstanceState {
void Initialize(); void Initialize();

View File

@ -1,4 +1,4 @@
namespace Phantom.Agent.Services.Instances.States; namespace Phantom.Agent.Services.Instances.States;
sealed class InstanceNotRunningState : IInstanceState { sealed class InstanceNotRunningState : IInstanceState {
public void Initialize() {} public void Initialize() {}

View File

@ -41,7 +41,7 @@ public sealed class MessageListener : IMessageToAgentListener {
} }
} }
await ServerMessaging.Send(new AdvertiseJavaRuntimesMessage(agent.JavaRuntimeRepository.All)); await connection.Send(new AdvertiseJavaRuntimesMessage(agent.JavaRuntimeRepository.All));
await agent.InstanceSessionManager.RefreshAgentStatus(); await agent.InstanceSessionManager.RefreshAgentStatus();
return NoReply.Instance; return NoReply.Instance;

View File

@ -1,4 +1,5 @@
using NetMQ; using NetMQ;
using Phantom.Common.Data;
using Phantom.Common.Data.Agent; using Phantom.Common.Data.Agent;
using Phantom.Common.Logging; using Phantom.Common.Logging;
using Phantom.Utils.Cryptography; using Phantom.Utils.Cryptography;

View File

@ -3,7 +3,7 @@ using Phantom.Common.Logging;
using Phantom.Utils.IO; using Phantom.Utils.IO;
using Serilog; using Serilog;
namespace Phantom.Agent; namespace Phantom.Agent;
static class GuidFile { static class GuidFile {
private static ILogger Logger { get; } = PhantomLogger.Create(nameof(GuidFile)); private static ILogger Logger { get; } = PhantomLogger.Create(nameof(GuidFile));

View File

@ -58,7 +58,7 @@ try {
var rpcDisconnectSemaphore = new SemaphoreSlim(0, 1); var rpcDisconnectSemaphore = new SemaphoreSlim(0, 1);
var rpcConfiguration = new RpcConfiguration(PhantomLogger.Create("Rpc"), PhantomLogger.Create<TaskManager>("Rpc"), controllerHost, controllerPort, controllerCertificate); var rpcConfiguration = new RpcConfiguration(PhantomLogger.Create("Rpc"), PhantomLogger.Create<TaskManager>("Rpc"), controllerHost, controllerPort, controllerCertificate);
var rpcTask = RpcLauncher.Launch(rpcConfiguration, agentToken, agentInfo, MessageListenerFactory, rpcDisconnectSemaphore, shutdownCancellationToken); var rpcTask = RpcClientRuntime.Launch(rpcConfiguration, agentToken, agentInfo, MessageListenerFactory, rpcDisconnectSemaphore, shutdownCancellationToken);
try { try {
await rpcTask.WaitAsync(shutdownCancellationToken); await rpcTask.WaitAsync(shutdownCancellationToken);
} finally { } finally {

View File

@ -1,6 +1,6 @@
using NUnit.Framework; using NUnit.Framework;
namespace Phantom.Common.Data.Tests; namespace Phantom.Common.Data.Tests;
[TestFixture] [TestFixture]
public sealed class AllowedPortsTests { public sealed class AllowedPortsTests {

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Database.Enums; namespace Phantom.Common.Data.Web.AuditLog;
public enum AuditLogEventType { public enum AuditLogEventType {
AdministratorUserCreated, AdministratorUserCreated,
@ -16,7 +16,7 @@ public enum AuditLogEventType {
InstanceCommandExecuted InstanceCommandExecuted
} }
static class AuditLogEventTypeExtensions { public static class AuditLogEventTypeExtensions {
private static readonly Dictionary<AuditLogEventType, AuditLogSubjectType> SubjectTypes = new () { private static readonly Dictionary<AuditLogEventType, AuditLogSubjectType> SubjectTypes = new () {
{ AuditLogEventType.AdministratorUserCreated, AuditLogSubjectType.User }, { AuditLogEventType.AdministratorUserCreated, AuditLogSubjectType.User },
{ AuditLogEventType.AdministratorUserModified, AuditLogSubjectType.User }, { AuditLogEventType.AdministratorUserModified, AuditLogSubjectType.User },
@ -41,7 +41,7 @@ static class AuditLogEventTypeExtensions {
} }
} }
internal static AuditLogSubjectType GetSubjectType(this AuditLogEventType type) { public static AuditLogSubjectType GetSubjectType(this AuditLogEventType type) {
return SubjectTypes[type]; return SubjectTypes[type];
} }
} }

View File

@ -1,6 +1,5 @@
using System.Text.Json; using System.Text.Json;
using Phantom.Controller.Database.Enums;
namespace Phantom.Controller.Services.Audit; namespace Phantom.Common.Data.Web.AuditLog;
public sealed record AuditLogItem(DateTime UtcTime, Guid? UserGuid, string? UserName, AuditLogEventType EventType, AuditLogSubjectType SubjectType, string? SubjectId, JsonDocument? Data); public sealed record AuditLogItem(DateTime UtcTime, Guid? UserGuid, string? UserName, AuditLogEventType EventType, AuditLogSubjectType SubjectType, string? SubjectId, JsonDocument? Data);

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Database.Enums; namespace Phantom.Common.Data.Web.AuditLog;
public enum AuditLogSubjectType { public enum AuditLogSubjectType {
User, User,

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Database.Enums; namespace Phantom.Common.Data.Web.EventLog;
public enum EventLogEventType { public enum EventLogEventType {
InstanceLaunchSucceded, InstanceLaunchSucceded,
@ -10,7 +10,7 @@ public enum EventLogEventType {
InstanceBackupFailed, InstanceBackupFailed,
} }
static class EventLogEventTypeExtensions { public static class EventLogEventTypeExtensions {
private static readonly Dictionary<EventLogEventType, EventLogSubjectType> SubjectTypes = new () { private static readonly Dictionary<EventLogEventType, EventLogSubjectType> SubjectTypes = new () {
{ EventLogEventType.InstanceLaunchSucceded, EventLogSubjectType.Instance }, { EventLogEventType.InstanceLaunchSucceded, EventLogSubjectType.Instance },
{ EventLogEventType.InstanceLaunchFailed, EventLogSubjectType.Instance }, { EventLogEventType.InstanceLaunchFailed, EventLogSubjectType.Instance },

View File

@ -1,6 +1,5 @@
using System.Text.Json; using System.Text.Json;
using Phantom.Controller.Database.Enums;
namespace Phantom.Controller.Services.Events; namespace Phantom.Common.Data.Web.EventLog;
public sealed record EventLogItem(DateTime UtcTime, Guid? AgentGuid, EventLogEventType EventType, EventLogSubjectType SubjectType, string SubjectId, JsonDocument? Data); public sealed record EventLogItem(DateTime UtcTime, Guid? AgentGuid, EventLogEventType EventType, EventLogSubjectType SubjectType, string SubjectId, JsonDocument? Data);

View File

@ -0,0 +1,5 @@
namespace Phantom.Common.Data.Web.EventLog;
public enum EventLogSubjectType {
Instance
}

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Services.Users.Roles; namespace Phantom.Common.Data.Web.Users;
public enum AddRoleError : byte { public enum AddRoleError : byte {
NameIsEmpty, NameIsEmpty,

View File

@ -1,25 +1,28 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users.AddUserErrors;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users {
[MemoryPackable]
[MemoryPackable] [MemoryPackUnion(0, typeof(NameIsInvalid))]
[MemoryPackUnion(0, typeof(NameIsInvalid))] [MemoryPackUnion(1, typeof(PasswordIsInvalid))]
[MemoryPackUnion(1, typeof(PasswordIsInvalid))] [MemoryPackUnion(2, typeof(NameAlreadyExists))]
[MemoryPackUnion(2, typeof(NameAlreadyExists))] [MemoryPackUnion(3, typeof(UnknownError))]
[MemoryPackUnion(3, typeof(UnknownError))] public abstract partial record AddUserError {
public abstract record AddUserError { internal AddUserError() {}
private AddUserError() {} }
}
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed record NameIsInvalid([property: MemoryPackOrder(0)] UsernameRequirementViolation Violation) : AddUserError; namespace Phantom.Common.Data.Web.Users.AddUserErrors {
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record NameIsInvalid([property: MemoryPackOrder(0)] UsernameRequirementViolation Violation) : AddUserError;
public sealed record PasswordIsInvalid([property: MemoryPackOrder(0)] ImmutableArray<PasswordRequirementViolation> Violations) : AddUserError;
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record PasswordIsInvalid([property: MemoryPackOrder(0)] ImmutableArray<PasswordRequirementViolation> Violations) : AddUserError;
public sealed record NameAlreadyExists : AddUserError;
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record NameAlreadyExists : AddUserError;
public sealed record UnknownError : AddUserError;
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record UnknownError : AddUserError;
} }

View File

@ -1,16 +1,19 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users {
[MemoryPackable]
[MemoryPackable] [MemoryPackUnion(0, typeof(Success))]
[MemoryPackUnion(0, typeof(Success))] [MemoryPackUnion(1, typeof(CreationFailed))]
[MemoryPackUnion(1, typeof(CreationFailed))] [MemoryPackUnion(2, typeof(UpdatingFailed))]
[MemoryPackUnion(2, typeof(UpdatingFailed))] [MemoryPackUnion(3, typeof(AddingToRoleFailed))]
[MemoryPackUnion(3, typeof(AddingToRoleFailed))] [MemoryPackUnion(4, typeof(UnknownError))]
[MemoryPackUnion(4, typeof(UnknownError))] public abstract partial record CreateOrUpdateAdministratorUserResult {
public abstract partial record CreateOrUpdateAdministratorUserResult { internal CreateOrUpdateAdministratorUserResult() {}
private CreateOrUpdateAdministratorUserResult() {} }
}
namespace Phantom.Common.Data.Web.Users.CreateOrUpdateAdministratorUserResults {
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record Success([property: MemoryPackOrder(0)] UserInfo User) : CreateOrUpdateAdministratorUserResult; public sealed partial record Success([property: MemoryPackOrder(0)] UserInfo User) : CreateOrUpdateAdministratorUserResult;
@ -19,10 +22,10 @@ public abstract partial record CreateOrUpdateAdministratorUserResult {
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record UpdatingFailed([property: MemoryPackOrder(0)] SetUserPasswordError Error) : CreateOrUpdateAdministratorUserResult; public sealed partial record UpdatingFailed([property: MemoryPackOrder(0)] SetUserPasswordError Error) : CreateOrUpdateAdministratorUserResult;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record AddingToRoleFailed : CreateOrUpdateAdministratorUserResult; public sealed partial record AddingToRoleFailed : CreateOrUpdateAdministratorUserResult;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record UnknownError : CreateOrUpdateAdministratorUserResult; public sealed partial record UnknownError : CreateOrUpdateAdministratorUserResult;
} }

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users;
public enum DeleteUserResult : byte { public enum DeleteUserResult : byte {
Deleted, Deleted,

View File

@ -1,6 +1,6 @@
using System.Collections.Immutable; using System.Collections.Immutable;
namespace Phantom.Common.Data.Web.Users.Permissions; namespace Phantom.Common.Data.Web.Users;
public sealed class IdentityPermissions { public sealed class IdentityPermissions {
public static IdentityPermissions None { get; } = new (ImmutableHashSet<string>.Empty); public static IdentityPermissions None { get; } = new (ImmutableHashSet<string>.Empty);

View File

@ -1,24 +1,27 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users.PasswordRequirementViolations;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users {
[MemoryPackable]
[MemoryPackable] [MemoryPackUnion(0, typeof(TooShort))]
[MemoryPackUnion(0, typeof(TooShort))] [MemoryPackUnion(1, typeof(MustContainLowercaseLetter))]
[MemoryPackUnion(1, typeof(LowercaseLetterRequired))] [MemoryPackUnion(2, typeof(MustContainUppercaseLetter))]
[MemoryPackUnion(2, typeof(UppercaseLetterRequired))] [MemoryPackUnion(3, typeof(MustContainDigit))]
[MemoryPackUnion(3, typeof(DigitRequired))] public abstract partial record PasswordRequirementViolation {
public abstract record PasswordRequirementViolation { internal PasswordRequirementViolation() {}
private PasswordRequirementViolation() {} }
}
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed record TooShort([property: MemoryPackOrder(0)] int MinimumLength) : PasswordRequirementViolation; namespace Phantom.Common.Data.Web.Users.PasswordRequirementViolations {
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record TooShort([property: MemoryPackOrder(0)] int MinimumLength) : PasswordRequirementViolation;
public sealed record LowercaseLetterRequired : PasswordRequirementViolation;
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record MustContainLowercaseLetter : PasswordRequirementViolation;
public sealed record UppercaseLetterRequired : PasswordRequirementViolation;
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record MustContainUppercaseLetter : PasswordRequirementViolation;
public sealed record DigitRequired : PasswordRequirementViolation;
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record MustContainDigit : PasswordRequirementViolation;
} }

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Web.Users.Permissions; namespace Phantom.Common.Data.Web.Users;
public sealed record Permission(string Id, Permission? Parent) { public sealed record Permission(string Id, Permission? Parent) {
private static readonly List<Permission> AllPermissions = new (); private static readonly List<Permission> AllPermissions = new ();

View File

@ -1,6 +1,6 @@
using MemoryPack; using MemoryPack;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record RoleInfo( public sealed partial record RoleInfo(

View File

@ -1,21 +1,24 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users.SetUserPasswordErrors;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users {
[MemoryPackable]
[MemoryPackable] [MemoryPackUnion(0, typeof(UserNotFound))]
[MemoryPackUnion(0, typeof(UserNotFound))] [MemoryPackUnion(1, typeof(PasswordIsInvalid))]
[MemoryPackUnion(1, typeof(PasswordIsInvalid))] [MemoryPackUnion(2, typeof(UnknownError))]
[MemoryPackUnion(2, typeof(UnknownError))] public abstract partial record SetUserPasswordError {
public abstract record SetUserPasswordError { internal SetUserPasswordError() {}
private SetUserPasswordError() {} }
}
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed record UserNotFound : SetUserPasswordError; namespace Phantom.Common.Data.Web.Users.SetUserPasswordErrors {
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record UserNotFound : SetUserPasswordError;
public sealed record PasswordIsInvalid(ImmutableArray<PasswordRequirementViolation> Violations) : SetUserPasswordError;
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record PasswordIsInvalid([property: MemoryPackOrder(0)] ImmutableArray<PasswordRequirementViolation> Violations) : SetUserPasswordError;
public sealed record UnknownError : SetUserPasswordError;
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record UnknownError : SetUserPasswordError;
} }

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users;
public static class UserPasswords { public static class UserPasswords {
public static string Hash(string password) { public static string Hash(string password) {

View File

@ -1,16 +1,19 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users.UsernameRequirementViolations;
namespace Phantom.Common.Data.Web.Users; namespace Phantom.Common.Data.Web.Users {
[MemoryPackable]
[MemoryPackable] [MemoryPackUnion(0, typeof(IsEmpty))]
[MemoryPackUnion(0, typeof(IsEmpty))] [MemoryPackUnion(1, typeof(TooLong))]
[MemoryPackUnion(1, typeof(TooLong))] public abstract partial record UsernameRequirementViolation {
public abstract record UsernameRequirementViolation { internal UsernameRequirementViolation() {}
private UsernameRequirementViolation() {} }
}
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed record IsEmpty : UsernameRequirementViolation; namespace Phantom.Common.Data.Web.Users.UsernameRequirementViolations {
[MemoryPackable(GenerateType.VersionTolerant)]
[MemoryPackable(GenerateType.VersionTolerant)] public sealed partial record IsEmpty : UsernameRequirementViolation;
public sealed record TooLong(int MaxLength) : UsernameRequirementViolation;
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record TooLong([property: MemoryPackOrder(0)] int MaxLength) : UsernameRequirementViolation;
} }

View File

@ -2,7 +2,7 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using MemoryPack; using MemoryPack;
namespace Phantom.Common.Data.Agent; namespace Phantom.Common.Data;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Agent; namespace Phantom.Common.Data;
public readonly record struct ConnectionCommonKey(byte[] CertificatePublicKey, AuthToken AuthToken) { public readonly record struct ConnectionCommonKey(byte[] CertificatePublicKey, AuthToken AuthToken) {
private const byte TokenLength = AuthToken.Length; private const byte TokenLength = AuthToken.Length;

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Instance; namespace Phantom.Common.Data.Instance;
public interface IInstanceEventVisitor { public interface IInstanceEventVisitor {
void OnLaunchSucceeded(InstanceLaunchSuccededEvent e); void OnLaunchSucceeded(InstanceLaunchSuccededEvent e);

View File

@ -1,7 +1,7 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Minecraft; using Phantom.Common.Data.Minecraft;
namespace Phantom.Common.Data.Instance; namespace Phantom.Common.Data.Instance;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record InstanceLaunchProperties( public sealed partial record InstanceLaunchProperties(

View File

@ -1,6 +1,6 @@
using MemoryPack; using MemoryPack;
namespace Phantom.Common.Data.Java; namespace Phantom.Common.Data.Java;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record TaggedJavaRuntime( public sealed partial record TaggedJavaRuntime(

View File

@ -2,7 +2,7 @@
using Phantom.Utils.Cryptography; using Phantom.Utils.Cryptography;
using Phantom.Utils.IO; using Phantom.Utils.IO;
namespace Phantom.Common.Data.Minecraft; namespace Phantom.Common.Data.Minecraft;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial class FileDownloadInfo { public sealed partial class FileDownloadInfo {

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Minecraft; namespace Phantom.Common.Data.Minecraft;
public enum MinecraftServerKind : ushort { public enum MinecraftServerKind : ushort {
Vanilla = 1, Vanilla = 1,

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Minecraft; namespace Phantom.Common.Data.Minecraft;
public sealed record MinecraftVersion( public sealed record MinecraftVersion(
string Id, string Id,

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Replies; namespace Phantom.Common.Data.Replies;
public enum ConfigureInstanceResult : byte { public enum ConfigureInstanceResult : byte {
Success Success

View File

@ -1,4 +1,4 @@
namespace Phantom.Common.Data.Replies; namespace Phantom.Common.Data.Replies;
public enum RegisterAgentFailure : byte { public enum RegisterAgentFailure : byte {
ConnectionAlreadyHasAnAgent, ConnectionAlreadyHasAnAgent,

View File

@ -1,7 +1,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Serilog.Events; using Serilog.Events;
namespace Phantom.Common.Logging; namespace Phantom.Common.Logging;
static class DefaultLogLevel { static class DefaultLogLevel {
private const string ENVIRONMENT_VARIABLE = "LOG_LEVEL"; private const string ENVIRONMENT_VARIABLE = "LOG_LEVEL";

View File

@ -1,6 +1,6 @@
using Serilog; using Serilog;
namespace Phantom.Common.Logging; namespace Phantom.Common.Logging;
public static class LoggerExtensions { public static class LoggerExtensions {
private static readonly string HeadingPadding = new (' ', 23); private static readonly string HeadingPadding = new (' ', 23);

View File

@ -5,7 +5,7 @@ using Phantom.Common.Messages.Agent.ToAgent;
using Phantom.Common.Messages.Agent.ToController; using Phantom.Common.Messages.Agent.ToController;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent; namespace Phantom.Common.Messages.Agent;
public static class AgentMessageRegistries { public static class AgentMessageRegistries {
public static MessageRegistry<IMessageToAgentListener> ToAgent { get; } = new (PhantomLogger.Create("MessageRegistry", nameof(ToAgent))); public static MessageRegistry<IMessageToAgentListener> ToAgent { get; } = new (PhantomLogger.Create("MessageRegistry", nameof(ToAgent)));
@ -34,14 +34,18 @@ public static class AgentMessageRegistries {
} }
private sealed class MessageDefinitions : IMessageDefinitions<IMessageToAgentListener, IMessageToControllerListener> { private sealed class MessageDefinitions : IMessageDefinitions<IMessageToAgentListener, IMessageToControllerListener> {
public MessageRegistry<IMessageToAgentListener> Outgoing => ToAgent; public MessageRegistry<IMessageToAgentListener> ToClient => ToAgent;
public MessageRegistry<IMessageToControllerListener> Incoming => ToController; public MessageRegistry<IMessageToControllerListener> ToServer => ToController;
public bool IsRegistrationMessage(Type messageType) { public bool IsRegistrationMessage(Type messageType) {
return messageType == typeof(RegisterAgentMessage); return messageType == typeof(RegisterAgentMessage);
} }
public IMessage<IMessageToAgentListener, NoReply> CreateReplyMessage( uint sequenceId, byte[] serializedReply) { public IMessage<IMessageToAgentListener, NoReply> CreateReplyToServerMessage( uint sequenceId, byte[] serializedReply) {
return new ReplyMessage(sequenceId, serializedReply);
}
public IMessage<IMessageToControllerListener, NoReply> CreateReplyToClientMessage(uint sequenceId, byte[] serializedReply) {
return new ReplyMessage(sequenceId, serializedReply); return new ReplyMessage(sequenceId, serializedReply);
} }
} }

View File

@ -2,7 +2,7 @@
using Phantom.Common.Messages.Agent.ToController; using Phantom.Common.Messages.Agent.ToController;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent; namespace Phantom.Common.Messages.Agent;
public interface IMessageToControllerListener { public interface IMessageToControllerListener {
Task<NoReply> HandleRegisterAgent(RegisterAgentMessage message); Task<NoReply> HandleRegisterAgent(RegisterAgentMessage message);

View File

@ -1,7 +1,7 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Replies; using Phantom.Common.Data.Replies;
namespace Phantom.Common.Messages.Agent.ToAgent; namespace Phantom.Common.Messages.Agent.ToAgent;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record LaunchInstanceMessage( public sealed partial record LaunchInstanceMessage(

View File

@ -1,7 +1,7 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Replies; using Phantom.Common.Data.Replies;
namespace Phantom.Common.Messages.Agent.ToAgent; namespace Phantom.Common.Messages.Agent.ToAgent;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record SendCommandToInstanceMessage( public sealed partial record SendCommandToInstanceMessage(

View File

@ -2,7 +2,7 @@
using Phantom.Common.Data.Minecraft; using Phantom.Common.Data.Minecraft;
using Phantom.Common.Data.Replies; using Phantom.Common.Data.Replies;
namespace Phantom.Common.Messages.Agent.ToAgent; namespace Phantom.Common.Messages.Agent.ToAgent;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record StopInstanceMessage( public sealed partial record StopInstanceMessage(

View File

@ -3,7 +3,7 @@ using MemoryPack;
using Phantom.Common.Data.Java; using Phantom.Common.Data.Java;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent.ToController; namespace Phantom.Common.Messages.Agent.ToController;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record AdvertiseJavaRuntimesMessage( public sealed partial record AdvertiseJavaRuntimesMessage(

View File

@ -1,7 +1,7 @@
using MemoryPack; using MemoryPack;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent.ToController; namespace Phantom.Common.Messages.Agent.ToController;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record AgentIsAliveMessage : IMessageToController { public sealed partial record AgentIsAliveMessage : IMessageToController {

View File

@ -1,4 +1,5 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data;
using Phantom.Common.Data.Agent; using Phantom.Common.Data.Agent;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;

View File

@ -2,7 +2,7 @@
using Phantom.Common.Data; using Phantom.Common.Data;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent.ToController; namespace Phantom.Common.Messages.Agent.ToController;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record ReportAgentStatusMessage( public sealed partial record ReportAgentStatusMessage(

View File

@ -2,7 +2,7 @@
using Phantom.Common.Data.Instance; using Phantom.Common.Data.Instance;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Agent.ToController; namespace Phantom.Common.Messages.Agent.ToController;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record ReportInstanceEventMessage( public sealed partial record ReportInstanceEventMessage(

View File

@ -3,9 +3,10 @@ using Phantom.Common.Messages.Web.BiDirectional;
using Phantom.Common.Messages.Web.ToController; using Phantom.Common.Messages.Web.ToController;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Web; namespace Phantom.Common.Messages.Web;
public interface IMessageToControllerListener { public interface IMessageToControllerListener {
Task<NoReply> HandleRegisterWeb(RegisterWebMessage message);
Task<CreateOrUpdateAdministratorUserResult> CreateOrUpdateAdministratorUser(CreateOrUpdateAdministratorUser message); Task<CreateOrUpdateAdministratorUserResult> CreateOrUpdateAdministratorUser(CreateOrUpdateAdministratorUser message);
Task<NoReply> HandleReply(ReplyMessage message); Task<NoReply> HandleReply(ReplyMessage message);
} }

View File

@ -1,7 +1,7 @@
using MemoryPack; using MemoryPack;
using Phantom.Common.Data.Web.Users; using Phantom.Common.Data.Web.Users;
namespace Phantom.Common.Messages.Web.ToController; namespace Phantom.Common.Messages.Web.ToController;
[MemoryPackable(GenerateType.VersionTolerant)] [MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record CreateOrUpdateAdministratorUser( public sealed partial record CreateOrUpdateAdministratorUser(

View File

@ -0,0 +1,14 @@
using MemoryPack;
using Phantom.Common.Data;
using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Web.ToController;
[MemoryPackable(GenerateType.VersionTolerant)]
public sealed partial record RegisterWebMessage(
[property: MemoryPackOrder(0)] AuthToken AuthToken
) : IMessageToController {
public Task<NoReply> Accept(IMessageToControllerListener listener) {
return listener.HandleRegisterWeb(this);
}
}

View File

@ -4,7 +4,7 @@ using Phantom.Common.Messages.Web.BiDirectional;
using Phantom.Common.Messages.Web.ToController; using Phantom.Common.Messages.Web.ToController;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Common.Messages.Web; namespace Phantom.Common.Messages.Web;
public static class WebMessageRegistries { public static class WebMessageRegistries {
public static MessageRegistry<IMessageToControllerListener> ToController { get; } = new (PhantomLogger.Create("MessageRegistry", nameof(ToController))); public static MessageRegistry<IMessageToControllerListener> ToController { get; } = new (PhantomLogger.Create("MessageRegistry", nameof(ToController)));
@ -20,14 +20,18 @@ public static class WebMessageRegistries {
} }
private sealed class MessageDefinitions : IMessageDefinitions<IMessageToWebListener, IMessageToControllerListener> { private sealed class MessageDefinitions : IMessageDefinitions<IMessageToWebListener, IMessageToControllerListener> {
public MessageRegistry<IMessageToWebListener> Outgoing => ToWeb; public MessageRegistry<IMessageToWebListener> ToClient => ToWeb;
public MessageRegistry<IMessageToControllerListener> Incoming => ToController; public MessageRegistry<IMessageToControllerListener> ToServer => ToController;
public bool IsRegistrationMessage(Type messageType) { public bool IsRegistrationMessage(Type messageType) {
return false; return false;
} }
public IMessage<IMessageToWebListener, NoReply> CreateReplyMessage( uint sequenceId, byte[] serializedReply) { public IMessage<IMessageToWebListener, NoReply> CreateReplyToServerMessage( uint sequenceId, byte[] serializedReply) {
return new ReplyMessage(sequenceId, serializedReply);
}
public IMessage<IMessageToControllerListener, NoReply> CreateReplyToClientMessage(uint sequenceId, byte[] serializedReply) {
return new ReplyMessage(sequenceId, serializedReply); return new ReplyMessage(sequenceId, serializedReply);
} }
} }

View File

@ -2,7 +2,7 @@
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure; using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
namespace Phantom.Controller.Database.Postgres; namespace Phantom.Controller.Database.Postgres;
public sealed class ApplicationDbContextFactory : IDbContextProvider { public sealed class ApplicationDbContextFactory : IDbContextProvider {
private readonly PooledDbContextFactory<ApplicationDbContext> factory; private readonly PooledDbContextFactory<ApplicationDbContext> factory;

View File

@ -3,9 +3,10 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Phantom.Common.Data; using Phantom.Common.Data;
using Phantom.Common.Data.Minecraft; using Phantom.Common.Data.Minecraft;
using Phantom.Common.Data.Web.AuditLog;
using Phantom.Common.Data.Web.EventLog;
using Phantom.Controller.Database.Converters; using Phantom.Controller.Database.Converters;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
using Phantom.Controller.Database.Enums;
using Phantom.Controller.Database.Factories; using Phantom.Controller.Database.Factories;
namespace Phantom.Controller.Database; namespace Phantom.Controller.Database;

View File

@ -3,7 +3,7 @@ using Phantom.Common.Logging;
using Phantom.Utils.Tasks; using Phantom.Utils.Tasks;
using Serilog; using Serilog;
namespace Phantom.Controller.Database; namespace Phantom.Controller.Database;
public static class DatabaseMigrator { public static class DatabaseMigrator {
private static readonly ILogger Logger = PhantomLogger.Create(nameof(DatabaseMigrator)); private static readonly ILogger Logger = PhantomLogger.Create(nameof(DatabaseMigrator));

View File

@ -2,9 +2,9 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.Json; using System.Text.Json;
using Phantom.Controller.Database.Enums; using Phantom.Common.Data.Web.AuditLog;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("AuditLog", Schema = "system")] [Table("AuditLog", Schema = "system")]
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]

View File

@ -2,9 +2,9 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.Json; using System.Text.Json;
using Phantom.Controller.Database.Enums; using Phantom.Common.Data.Web.EventLog;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("EventLog", Schema = "system")] [Table("EventLog", Schema = "system")]
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]

View File

@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using Phantom.Common.Data; using Phantom.Common.Data;
using Phantom.Common.Data.Minecraft; using Phantom.Common.Data.Minecraft;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("Instances", Schema = "agents")] [Table("Instances", Schema = "agents")]
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")] [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("Permissions", Schema = "identity")] [Table("Permissions", Schema = "identity")]
public sealed class PermissionEntity { public sealed class PermissionEntity {

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("Roles", Schema = "identity")] [Table("Roles", Schema = "identity")]
public sealed class RoleEntity { public sealed class RoleEntity {

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("RolePermissions", Schema = "identity")] [Table("RolePermissions", Schema = "identity")]
public sealed class RolePermissionEntity { public sealed class RolePermissionEntity {

View File

@ -2,7 +2,7 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using Phantom.Common.Data.Web.Users; using Phantom.Common.Data.Web.Users;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("Users", Schema = "identity")] [Table("Users", Schema = "identity")]
public sealed class UserEntity { public sealed class UserEntity {

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace Phantom.Controller.Database.Entities; namespace Phantom.Controller.Database.Entities;
[Table("UserRoles", Schema = "identity")] [Table("UserRoles", Schema = "identity")]
public sealed class UserRoleEntity { public sealed class UserRoleEntity {

View File

@ -1,5 +0,0 @@
namespace Phantom.Controller.Database.Enums;
public enum EventLogSubjectType {
Instance
}

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
namespace Phantom.Controller.Database.Factories; namespace Phantom.Controller.Database.Factories;
public sealed class AgentEntityUpsert : AbstractUpsertHelper<AgentEntity> { public sealed class AgentEntityUpsert : AbstractUpsertHelper<AgentEntity> {
internal AgentEntityUpsert(ApplicationDbContext ctx) : base(ctx) {} internal AgentEntityUpsert(ApplicationDbContext ctx) : base(ctx) {}

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
namespace Phantom.Controller.Database.Factories; namespace Phantom.Controller.Database.Factories;
public sealed class InstanceEntityUpsert : AbstractUpsertHelper<InstanceEntity> { public sealed class InstanceEntityUpsert : AbstractUpsertHelper<InstanceEntity> {
internal InstanceEntityUpsert(ApplicationDbContext ctx) : base(ctx) {} internal InstanceEntityUpsert(ApplicationDbContext ctx) : base(ctx) {}

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Database; namespace Phantom.Controller.Database;
public interface IDbContextProvider { public interface IDbContextProvider {
ApplicationDbContext Eager(); ApplicationDbContext Eager();

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Database; namespace Phantom.Controller.Database;
public interface ILazyDbContext : IAsyncDisposable { public interface ILazyDbContext : IAsyncDisposable {
ApplicationDbContext Ctx { get; } ApplicationDbContext Ctx { get; }

View File

@ -1,5 +1,5 @@
using Phantom.Controller.Database.Entities; using Phantom.Common.Data.Web.AuditLog;
using Phantom.Controller.Database.Enums; using Phantom.Controller.Database.Entities;
namespace Phantom.Controller.Database.Repositories; namespace Phantom.Controller.Database.Repositories;

View File

@ -1,7 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Phantom.Common.Data.Web.AuditLog;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
using Phantom.Controller.Database.Enums;
using Phantom.Controller.Services.Audit;
namespace Phantom.Controller.Database.Repositories; namespace Phantom.Controller.Database.Repositories;

View File

@ -1,12 +1,11 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Phantom.Controller.Database; using Phantom.Common.Data.Web.Users;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
using Phantom.Controller.Services.Users.Roles;
using Phantom.Utils.Collections; using Phantom.Utils.Collections;
using Phantom.Utils.Tasks; using Phantom.Utils.Tasks;
namespace Phantom.Controller.Services.Users; namespace Phantom.Controller.Database.Repositories;
public sealed class RoleRepository { public sealed class RoleRepository {
private const int MaxRoleNameLength = 40; private const int MaxRoleNameLength = 40;

View File

@ -1,6 +1,9 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Phantom.Common.Data.Web.Users; using Phantom.Common.Data.Web.Users;
using Phantom.Common.Data.Web.Users.AddUserErrors;
using Phantom.Common.Data.Web.Users.PasswordRequirementViolations;
using Phantom.Common.Data.Web.Users.UsernameRequirementViolations;
using Phantom.Controller.Database.Entities; using Phantom.Controller.Database.Entities;
using Phantom.Utils.Collections; using Phantom.Utils.Collections;
using Phantom.Utils.Tasks; using Phantom.Utils.Tasks;
@ -13,10 +16,10 @@ public sealed class UserRepository {
private static UsernameRequirementViolation? CheckUsernameRequirements(string username) { private static UsernameRequirementViolation? CheckUsernameRequirements(string username) {
if (string.IsNullOrWhiteSpace(username)) { if (string.IsNullOrWhiteSpace(username)) {
return new UsernameRequirementViolation.IsEmpty(); return new IsEmpty();
} }
else if (username.Length > MaxUserNameLength) { else if (username.Length > MaxUserNameLength) {
return new UsernameRequirementViolation.TooLong(MaxUserNameLength); return new TooLong(MaxUserNameLength);
} }
else { else {
return null; return null;
@ -27,19 +30,19 @@ public sealed class UserRepository {
var violations = ImmutableArray.CreateBuilder<PasswordRequirementViolation>(); var violations = ImmutableArray.CreateBuilder<PasswordRequirementViolation>();
if (password.Length < MinimumPasswordLength) { if (password.Length < MinimumPasswordLength) {
violations.Add(new PasswordRequirementViolation.TooShort(MinimumPasswordLength)); violations.Add(new TooShort(MinimumPasswordLength));
} }
if (!password.Any(char.IsLower)) { if (!password.Any(char.IsLower)) {
violations.Add(new PasswordRequirementViolation.LowercaseLetterRequired()); violations.Add(new MustContainLowercaseLetter());
} }
if (!password.Any(char.IsUpper)) { if (!password.Any(char.IsUpper)) {
violations.Add(new PasswordRequirementViolation.UppercaseLetterRequired()); violations.Add(new MustContainUppercaseLetter());
} }
if (!password.Any(char.IsDigit)) { if (!password.Any(char.IsDigit)) {
violations.Add(new PasswordRequirementViolation.DigitRequired()); violations.Add(new MustContainDigit());
} }
return violations.ToImmutable(); return violations.ToImmutable();
@ -73,16 +76,16 @@ public sealed class UserRepository {
public async Task<Result<UserEntity, AddUserError>> CreateUser(string username, string password) { public async Task<Result<UserEntity, AddUserError>> CreateUser(string username, string password) {
var usernameRequirementViolation = CheckUsernameRequirements(username); var usernameRequirementViolation = CheckUsernameRequirements(username);
if (usernameRequirementViolation != null) { if (usernameRequirementViolation != null) {
return new AddUserError.NameIsInvalid(usernameRequirementViolation); return new NameIsInvalid(usernameRequirementViolation);
} }
var passwordRequirementViolations = CheckPasswordRequirements(password); var passwordRequirementViolations = CheckPasswordRequirements(password);
if (!passwordRequirementViolations.IsEmpty) { if (!passwordRequirementViolations.IsEmpty) {
return new AddUserError.PasswordIsInvalid(passwordRequirementViolations); return new PasswordIsInvalid(passwordRequirementViolations);
} }
if (await db.Ctx.Users.AnyAsync(user => user.Name == username)) { if (await db.Ctx.Users.AnyAsync(user => user.Name == username)) {
return new AddUserError.NameAlreadyExists(); return new NameAlreadyExists();
} }
var user = new UserEntity(Guid.NewGuid(), username, UserPasswords.Hash(password)); var user = new UserEntity(Guid.NewGuid(), username, UserPasswords.Hash(password));
@ -96,7 +99,7 @@ public sealed class UserRepository {
public Result<SetUserPasswordError> SetUserPassword(UserEntity user, string password) { public Result<SetUserPasswordError> SetUserPassword(UserEntity user, string password) {
var requirementViolations = CheckPasswordRequirements(password); var requirementViolations = CheckPasswordRequirements(password);
if (!requirementViolations.IsEmpty) { if (!requirementViolations.IsEmpty) {
return new SetUserPasswordError.PasswordIsInvalid(requirementViolations); return new Common.Data.Web.Users.SetUserPasswordErrors.PasswordIsInvalid(requirementViolations);
} }
user.PasswordHash = UserPasswords.Hash(password); user.PasswordHash = UserPasswords.Hash(password);

View File

@ -1,4 +1,4 @@
namespace Phantom.Controller.Rpc; namespace Phantom.Controller.Rpc;
sealed class RpcClientConnectionClosedEventArgs : EventArgs { sealed class RpcClientConnectionClosedEventArgs : EventArgs {
public uint RoutingId { get; } public uint RoutingId { get; }

View File

@ -1,11 +1,10 @@
using NetMQ; using NetMQ;
using NetMQ.Sockets; using NetMQ.Sockets;
using Phantom.Common.Messages.Agent.BiDirectional;
using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Message;
namespace Phantom.Controller.Rpc; namespace Phantom.Controller.Rpc;
public sealed class RpcClientConnection<TListener> { public sealed class RpcConnectionToClient<TListener> {
private readonly ServerSocket socket; private readonly ServerSocket socket;
private readonly uint routingId; private readonly uint routingId;
@ -15,14 +14,14 @@ public sealed class RpcClientConnection<TListener> {
internal event EventHandler<RpcClientConnectionClosedEventArgs>? Closed; internal event EventHandler<RpcClientConnectionClosedEventArgs>? Closed;
private bool isClosed; private bool isClosed;
internal RpcClientConnection(ServerSocket socket, uint routingId, MessageRegistry<TListener> messageRegistry, MessageReplyTracker messageReplyTracker) { internal RpcConnectionToClient(ServerSocket socket, uint routingId, MessageRegistry<TListener> messageRegistry, MessageReplyTracker messageReplyTracker) {
this.socket = socket; this.socket = socket;
this.routingId = routingId; this.routingId = routingId;
this.messageRegistry = messageRegistry; this.messageRegistry = messageRegistry;
this.messageReplyTracker = messageReplyTracker; this.messageReplyTracker = messageReplyTracker;
} }
public bool IsSame(RpcClientConnection<TListener> other) { public bool IsSame(RpcConnectionToClient<TListener> other) {
return this.routingId == other.routingId && this.socket == other.socket; return this.routingId == other.routingId && this.socket == other.socket;
} }
@ -63,7 +62,7 @@ public sealed class RpcClientConnection<TListener> {
return await messageReplyTracker.WaitForReply<TReply>(sequenceId, waitForReplyTime, waitForReplyCancellationToken); return await messageReplyTracker.WaitForReply<TReply>(sequenceId, waitForReplyTime, waitForReplyCancellationToken);
} }
public void Receive(ReplyMessage message) { public void Receive(IReply message) {
messageReplyTracker.ReceiveReply(message.SequenceId, message.SerializedReply); messageReplyTracker.ReceiveReply(message.SequenceId, message.SerializedReply);
} }
} }

View File

@ -8,14 +8,14 @@ using Serilog.Events;
namespace Phantom.Controller.Rpc; namespace Phantom.Controller.Rpc;
public static class RpcRuntime { public static class RpcRuntime {
public static Task Launch<TOutgoingListener, TIncomingListener>(RpcConfiguration config, IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions, Func<RpcClientConnection<TOutgoingListener>, TIncomingListener> listenerFactory, CancellationToken cancellationToken) { public static Task Launch<TClientListener, TServerListener>(RpcConfiguration config, IMessageDefinitions<TClientListener, TServerListener> messageDefinitions, Func<RpcConnectionToClient<TClientListener>, TServerListener> listenerFactory, CancellationToken cancellationToken) {
return RpcRuntime<TOutgoingListener, TIncomingListener>.Launch(config, messageDefinitions, listenerFactory, cancellationToken); return RpcRuntime<TClientListener, TServerListener>.Launch(config, messageDefinitions, listenerFactory, cancellationToken);
} }
} }
internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRuntime<ServerSocket> { internal sealed class RpcRuntime<TClientListener, TServerListener> : RpcRuntime<ServerSocket> {
internal static Task Launch(RpcConfiguration config, IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions, Func<RpcClientConnection<TOutgoingListener>, TIncomingListener> listenerFactory, CancellationToken cancellationToken) { internal static Task Launch(RpcConfiguration config, IMessageDefinitions<TClientListener, TServerListener> messageDefinitions, Func<RpcConnectionToClient<TClientListener>, TServerListener> listenerFactory, CancellationToken cancellationToken) {
return new RpcRuntime<TOutgoingListener, TIncomingListener>(config, messageDefinitions, listenerFactory, cancellationToken).Launch(); return new RpcRuntime<TClientListener, TServerListener>(config, messageDefinitions, listenerFactory, cancellationToken).Launch();
} }
private static ServerSocket CreateSocket(RpcConfiguration config) { private static ServerSocket CreateSocket(RpcConfiguration config) {
@ -29,11 +29,11 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
} }
private readonly RpcConfiguration config; private readonly RpcConfiguration config;
private readonly IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions; private readonly IMessageDefinitions<TClientListener, TServerListener> messageDefinitions;
private readonly Func<RpcClientConnection<TOutgoingListener>, TIncomingListener> listenerFactory; private readonly Func<RpcConnectionToClient<TClientListener>, TServerListener> listenerFactory;
private readonly CancellationToken cancellationToken; private readonly CancellationToken cancellationToken;
private RpcRuntime(RpcConfiguration config, IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions, Func<RpcClientConnection<TOutgoingListener>, TIncomingListener> listenerFactory, CancellationToken cancellationToken) : base(config, CreateSocket(config)) { private RpcRuntime(RpcConfiguration config, IMessageDefinitions<TClientListener, TServerListener> messageDefinitions, Func<RpcConnectionToClient<TClientListener>, TServerListener> listenerFactory, CancellationToken cancellationToken) : base(config, CreateSocket(config)) {
this.config = config; this.config = config;
this.messageDefinitions = messageDefinitions; this.messageDefinitions = messageDefinitions;
this.listenerFactory = listenerFactory; this.listenerFactory = listenerFactory;
@ -71,7 +71,7 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
continue; continue;
} }
var connection = new RpcClientConnection<TOutgoingListener>(socket, routingId, messageDefinitions.Outgoing, replyTracker); var connection = new RpcConnectionToClient<TClientListener>(socket, routingId, messageDefinitions.ToClient, replyTracker);
connection.Closed += OnConnectionClosed; connection.Closed += OnConnectionClosed;
client = new Client(connection, messageDefinitions, listenerFactory(connection), logger, taskManager, cancellationToken); client = new Client(connection, messageDefinitions, listenerFactory(connection), logger, taskManager, cancellationToken);
@ -79,7 +79,7 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
} }
LogMessageType(logger, routingId, data); LogMessageType(logger, routingId, data);
messageDefinitions.Incoming.Handle(data, client); messageDefinitions.ToServer.Handle(data, client);
} }
foreach (var client in clients.Values) { foreach (var client in clients.Values) {
@ -92,7 +92,7 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
return; return;
} }
if (data.Length > 0 && messageDefinitions.Incoming.TryGetType(data, out var type)) { if (data.Length > 0 && messageDefinitions.ToServer.TryGetType(data, out var type)) {
logger.Verbose("Received {MessageType} ({Bytes} B) from {RoutingId}.", type.Name, data.Length, routingId); logger.Verbose("Received {MessageType} ({Bytes} B) from {RoutingId}.", type.Name, data.Length, routingId);
} }
else { else {
@ -101,7 +101,7 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
} }
private bool CheckIsRegistrationMessage(ReadOnlyMemory<byte> data, ILogger logger, uint routingId) { private bool CheckIsRegistrationMessage(ReadOnlyMemory<byte> data, ILogger logger, uint routingId) {
if (messageDefinitions.Incoming.TryGetType(data, out var type) && messageDefinitions.IsRegistrationMessage(type)) { if (messageDefinitions.ToServer.TryGetType(data, out var type) && messageDefinitions.IsRegistrationMessage(type)) {
return true; return true;
} }
@ -109,18 +109,18 @@ internal sealed class RpcRuntime<TOutgoingListener, TIncomingListener> : RpcRunt
return false; return false;
} }
private sealed class Client : MessageHandler<TIncomingListener> { private sealed class Client : MessageHandler<TServerListener> {
public RpcClientConnection<TOutgoingListener> Connection { get; } public RpcConnectionToClient<TClientListener> Connection { get; }
private readonly IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions; private readonly IMessageDefinitions<TClientListener, TServerListener> messageDefinitions;
public Client(RpcClientConnection<TOutgoingListener> connection, IMessageDefinitions<TOutgoingListener, TIncomingListener> messageDefinitions, TIncomingListener listener, ILogger logger, TaskManager taskManager, CancellationToken cancellationToken) : base(listener, logger, taskManager, cancellationToken) { public Client(RpcConnectionToClient<TClientListener> connection, IMessageDefinitions<TClientListener, TServerListener> messageDefinitions, TServerListener listener, ILogger logger, TaskManager taskManager, CancellationToken cancellationToken) : base(listener, logger, taskManager, cancellationToken) {
this.Connection = connection; this.Connection = connection;
this.messageDefinitions = messageDefinitions; this.messageDefinitions = messageDefinitions;
} }
protected override Task SendReply(uint sequenceId, byte[] serializedReply) { protected override Task SendReply(uint sequenceId, byte[] serializedReply) {
return Connection.Send(messageDefinitions.CreateReplyMessage(sequenceId, serializedReply)); return Connection.Send(messageDefinitions.CreateReplyToServerMessage(sequenceId, serializedReply));
} }
} }
} }

View File

@ -4,13 +4,13 @@ using Phantom.Controller.Rpc;
namespace Phantom.Controller.Services.Agents; namespace Phantom.Controller.Services.Agents;
sealed class AgentConnection { sealed class AgentConnection {
private readonly RpcClientConnection<IMessageToAgentListener> connection; private readonly RpcConnectionToClient<IMessageToAgentListener> connection;
internal AgentConnection(RpcClientConnection<IMessageToAgentListener> connection) { internal AgentConnection(RpcConnectionToClient<IMessageToAgentListener> connection) {
this.connection = connection; this.connection = connection;
} }
public bool IsSame(RpcClientConnection<IMessageToAgentListener> connection) { public bool IsSame(RpcConnectionToClient<IMessageToAgentListener> connection) {
return this.connection.IsSame(connection); return this.connection.IsSame(connection);
} }

View File

@ -2,7 +2,7 @@
using Phantom.Common.Data.Java; using Phantom.Common.Data.Java;
using Phantom.Utils.Collections; using Phantom.Utils.Collections;
namespace Phantom.Controller.Services.Agents; namespace Phantom.Controller.Services.Agents;
public sealed class AgentJavaRuntimesManager { public sealed class AgentJavaRuntimesManager {
private readonly RwLockedDictionary<Guid, ImmutableArray<TaggedJavaRuntime>> runtimes = new (LockRecursionPolicy.NoRecursion); private readonly RwLockedDictionary<Guid, ImmutableArray<TaggedJavaRuntime>> runtimes = new (LockRecursionPolicy.NoRecursion);

View File

@ -52,7 +52,7 @@ public sealed class AgentManager {
return agents.ByGuid.ToImmutable(); return agents.ByGuid.ToImmutable();
} }
internal async Task<bool> RegisterAgent(AuthToken authToken, AgentInfo agentInfo, InstanceManager instanceManager, RpcClientConnection<IMessageToAgentListener> connection) { internal async Task<bool> RegisterAgent(AuthToken authToken, AgentInfo agentInfo, InstanceManager instanceManager, RpcConnectionToClient<IMessageToAgentListener> connection) {
if (!this.authToken.FixedTimeEquals(authToken)) { if (!this.authToken.FixedTimeEquals(authToken)) {
await connection.Send(new RegisterAgentFailureMessage(RegisterAgentFailure.InvalidToken)); await connection.Send(new RegisterAgentFailureMessage(RegisterAgentFailure.InvalidToken));
return false; return false;
@ -88,7 +88,7 @@ public sealed class AgentManager {
return true; return true;
} }
internal bool UnregisterAgent(Guid agentGuid, RpcClientConnection<IMessageToAgentListener> connection) { internal bool UnregisterAgent(Guid agentGuid, RpcConnectionToClient<IMessageToAgentListener> connection) {
if (agents.ByGuid.TryReplaceIf(agentGuid, static oldAgent => oldAgent.AsOffline(), oldAgent => oldAgent.Connection?.IsSame(connection) == true)) { if (agents.ByGuid.TryReplaceIf(agentGuid, static oldAgent => oldAgent.AsOffline(), oldAgent => oldAgent.Connection?.IsSame(connection) == true)) {
Logger.Information("Unregistered agent with GUID {Guid}.", agentGuid); Logger.Information("Unregistered agent with GUID {Guid}.", agentGuid);
return true; return true;

Some files were not shown because too many files have changed in this diff Show More