From 7897557dbc65500cfbffe0cae8f4c26996810bc2 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Mon, 17 Feb 2025 23:19:54 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=BE=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B1=D0=B0=D0=B7=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20=D1=83?= =?UTF-8?q?=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=8A=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mROA/Abstract/ICommandExecution.cs | 2 +- mROA/Abstract/IRemoteObject.cs | 7 --- .../Backend/BasicExecutionModule.cs | 12 ++-- .../Backend/NetworkGatewayModule.cs | 7 +-- mROA/Implementation/CallRequest.cs | 7 ++- .../ExceptionCommandExecution.cs | 11 +++- .../CommandExecution/FinalCommandExecution.cs | 2 +- .../Frontend/RequestExtractor.cs | 48 ++++++++++----- mROA/Implementation/NetworkMessage.cs | 2 +- .../Implementation/RemoteContextRepository.cs | 2 +- mROA/Implementation/RemoteObjectBase.cs | 59 +++++++++++++++++++ mROA/Implementation/SharedObject.cs | 2 +- 12 files changed, 118 insertions(+), 43 deletions(-) delete mode 100644 mROA/Abstract/IRemoteObject.cs create mode 100644 mROA/Implementation/RemoteObjectBase.cs diff --git a/mROA/Abstract/ICommandExecution.cs b/mROA/Abstract/ICommandExecution.cs index 1d12a6e..4566f1d 100644 --- a/mROA/Abstract/ICommandExecution.cs +++ b/mROA/Abstract/ICommandExecution.cs @@ -2,7 +2,7 @@ namespace mROA.Abstract; public interface ICommandExecution { - Guid CallRequestId { get; init; } + Guid Id { get; init; } int ClientId { get; set; } int CommandId { get; } } \ No newline at end of file diff --git a/mROA/Abstract/IRemoteObject.cs b/mROA/Abstract/IRemoteObject.cs deleted file mode 100644 index 1c1d0f1..0000000 --- a/mROA/Abstract/IRemoteObject.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace mROA.Abstract; - -public interface IRemoteObject -{ - public int Id { get; } - public int OwnerId { get; } -} \ No newline at end of file diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index f8b2fff..946ba96 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -48,7 +48,7 @@ public class BasicExecutionModule : IExecuteModule return new TypedFinalCommandExecution { CommandId = command.CommandId, Result = finalResult, - CallRequestId = command.CallRequestId, + Id = command.CallRequestId, Type = currentCommand.ReturnType }; } @@ -56,7 +56,7 @@ public class BasicExecutionModule : IExecuteModule { return new ExceptionCommandExecution { - CallRequestId = command.CallRequestId, CommandId = command.CommandId, + Id = command.CallRequestId, CommandId = command.CommandId, Exception = e.ToString() }; } @@ -75,13 +75,13 @@ public class BasicExecutionModule : IExecuteModule result.Wait(token); - return new FinalCommandExecution { CommandId = command.CommandId, CallRequestId = command.CallRequestId }; + return new FinalCommandExecution { CommandId = command.CommandId, Id = command.CallRequestId }; } catch (Exception e) { return new ExceptionCommandExecution { - CallRequestId = command.CallRequestId, CommandId = command.CommandId, + Id = command.CallRequestId, CommandId = command.CommandId, Exception = e.ToString() }; } @@ -102,7 +102,7 @@ public class BasicExecutionModule : IExecuteModule var finalResult = result.GetType().GetProperty("Result")?.GetValue(result); return new TypedFinalCommandExecution { - CallRequestId = command.CallRequestId, + Id = command.CallRequestId, Result = finalResult, CommandId = command.CommandId, Type = finalResult?.GetType() @@ -112,7 +112,7 @@ public class BasicExecutionModule : IExecuteModule { return new ExceptionCommandExecution { - CallRequestId = command.CallRequestId, CommandId = command.CommandId, + Id = command.CallRequestId, CommandId = command.CommandId, Exception = e.ToString() }; } diff --git a/mROA/Implementation/Backend/NetworkGatewayModule.cs b/mROA/Implementation/Backend/NetworkGatewayModule.cs index d2da8cb..4865db0 100644 --- a/mROA/Implementation/Backend/NetworkGatewayModule.cs +++ b/mROA/Implementation/Backend/NetworkGatewayModule.cs @@ -6,7 +6,6 @@ namespace mROA.Implementation.Backend; public class NetworkGatewayModule : IGatewayModule { - private readonly IPEndPoint? _endpoint; private readonly Type? _interactionModuleType; private readonly IInjectableModule[]? _injectableModules; private readonly TcpListener? _tcpListener; @@ -14,16 +13,14 @@ public class NetworkGatewayModule : IGatewayModule public NetworkGatewayModule(IPEndPoint endpoint, Type interactionModuleType, IInjectableModule[] injectableModules) { - _endpoint = endpoint; - _tcpListener = new(_endpoint); - + _tcpListener = new(endpoint); _interactionModuleType = interactionModuleType; _injectableModules = injectableModules; } public void Run() { - _tcpListener.Start(); + _tcpListener!.Start(); Console.WriteLine($"Listening on {_tcpListener.LocalEndpoint}"); Console.WriteLine("Enter Backspace to stop"); diff --git a/mROA/Implementation/CallRequest.cs b/mROA/Implementation/CallRequest.cs index faa680d..0b5f17d 100644 --- a/mROA/Implementation/CallRequest.cs +++ b/mROA/Implementation/CallRequest.cs @@ -1,4 +1,6 @@ -namespace mROA.Implementation; +using System.Text.Json.Serialization; + +namespace mROA.Implementation; public interface ICallRequest { @@ -14,6 +16,7 @@ public class DefaultCallRequest : ICallRequest public int CommandId { get; init; } public int ObjectId { get; init; } = -1; - public Type ParameterType { get; init; } + [JsonIgnore] + public Type? ParameterType { get; init; } public object? Parameter { get; set; } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs index 5df0742..58ef0a4 100644 --- a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs @@ -1,11 +1,18 @@ -using mROA.Abstract; +using System.Text.Json; +using mROA.Abstract; +using mROA.Implementation.Frontend; namespace mROA.Implementation; public class ExceptionCommandExecution : ICommandExecution { - public Guid CallRequestId { get; init; } + public Guid Id { get; init; } public int ClientId { get; set; } public int CommandId { get; init; } public required string Exception { get; set; } + + public RemoteException GetException() + { + return new RemoteException(Exception) { CallRequestId = Id }; + } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs index 9e3193a..e0b21f4 100644 --- a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs @@ -7,7 +7,7 @@ namespace mROA.Implementation; public class FinalCommandExecution : ICommandExecution { - public Guid CallRequestId { get; init; } + public Guid Id { get; init; } [JsonIgnore] public int ClientId { get; set; } [JsonIgnore] diff --git a/mROA/Implementation/Frontend/RequestExtractor.cs b/mROA/Implementation/Frontend/RequestExtractor.cs index 1129b2a..6c52060 100644 --- a/mROA/Implementation/Frontend/RequestExtractor.cs +++ b/mROA/Implementation/Frontend/RequestExtractor.cs @@ -1,4 +1,5 @@ using mROA.Abstract; +using mROA.Implementation.Backend; namespace mROA.Implementation.Frontend; @@ -9,6 +10,7 @@ public class RequestExtractor : IRequestExtractor private IMethodRepository? _methodRepository; private IExecuteModule? _executeModule; private ISerializationToolkit? _serializationToolkit; + public void Inject(T dependency) { switch (dependency) @@ -43,25 +45,39 @@ public class RequestExtractor : IRequestExtractor throw new NullReferenceException("Representation module is null."); if (_methodRepository == null) throw new NullReferenceException("Method repository is null."); - - while (true) + + var multiClientOwnershipRepository = TransmissionConfig.OwnershipRepository as MultiClientOwnershipRepository; + + + multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); + + try { - var request = await _representationModule!.GetMessage(messageType: MessageType.CallRequest); - - if (request.Parameter is not null) + while (true) { - var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First().ParameterType; - request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType); + var request = + await _representationModule!.GetMessage(messageType: MessageType.CallRequest); + + if (request.Parameter is not null) + { + var parameterType = _methodRepository!.GetMethod(request.CommandId).GetParameters().First() + .ParameterType; + + request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType); + } + + var result = _executeModule.Execute(request, _contextRepository); + + var resultType = result is FinalCommandExecution + ? MessageType.FinishedCommandExecution + : MessageType.ExceptionCommandExecution; + + await _representationModule.PostCallMessage(request.CallRequestId, resultType, result); } - - var result = _executeModule.Execute(request, _contextRepository); - - var resultType = result is FinalCommandExecution - ? MessageType.FinishedCommandExecution - : MessageType.ErrorCommandExecution; - - await _representationModule.PostCallMessage(request.CallRequestId, resultType, result); - + } + catch + { + multiClientOwnershipRepository?.RegisterOwnership(_representationModule.Id); } } } \ No newline at end of file diff --git a/mROA/Implementation/NetworkMessage.cs b/mROA/Implementation/NetworkMessage.cs index bd70245..066efe2 100644 --- a/mROA/Implementation/NetworkMessage.cs +++ b/mROA/Implementation/NetworkMessage.cs @@ -12,5 +12,5 @@ public class NetworkMessage public enum MessageType { - Unknown, FinishedCommandExecution, ErrorCommandExecution, AcyncCancelCommandExecution, CallRequest, IdAssigning + Unknown, FinishedCommandExecution, ExceptionCommandExecution, AcyncCancelCommandExecution, CallRequest, IdAssigning } \ No newline at end of file diff --git a/mROA/Implementation/RemoteContextRepository.cs b/mROA/Implementation/RemoteContextRepository.cs index 3236944..7ff911a 100644 --- a/mROA/Implementation/RemoteContextRepository.cs +++ b/mROA/Implementation/RemoteContextRepository.cs @@ -39,7 +39,7 @@ public class RemoteContextRepository : IContextRepository public int GetObjectIndex(object o) { - if (o is IRemoteObject remote) + if (o is RemoteObjectBase remote) { return remote.Id; } diff --git a/mROA/Implementation/RemoteObjectBase.cs b/mROA/Implementation/RemoteObjectBase.cs new file mode 100644 index 0000000..00c7129 --- /dev/null +++ b/mROA/Implementation/RemoteObjectBase.cs @@ -0,0 +1,59 @@ +using mROA.Implementation; +// ReSharper disable UnusedMember.Global + +namespace mROA.Abstract; + +public abstract class RemoteObjectBase +{ + private readonly int _id; + private readonly IRepresentationModule _representationModule; + public int Id => _id; + public int OwnerId => _representationModule.Id; + + public RemoteObjectBase(int id, IRepresentationModule representationModule) + { + _id = id; + _representationModule = representationModule; + } + + public async Task GetResultAsync(int methodId, object? parameter = default) + { + var request = new DefaultCallRequest + { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() }; + await _representationModule.PostCallMessage(request.CallRequestId, MessageType.CallRequest, request); + + var successResponse = + _representationModule.GetMessage>( + messageType: MessageType.FinishedCommandExecution, requestId: request.CallRequestId); + var errorResponse = + _representationModule.GetMessage( + messageType: MessageType.ExceptionCommandExecution, requestId: request.CallRequestId); + Task.WaitAny(successResponse, errorResponse); + + if (successResponse.IsCompletedSuccessfully) + return successResponse.Result.Result!; + + throw errorResponse.Result.GetException(); + } + + public async Task CallAsync(int methodId, object? parameter = default) + { + var request = new DefaultCallRequest + { CommandId = methodId, ObjectId = _id, Parameter = parameter, ParameterType = parameter?.GetType() }; + await _representationModule.PostCallMessage(request.CallRequestId, MessageType.CallRequest, request); + + var successResponse = + _representationModule.GetMessage( + messageType: MessageType.FinishedCommandExecution, requestId: request.CallRequestId); + var errorResponse = + _representationModule.GetMessage( + messageType: MessageType.ExceptionCommandExecution, requestId: request.CallRequestId); + + Task.WaitAny(successResponse, errorResponse); + + if (successResponse.IsCompletedSuccessfully) + return; + + throw errorResponse.Result.GetException(); + } +} \ No newline at end of file diff --git a/mROA/Implementation/SharedObject.cs b/mROA/Implementation/SharedObject.cs index 0864440..c91ce50 100644 --- a/mROA/Implementation/SharedObject.cs +++ b/mROA/Implementation/SharedObject.cs @@ -63,7 +63,7 @@ public class SharedObject where T : notnull { Value = value; - if (value is IRemoteObject ro) + if (value is RemoteObjectBase ro) { _ownerId = ro.OwnerId; _contextId = ro.Id;