Merge remote-tracking branch 'origin/Distribution'

This commit is contained in:
2025-07-19 21:15:53 +03:00
20 changed files with 228 additions and 189 deletions
+4 -8
View File
@@ -1,5 +1,4 @@
using System; using System;
using System.Linq;
using System.Net; using System.Net;
using Example.Backend; using Example.Backend;
using Example.Shared; using Example.Shared;
@@ -10,24 +9,26 @@ using mROA.Implementation;
using mROA.Implementation.Backend; using mROA.Implementation.Backend;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program class Program
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
var builder = Host.CreateApplicationBuilder(); var builder = Host.CreateApplicationBuilder();
builder.Services.AddLogging(l => l.AddConsole());
builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>(); builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>();
builder.Services.AddSingleton<IIdentityGenerator, BackendIdentityGenerator>(); builder.Services.AddSingleton<IIdentityGenerator, BackendIdentityGenerator>();
builder.Services.AddSingleton<IGatewayModule, NetworkGatewayModule>(); builder.Services.AddSingleton<IGatewayModule, NetworkGatewayModule>();
builder.Services.AddSingleton<IUntrustedGateway, UdpGateway>(); builder.Services.AddSingleton<IUntrustedGateway, UdpGateway>();
builder.Services.AddSingleton<IConnectionHub, ConnectionHub>(); builder.Services.AddSingleton<IConnectionHub, ConnectionHub>();
builder.Services.AddOptions(); builder.Services.AddOptions();
var listening = new IPEndPoint(IPAddress.Any, 4567); var listening = new IPEndPoint(IPAddress.Any, 4567);
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = listening); builder.Services.Configure<GatewayOptions>(options => options.Endpoint = listening);
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.ExtractorFirst);
builder.Services.AddSingleton<HubRequestExtractor>(); builder.Services.AddSingleton<HubRequestExtractor>();
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>(); builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
builder.Services.AddSingleton<IRepresentationModuleProducer, CreativeRepresentationModuleProducer>(); builder.Services.AddSingleton<IRepresentationModuleProducer, CreativeRepresentationModuleProducer>();
builder.Services.AddSingleton<IInstanceRepository, RemoteInstanceRepository>(); builder.Services.AddSingleton<IInstanceRepository, RemoteInstanceRepository>();
@@ -40,7 +41,6 @@ class Program
return repo; return repo;
})); }));
builder.Services.AddSingleton<IMessageDistributorFactory, ChannelDistributorFactory>();
builder.Services.AddSingleton<IMethodRepository>(p => builder.Services.AddSingleton<IMethodRepository>(p =>
{ {
var methodRepo = new CollectableMethodRepository(); var methodRepo = new CollectableMethodRepository();
@@ -52,17 +52,13 @@ class Program
builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>(); builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>();
var host = builder.Build(); var host = builder.Build();
host.Services.GetService<HubRequestExtractor>();
// //
// builder.Build();
new RemoteTypeBinder(); new RemoteTypeBinder();
//
// //
_ = host.Services.GetService<IUntrustedGateway>()!.Start(); _ = host.Services.GetService<IUntrustedGateway>()!.Start();
var gateway = host.Services.GetService<IGatewayModule>(); var gateway = host.Services.GetService<IGatewayModule>();
gateway.Run(); gateway.Run();
Console.ReadLine(); Console.ReadLine();
} }
} }
+6
View File
@@ -8,6 +8,7 @@ using Example.Frontend;
using Example.Shared; using Example.Shared;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using mROA.Abstract; using mROA.Abstract;
using mROA.Cbor; using mROA.Cbor;
using mROA.Codegen; using mROA.Codegen;
@@ -23,6 +24,8 @@ class Program
new RemoteTypeBinder(); new RemoteTypeBinder();
var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true }); var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true });
builder.Services.AddLogging(l => l.SetMinimumLevel(LogLevel.Trace).AddConsole());
builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>(); builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>();
builder.Services.AddSingleton<IEndPointContext, EndPointContext>(); builder.Services.AddSingleton<IEndPointContext, EndPointContext>();
builder.Services.AddSingleton<IRealStoreInstanceRepository, InstanceRepository>(provider => builder.Services.AddSingleton<IRealStoreInstanceRepository, InstanceRepository>(provider =>
@@ -39,8 +42,11 @@ class Program
builder.Services.AddSingleton<IRepresentationModule, RepresentationModule>(); builder.Services.AddSingleton<IRepresentationModule, RepresentationModule>();
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567); var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567);
builder.Services.AddSingleton<IFrontendBridge, NetworkFrontendBridge>(); builder.Services.AddSingleton<IFrontendBridge, NetworkFrontendBridge>();
builder.Services.AddOptions(); builder.Services.AddOptions();
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint); builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.Channeled);
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>(); builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>(); builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>(); builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
+1 -1
View File
@@ -32,7 +32,7 @@ Console.WriteLine("End waiting");
var totalRequests = tasks.Sum(i => i.Result); var totalRequests = tasks.Sum(i => i.Result);
Console.WriteLine($"Total requests: {totalRequests:N0}"); Console.WriteLine($"Total requests: {totalRequests:N0}");
Console.WriteLine($"Results: {totalRequests / time.TotalSeconds:N} RPS"); Console.WriteLine($"Results: {totalRequests / time.TotalSeconds:N} RPS");
File.AppendAllText("results.txt", $"[DIRECT TO EXE RUN] {totalRequests}\r\n");
async Task<List<ILoadTest>> GetLoadEndpoints(int count) async Task<List<ILoadTest>> GetLoadEndpoints(int count)
{ {
@@ -1,15 +0,0 @@
using System.Threading.Tasks;
using mROA.Implementation;
namespace mROA.Abstract
{
public interface IPrimaryMessageDistributior
{
Task Distribute(NetworkMessageHeader message);
}
public interface IMessageDistributorFactory
{
IPrimaryMessageDistributior Produce(int clientId);
}
}
@@ -1,5 +1,6 @@
using System; using System;
using System.Threading; using System.Threading;
using Microsoft.Extensions.Logging;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.CommandExecution; using mROA.Implementation.CommandExecution;
@@ -10,17 +11,20 @@ namespace mROA.Implementation.Backend
private readonly ICancellationRepository _cancellationRepo; private readonly ICancellationRepository _cancellationRepo;
private readonly IMethodRepository _methodRepo; private readonly IMethodRepository _methodRepo;
private readonly IContextualSerializationToolKit _serialization; private readonly IContextualSerializationToolKit _serialization;
private readonly ILogger<BasicExecutionModule> _logger;
public BasicExecutionModule(ICancellationRepository cancellationRepo, IMethodRepository methodRepo, IContextualSerializationToolKit serialization) public BasicExecutionModule(ICancellationRepository cancellationRepo, IMethodRepository methodRepo, IContextualSerializationToolKit serialization, ILogger<BasicExecutionModule> logger)
{ {
_cancellationRepo = cancellationRepo; _cancellationRepo = cancellationRepo;
_methodRepo = methodRepo; _methodRepo = methodRepo;
_serialization = serialization; _serialization = serialization;
_logger = logger;
} }
public ICommandExecution Execute(ICallRequest command, IInstanceRepository instanceRepository, public ICommandExecution Execute(ICallRequest command, IInstanceRepository instanceRepository,
IRepresentationModule representationModule, IEndPointContext endPointContext) IRepresentationModule representationModule, IEndPointContext endPointContext)
{ {
// _logger.LogInformation("Executing {0}", command.Id);
try try
{ {
if (command is CancelRequest) if (command is CancelRequest)
@@ -7,18 +7,10 @@ namespace mROA.Implementation.Backend
public class ConnectionHub : IConnectionHub public class ConnectionHub : IConnectionHub
{ {
private readonly Dictionary<int, IChannelInteractionModule> _connections = new(); private readonly Dictionary<int, IChannelInteractionModule> _connections = new();
private readonly IContextualSerializationToolKit _serializationToolkit;
public ConnectionHub(IContextualSerializationToolKit serializationToolkit)
{
_serializationToolkit = serializationToolkit;
}
public void RegisterInteraction(IChannelInteractionModule interaction) public void RegisterInteraction(IChannelInteractionModule interaction)
{ {
_connections.Add(interaction.ConnectionId, interaction); _connections.Add(interaction.ConnectionId, interaction);
var module = new RepresentationModule(interaction, _serializationToolkit);
OnConnected?.Invoke(module);
} }
public IChannelInteractionModule GetInteraction(int id) public IChannelInteractionModule GetInteraction(int id)
@@ -1,3 +1,5 @@
using System.Collections.Generic;
using Microsoft.Extensions.Options;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.Frontend; using mROA.Implementation.Frontend;
@@ -5,30 +7,36 @@ namespace mROA.Implementation.Backend
{ {
public class HubRequestExtractor public class HubRequestExtractor
{ {
private IRealStoreInstanceRepository _contextRepository; private readonly IRealStoreInstanceRepository _contextRepository;
private IInstanceRepository _remoteContextRepository; private readonly IInstanceRepository _remoteContextRepository;
private IMethodRepository _methodRepository; private readonly IExecuteModule _executeModule;
private IContextualSerializationToolKit _serializationToolkit; private readonly DistributionOptions _mode;
private IExecuteModule _executeModule; private Dictionary<int, IRequestExtractor> _producedExtractors = new();
public HubRequestExtractor(IConnectionHub hub, IRealStoreInstanceRepository contextRepository, public HubRequestExtractor(IRealStoreInstanceRepository contextRepository,
IInstanceRepository remoteContextRepository, IMethodRepository methodRepository, IInstanceRepository remoteContextRepository, IExecuteModule executeModule,
IContextualSerializationToolKit serializationToolkit, IExecuteModule executeModule) IOptions<DistributionOptions> mode)
{ {
hub.OnConnected += HubOnOnConnected;
_contextRepository = contextRepository; _contextRepository = contextRepository;
_remoteContextRepository = remoteContextRepository; _remoteContextRepository = remoteContextRepository;
_methodRepository = methodRepository;
_serializationToolkit = serializationToolkit;
_executeModule = executeModule; _executeModule = executeModule;
_mode = mode.Value;
} }
private void HubOnOnConnected(IRepresentationModule interaction) public IRequestExtractor this[int id] => _producedExtractors[id];
public IRequestExtractor HubOnOnConnected(IRepresentationModule interaction)
{ {
var extractor = CreateExtractor(interaction); var extractor = CreateExtractor(interaction);
if (_mode.DistributionType == EDistributionType.Channeled)
{
extractor.StartExtraction().ContinueWith(_ => OnDisconnected(interaction)); extractor.StartExtraction().ContinueWith(_ => OnDisconnected(interaction));
} }
_producedExtractors[interaction.Id] = extractor;
return extractor;
}
private void OnDisconnected(IRepresentationModule representationModule) private void OnDisconnected(IRepresentationModule representationModule)
{ {
if (_contextRepository is IContextRepositoryHub contextHub) if (_contextRepository is IContextRepositoryHub contextHub)
@@ -11,7 +11,7 @@ namespace mROA.Implementation.Backend
{ {
public static object[] EventBinders = { }; public static object[] EventBinders = { };
private IRepresentationModuleProducer _representationModuleProducer; private readonly IRepresentationModuleProducer _representationModuleProducer;
private Dictionary<int, object?> _singletons = new(); private Dictionary<int, object?> _singletons = new();
private readonly IStorage<object> _storage; private readonly IStorage<object> _storage;
@@ -4,6 +4,7 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using mROA.Abstract; using mROA.Abstract;
@@ -13,19 +14,26 @@ namespace mROA.Implementation.Backend
{ {
private readonly TcpListener _tcpListener; private readonly TcpListener _tcpListener;
private readonly IConnectionHub _hub; private readonly IConnectionHub _hub;
private readonly HubRequestExtractor _hre;
private readonly ILogger _logger;
private readonly DistributionOptions _distribution;
private readonly IContextualSerializationToolKit _serialization; private readonly IContextualSerializationToolKit _serialization;
private readonly Dictionary<int, CancellationTokenSource> _extractorsCTS = new(); private readonly Dictionary<int, CancellationTokenSource> _extractorsTokenSources = new();
private ICallIndexProvider _callIndexProvider; private readonly ICallIndexProvider _callIndexProvider;
private readonly IIdentityGenerator _identityGenerator; private readonly IIdentityGenerator _identityGenerator;
private readonly IMessageDistributorFactory _distributorFactory;
public NetworkGatewayModule(IOptions<GatewayOptions> options, IIdentityGenerator identityGenerator, IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub, IMessageDistributorFactory distributorFactory) public NetworkGatewayModule(IOptions<GatewayOptions> options, IIdentityGenerator identityGenerator,
IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub,
IOptions<DistributionOptions> distribution, HubRequestExtractor hre, ILogger<ChannelInteractionModule.StreamExtractor> logger)
{ {
_tcpListener = new(options.Value.Endpoint); _tcpListener = new(options.Value.Endpoint);
_identityGenerator = identityGenerator; _identityGenerator = identityGenerator;
_serialization = serialization; _serialization = serialization;
_callIndexProvider = callIndexProvider; _callIndexProvider = callIndexProvider;
_hub = hub; _hub = hub;
_distributorFactory = distributorFactory; _hre = hre;
_logger = logger;
_distribution = distribution.Value;
} }
public void Run() public void Run()
@@ -47,17 +55,25 @@ namespace mROA.Implementation.Backend
while (true) while (true)
{ {
var client = await _tcpListener.AcceptTcpClientAsync(); var client = await _tcpListener.AcceptTcpClientAsync();
_ = HandleConnection(client).ConfigureAwait(false);
}
}
private async Task HandleConnection(TcpClient client)
{
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}"); Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
var interaction = new ChannelInteractionModule(_serialization, _identityGenerator); var interaction = new ChannelInteractionModule(_serialization, _identityGenerator);
var context = new EndPointContext(null, null); var context = new EndPointContext(null, null)
context.CallIndexProvider = _callIndexProvider; {
CallIndexProvider = _callIndexProvider
};
var streamExtractor = var streamExtractor =
new ChannelInteractionModule.StreamExtractor(client.GetStream(), _serialization, context); new ChannelInteractionModule.StreamExtractor(client.GetStream(), _serialization, context, _logger);
interaction.IsConnected = () => streamExtractor.IsConnected; interaction.IsConnected = () => streamExtractor.IsConnected;
streamExtractor.MessageReceived = async message => streamExtractor.MessageReceived = async message =>
{ {
await interaction.ReceiveChanel.Writer.WriteAsync(message); await interaction.ReceiveChanel.Writer.WriteAsync(message).ConfigureAwait(false);
}; };
_ = Task.Run(() => streamExtractor.SingleReceive()); _ = Task.Run(() => streamExtractor.SingleReceive());
var connectionRequest = await interaction.ReceiveChanel.Reader.ReadAsync(); var connectionRequest = await interaction.ReceiveChanel.Reader.ReadAsync();
@@ -66,35 +82,11 @@ namespace mROA.Implementation.Backend
switch (connectionRequest.MessageType) switch (connectionRequest.MessageType)
{ {
case EMessageType.ClientConnect: case EMessageType.ClientConnect:
context.HostId = 0; HandleNewClient(context, interaction, streamExtractor, cts);
context.OwnerId = -interaction.ConnectionId;
interaction.Context = context;
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token));
_ = streamExtractor.SendFromChannel(interaction.TrustedPostChanel, cts.Token);
interaction.PostMessageAsync(new NetworkMessageHeader(_serialization!,
new IdAssignment { Id = interaction.ConnectionId }, null));
_extractorsCTS[interaction.ConnectionId] = cts;
_hub.RegisterInteraction(interaction);
Console.WriteLine("Client registered");
break; break;
case EMessageType.ClientRecovery: case EMessageType.ClientRecovery:
{ {
var recoveryRequest = _serialization!.Deserialize<ClientRecovery>(connectionRequest.Data, null); RecoverDisconnectedClient(connectionRequest, streamExtractor, cts);
var recoveryInteraction = _hub.GetInteraction(recoveryRequest.Id);
_extractorsCTS[-recoveryRequest.Id].Cancel();
recoveryInteraction.IsConnected = () => streamExtractor.IsConnected;
streamExtractor.MessageReceived = message =>
{
recoveryInteraction.ReceiveChanel.Writer.WriteAsync(message);
};
_ = streamExtractor.SendFromChannel(recoveryInteraction.TrustedPostChanel, cts.Token);
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token));
recoveryInteraction.Restart(false);
break; break;
} }
default: default:
@@ -102,6 +94,78 @@ namespace mROA.Implementation.Backend
break; break;
} }
} }
private void HandleNewClient(EndPointContext context, ChannelInteractionModule interaction,
ChannelInteractionModule.StreamExtractor streamExtractor, CancellationTokenSource cts)
{
context.HostId = 0;
context.OwnerId = -interaction.ConnectionId;
interaction.Context = context;
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token));
_ = streamExtractor.SendFromChannel(interaction.TrustedPostChanel, cts.Token);
interaction.PostMessageAsync(new NetworkMessageHeader(_serialization,
new IdAssignment { Id = interaction.ConnectionId }, null));
_extractorsTokenSources[interaction.ConnectionId] = cts;
_hub.RegisterInteraction(interaction);
var requestExtractor = _hre.HubOnOnConnected(new RepresentationModule(interaction, _serialization));
if (_distribution.DistributionType != EDistributionType.Channeled)
{
BindRequestFirstDistribution(context, interaction, streamExtractor, requestExtractor);
}
}
private void BindRequestFirstDistribution(IEndPointContext context, IChannelInteractionModule interaction,
ChannelInteractionModule.StreamExtractor streamExtractor, IRequestExtractor requestExtractor)
{
var converters = requestExtractor.Converters;
streamExtractor.MessageReceived = message =>
{
if (requestExtractor.Rule(message))
{
for (int i = 0; i < converters.Length; i++)
{
var func = converters[i];
if (func(message) is { } t)
{
var deserialized = _serialization.Deserialize(message.Data, t, context);
Task.Run(() => requestExtractor.PushMessage(deserialized, message.MessageType));
break;
}
}
return;
}
interaction.ReceiveChanel.Writer.WriteAsync(message).ConfigureAwait(false);
};
}
private void RecoverDisconnectedClient(NetworkMessageHeader connectionRequest,
ChannelInteractionModule.StreamExtractor streamExtractor,
CancellationTokenSource cts)
{
var recoveryRequest = _serialization.Deserialize<ClientRecovery>(connectionRequest.Data, null);
var recoveryInteraction = _hub.GetInteraction(recoveryRequest.Id);
_extractorsTokenSources[-recoveryRequest.Id].Cancel();
recoveryInteraction.IsConnected = () => streamExtractor.IsConnected;
streamExtractor.MessageReceived = message =>
{
recoveryInteraction.ReceiveChanel.Writer.WriteAsync(message).ConfigureAwait(false);
};
_ = streamExtractor.SendFromChannel(recoveryInteraction.TrustedPostChanel, cts.Token);
if (_distribution.DistributionType == EDistributionType.ExtractorFirst)
{
BindRequestFirstDistribution(recoveryInteraction.Context, recoveryInteraction, streamExtractor, _hre[recoveryInteraction.ConnectionId]);
}
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token).ConfigureAwait(false));
recoveryInteraction.Restart(false);
} }
} }
+5 -5
View File
@@ -12,11 +12,11 @@ namespace mROA.Implementation.Backend
{ {
public class UdpGateway : IUntrustedGateway public class UdpGateway : IUntrustedGateway
{ {
private IConnectionHub _hub; private readonly IConnectionHub _hub;
private UdpClient _client; private readonly UdpClient _client;
private Dictionary<IPEndPoint, int> _reservedPorts = new(); private readonly Dictionary<IPEndPoint, int> _reservedPorts = new();
private CancellationTokenSource _tokenSource = new(); private readonly CancellationTokenSource _tokenSource = new();
private IContextualSerializationToolKit _serializationToolkit; private readonly IContextualSerializationToolKit _serializationToolkit;
public UdpGateway(IOptions<GatewayOptions> options, IConnectionHub hub, IContextualSerializationToolKit serializationToolkit) public UdpGateway(IOptions<GatewayOptions> options, IConnectionHub hub, IContextualSerializationToolKit serializationToolkit)
{ {
@@ -1,35 +0,0 @@
using System.Threading.Channels;
using System.Threading.Tasks;
using mROA.Abstract;
namespace mROA.Implementation
{
public class ChannelDistributorFactory : IMessageDistributorFactory
{
private readonly IConnectionHub _hub;
public ChannelDistributorFactory(IConnectionHub hub)
{
_hub = hub;
}
public IPrimaryMessageDistributior Produce(int clientId)
{
return new ChannelMessageDistributor(_hub.GetInteraction(clientId).ReceiveChanel.Writer);
}
}
public class ChannelMessageDistributor : IPrimaryMessageDistributior
{
private readonly ChannelWriter<NetworkMessageHeader> _writer;
public ChannelMessageDistributor(ChannelWriter<NetworkMessageHeader> writer)
{
_writer = writer;
}
public async Task Distribute(NetworkMessageHeader message)
{
await _writer.WriteAsync(message);
}
}
}
@@ -4,6 +4,7 @@ using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Channels; using System.Threading.Channels;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using mROA.Abstract; using mROA.Abstract;
namespace mROA.Implementation namespace mROA.Implementation
@@ -62,11 +63,7 @@ namespace mROA.Implementation
public ValueTask<NetworkMessageHeader> GetNextMessageReceiving(bool infinite = true) public ValueTask<NetworkMessageHeader> GetNextMessageReceiving(bool infinite = true)
{ {
return _receiveReader.ReadAsync(); return _receiveReader.ReadAsync();
// if (_currentReceiving != null) return _currentReceiving;
// _currentReceiving = Task.Run(async () => await GetNextMessage());
// return _currentReceiving;
} }
#pragma warning disable CS8602 // Dereference of a possibly null reference.
private async ValueTask<bool> PostMessageInternal(NetworkMessageHeader messageHeader) private async ValueTask<bool> PostMessageInternal(NetworkMessageHeader messageHeader)
{ {
if (!IsConnected()) if (!IsConnected())
@@ -77,8 +74,6 @@ namespace mROA.Implementation
await _trustedWriter.WriteAsync(messageHeader); await _trustedWriter.WriteAsync(messageHeader);
return true; return true;
} }
#pragma warning restore CS8602 // Dereference of a possibly null reference.
public async Task PostMessageAsync(NetworkMessageHeader messageHeader) public async Task PostMessageAsync(NetworkMessageHeader messageHeader)
{ {
@@ -153,14 +148,16 @@ namespace mROA.Implementation
private readonly IContextualSerializationToolKit _serializationToolkit; private readonly IContextualSerializationToolKit _serializationToolkit;
private readonly Memory<byte> _buffer = new byte[BufferSize]; private readonly Memory<byte> _buffer = new byte[BufferSize];
private readonly IEndPointContext _context; private readonly IEndPointContext _context;
private readonly ILogger _logger;
private readonly byte[] _lenBuffer; private readonly byte[] _lenBuffer;
public StreamExtractor(Stream ioStream, IContextualSerializationToolKit serializationToolkit, public StreamExtractor(Stream ioStream, IContextualSerializationToolKit serializationToolkit,
IEndPointContext context) IEndPointContext context, ILogger logger)
{ {
_ioStream = ioStream; _ioStream = ioStream;
_serializationToolkit = serializationToolkit; _serializationToolkit = serializationToolkit;
_context = context; _context = context;
_logger = logger;
_lenBuffer = new byte[2]; _lenBuffer = new byte[2];
} }
@@ -182,6 +179,7 @@ namespace mROA.Implementation
await _ioStream.ReadExactlyAsync(localSpan, cancellationToken: token); await _ioStream.ReadExactlyAsync(localSpan, cancellationToken: token);
var message = _serializationToolkit.Deserialize<NetworkMessageHeader>(localSpan, _context); var message = _serializationToolkit.Deserialize<NetworkMessageHeader>(localSpan, _context);
// _logger.LogTrace("RECV {0}", message.ToString());
MessageReceived(message); MessageReceived(message);
} }
@@ -201,6 +199,8 @@ namespace mROA.Implementation
header.CopyTo(_buffer); header.CopyTo(_buffer);
var sendingSpan = _buffer[..(len + 2)]; var sendingSpan = _buffer[..(len + 2)];
await _ioStream.WriteAsync(sendingSpan, token); await _ioStream.WriteAsync(sendingSpan, token);
// _logger.LogTrace("SEND {0}", message.ToString());
} }
public async Task SendFromChannel(ChannelReader<NetworkMessageHeader> channel, public async Task SendFromChannel(ChannelReader<NetworkMessageHeader> channel,
@@ -5,7 +5,7 @@ namespace mROA.Implementation
{ {
public class CollectableMethodRepository : IMethodRepository public class CollectableMethodRepository : IMethodRepository
{ {
private List<IMethodInvoker> _methods = new(); private readonly List<IMethodInvoker> _methods = new();
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers) public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
{ {
@@ -1,16 +1,13 @@
using System; using mROA.Abstract;
using mROA.Abstract;
namespace mROA.Implementation namespace mROA.Implementation
{ {
public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer public class CreativeRepresentationModuleProducer : IRepresentationModuleProducer
{ {
private IServiceProvider _creationModules; private readonly IConnectionHub _hub;
private IConnectionHub _hub; private readonly IContextualSerializationToolKit _serialization;
private IContextualSerializationToolKit _serialization; public CreativeRepresentationModuleProducer(IConnectionHub hub, IContextualSerializationToolKit serialization)
public CreativeRepresentationModuleProducer(IServiceProvider creationModules, IConnectionHub hub, IContextualSerializationToolKit serialization)
{ {
_creationModules = creationModules;
_hub = hub; _hub = hub;
_serialization = serialization; _serialization = serialization;
} }
@@ -0,0 +1,13 @@
namespace mROA.Implementation
{
public class DistributionOptions
{
public EDistributionType DistributionType { get; set; }
}
public enum EDistributionType
{
Channeled,
ExtractorFirst
}
}
@@ -3,6 +3,7 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using mROA.Abstract; using mROA.Abstract;
using mROA.Implementation.Backend; using mROA.Implementation.Backend;
@@ -14,18 +15,20 @@ namespace mROA.Implementation.Frontend
{ {
private readonly IPEndPoint _serverEndPoint; private readonly IPEndPoint _serverEndPoint;
private TcpClient _tcpClient = new(); private TcpClient _tcpClient = new();
private IChannelInteractionModule _interactionModule; private readonly IChannelInteractionModule _interactionModule;
private IContextualSerializationToolKit _serialization; private readonly ILogger _logger;
private readonly IContextualSerializationToolKit _serialization;
private ChannelInteractionModule.StreamExtractor? _currentExtractor; private ChannelInteractionModule.StreamExtractor? _currentExtractor;
private CancellationTokenSource _rawExtractorCancellation; private CancellationTokenSource _rawExtractorCancellation;
private IEndPointContext _context; private readonly IEndPointContext _context;
public NetworkFrontendBridge(IOptions<GatewayOptions> options, IEndPointContext context, IContextualSerializationToolKit serialization, IChannelInteractionModule interactionModule) public NetworkFrontendBridge(IOptions<GatewayOptions> options, IEndPointContext context, IContextualSerializationToolKit serialization, IChannelInteractionModule interactionModule, ILogger<ChannelInteractionModule.StreamExtractor> logger)
{ {
_serverEndPoint = options.Value.Endpoint; _serverEndPoint = options.Value.Endpoint;
_context = context; _context = context;
_serialization = serialization; _serialization = serialization;
_interactionModule = interactionModule; _interactionModule = interactionModule;
_logger = logger;
_rawExtractorCancellation = new CancellationTokenSource(); _rawExtractorCancellation = new CancellationTokenSource();
} }
@@ -61,9 +64,9 @@ namespace mROA.Implementation.Frontend
private void PrepareExtractor() private void PrepareExtractor()
{ {
_currentExtractor = _currentExtractor =
new ChannelInteractionModule.StreamExtractor(_tcpClient.GetStream(), _serialization, _context); new ChannelInteractionModule.StreamExtractor(_tcpClient.GetStream(), _serialization, _context, _logger);
_ = _currentExtractor.SendFromChannel(_interactionModule!.TrustedPostChanel, _ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel,
_rawExtractorCancellation.Token); _rawExtractorCancellation.Token);
_currentExtractor.MessageReceived = message => _currentExtractor.MessageReceived = message =>
{ {
@@ -93,7 +96,7 @@ namespace mROA.Implementation.Frontend
public void Disconnect() public void Disconnect()
{ {
_ = _interactionModule!.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientDisconnect(), _ = _interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientDisconnect(),
_context)); _context));
_interactionModule.Dispose(); _interactionModule.Dispose();
_tcpClient.Dispose(); _tcpClient.Dispose();
@@ -10,10 +10,10 @@ namespace mROA.Implementation.Frontend
public class RequestExtractor : IRequestExtractor public class RequestExtractor : IRequestExtractor
{ {
private IExecuteModule _executeModule; private readonly IExecuteModule _executeModule;
private IRepresentationModule _representationModule; private readonly IRepresentationModule _representationModule;
private IEndPointContext _context; private readonly IEndPointContext _context;
public RequestExtractor(IExecuteModule executeModule, IRepresentationModule representationModule, IEndPointContext context) public RequestExtractor(IExecuteModule executeModule, IRepresentationModule representationModule, IEndPointContext context)
{ {
@@ -84,7 +84,7 @@ namespace mROA.Implementation.Frontend
return; return;
} }
_representationModule.PostCallMessage(request.Id, resultType, result, _context); _representationModule.PostCallMessageAsync(request.Id, resultType, result, _context).ConfigureAwait(false);
} }
private void HandleEventRequest(DefaultCallRequest request) private void HandleEventRequest(DefaultCallRequest request)
@@ -7,10 +7,10 @@ namespace mROA.Implementation
{ {
public class RemoteInstanceRepository : IInstanceRepository public class RemoteInstanceRepository : IInstanceRepository
{ {
private List<RemoteObjectBase> _producedProxys = new(); private readonly List<RemoteObjectBase> _producedProxies = new();
private ICallIndexProvider _callIndexProvider; private readonly ICallIndexProvider _callIndexProvider;
private IRepresentationModuleProducer _representationProducer; private readonly IRepresentationModuleProducer _representationProducer;
public RemoteInstanceRepository(ICallIndexProvider callIndexProvider, IRepresentationModuleProducer representationProducer) public RemoteInstanceRepository(ICallIndexProvider callIndexProvider, IRepresentationModuleProducer representationProducer)
{ {
@@ -31,7 +31,7 @@ namespace mROA.Implementation
public T GetObject<T>(ComplexObjectIdentifier id, IEndPointContext context) where T : class public T GetObject<T>(ComplexObjectIdentifier id, IEndPointContext context) where T : class
{ {
var index = _producedProxys.Find(i => i.Identifier.Equals(id)); var index = _producedProxies.Find(i => i.Identifier.Equals(id));
if (index is not null) if (index is not null)
return (T)(index as object); return (T)(index as object);
@@ -42,7 +42,7 @@ namespace mROA.Implementation
var remote = remoteType(id.ContextId, var remote = remoteType(id.ContextId,
representationModule, context, _callIndexProvider.GetIndices(typeof(T))); representationModule, context, _callIndexProvider.GetIndices(typeof(T)));
_producedProxys.Add(remote!); _producedProxies.Add(remote!);
return (remote as T)!; return (remote as T)!;
} }
@@ -62,9 +62,9 @@ namespace mROA.Implementation
var remoteObjectBase = instance; var remoteObjectBase = instance;
_producedProxys.Add(remoteObjectBase); _producedProxies.Add(remoteObjectBase);
return _producedProxys.Last(); return _producedProxies.Last();
} }
public int GetObjectIndex<T>(object o, IEndPointContext context) public int GetObjectIndex<T>(object o, IEndPointContext context)
+2 -2
View File
@@ -12,8 +12,8 @@ namespace mROA.Implementation
{ {
public class RepresentationModule : IRepresentationModule public class RepresentationModule : IRepresentationModule
{ {
private IChannelInteractionModule _interaction; private readonly IChannelInteractionModule _interaction;
private IContextualSerializationToolKit _serialization; private readonly IContextualSerializationToolKit _serialization;
public RepresentationModule(IChannelInteractionModule interaction, IContextualSerializationToolKit serialization) public RepresentationModule(IChannelInteractionModule interaction, IContextualSerializationToolKit serialization)
{ {
+6
View File
@@ -39,4 +39,10 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Extensions.Logging.Abstractions">
<HintPath>..\..\..\..\.nuget\packages\microsoft.extensions.logging.abstractions\9.0.7\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
</ItemGroup>
</Project> </Project>