Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dce374035f | ||
|
|
a4c05af5c8 | ||
|
|
1ecca099d8 | ||
|
|
5cc76ddbcc | ||
|
|
84f9840024 | ||
|
|
b4280cd06d | ||
|
|
aae30af664 | ||
|
|
dca21339db | ||
|
|
dfad8b9141 | ||
|
|
46d741a287 | ||
|
|
24d346795d | ||
|
|
8c137115f4 | ||
|
|
cc7d2d478c | ||
|
|
b409e5ef08 | ||
|
|
c29db73a0e | ||
|
|
0f355b9df3 | ||
|
|
89a2bee8d2 | ||
|
|
37f5d8a198 | ||
|
|
e7c9bec4cd | ||
|
|
fd971cdecc | ||
|
|
37e768d6e8 | ||
|
|
5ece345a3f | ||
|
|
304811c964 | ||
|
|
2cbcc6b201 | ||
|
|
0818ed6a5a | ||
|
|
3aa723c2ca | ||
|
|
dea464d251 | ||
|
|
4dca13b85b | ||
|
|
9425f25081 | ||
|
|
965c8eb823 | ||
|
|
6c55567d3f | ||
|
|
bb3c4887df | ||
|
|
be12f1da65 | ||
|
|
31d4102dac | ||
|
|
14ec6abd8d | ||
|
|
f8998178ff | ||
|
|
5cbfb4d2b1 | ||
|
|
83391bd55e | ||
|
|
e4d6709a77 | ||
|
|
c7c5b1637c | ||
|
|
79d0e4b5b1 | ||
|
|
0c648f0af0 | ||
|
|
85cf1bc48a | ||
|
|
153272a1fa | ||
|
|
17a6d3aad6 |
@@ -7,14 +7,14 @@
|
|||||||
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<LangVersion>9</LangVersion>
|
<LangVersion>12</LangVersion>
|
||||||
|
|
||||||
<PublishAot>true</PublishAot>
|
<PublishAot>true</PublishAot>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Example.Backend
|
|||||||
{
|
{
|
||||||
private readonly List<IPrinter> _printers = new();
|
private readonly List<IPrinter> _printers = new();
|
||||||
|
|
||||||
public IPrinter Create(string printerName)
|
public IPrinter Create(in string printerName)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Creating printer");
|
Console.WriteLine("Creating printer");
|
||||||
return new Printer { Name = printerName };
|
return new Printer { Name = printerName };
|
||||||
|
|||||||
+11
-16
@@ -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.AddSingleton<IDistributionModule, ExtractorFirstDistributionModule>();
|
||||||
|
builder.Services.Configure<SerializationBufferOffset>(options => options.Offset = 0);
|
||||||
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>();
|
||||||
@@ -39,7 +40,6 @@ class Program
|
|||||||
|
|
||||||
return repo;
|
return repo;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
builder.Services.AddSingleton<IMethodRepository>(p =>
|
builder.Services.AddSingleton<IMethodRepository>(p =>
|
||||||
{
|
{
|
||||||
var methodRepo = new CollectableMethodRepository();
|
var methodRepo = new CollectableMethodRepository();
|
||||||
@@ -47,21 +47,16 @@ class Program
|
|||||||
return methodRepo;
|
return methodRepo;
|
||||||
});
|
});
|
||||||
builder.Services.AddSingleton<ICallIndexProvider, GeneratedCallIndexProvider>();
|
builder.Services.AddSingleton<ICallIndexProvider, GeneratedCallIndexProvider>();
|
||||||
|
|
||||||
builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>();
|
builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>();
|
||||||
|
builder.Services.Configure<DistributionOptions>(o => o.DistributionType = EDistributionType.ExtractorFirst);
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
host.Services.GetService<HubRequestExtractor>();
|
new RemoteTypeBinder();
|
||||||
//
|
|
||||||
// builder.Build();
|
|
||||||
new RemoteTypeBinder();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
_ = host.Services.GetService<IUntrustedGateway>()!.Start();
|
|
||||||
var gateway = host.Services.GetService<IGatewayModule>();
|
|
||||||
gateway.Run();
|
|
||||||
|
|
||||||
Console.ReadLine();
|
_ = host.Services.GetService<IUntrustedGateway>()!.Start();
|
||||||
|
var gateway = host.Services.GetService<IGatewayModule>();
|
||||||
|
gateway.Run();
|
||||||
|
|
||||||
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ namespace Example.Frontend
|
|||||||
|
|
||||||
public string GetName()
|
public string GetName()
|
||||||
{
|
{
|
||||||
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
|
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!!");
|
||||||
DemoCheck.BackwardCall = true;
|
DemoCheck.BackwardCall = true;
|
||||||
|
|
||||||
return "ClientBasedPrinter from mroa";
|
return "ClientBasedPrinter from mroa";
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<LangVersion>9</LangVersion>
|
<LangVersion>12</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
|||||||
+19
-10
@@ -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;
|
||||||
@@ -15,7 +16,6 @@ using mROA.Implementation;
|
|||||||
using mROA.Implementation.Backend;
|
using mROA.Implementation.Backend;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
@@ -23,6 +23,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 +41,12 @@ 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.Configure<SerializationBufferOffset>(options => options.Offset = 0);
|
||||||
|
|
||||||
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>();
|
||||||
@@ -70,7 +76,14 @@ class Program
|
|||||||
|
|
||||||
using (var disposingPrinter = factory.Create("Test"))
|
using (var disposingPrinter = factory.Create("Test"))
|
||||||
{
|
{
|
||||||
disposingPrinter.SetFingerPrint(new[] { 1, 2, 3 }).ContinueWith(r => { Console.WriteLine(r.Status); });
|
disposingPrinter.SetFingerPrint(new[] { 1, 2, 3 }).ContinueWith(r =>
|
||||||
|
{
|
||||||
|
Console.WriteLine(r.Status);
|
||||||
|
if (r.Status == TaskStatus.Faulted)
|
||||||
|
{
|
||||||
|
Console.WriteLine(r.Exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await disposingPrinter.IntTest(new MyData { Id = 5, Score = 7, Name = "Test" });
|
await disposingPrinter.IntTest(new MyData { Id = 5, Score = 7, Name = "Test" });
|
||||||
DemoCheck.CreatingPrinter = true;
|
DemoCheck.CreatingPrinter = true;
|
||||||
@@ -80,14 +93,12 @@ class Program
|
|||||||
DemoCheck.EventCallback = true;
|
DemoCheck.EventCallback = true;
|
||||||
};
|
};
|
||||||
Console.WriteLine("Printer created");
|
Console.WriteLine("Printer created");
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
frontendBridge.Obstacle();
|
// frontendBridge.Obstacle();
|
||||||
var name = disposingPrinter.GetName();
|
var name = disposingPrinter.GetName();
|
||||||
DemoCheck.BasicNonParamsCall = true;
|
DemoCheck.BasicNonParamsCall = true;
|
||||||
Console.WriteLine("Printer name : {0}", name);
|
Console.WriteLine("Printer name : {0}", name);
|
||||||
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
disposingPrinter.SomeoneIsApproaching("Mikhail");
|
disposingPrinter.SomeoneIsApproaching("Mikhail");
|
||||||
Console.WriteLine("Approaching detected");
|
Console.WriteLine("Approaching detected");
|
||||||
@@ -96,17 +107,14 @@ class Program
|
|||||||
factory.Register(disposingPrinter);
|
factory.Register(disposingPrinter);
|
||||||
DemoCheck.ClientBasedImplementation = true;
|
DemoCheck.ClientBasedImplementation = true;
|
||||||
Console.WriteLine("Registered printer");
|
Console.WriteLine("Registered printer");
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
|
|
||||||
var registered = factory.GetFirstPrinter();
|
var registered = factory.GetFirstPrinter();
|
||||||
Console.WriteLine("First printer");
|
Console.WriteLine("First printer");
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
Console.WriteLine(registered);
|
Console.WriteLine(registered);
|
||||||
Console.WriteLine("Collecting all printers");
|
Console.WriteLine("Collecting all printers");
|
||||||
var names = factory.CollectAllNames();
|
var names = factory.CollectAllNames();
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
Console.WriteLine("Names: " + string.Join(", ", names));
|
Console.WriteLine("Names: " + string.Join(", ", names));
|
||||||
|
|
||||||
@@ -139,13 +147,14 @@ class Program
|
|||||||
var token = cts.Token;
|
var token = cts.Token;
|
||||||
var t = Task.Run(async () => await loadSingleton!.AsyncTest(token));
|
var t = Task.Run(async () => await loadSingleton!.AsyncTest(token));
|
||||||
|
|
||||||
Thread.Sleep(5000);
|
Console.WriteLine("Waiting for timer");
|
||||||
|
Thread.Sleep(2000);
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
Console.WriteLine($"Token state {cts.Token.IsCancellationRequested}");
|
Console.WriteLine($"Token state {cts.Token.IsCancellationRequested}");
|
||||||
DemoCheck.TaskCancelation = true;
|
DemoCheck.TaskCancelation = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const int iterations = 10_000;
|
const int iterations = 5;
|
||||||
var timer = Stopwatch.StartNew();
|
var timer = Stopwatch.StartNew();
|
||||||
var x = 0;
|
var x = 0;
|
||||||
for (int i = 0; i < iterations; i++)
|
for (int i = 0; i < iterations; i++)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+89
-70
@@ -1,6 +1,7 @@
|
|||||||
using System.Net;
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
@@ -10,14 +11,13 @@ using mROA.Implementation;
|
|||||||
using mROA.Implementation.Backend;
|
using mROA.Implementation.Backend;
|
||||||
using mROA.Implementation.Frontend;
|
using mROA.Implementation.Frontend;
|
||||||
|
|
||||||
|
|
||||||
const int C = 100;
|
const int C = 100;
|
||||||
var time = TimeSpan.FromSeconds(10);
|
var time = TimeSpan.FromSeconds(10);
|
||||||
Console.WriteLine($"Starting bench for {time} from {C} connections");
|
Console.WriteLine($"Starting bench for {time} from {C} connections");
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
new RemoteTypeBinder();
|
new RemoteTypeBinder();
|
||||||
var eps = await GetLoadEndpoints(C);
|
var eps = await GetLoadEndpoints(C);
|
||||||
var tasks = new Task<int>[C];
|
var tasks = new Task<(int, double[])>[C];
|
||||||
for (int i = 0; i < C; i++)
|
for (int i = 0; i < C; i++)
|
||||||
{
|
{
|
||||||
tasks[i] = Requests(cts.Token, i, eps[i]);
|
tasks[i] = Requests(cts.Token, i, eps[i]);
|
||||||
@@ -29,83 +29,102 @@ Console.WriteLine("Start waiting");
|
|||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
Console.WriteLine("End waiting");
|
Console.WriteLine("End waiting");
|
||||||
|
|
||||||
var totalRequests = tasks.Sum(i => i.Result);
|
var totalRequests = tasks.Sum(i => i.Result.Item1);
|
||||||
|
var totalLatency = tasks.SelectMany(i => i.Result.Item2).ToList();
|
||||||
|
totalLatency.Sort();
|
||||||
|
var n = totalLatency.Count;
|
||||||
|
|
||||||
|
var p50 = totalLatency[(int)(n * 50f / 100f)];
|
||||||
|
var p95 = totalLatency[(int)(n * 95f / 100f)];
|
||||||
|
var p99 = totalLatency[(int)(n * 99f / 100f)];
|
||||||
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");
|
||||||
|
Console.WriteLine("Latency (µs): p50={0} p95={1} p99={2}", p50, p95, p99);
|
||||||
|
File.AppendAllText("results.txt", $"[FAST ID] {totalRequests}\r\n");
|
||||||
|
|
||||||
async Task<List<ILoadTest>> GetLoadEndpoints(int count)
|
async Task<List<ILoadTest>> GetLoadEndpoints(int count)
|
||||||
{
|
|
||||||
var loads = new List<ILoadTest>();
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true });
|
|
||||||
builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>();
|
|
||||||
builder.Services.AddSingleton<IEndPointContext, EndPointContext>();
|
|
||||||
builder.Services.AddSingleton<IRealStoreInstanceRepository, InstanceRepository>(provider =>
|
|
||||||
{
|
|
||||||
var repo = new InstanceRepository(provider.GetService<IRepresentationModuleProducer>());
|
|
||||||
repo.FillSingletons(typeof(Program).Assembly);
|
|
||||||
return repo;
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Services.AddSingleton<IInstanceRepository, RemoteInstanceRepository>();
|
|
||||||
builder.Services.AddSingleton<IChannelInteractionModule, ChannelInteractionModule>();
|
|
||||||
// builder.Services.AddSingleton<IUntrustedInteractionModule, UdpUntrustedInteraction>();
|
|
||||||
builder.Services.AddSingleton<IRepresentationModule, RepresentationModule>();
|
|
||||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567);
|
|
||||||
builder.Services.AddSingleton<IFrontendBridge, NetworkFrontendBridge>();
|
|
||||||
builder.Services.AddOptions();
|
|
||||||
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
|
|
||||||
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
|
|
||||||
// builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
|
|
||||||
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
|
|
||||||
|
|
||||||
builder.Services.AddSingleton<IMethodRepository, CollectableMethodRepository>(p =>
|
|
||||||
{
|
|
||||||
var methodRepo = new CollectableMethodRepository();
|
|
||||||
methodRepo.AppendInvokers(new GeneratedInvokersCollection());
|
|
||||||
return methodRepo;
|
|
||||||
});
|
|
||||||
builder.Services.AddSingleton<ICallIndexProvider, GeneratedCallIndexProvider>();
|
|
||||||
builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>();
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
var frontendBridge = app.Services.GetService<IFrontendBridge>()!;
|
|
||||||
await frontendBridge.Connect();
|
|
||||||
// _ = app.Services.GetService<IRequestExtractor>()!.StartExtraction();
|
|
||||||
// _ = app.Services.GetService<IUntrustedInteractionModule>().Start(serverEndPoint);
|
|
||||||
var context = app.Services.GetService<IInstanceRepository>();
|
|
||||||
|
|
||||||
|
|
||||||
var singletonObject =
|
|
||||||
context.GetSingletonObject<ILoadTest>(
|
|
||||||
app.Services.GetService<IEndPointContext>());
|
|
||||||
loads.Add(singletonObject);
|
|
||||||
}
|
|
||||||
return loads;
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<int> Requests(CancellationToken token, int id, ILoadTest load)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var loads = new List<ILoadTest>();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
int count = 0;
|
{
|
||||||
while (true){
|
var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true });
|
||||||
if (token.IsCancellationRequested)
|
builder.Services.AddSingleton<IContextualSerializationToolKit, CborSerializationToolkit>();
|
||||||
|
builder.Services.AddSingleton<IEndPointContext, EndPointContext>();
|
||||||
|
builder.Services.AddSingleton<IRealStoreInstanceRepository, InstanceRepository>(provider =>
|
||||||
{
|
{
|
||||||
break;
|
var repo = new InstanceRepository(provider.GetService<IRepresentationModuleProducer>());
|
||||||
}
|
repo.FillSingletons(typeof(Program).Assembly);
|
||||||
|
return repo;
|
||||||
|
});
|
||||||
|
|
||||||
await load.Next(2);
|
builder.Services.AddSingleton<IInstanceRepository, RemoteInstanceRepository>();
|
||||||
count++;
|
builder.Services.AddSingleton<IChannelInteractionModule, ChannelInteractionModule>();
|
||||||
|
// builder.Services.AddSingleton<IUntrustedInteractionModule, UdpUntrustedInteraction>();
|
||||||
|
builder.Services.AddSingleton<IRepresentationModule, RepresentationModule>();
|
||||||
|
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567);
|
||||||
|
builder.Services.AddSingleton<IFrontendBridge, NetworkFrontendBridge>();
|
||||||
|
builder.Services.AddOptions();
|
||||||
|
builder.Services.Configure<GatewayOptions>(options => options.Endpoint = serverEndPoint);
|
||||||
|
builder.Services.AddSingleton<IRepresentationModuleProducer, StaticRepresentationModuleProducer>();
|
||||||
|
// builder.Services.AddSingleton<IRequestExtractor, RequestExtractor>();
|
||||||
|
builder.Services.AddSingleton<IExecuteModule, BasicExecutionModule>();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IMethodRepository, CollectableMethodRepository>(p =>
|
||||||
|
{
|
||||||
|
var methodRepo = new CollectableMethodRepository();
|
||||||
|
methodRepo.AppendInvokers(new GeneratedInvokersCollection());
|
||||||
|
return methodRepo;
|
||||||
|
});
|
||||||
|
builder.Services.AddSingleton<ICallIndexProvider, GeneratedCallIndexProvider>();
|
||||||
|
builder.Services.AddSingleton<ICancellationRepository, CancellationRepository>();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
var frontendBridge = app.Services.GetService<IFrontendBridge>()!;
|
||||||
|
await frontendBridge.Connect();
|
||||||
|
// _ = app.Services.GetService<IRequestExtractor>()!.StartExtraction();
|
||||||
|
// _ = app.Services.GetService<IUntrustedInteractionModule>().Start(serverEndPoint);
|
||||||
|
var context = app.Services.GetService<IInstanceRepository>();
|
||||||
|
|
||||||
|
var singletonObject =
|
||||||
|
context.GetSingletonObject<ILoadTest>(
|
||||||
|
app.Services.GetService<IEndPointContext>());
|
||||||
|
loads.Add(singletonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(id);
|
return loads;
|
||||||
return count;
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<(int, double[])> Requests(CancellationToken token, int id, ILoadTest load)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var latencyList = new List<double>();
|
||||||
|
var sw = new Stopwatch();
|
||||||
|
int count = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Restart();
|
||||||
|
await load.Next(2);
|
||||||
|
sw.Stop();
|
||||||
|
latencyList.Add(sw.Elapsed.TotalMicroseconds);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count, latencyList.ToArray());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,12 +10,10 @@
|
|||||||
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj" />
|
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj" />
|
||||||
<ProjectReference Include="..\mROA\mROA.csproj"/>
|
<ProjectReference Include="..\mROA\mROA.csproj"/>
|
||||||
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.7" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.7" />
|
||||||
<PackageReference Include="mROA.Codegen" Version="2.0.5" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared
|
namespace Example.Shared
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared
|
namespace Example.Shared
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ namespace Example.Shared
|
|||||||
{
|
{
|
||||||
double Resource { get; set; }
|
double Resource { get; set; }
|
||||||
string GetName();
|
string GetName();
|
||||||
Task<IPage> Print(string text, bool someParameter, RequestContext context, CancellationToken cancellationToken);
|
Task<IPage> Print(string text, bool someParameter,
|
||||||
|
RequestContext context, CancellationToken cancellationToken);
|
||||||
event Action<IPage, RequestContext> OnPrint;
|
event Action<IPage, RequestContext> OnPrint;
|
||||||
|
|
||||||
[Untrusted]
|
[Untrusted]
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared
|
namespace Example.Shared
|
||||||
@@ -7,7 +6,7 @@ namespace Example.Shared
|
|||||||
[SharedObjectInterface]
|
[SharedObjectInterface]
|
||||||
public interface IPrinterFactory : IShared
|
public interface IPrinterFactory : IShared
|
||||||
{
|
{
|
||||||
IPrinter Create(string printerName);
|
IPrinter Create(in string printerName);
|
||||||
void Register(IPrinter printer);
|
void Register(IPrinter printer);
|
||||||
IPrinter GetPrinterByName(string printerName);
|
IPrinter GetPrinterByName(string printerName);
|
||||||
IPrinter GetFirstPrinter();
|
IPrinter GetFirstPrinter();
|
||||||
|
|||||||
@@ -1,21 +1,201 @@
|
|||||||
MIT License
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
Copyright (c) 2025 YaslePoy
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
1. Definitions.
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
copies or substantial portions of the Software.
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
the copyright owner that is granting the License.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
other entities that control, are controlled by, or are under common
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
control with that entity. For the purposes of this definition,
|
||||||
SOFTWARE.
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2025 Mitrofanov M. M.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Formats.Cbor;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
public static class CborExtensions
|
||||||
|
{
|
||||||
|
public static unsafe void WriteToCbor(this RequestId id, CborWriter writer)
|
||||||
|
{
|
||||||
|
Span<byte> span = stackalloc byte[16];
|
||||||
|
MemoryMarshal.Write(span, ref id);
|
||||||
|
writer.WriteByteString(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe void WriteToCborInline(this RequestId id, CborWriter writer)
|
||||||
|
{
|
||||||
|
Span<byte> span = stackalloc byte[16];
|
||||||
|
MemoryMarshal.Write(span, ref id);
|
||||||
|
writer.WriteByteString(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteToDest(this RequestId id, Span<byte> destination)
|
||||||
|
{
|
||||||
|
MemoryMarshal.Write(destination, ref id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static unsafe void WriteToCborOpt(this RequestId id, CborWriter writer)
|
||||||
|
{
|
||||||
|
Span<byte> span = stackalloc byte[16];
|
||||||
|
MemoryMarshal.Write(span, ref id);
|
||||||
|
writer.WriteByteString(span);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static RequestId ReadFromTrueCbor(CborReader reader)
|
||||||
|
{
|
||||||
|
var enc = reader.ReadEncodedValue(true);
|
||||||
|
return MemoryMarshal.Read<RequestId>(enc.Span[1..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static RequestId ReadFromCbor(CborReader reader)
|
||||||
|
{
|
||||||
|
var enc = reader.ReadEncodedValue();
|
||||||
|
return MemoryMarshal.Read<RequestId>(enc.Span[1..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
using System.Formats.Cbor;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class CborTest
|
||||||
|
{
|
||||||
|
private CborWriter _writer;
|
||||||
|
private CborReader _reader;
|
||||||
|
|
||||||
|
private Memory<byte> FlatEncoded;
|
||||||
|
private Memory<byte> ArrayEncoded;
|
||||||
|
public CborTest()
|
||||||
|
{
|
||||||
|
_writer = new CborWriter(initialCapacity:512);
|
||||||
|
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteByteString([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteInt32(12);
|
||||||
|
_writer.WriteTextString("tralala");
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
|
||||||
|
ArrayEncoded = _writer.Encode();
|
||||||
|
|
||||||
|
_writer.Reset();
|
||||||
|
|
||||||
|
_writer.WriteStartArray(3);
|
||||||
|
_writer.WriteByteString([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
_writer.WriteInt32(12);
|
||||||
|
_writer.WriteTextString("tralala");
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
FlatEncoded = _writer.Encode();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int FlatWrite()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
_writer.WriteStartArray(3);
|
||||||
|
_writer.WriteByteString([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
_writer.WriteInt32(12);
|
||||||
|
_writer.WriteTextString("tralala");
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
var len = _writer.Encode(FlatEncoded.Span);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int ArrayWrite()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteByteString([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteInt32(12);
|
||||||
|
_writer.WriteTextString("tralala");
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
var len = _writer.Encode(ArrayEncoded.Span);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
[Benchmark]
|
||||||
|
public int FlatRead()
|
||||||
|
{
|
||||||
|
var reader = new CborReader(FlatEncoded);
|
||||||
|
reader.ReadStartArray();
|
||||||
|
var arr = reader.ReadByteString();
|
||||||
|
var i = reader.ReadInt32();
|
||||||
|
var text = reader.ReadTextString();
|
||||||
|
reader.ReadEndArray();
|
||||||
|
|
||||||
|
return arr.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int ArrayRead()
|
||||||
|
{
|
||||||
|
var reader = new CborReader(ArrayEncoded);
|
||||||
|
reader.ReadStartArray();
|
||||||
|
var arr = reader.ReadByteString();
|
||||||
|
reader.ReadStartArray();
|
||||||
|
var i = reader.ReadInt32();
|
||||||
|
var text = reader.ReadTextString();
|
||||||
|
reader.ReadEndArray();
|
||||||
|
reader.ReadEndArray();
|
||||||
|
|
||||||
|
return arr.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
using System.Formats.Cbor;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class ConcurrentAlloc
|
||||||
|
{
|
||||||
|
private readonly CircularMemoryManager _cmm = new(1024);
|
||||||
|
private readonly FastCircularMemoryManager _fmm = new();
|
||||||
|
private CborWriter _writer = new();
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteByteString([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
|
_writer.WriteStartArray(2);
|
||||||
|
_writer.WriteInt32(12);
|
||||||
|
_writer.WriteTextString("tralala 7EBC1458-BB53-49EA-84C9-EFECC0FC08FD");
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
_writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public int CircularAllocate()
|
||||||
|
{
|
||||||
|
var writer = _writer;
|
||||||
|
var buffer = _cmm.AllocSlice(writer.BytesWritten);
|
||||||
|
writer.Encode(buffer);
|
||||||
|
|
||||||
|
return buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int CircularMemoryAllocate()
|
||||||
|
{
|
||||||
|
var writer = _writer;
|
||||||
|
var buffer = _cmm.AllocMemory(writer.BytesWritten);
|
||||||
|
writer.Encode(buffer.Span);
|
||||||
|
return buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int FastCircularAllocate()
|
||||||
|
{
|
||||||
|
var writer = _writer;
|
||||||
|
var buffer = _fmm.Alloc(writer.BytesWritten);
|
||||||
|
writer.Encode(buffer);
|
||||||
|
return buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int FastMemoryCircularAllocate()
|
||||||
|
{
|
||||||
|
var writer = _writer;
|
||||||
|
var buffer = _fmm.AllocMem(writer.BytesWritten);
|
||||||
|
writer.Encode(buffer.Span);
|
||||||
|
return buffer.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int HeapAllocate()
|
||||||
|
{
|
||||||
|
var writer = _writer;
|
||||||
|
var encoded = writer.Encode();
|
||||||
|
return encoded.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FastCircularMemoryManager
|
||||||
|
{
|
||||||
|
private readonly byte[] _buffer;
|
||||||
|
private long _offset; // atomic offset (in bytes)
|
||||||
|
private readonly int _mask; // если размер степени двойки — можно использовать маску
|
||||||
|
|
||||||
|
public FastCircularMemoryManager(int size = 4096) // 4KB buffer
|
||||||
|
{
|
||||||
|
if (!IsPowerOfTwo(size))
|
||||||
|
throw new ArgumentException("Size should be power of two for performance.", nameof(size));
|
||||||
|
|
||||||
|
_buffer = new byte[size];
|
||||||
|
_offset = 0;
|
||||||
|
_mask = size - 1; // для быстрого циклического сдвига: (offset & _mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsPowerOfTwo(int x) => x > 0 && (x & (x - 1)) == 0;
|
||||||
|
|
||||||
|
public Span<byte> Alloc(int size)
|
||||||
|
{
|
||||||
|
if (size > _buffer.Length)
|
||||||
|
return new byte[size]; // fallback
|
||||||
|
|
||||||
|
long oldOffset, newOffset;
|
||||||
|
int start;
|
||||||
|
|
||||||
|
// Atomic "bump pointer" с циклическим переполнением
|
||||||
|
do
|
||||||
|
{
|
||||||
|
oldOffset = Volatile.Read(ref _offset);
|
||||||
|
start = (int)(oldOffset & _mask);
|
||||||
|
|
||||||
|
// Проверяем, не пересекает ли выделение границу буфера
|
||||||
|
if (start + size > _buffer.Length)
|
||||||
|
{
|
||||||
|
// Переполнение — обнуляем (циклический буфер)
|
||||||
|
newOffset = size; // сбрасываем на начало + size
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newOffset = oldOffset + size;
|
||||||
|
}
|
||||||
|
} while (Interlocked.CompareExchange(ref _offset, newOffset, oldOffset) != oldOffset);
|
||||||
|
|
||||||
|
return _buffer.AsSpan(start, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Memory<byte> AllocMem(int size)
|
||||||
|
{
|
||||||
|
if (size > _buffer.Length)
|
||||||
|
return new byte[size]; // fallback
|
||||||
|
|
||||||
|
long oldOffset, newOffset;
|
||||||
|
int start;
|
||||||
|
|
||||||
|
// Atomic "bump pointer" с циклическим переполнением
|
||||||
|
do
|
||||||
|
{
|
||||||
|
oldOffset = Volatile.Read(ref _offset);
|
||||||
|
start = (int)(oldOffset & _mask);
|
||||||
|
|
||||||
|
// Проверяем, не пересекает ли выделение границу буфера
|
||||||
|
if (start + size > _buffer.Length)
|
||||||
|
{
|
||||||
|
// Переполнение — обнуляем (циклический буфер)
|
||||||
|
newOffset = size; // сбрасываем на начало + size
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newOffset = oldOffset + size;
|
||||||
|
}
|
||||||
|
} while (Interlocked.CompareExchange(ref _offset, newOffset, oldOffset) != oldOffset);
|
||||||
|
|
||||||
|
return _buffer.AsMemory(start, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark
|
||||||
|
{
|
||||||
|
[SharedObjectInterface]
|
||||||
|
public interface ILoadTest : IShared
|
||||||
|
{
|
||||||
|
Task<int> Next(int last);
|
||||||
|
int Last(int next);
|
||||||
|
void C();
|
||||||
|
void A();
|
||||||
|
Task AsyncTest(CancellationToken token = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark
|
||||||
|
{
|
||||||
|
[SharedObjectInterface]
|
||||||
|
public interface IPage : IShared
|
||||||
|
{
|
||||||
|
byte[] GetData();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark
|
||||||
|
{
|
||||||
|
[SharedObjectInterface]
|
||||||
|
public partial interface IPrinter : IDisposable, IShared
|
||||||
|
{
|
||||||
|
double Resource { get; set; }
|
||||||
|
string GetName();
|
||||||
|
Task<IPage> Print(string text, bool someParameter, RequestContext context, CancellationToken cancellationToken);
|
||||||
|
event Action<IPage, RequestContext> OnPrint;
|
||||||
|
|
||||||
|
[Untrusted]
|
||||||
|
Task SomeoneIsApproaching(string humanName);
|
||||||
|
|
||||||
|
Task SetFingerPrint(int[] fingerPrint);
|
||||||
|
Task IntTest(MyData data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MyData
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public double Score { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{{{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Score)}: {Score}}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool Equals(MyData other)
|
||||||
|
{
|
||||||
|
return Id == other.Id && Name == other.Name && Score.Equals(other.Score);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is null) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != GetType()) return false;
|
||||||
|
return Equals((MyData)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Id, Name, Score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark
|
||||||
|
{
|
||||||
|
[SharedObjectInterface]
|
||||||
|
public interface IPrinterFactory : IShared
|
||||||
|
{
|
||||||
|
IPrinter Create(string printerName);
|
||||||
|
void Register(IPrinter printer);
|
||||||
|
IPrinter GetPrinterByName(string printerName);
|
||||||
|
IPrinter GetFirstPrinter();
|
||||||
|
string[] CollectAllNames();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
public class IdGeneration
|
||||||
|
{
|
||||||
|
public static int X = 0;
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public Guid GuidGeneration()
|
||||||
|
{
|
||||||
|
return Guid.NewGuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public RequestId ReqIdGeneration()
|
||||||
|
{
|
||||||
|
return RequestId.Generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public RequestId ReqIdIfGeneration()
|
||||||
|
{
|
||||||
|
var reqId = RequestId.Generate();
|
||||||
|
if (++X % 2 == 0)
|
||||||
|
{
|
||||||
|
reqId.P0 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reqId.P1 = 0;
|
||||||
|
}
|
||||||
|
return reqId;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[DisassemblyDiagnoser]
|
||||||
|
public class InvokePerformance
|
||||||
|
{
|
||||||
|
public Func<int, int> A = x =>
|
||||||
|
{
|
||||||
|
var result = x * 5 + x * x / 5;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
public SomeMath B = x => x * 5 + x * x / 5;
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public int ActionInvoke()
|
||||||
|
{
|
||||||
|
return A(132);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int DelegateInvoke()
|
||||||
|
{
|
||||||
|
return A(132);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate int SomeMath(int x);
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Codegen;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
// [DisassemblyDiagnoser]
|
||||||
|
public class MethodAccess
|
||||||
|
{
|
||||||
|
private CollectableMethodRepository _current = new();
|
||||||
|
private FastMethodRepository _fast = new();
|
||||||
|
private readonly int _count = new GeneratedInvokersCollection().Count;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void SetupMethodAccess()
|
||||||
|
{
|
||||||
|
_current.AppendInvokers(new GeneratedInvokersCollection());
|
||||||
|
_fast.AppendInvokers(new GeneratedInvokersCollection());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [Benchmark(Baseline = true)]
|
||||||
|
// public IMethodInvoker CurrentSingle()
|
||||||
|
// {
|
||||||
|
// return _current.GetMethod(0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// [Benchmark]
|
||||||
|
// public IMethodInvoker CurrentDispose()
|
||||||
|
// {
|
||||||
|
// return _current.GetMethod(-1);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// [Benchmark]
|
||||||
|
// public IMethodInvoker FastSingle()
|
||||||
|
// {
|
||||||
|
// return _fast.GetMethod(0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// [Benchmark]
|
||||||
|
// public IMethodInvoker FastDispose()
|
||||||
|
// {
|
||||||
|
// return _fast.GetMethod(-1);
|
||||||
|
// }
|
||||||
|
// [Benchmark]
|
||||||
|
// public IMethodInvoker FastSingleBaked()
|
||||||
|
// {
|
||||||
|
// return _fast.GetMethodBaked(0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// [Benchmark]
|
||||||
|
// public IMethodInvoker FastDisposeBaked()
|
||||||
|
// {
|
||||||
|
// return _fast.GetMethodBaked(-1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public IMethodInvoker CurrentAll()
|
||||||
|
{
|
||||||
|
IMethodInvoker inv = null;
|
||||||
|
for (int i = -1; i < _count; i++)
|
||||||
|
{
|
||||||
|
inv = _current.GetMethod(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public IMethodInvoker FastAll()
|
||||||
|
{
|
||||||
|
IMethodInvoker inv = null;
|
||||||
|
for (int i = -1; i < _count; i++)
|
||||||
|
{
|
||||||
|
inv = _fast.GetMethod(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public IMethodInvoker FastAllBaked()
|
||||||
|
{
|
||||||
|
IMethodInvoker inv = null;
|
||||||
|
for (int i = -1; i < _count; i++)
|
||||||
|
{
|
||||||
|
inv = _fast.GetMethodBaked(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public IMethodInvoker FastAllBakedPreicrement()
|
||||||
|
{
|
||||||
|
IMethodInvoker inv = null;
|
||||||
|
for (int i = -1; i < _count; i++)
|
||||||
|
{
|
||||||
|
inv = _fast.GetMethodBakedPreicrement(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class FastMethodRepository : IMethodRepository
|
||||||
|
{
|
||||||
|
private readonly List<IMethodInvoker> _methods = [MethodInvoker.Dispose];
|
||||||
|
private IMethodInvoker[] _baked = [];
|
||||||
|
|
||||||
|
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
|
||||||
|
{
|
||||||
|
_methods.AddRange(methodInvokers);
|
||||||
|
_baked = _methods.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethodInvoker GetMethod(int id)
|
||||||
|
{
|
||||||
|
return _methods[id + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethodInvoker GetMethodBaked(int id)
|
||||||
|
{
|
||||||
|
return _baked[id + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethodInvoker GetMethodBakedPreicrement(int id)
|
||||||
|
{
|
||||||
|
return _baked[++id];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
// See https://aka.ms/new-console-template for more information
|
||||||
using System.Linq;
|
|
||||||
using BenchmarkDotNet.Attributes;
|
|
||||||
|
|
||||||
namespace mROA.Benchmark
|
using BenchmarkDotNet.Running;
|
||||||
{
|
using mROA.Benchmark;
|
||||||
class Program
|
|
||||||
{
|
|
||||||
static void Main(string[] args)
|
|
||||||
{
|
|
||||||
// Console.WriteLine("Hello, World!");
|
|
||||||
// var summary = BenchmarkRunner.Run<CollectionsSpeed>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CollectionsSpeed
|
Console.WriteLine("Hello, Performance!");
|
||||||
{
|
|
||||||
private const int N = 1000;
|
|
||||||
|
|
||||||
private readonly List<int> _immutable;
|
BenchmarkRunner.Run<MethodAccess>();
|
||||||
private readonly int[] _array;
|
|
||||||
|
|
||||||
public CollectionsSpeed()
|
|
||||||
{
|
|
||||||
_array = Enumerable.Range(0, N).ToArray();
|
|
||||||
// _immutable = [.._array];
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public int DefaultArray()
|
|
||||||
{
|
|
||||||
var sum = 0;
|
|
||||||
for (int i = 0; i < N; i++)
|
|
||||||
{
|
|
||||||
sum += _array[i];
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public int ImmutableArray()
|
|
||||||
{
|
|
||||||
var sum = 0;
|
|
||||||
for (int i = 0; i < N; i++)
|
|
||||||
{
|
|
||||||
sum += _immutable[i];
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System.Formats.Cbor;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[DisassemblyDiagnoser]
|
||||||
|
public class RequestReader
|
||||||
|
{
|
||||||
|
private ReadOnlyMemory<byte> _data;
|
||||||
|
|
||||||
|
public RequestReader()
|
||||||
|
{
|
||||||
|
_data = new ReadOnlyMemory<byte>([80, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public ulong DefaultRead()
|
||||||
|
{
|
||||||
|
var reader = new CborReader(_data);
|
||||||
|
return new RequestId(reader.ReadByteString()).P0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public ulong MemoryRead()
|
||||||
|
{
|
||||||
|
var reader = new CborReader(_data);
|
||||||
|
return CborExtensions.ReadFromCbor(reader).P0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public ulong MemoryTrueRead()
|
||||||
|
{
|
||||||
|
var reader = new CborReader(_data);
|
||||||
|
return CborExtensions.ReadFromTrueCbor(reader).P0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System.Formats.Cbor;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class RequestWriter
|
||||||
|
{
|
||||||
|
public RequestId Id;
|
||||||
|
private readonly CborWriter _writer;
|
||||||
|
|
||||||
|
public RequestWriter()
|
||||||
|
{
|
||||||
|
_writer = new CborWriter(initialCapacity: 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public int DefaultCbor()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
_writer.WriteByteString(Id.ToByteArray());
|
||||||
|
return _writer.BytesWritten;
|
||||||
|
}
|
||||||
|
[Benchmark]
|
||||||
|
public int DirectCbor()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
Id.WriteToCbor(_writer);
|
||||||
|
return _writer.BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int Stackalloc()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
Span<byte> span = stackalloc byte[16];
|
||||||
|
Id.WriteToDest(span);
|
||||||
|
_writer.WriteByteString(span);
|
||||||
|
return _writer.BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int DirectCborInline()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
Id.WriteToCborInline(_writer);
|
||||||
|
return _writer.BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public int DirectCborOpt()
|
||||||
|
{
|
||||||
|
_writer.Reset();
|
||||||
|
Id.WriteToCborOpt(_writer);
|
||||||
|
return _writer.BytesWritten;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
public class StackOperations
|
||||||
|
{
|
||||||
|
private Stack<StackFrame> stack = new();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public StackOperations()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Stack()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
private readonly struct StackFrame
|
||||||
|
{
|
||||||
|
public StackFrame(
|
||||||
|
CborMajorType? type,
|
||||||
|
int frameOffset,
|
||||||
|
int? definiteLength,
|
||||||
|
int itemsWritten,
|
||||||
|
int? currentKeyOffset,
|
||||||
|
int? currentValueOffset,
|
||||||
|
List<int>? keyValuePairEncodingRanges,
|
||||||
|
HashSet<(int Offset, int Length)>? keyEncodingRanges)
|
||||||
|
{
|
||||||
|
MajorType = type;
|
||||||
|
FrameOffset = frameOffset;
|
||||||
|
DefiniteLength = definiteLength;
|
||||||
|
ItemsWritten = itemsWritten;
|
||||||
|
CurrentKeyOffset = currentKeyOffset;
|
||||||
|
CurrentValueOffset = currentValueOffset;
|
||||||
|
KeyValuePairEncodingRanges = keyValuePairEncodingRanges;
|
||||||
|
KeyEncodingRanges = keyEncodingRanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CborMajorType? MajorType { get; }
|
||||||
|
public int FrameOffset { get; }
|
||||||
|
public int? DefiniteLength { get; }
|
||||||
|
public int ItemsWritten { get; }
|
||||||
|
|
||||||
|
public int? CurrentKeyOffset { get; }
|
||||||
|
public int? CurrentValueOffset { get; }
|
||||||
|
public List<int>? KeyValuePairEncodingRanges { get; }
|
||||||
|
public HashSet<(int Offset, int Length)>? KeyEncodingRanges { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum CborMajorType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Int8,
|
||||||
|
Int16,
|
||||||
|
Int32,
|
||||||
|
Int64,
|
||||||
|
UInt8,
|
||||||
|
UInt16,
|
||||||
|
UInt32,
|
||||||
|
UInt64,
|
||||||
|
Float32,
|
||||||
|
Float64,
|
||||||
|
Double,
|
||||||
|
Double2,
|
||||||
|
Double3,
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Cbor;
|
||||||
|
using mROA.Implementation;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
using mROA.Implementation.Backend;
|
||||||
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
public class TaskWaiting
|
||||||
|
{
|
||||||
|
private readonly BasicExecutionModule _executionModule;
|
||||||
|
private readonly CallRequest _syncRequest;
|
||||||
|
private readonly CallRequest _asyncRequest;
|
||||||
|
private readonly InstanceRepository _instanceRepo;
|
||||||
|
private readonly EndPointContext _endPointContext;
|
||||||
|
private readonly FastRepresentationModule _representationModule;
|
||||||
|
public TaskWaiting()
|
||||||
|
{
|
||||||
|
_executionModule = new BasicExecutionModule(new CancellationRepository(), new TestMethodRepo(), new CborSerializationToolkit(null));
|
||||||
|
_syncRequest = new CallRequest{CommandId = 0, Parameters = null, Id = RequestId.Generate(), ObjectId = new ComplexObjectIdentifier(-1, 0)};
|
||||||
|
_asyncRequest = new CallRequest{CommandId = 1, Parameters = null, Id = RequestId.Generate(), ObjectId = new ComplexObjectIdentifier(-1, 0)};
|
||||||
|
_instanceRepo = new InstanceRepository(null);
|
||||||
|
_instanceRepo.FillSingletons(typeof(TaskWaiting).Assembly);
|
||||||
|
_endPointContext = new EndPointContext(_instanceRepo, null)
|
||||||
|
{
|
||||||
|
OwnerId = 0
|
||||||
|
};
|
||||||
|
_representationModule = new FastRepresentationModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public int DefaultJob()
|
||||||
|
{
|
||||||
|
return (int)((FinalCommandExecution<object>)_executionModule.Execute(_syncRequest, _instanceRepo, _representationModule, _endPointContext)).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public async Task<int> DefaultJobAsync()
|
||||||
|
{
|
||||||
|
_representationModule.Signal = new TaskCompletionSource<int>();
|
||||||
|
var task = _representationModule.Signal.Task;
|
||||||
|
_ = _executionModule.Execute(_asyncRequest, _instanceRepo, _representationModule, _endPointContext);
|
||||||
|
_ = await task;
|
||||||
|
return (int)((FinalCommandExecution<object>)_representationModule.Result).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestMethodRepo : IMethodRepository
|
||||||
|
{
|
||||||
|
public IMethodInvoker GetMethod(int id)
|
||||||
|
{
|
||||||
|
if (id == 0)
|
||||||
|
return new MethodInvoker
|
||||||
|
{
|
||||||
|
IsVoid = false,
|
||||||
|
IsTrusted = true,
|
||||||
|
ReturnType = typeof(int),
|
||||||
|
ParameterTypes = Type.EmptyTypes,
|
||||||
|
SuitableType = typeof(IJobClass),
|
||||||
|
Invoking = (i, _, _) => (i as IJobClass).A()
|
||||||
|
};
|
||||||
|
|
||||||
|
return new AsyncMethodInvoker
|
||||||
|
{
|
||||||
|
IsVoid = false,
|
||||||
|
IsTrusted = true,
|
||||||
|
ReturnType = typeof(int),
|
||||||
|
ParameterTypes = Type.EmptyTypes,
|
||||||
|
SuitableType = typeof(IJobClass),
|
||||||
|
Invoking = (i, _, _, post) => (i as IJobClass).B().ContinueWith(task => post(task.Result))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SharedObjectInterface]
|
||||||
|
public interface IJobClass
|
||||||
|
{
|
||||||
|
int A();
|
||||||
|
Task<int> B();
|
||||||
|
}
|
||||||
|
|
||||||
|
[SharedObjectSingleton]
|
||||||
|
public class JobClass : IJobClass
|
||||||
|
{
|
||||||
|
private readonly RequestWriter _requestWriter = new();
|
||||||
|
public int A()
|
||||||
|
{
|
||||||
|
return _requestWriter.DefaultCbor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> B()
|
||||||
|
{
|
||||||
|
return Task.FromResult(_requestWriter.DefaultCbor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FastRepresentationModule : IRepresentationModule
|
||||||
|
{
|
||||||
|
public TaskCompletionSource<int> Signal = new();
|
||||||
|
|
||||||
|
public object Result;
|
||||||
|
public int Id { get; }
|
||||||
|
public IEndPointContext Context { get; }
|
||||||
|
public Task<(object? Deserialized, EMessageType MessageType)> GetSingle(Predicate<NetworkMessage> rule, IEndPointContext? context, CancellationToken token = default, params Func<NetworkMessage, Type?>[] converter)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(Predicate<NetworkMessage> rule, IEndPointContext? context, CancellationToken token = default,
|
||||||
|
params Func<NetworkMessage, Type?>[] converter)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task PostCallMessageAsync<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull
|
||||||
|
{
|
||||||
|
Result = payload;
|
||||||
|
Signal.SetResult(0);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostCallMessage<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task PostCallMessageUntrustedAsync<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Benchmark;
|
||||||
|
|
||||||
|
public class VirtualOverhead
|
||||||
|
{
|
||||||
|
private CallRequest _directRequest;
|
||||||
|
private RawCallRequest _rawRequest;
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup() {
|
||||||
|
_directRequest = new CallRequest
|
||||||
|
{
|
||||||
|
CommandId = 5, Id = new RequestId(), ObjectId = ComplexObjectIdentifier.Null, Parameters = null
|
||||||
|
};
|
||||||
|
_rawRequest = new RawCallRequest
|
||||||
|
{
|
||||||
|
CommandId = _directRequest.CommandId, Id = _directRequest.Id, ObjectId = _directRequest.ObjectId,
|
||||||
|
Parameters = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public long DirectUsage()
|
||||||
|
{
|
||||||
|
var req = _directRequest;
|
||||||
|
long acc = 0;
|
||||||
|
acc += req.CommandId;
|
||||||
|
acc += (long)(req.Id.P1 + req.Id.P0);
|
||||||
|
acc += req.ObjectId.ContextId + req.ObjectId.OwnerId;
|
||||||
|
acc += (req.Parameters ?? []).Length;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public long RawUsage()
|
||||||
|
{
|
||||||
|
var req = _rawRequest;
|
||||||
|
long acc = 0;
|
||||||
|
acc += req.CommandId;
|
||||||
|
acc += (long)(req.Id.P1 + req.Id.P0);
|
||||||
|
acc += req.ObjectId.ContextId + req.ObjectId.OwnerId;
|
||||||
|
acc += (req.Parameters ?? []).Length;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public long ParamUsage()
|
||||||
|
{
|
||||||
|
return Call(_directRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public long ParamInUsage()
|
||||||
|
{
|
||||||
|
return CallIn(in _directRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public long Call(CallRequest req)
|
||||||
|
{
|
||||||
|
long acc = 0;
|
||||||
|
acc += req.CommandId;
|
||||||
|
acc += (long)(req.Id.P1 + req.Id.P0);
|
||||||
|
acc += req.ObjectId.ContextId + req.ObjectId.OwnerId;
|
||||||
|
acc += (req.Parameters ?? []).Length;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public long CallIn(in CallRequest req)
|
||||||
|
{
|
||||||
|
long acc = 0;
|
||||||
|
acc += req.CommandId;
|
||||||
|
acc += (long)(req.Id.P1 + req.Id.P0);
|
||||||
|
acc += req.ObjectId.ContextId + req.ObjectId.OwnerId;
|
||||||
|
acc += (req.Parameters ?? []).Length;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct RawCallRequest
|
||||||
|
{
|
||||||
|
public RequestId Id;
|
||||||
|
public int CommandId;
|
||||||
|
public ComplexObjectIdentifier ObjectId;
|
||||||
|
|
||||||
|
public object?[]? Parameters;
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Call request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,21 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.15.2"/>
|
||||||
|
<PackageReference Include="System.Formats.Cbor" Version="9.0.8"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj"/>
|
||||||
|
<ProjectReference Include="..\mROA.Codegen\mROA.Codegen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||||
|
<ProjectReference Include="..\mROA\mROA.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Formats.Cbor;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Cbor
|
||||||
|
{
|
||||||
|
public static class CborExtensions
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe void WriteToCborInline(this RequestId id, CborWriter writer)
|
||||||
|
{
|
||||||
|
Span<byte> span = stackalloc byte[16];
|
||||||
|
MemoryMarshal.Write(span, ref id);
|
||||||
|
writer.WriteByteString(span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Formats.Cbor;
|
using System.Formats.Cbor;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
@@ -14,59 +15,73 @@ namespace mROA.Cbor
|
|||||||
{
|
{
|
||||||
public class CborSerializationToolkit : IContextualSerializationToolKit
|
public class CborSerializationToolkit : IContextualSerializationToolKit
|
||||||
{
|
{
|
||||||
private readonly IOrdinaryStructureParser[] _parsers = {
|
private readonly ThreadLocal<CborWriter> _writer = new(() => new CborWriter(initialCapacity: 2048));
|
||||||
new NetworkMessageHeaderParser(), new DefaultCallRequestParser(), new FinalCommandExecutionParser(),
|
private readonly int _offset;
|
||||||
|
|
||||||
|
public CborSerializationToolkit(IOptions<SerializationBufferOffset> offsetOptions) : this(offsetOptions.Value
|
||||||
|
.Offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IOrdinaryStructureParser[] _parsers =
|
||||||
|
{
|
||||||
|
new CallRequestParser(), new FinalCommandExecutionParser(),
|
||||||
new FinalCommandExecutionResultlessParser()
|
new FinalCommandExecutionResultlessParser()
|
||||||
};
|
};
|
||||||
// private Dictionary<Type, IOrdinaryStructureParser> _parsers = new(){{typeof(NetworkMessageHeader), new NetworkMessageHeaderParser()}, {typeof(DefaultCallRequest), new DefaultCallRequestParser()}, {typeof(FinalCommandExecution<object>), new FinalCommandExecutionParser()}, {typeof(FinalCommandExecution), new FinalCommandExecutionResultlessParser()}}; //
|
|
||||||
private Dictionary<Type, List<PropertyInfo>> _propertiesCache = new();
|
private readonly Dictionary<Type, List<PropertyInfo>> _propertiesCache = new();
|
||||||
|
|
||||||
|
public CborSerializationToolkit(int offset)
|
||||||
|
{
|
||||||
|
_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
public static TimeSpan SerializationTime = TimeSpan.Zero;
|
public static TimeSpan SerializationTime = TimeSpan.Zero;
|
||||||
|
|
||||||
private bool FindParser(Type t, out IOrdinaryStructureParser parser)
|
private bool FindParser(Type t, out IOrdinaryStructureParser parser)
|
||||||
{
|
{
|
||||||
if (t == typeof(NetworkMessageHeader))
|
if (t == typeof(CallRequest))
|
||||||
{
|
{
|
||||||
parser = _parsers[0];
|
parser = _parsers[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == typeof(DefaultCallRequest))
|
if (t == typeof(FinalCommandExecution<object>))
|
||||||
{
|
{
|
||||||
parser = _parsers[1];
|
parser = _parsers[1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == typeof(FinalCommandExecution<object>))
|
|
||||||
{
|
|
||||||
parser = _parsers[2];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t == typeof(FinalCommandExecution))
|
if (t == typeof(FinalCommandExecution))
|
||||||
{
|
{
|
||||||
parser = _parsers[3];
|
parser = _parsers[2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser = null;
|
parser = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize(object objectToSerialize, IEndPointContext context)
|
public byte[] Serialize(object objectToSerialize, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var sw = Stopwatch.StartNew();
|
var writer = _writer.Value;
|
||||||
var writer = new CborWriter(initialCapacity:64);
|
writer.Reset();
|
||||||
WriteData(objectToSerialize, writer, context);
|
WriteData(objectToSerialize, writer, context);
|
||||||
var result = writer.Encode();
|
var result = new byte[_offset + writer.BytesWritten];
|
||||||
sw.Stop();
|
var span = result.AsSpan();
|
||||||
SerializationTime = SerializationTime.Add(sw.Elapsed);
|
writer.Encode(span[_offset..]);
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Serialize(object objectToSerialize, Span<byte> destination, IEndPointContext context)
|
public int Serialize(object objectToSerialize, Span<byte> destination, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var writer = new CborWriter(initialCapacity:64);
|
var writer = _writer.Value;
|
||||||
WriteData(objectToSerialize, writer, context);
|
writer.Reset();
|
||||||
return writer.Encode(destination);
|
WriteData(objectToSerialize, writer, context);
|
||||||
|
return writer.Encode(destination);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Deserialize<T>(byte[] rawData, IEndPointContext? context)
|
public T Deserialize<T>(byte[] rawData, IEndPointContext? context)
|
||||||
@@ -86,13 +101,17 @@ namespace mROA.Cbor
|
|||||||
|
|
||||||
public object? Deserialize(ReadOnlyMemory<byte> rawMemory, Type type, IEndPointContext? context)
|
public object? Deserialize(ReadOnlyMemory<byte> rawMemory, Type type, IEndPointContext? context)
|
||||||
{
|
{
|
||||||
var reader = new CborReader(rawMemory);
|
try
|
||||||
return ReadData(reader, type, context);
|
{
|
||||||
}
|
var reader = new CborReader(rawMemory);
|
||||||
|
return ReadData(reader, type, context);
|
||||||
public T Cast<T>(object nonCasted, IEndPointContext? context)
|
}
|
||||||
{
|
catch (Exception)
|
||||||
return (T)Cast(nonCasted, typeof(T), context);
|
{
|
||||||
|
Console.WriteLine(
|
||||||
|
$"Bad deserialization for type {type}. Bytes: {BitConverter.ToString(rawMemory.ToArray())}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
|
public object? Cast(object? nonCasted, Type type, IEndPointContext? context)
|
||||||
@@ -107,56 +126,22 @@ namespace mROA.Cbor
|
|||||||
return preParsed.ToObject(type, context);
|
return preParsed.ToObject(type, context);
|
||||||
|
|
||||||
|
|
||||||
if (type == typeof(Guid))
|
if (type == typeof(RequestId))
|
||||||
{
|
{
|
||||||
return new Guid((byte[])nonCasted);
|
return new RequestId((byte[])nonCasted);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsInterface)
|
||||||
|
{
|
||||||
|
return ReadSharedShell(type, context, (ulong)nonCasted);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Convert.ChangeType(nonCasted, type);
|
return Convert.ChangeType(nonCasted, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject(object dependency)
|
public IContextualSerializationToolKit Clone()
|
||||||
{
|
{
|
||||||
}
|
return new CborSerializationToolkit(_offset);
|
||||||
|
|
||||||
public byte[] Serialize<T>(T objectToSerialize)
|
|
||||||
{
|
|
||||||
return Serialize(objectToSerialize, typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Serialize(object objectToSerialize, Type type)
|
|
||||||
{
|
|
||||||
return Serialize(objectToSerialize, context: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Deserialize<T>(byte[] rawData)
|
|
||||||
{
|
|
||||||
return Deserialize<T>(rawData: rawData, context: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object? Deserialize(byte[] rawData, Type type)
|
|
||||||
{
|
|
||||||
return Deserialize(rawData: rawData, type, context: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Deserialize<T>(Span<byte> rawData)
|
|
||||||
{
|
|
||||||
return Deserialize<T>(rawData.ToArray().AsMemory(), context: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object? Deserialize(Span<byte> rawData, Type type)
|
|
||||||
{
|
|
||||||
return Deserialize(rawData: rawData.ToArray(), type: type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Cast<T>(object nonCasted)
|
|
||||||
{
|
|
||||||
return Cast<T>(nonCasted: nonCasted, context: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Cast(object nonCasted, Type type)
|
|
||||||
{
|
|
||||||
return Cast(nonCasted: nonCasted, type: type, context: null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
|
public void WriteData(object? obj, CborWriter writer, IEndPointContext? context)
|
||||||
@@ -199,8 +184,9 @@ namespace mROA.Cbor
|
|||||||
case DateTimeOffset dto:
|
case DateTimeOffset dto:
|
||||||
writer.WriteDateTimeOffset(dto);
|
writer.WriteDateTimeOffset(dto);
|
||||||
break;
|
break;
|
||||||
case Guid g:
|
case RequestId g:
|
||||||
writer.WriteByteString(g.ToByteArray());
|
// writer.WriteByteString(g.ToByteArray());
|
||||||
|
g.WriteToCborInline(writer);
|
||||||
break;
|
break;
|
||||||
case byte[] bytes:
|
case byte[] bytes:
|
||||||
writer.WriteByteString(bytes);
|
writer.WriteByteString(bytes);
|
||||||
@@ -217,9 +203,20 @@ namespace mROA.Cbor
|
|||||||
WriteObject(sharedObject, writer, context);
|
WriteObject(sharedObject, writer, context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (obj.GetType().IsEnum)
|
var objType = obj.GetType();
|
||||||
|
if (objType.IsEnum)
|
||||||
{
|
{
|
||||||
writer.WriteInt32((int)obj);
|
var basicType = Enum.GetUnderlyingType(obj.GetType());
|
||||||
|
|
||||||
|
if (basicType == typeof(byte))
|
||||||
|
{
|
||||||
|
writer.WriteInt32((byte)obj);
|
||||||
|
}
|
||||||
|
else if (basicType == typeof(int))
|
||||||
|
{
|
||||||
|
writer.WriteInt32((byte)obj);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,9 +267,7 @@ namespace mROA.Cbor
|
|||||||
Activator.CreateInstance(sharedShell, obj, context) as
|
Activator.CreateInstance(sharedShell, obj, context) as
|
||||||
ISharedObjectShell;
|
ISharedObjectShell;
|
||||||
|
|
||||||
writer.WriteStartArray(1);
|
|
||||||
writer.WriteUInt64(so.Identifier.Flat);
|
writer.WriteUInt64(so.Identifier.Flat);
|
||||||
writer.WriteEndArray();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -288,6 +283,7 @@ namespace mROA.Cbor
|
|||||||
{
|
{
|
||||||
return parser.Read(reader, context, this);
|
return parser.Read(reader, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var state = reader.PeekState();
|
var state = reader.PeekState();
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
@@ -301,13 +297,15 @@ namespace mROA.Cbor
|
|||||||
return reader.ReadInt64();
|
return reader.ReadInt64();
|
||||||
if (type == typeof(uint))
|
if (type == typeof(uint))
|
||||||
return reader.ReadUInt32();
|
return reader.ReadUInt32();
|
||||||
if (type == typeof(ulong))
|
if (type.IsInterface)
|
||||||
return reader.ReadUInt64();
|
{
|
||||||
|
return ReadSharedShell(type, context, reader.ReadUInt64());
|
||||||
|
}
|
||||||
|
|
||||||
return reader.ReadUInt64();
|
return reader.ReadUInt64();
|
||||||
case CborReaderState.ByteString:
|
case CborReaderState.ByteString:
|
||||||
if (type == typeof(Guid))
|
if (type == typeof(RequestId))
|
||||||
return new Guid(reader.ReadByteString());
|
return new RequestId(reader.ReadByteString());
|
||||||
return reader.ReadByteString();
|
return reader.ReadByteString();
|
||||||
case CborReaderState.TextString:
|
case CborReaderState.TextString:
|
||||||
return reader.ReadTextString();
|
return reader.ReadTextString();
|
||||||
@@ -414,19 +412,9 @@ namespace mROA.Cbor
|
|||||||
|
|
||||||
if (type.IsInterface)
|
if (type.IsInterface)
|
||||||
{
|
{
|
||||||
var sharedShell = typeof(SharedObjectShellShell<>).MakeGenericType(type);
|
|
||||||
var so =
|
|
||||||
Activator.CreateInstance(sharedShell) as
|
|
||||||
ISharedObjectShell;
|
|
||||||
if (context != null)
|
|
||||||
so.EndPointContext = context;
|
|
||||||
|
|
||||||
reader.ReadStartArray();
|
|
||||||
var identifier = reader.ReadUInt64();
|
var identifier = reader.ReadUInt64();
|
||||||
reader.ReadEndArray();
|
|
||||||
|
|
||||||
so.Identifier = ComplexObjectIdentifier.FromFlat(identifier);
|
return ReadSharedShell(type, context, identifier);
|
||||||
return so.UniversalValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance = Activator.CreateInstance(type)!;
|
var instance = Activator.CreateInstance(type)!;
|
||||||
@@ -436,6 +424,20 @@ namespace mROA.Cbor
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object ReadSharedShell(Type type, IEndPointContext? context, ulong identifier)
|
||||||
|
{
|
||||||
|
var sharedShell = typeof(SharedObjectShellShell<>).MakeGenericType(type);
|
||||||
|
var so =
|
||||||
|
Activator.CreateInstance(sharedShell) as
|
||||||
|
ISharedObjectShell;
|
||||||
|
if (context != null)
|
||||||
|
so.EndPointContext = context;
|
||||||
|
|
||||||
|
|
||||||
|
so.Identifier = ComplexObjectIdentifier.FromFlat(identifier);
|
||||||
|
return so.UniversalValue;
|
||||||
|
}
|
||||||
|
|
||||||
private ISharedObjectShell ReadSharedObject(CborReader reader, Type type, IEndPointContext? context)
|
private ISharedObjectShell ReadSharedObject(CborReader reader, Type type, IEndPointContext? context)
|
||||||
{
|
{
|
||||||
var sharedObject = (Activator.CreateInstance(type) as ISharedObjectShell)!;
|
var sharedObject = (Activator.CreateInstance(type) as ISharedObjectShell)!;
|
||||||
@@ -463,6 +465,15 @@ namespace mROA.Cbor
|
|||||||
{
|
{
|
||||||
var property = properties[index];
|
var property = properties[index];
|
||||||
var value = ReadData(reader, property.PropertyType, context);
|
var value = ReadData(reader, property.PropertyType, context);
|
||||||
|
|
||||||
|
if (property.PropertyType.IsEnum)
|
||||||
|
{
|
||||||
|
if (property.PropertyType.GetEnumUnderlyingType() == typeof(byte))
|
||||||
|
{
|
||||||
|
value = Convert.ChangeType(value, typeof(byte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property.SetValue(obj, value);
|
property.SetValue(obj, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,11 +496,11 @@ namespace mROA.Cbor
|
|||||||
for (int i = 0; i < properties.Length; i++)
|
for (int i = 0; i < properties.Length; i++)
|
||||||
{
|
{
|
||||||
var property = properties[i];
|
var property = properties[i];
|
||||||
if (property is not { CanRead: true, CanWrite: true } || property.GetCustomAttribute<SerializationIgnoreAttribute>() != null)
|
if (property is not { CanRead: true, CanWrite: true } ||
|
||||||
|
property.GetCustomAttribute<SerializationIgnoreAttribute>() != null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
finalProperties.Add(property);
|
finalProperties.Add(property);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalProperties;
|
return finalProperties;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Formats.Cbor;
|
using System.Formats.Cbor;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
@@ -12,42 +14,17 @@ namespace mROA.Cbor
|
|||||||
object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization);
|
object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NetworkMessageHeaderParser : IOrdinaryStructureParser
|
public class CallRequestParser : IOrdinaryStructureParser
|
||||||
{
|
{
|
||||||
public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization)
|
public void Write(CborWriter writer, object value, IEndPointContext context,
|
||||||
|
CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
var v = value as NetworkMessageHeader;
|
var v = (CallRequest)value;
|
||||||
writer.WriteStartArray(3);
|
|
||||||
writer.WriteByteString(v.Id.ToByteArray());
|
|
||||||
writer.WriteInt32((int)v.MessageType);
|
|
||||||
writer.WriteByteString(v.Data);
|
|
||||||
writer.WriteEndArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization)
|
|
||||||
{
|
|
||||||
reader.ReadStartArray();
|
|
||||||
var value = new NetworkMessageHeader
|
|
||||||
{
|
|
||||||
Id = new Guid(reader.ReadByteString()),
|
|
||||||
MessageType = (EMessageType)reader.ReadInt32(),
|
|
||||||
Data = reader.ReadByteString()
|
|
||||||
};
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DefaultCallRequestParser : IOrdinaryStructureParser
|
|
||||||
{
|
|
||||||
public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization)
|
|
||||||
{
|
|
||||||
var v = (DefaultCallRequest)value;
|
|
||||||
writer.WriteStartArray(4);
|
writer.WriteStartArray(4);
|
||||||
writer.WriteByteString(v.Id.ToByteArray());
|
v.Id.WriteToCborInline(writer);
|
||||||
|
// writer.WriteByteString(v.Id.ToByteArray());
|
||||||
writer.WriteInt32(v.CommandId);
|
writer.WriteInt32(v.CommandId);
|
||||||
writer.WriteStartArray(1);
|
|
||||||
writer.WriteUInt64(v.ObjectId.Flat);
|
writer.WriteUInt64(v.ObjectId.Flat);
|
||||||
writer.WriteEndArray();
|
|
||||||
serialization.WriteData(v.Parameters, writer, context);
|
serialization.WriteData(v.Parameters, writer, context);
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
@@ -55,11 +32,12 @@ namespace mROA.Cbor
|
|||||||
public object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization)
|
public object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
reader.ReadStartArray();
|
reader.ReadStartArray();
|
||||||
var value = new DefaultCallRequest
|
var value = new CallRequest
|
||||||
{
|
{
|
||||||
Id = new Guid(reader.ReadByteString()),
|
Id = new RequestId(reader.ReadByteString()),
|
||||||
CommandId = reader.ReadInt32(),
|
CommandId = reader.ReadInt32(),
|
||||||
ObjectId = (ComplexObjectIdentifier)ComplexObjectIdentifierParser.Instance.Read(reader, context, serialization),
|
ObjectId = (ComplexObjectIdentifier)ComplexObjectIdentifierParser.Instance.Read(reader, context,
|
||||||
|
serialization),
|
||||||
Parameters = serialization.ReadData(reader, typeof(object[]), context) as object[]
|
Parameters = serialization.ReadData(reader, typeof(object[]), context) as object[]
|
||||||
};
|
};
|
||||||
reader.ReadEndArray();
|
reader.ReadEndArray();
|
||||||
@@ -70,29 +48,29 @@ namespace mROA.Cbor
|
|||||||
public class ComplexObjectIdentifierParser : IOrdinaryStructureParser
|
public class ComplexObjectIdentifierParser : IOrdinaryStructureParser
|
||||||
{
|
{
|
||||||
public static readonly ComplexObjectIdentifierParser Instance = new();
|
public static readonly ComplexObjectIdentifierParser Instance = new();
|
||||||
public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization)
|
|
||||||
|
public void Write(CborWriter writer, object value, IEndPointContext context,
|
||||||
|
CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
writer.WriteStartArray(1);
|
|
||||||
writer.WriteUInt64(((ComplexObjectIdentifier)value).Flat);
|
writer.WriteUInt64(((ComplexObjectIdentifier)value).Flat);
|
||||||
writer.WriteEndArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization)
|
public object Read(CborReader reader, IEndPointContext context, CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
reader.ReadStartArray();
|
|
||||||
var value = new ComplexObjectIdentifier { Flat = reader.ReadUInt64() };
|
var value = new ComplexObjectIdentifier { Flat = reader.ReadUInt64() };
|
||||||
reader.ReadEndArray();
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FinalCommandExecutionParser : IOrdinaryStructureParser
|
public class FinalCommandExecutionParser : IOrdinaryStructureParser
|
||||||
{
|
{
|
||||||
public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization)
|
public void Write(CborWriter writer, object value, IEndPointContext context,
|
||||||
|
CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
var v = (FinalCommandExecution<object>)value;
|
var v = (FinalCommandExecution<object>)value;
|
||||||
writer.WriteStartArray(2);
|
writer.WriteStartArray(2);
|
||||||
writer.WriteByteString(v.Id.ToByteArray());
|
// writer.WriteByteString(v.Id.ToByteArray());
|
||||||
|
v.Id.WriteToCborInline(writer);
|
||||||
serialization.WriteData(v.Result, writer, context);
|
serialization.WriteData(v.Result, writer, context);
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
@@ -102,21 +80,22 @@ namespace mROA.Cbor
|
|||||||
reader.ReadStartArray();
|
reader.ReadStartArray();
|
||||||
var result = new FinalCommandExecution<object>
|
var result = new FinalCommandExecution<object>
|
||||||
{
|
{
|
||||||
Id = new Guid(reader.ReadByteString()),
|
Id = new RequestId(reader.ReadByteString()),
|
||||||
Result = serialization.ReadData(reader, typeof(object), context),
|
Result = serialization.ReadData(reader, typeof(object), context),
|
||||||
};
|
};
|
||||||
reader.ReadEndArray();
|
reader.ReadEndArray();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FinalCommandExecutionResultlessParser : IOrdinaryStructureParser
|
public class FinalCommandExecutionResultlessParser : IOrdinaryStructureParser
|
||||||
{
|
{
|
||||||
public void Write(CborWriter writer, object value, IEndPointContext context, CborSerializationToolkit serialization)
|
public void Write(CborWriter writer, object value, IEndPointContext context,
|
||||||
|
CborSerializationToolkit serialization)
|
||||||
{
|
{
|
||||||
var v = (FinalCommandExecution)value;
|
var v = (FinalCommandExecution)value;
|
||||||
writer.WriteStartArray(1);
|
writer.WriteStartArray(1);
|
||||||
writer.WriteByteString(v.Id.ToByteArray());
|
v.Id.WriteToCborInline(writer);
|
||||||
writer.WriteEndArray();
|
writer.WriteEndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +104,7 @@ namespace mROA.Cbor
|
|||||||
reader.ReadStartArray();
|
reader.ReadStartArray();
|
||||||
var result = new FinalCommandExecution
|
var result = new FinalCommandExecution
|
||||||
{
|
{
|
||||||
Id = new Guid(reader.ReadByteString())
|
Id = new RequestId(reader.ReadByteString())
|
||||||
};
|
};
|
||||||
reader.ReadEndArray();
|
reader.ReadEndArray();
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Version>2.0.7</Version>
|
<Version>3.0.4</Version>
|
||||||
<LangVersion>9</LangVersion>
|
<LangVersion>9</LangVersion>
|
||||||
<PackageIcon>mroaLogo.png</PackageIcon>
|
<PackageIcon>mroaLogo.png</PackageIcon>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
@@ -21,10 +22,6 @@
|
|||||||
<ProjectReference Include="..\mROA\mROA.csproj" />
|
<ProjectReference Include="..\mROA\mROA.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.Formats.Cbor" Version="9.0.2" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="mroaLogo.png">
|
<None Update="mroaLogo.png">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
@@ -32,4 +29,8 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.Formats.Cbor" Version="9.0.8" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -23,6 +23,7 @@ namespace mROA.Codegen
|
|||||||
ReturnType = typeof(<!L returnType>),
|
ReturnType = typeof(<!L returnType>),
|
||||||
ParameterTypes = new Type[] { <!L parametersType> },
|
ParameterTypes = new Type[] { <!L parametersType> },
|
||||||
SuitableType = typeof(<!L suitableType>),
|
SuitableType = typeof(<!L suitableType>),
|
||||||
|
RequireCancellation = <!L cancellation>,
|
||||||
Invoking = (i, parameters, special, post) => <!L funcInvoking>,
|
Invoking = (i, parameters, special, post) => <!L funcInvoking>,
|
||||||
}<!T>
|
}<!T>
|
||||||
<!T syncInvoker>
|
<!T syncInvoker>
|
||||||
|
|||||||
@@ -26,12 +26,11 @@ namespace mROA.Codegen
|
|||||||
<!T eventBinderTemplate>
|
<!T eventBinderTemplate>
|
||||||
(instance as <!L type>).<!L eventName> += (<!L parametersDeclaration>) =>
|
(instance as <!L type>).<!L eventName> += (<!L parametersDeclaration>) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Try to send to {ownerId} with hash code {context.GetHashCode()}");
|
|
||||||
<!I callFilter>
|
<!I callFilter>
|
||||||
Console.WriteLine("Sending event...");
|
Console.WriteLine("Sending event...");
|
||||||
var request = new DefaultCallRequest
|
var request = new CallRequest
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(),
|
Id = RequestId.Generate(),
|
||||||
CommandId = <!L commandId>,
|
CommandId = <!L commandId>,
|
||||||
ObjectId = new ComplexObjectIdentifier(index, ownerId),
|
ObjectId = new ComplexObjectIdentifier(index, ownerId),
|
||||||
Parameters = new object[] { <!L transferParameters> }
|
Parameters = new object[] { <!L transferParameters> }
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string CommandIdTag = "commandId";
|
private const string CommandIdTag = "commandId";
|
||||||
private const string TransferParametersTag = "transferParameters";
|
private const string TransferParametersTag = "transferParameters";
|
||||||
|
|
||||||
public EventBinderTemplate(TemplateDocument template) : base(template) { }
|
public EventBinderTemplate(TemplateDocument template) : base(template)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineCallFilter(string value)
|
public void DefineCallFilter(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string IndexSpanTag = "indexSpan";
|
private const string IndexSpanTag = "indexSpan";
|
||||||
private const string RemoteTypePairTag = "remoteTypePair";
|
private const string RemoteTypePairTag = "remoteTypePair";
|
||||||
|
|
||||||
public IndexProviderTemplate() : base(TemplateFile) { }
|
public IndexProviderTemplate() : base(TemplateFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineNamespace(string value)
|
public void DefineNamespace(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string ParametersTypeTag = "parametersType";
|
private const string ParametersTypeTag = "parametersType";
|
||||||
private const string SuitableTypeTag = "suitableType";
|
private const string SuitableTypeTag = "suitableType";
|
||||||
private const string FuncInvokingTag = "funcInvoking";
|
private const string FuncInvokingTag = "funcInvoking";
|
||||||
|
private const string CancellationTag = "cancellation";
|
||||||
private const string IsTrustedTag = "isTrusted";
|
private const string IsTrustedTag = "isTrusted";
|
||||||
|
|
||||||
public InvokerTemplate(TemplateDocument template) : base(template) { }
|
public InvokerTemplate(TemplateDocument template) : base(template)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineIsVoid(string value)
|
public void DefineIsVoid(string value)
|
||||||
{
|
{
|
||||||
@@ -42,5 +45,10 @@ namespace mROA.Codegen.Templates
|
|||||||
{
|
{
|
||||||
Define(IsTrustedTag, value);
|
Define(IsTrustedTag, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DefineCancellation(string value)
|
||||||
|
{
|
||||||
|
Define(CancellationTag, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,9 @@ namespace mROA.Codegen.Templates
|
|||||||
|
|
||||||
private const string InvokerTag = "invoker";
|
private const string InvokerTag = "invoker";
|
||||||
|
|
||||||
public MethodRepoTemplate() : base(TemplateFile) { }
|
public MethodRepoTemplate() : base(TemplateFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void InsertInvoke(string value)
|
public void InsertInvoke(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string TypeTag = "type";
|
private const string TypeTag = "type";
|
||||||
private const string EventBinderTag = "eventBinder";
|
private const string EventBinderTag = "eventBinder";
|
||||||
|
|
||||||
public ObjectBinderTemplate(TemplateDocument template) : base(template) { }
|
public ObjectBinderTemplate(TemplateDocument template) : base(template)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineType(string value)
|
public void DefineType(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string NamespaceTag = "namespace";
|
private const string NamespaceTag = "namespace";
|
||||||
private const string SignatureTag = "signature";
|
private const string SignatureTag = "signature";
|
||||||
|
|
||||||
public PartialInterfaceTemplate() : base(TemplateFile) { }
|
public PartialInterfaceTemplate() : base(TemplateFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineName(string value)
|
public void DefineName(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ namespace mROA.Codegen.Templates
|
|||||||
|
|
||||||
private const string ClassNameTag = "className";
|
private const string ClassNameTag = "className";
|
||||||
private const string OriginalNameTag = "originalName";
|
private const string OriginalNameTag = "originalName";
|
||||||
private const string NamespaceNameTag= "namespaceName";
|
private const string NamespaceNameTag = "namespaceName";
|
||||||
private const string MethodsTag = "methods";
|
private const string MethodsTag = "methods";
|
||||||
|
|
||||||
public ProxyTemplate() : base(TemplateFile) { }
|
public ProxyTemplate() : base(TemplateFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void DefineClassName(string value)
|
public void DefineClassName(string value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ namespace mROA.Codegen.Templates
|
|||||||
private const string ObjectBinderTemplateTag = "objectBinderTemplate";
|
private const string ObjectBinderTemplateTag = "objectBinderTemplate";
|
||||||
private const string EventBinderTag = "eventBinder";
|
private const string EventBinderTag = "eventBinder";
|
||||||
|
|
||||||
public RemoteTypeBinderTemplate() : base(TemplateFile) { }
|
public RemoteTypeBinderTemplate() : base(TemplateFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public ObjectBinderTemplate CloneInnerObjectBinder()
|
public ObjectBinderTemplate CloneInnerObjectBinder()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,10 +17,18 @@
|
|||||||
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>
|
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Version>2.0.7</Version>
|
<Version>3.0.3</Version>
|
||||||
<PackageIcon>mroaLogo.png</PackageIcon>
|
<PackageIcon>mroaLogo.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<PackageLicenseFile>LICENSE-2.0.txt</PackageLicenseFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="LICENSE-2.0.txt" Pack="true" PackagePath="$(PackageLicenseFile)"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
@@ -32,8 +40,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
<None Update="mroaLogo.png">
|
<None Update="mroaLogo.png">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
<PackagePath></PackagePath>
|
<PackagePath></PackagePath>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -49,8 +57,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="IndexProvider.cstmpl" />
|
<None Remove="IndexProvider.cstmpl" />
|
||||||
<EmbeddedResource Include="IndexProvider.cstmpl" />
|
<EmbeddedResource Include="IndexProvider.cstmpl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using mROA.Codegen.Templates;
|
using mROA.Codegen.Templates;
|
||||||
|
|
||||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
|
||||||
|
|
||||||
namespace mROA.Codegen
|
namespace mROA.Codegen
|
||||||
{
|
{
|
||||||
@@ -138,15 +137,18 @@ namespace mROA.Codegen
|
|||||||
// declaredMethods.Add(impl);
|
// declaredMethods.Add(impl);
|
||||||
break;
|
break;
|
||||||
case IEventSymbol eventSymbol:
|
case IEventSymbol eventSymbol:
|
||||||
proxyTemplate.InsertMethods($"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};");
|
proxyTemplate.InsertMethods(
|
||||||
|
$"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};");
|
||||||
// declaredMethods.Add(
|
// declaredMethods.Add(
|
||||||
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateEventImplementation(proxyTemplate, methodRepoTemplate, typeBinder, classSymbol, invokers, context);
|
GenerateEventImplementation(proxyTemplate, methodRepoTemplate, typeBinder, classSymbol, invokers,
|
||||||
|
context);
|
||||||
var endInvokers = invokers.Count;
|
var endInvokers = invokers.Count;
|
||||||
indexProviderTemplate.InsertIndexSpan($"{{ typeof({originalName}), new[] {{ {CodegenUtilities.JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},");
|
indexProviderTemplate.InsertIndexSpan(
|
||||||
|
$"{{ typeof({originalName}), new[] {{ {CodegenUtilities.JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},");
|
||||||
proxyTemplate.DefineClassName(className);
|
proxyTemplate.DefineClassName(className);
|
||||||
proxyTemplate.DefineOriginalName(originalName);
|
proxyTemplate.DefineOriginalName(originalName);
|
||||||
proxyTemplate.DefineNamespaceName(namespaceName);
|
proxyTemplate.DefineNamespaceName(namespaceName);
|
||||||
@@ -158,7 +160,8 @@ namespace mROA.Codegen
|
|||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
indexProviderTemplate.InsertRemoteTypePair($"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}");
|
indexProviderTemplate.InsertRemoteTypePair(
|
||||||
|
$"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalMethods.Count != 0)
|
if (totalMethods.Count != 0)
|
||||||
@@ -185,7 +188,8 @@ namespace mROA.Codegen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateEventImplementation(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, RemoteTypeBinderTemplate remoteTypeBinder, INamedTypeSymbol classSymbol,
|
private void GenerateEventImplementation(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate,
|
||||||
|
RemoteTypeBinderTemplate remoteTypeBinder, INamedTypeSymbol classSymbol,
|
||||||
List<string> invokers, SourceProductionContext context)
|
List<string> invokers, SourceProductionContext context)
|
||||||
{
|
{
|
||||||
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
||||||
@@ -236,7 +240,8 @@ namespace mROA.Codegen
|
|||||||
return caller;
|
return caller;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateDeclaredMethod(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, IMethodSymbol method, List<string> invokers,
|
private void GenerateDeclaredMethod(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate,
|
||||||
|
IMethodSymbol method, List<string> invokers,
|
||||||
INamedTypeSymbol baseInterface)
|
INamedTypeSymbol baseInterface)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@@ -317,14 +322,17 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
var parametersInsertList = new List<string>();
|
var parametersInsertList = new List<string>();
|
||||||
|
|
||||||
|
var useCancellationToken = false;
|
||||||
|
|
||||||
foreach (var parameter in method.Parameters)
|
foreach (var parameter in method.Parameters)
|
||||||
switch (parameter.Type.Name)
|
switch (parameter.Type.Name)
|
||||||
{
|
{
|
||||||
case "CancellationToken":
|
case "CancellationToken":
|
||||||
parametersInsertList.Add("(CancellationToken)special[1]");
|
parametersInsertList.Add("(CancellationToken)special[1]");
|
||||||
|
useCancellationToken = true;
|
||||||
break;
|
break;
|
||||||
case "RequestContext":
|
case "RequestContext":
|
||||||
parametersInsertList.Add("special[0] as RequestContext");
|
parametersInsertList.Add("(RequestContext)special[0]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parametersInsertList.Add(CodegenUtilities.Caster(parameter.Type,
|
parametersInsertList.Add(CodegenUtilities.Caster(parameter.Type,
|
||||||
@@ -360,6 +368,7 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
|
invokerTemplate.DefineCancellation(useCancellationToken.ToString().ToLower());
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -371,6 +380,7 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +389,8 @@ namespace mROA.Codegen
|
|||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateBinderCode(ObjectBinderTemplate objectBinderTemplate, IEventSymbol eventSymbol, INamedTypeSymbol baseType)
|
private void GenerateBinderCode(ObjectBinderTemplate objectBinderTemplate, IEventSymbol eventSymbol,
|
||||||
|
INamedTypeSymbol baseType)
|
||||||
{
|
{
|
||||||
var eventBinderTemplate = objectBinderTemplate.CloneInnerEventBinder();
|
var eventBinderTemplate = objectBinderTemplate.CloneInnerEventBinder();
|
||||||
|
|
||||||
@@ -404,13 +415,15 @@ namespace mROA.Codegen
|
|||||||
eventBinderTemplate.DefineType(baseType.ToUnityString());
|
eventBinderTemplate.DefineType(baseType.ToUnityString());
|
||||||
eventBinderTemplate.DefineEventName(eventSymbol.Name);
|
eventBinderTemplate.DefineEventName(eventSymbol.Name);
|
||||||
eventBinderTemplate.DefineParametersDeclaration(parametersDeclaration);
|
eventBinderTemplate.DefineParametersDeclaration(parametersDeclaration);
|
||||||
eventBinderTemplate.DefineCommandIdTag($"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]");
|
eventBinderTemplate.DefineCommandIdTag(
|
||||||
|
$"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]");
|
||||||
eventBinderTemplate.DefineTransferParameters(transferParameters);
|
eventBinderTemplate.DefineTransferParameters(transferParameters);
|
||||||
var eventBinderCode = eventBinderTemplate.Compile();
|
var eventBinderCode = eventBinderTemplate.Compile();
|
||||||
objectBinderTemplate.InsertEventBinder(eventBinderCode);
|
objectBinderTemplate.InsertEventBinder(eventBinderCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateEventCode(MethodRepoTemplate methodRepoTemplate, IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
private void GenerateEventCode(MethodRepoTemplate methodRepoTemplate, IEventSymbol eventSymbol,
|
||||||
|
List<string> invokers, ITypeSymbol baseInterface)
|
||||||
{
|
{
|
||||||
var level = "\t\t\t";
|
var level = "\t\t\t";
|
||||||
|
|
||||||
@@ -430,7 +443,7 @@ namespace mROA.Codegen
|
|||||||
parametersInsertList.Add("(CancellationToken)special[1]");
|
parametersInsertList.Add("(CancellationToken)special[1]");
|
||||||
break;
|
break;
|
||||||
case "RequestContext":
|
case "RequestContext":
|
||||||
parametersInsertList.Add("special[0] as RequestContext");
|
parametersInsertList.Add("(RequestContext)special[0]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parametersInsertList.Add(CodegenUtilities.Caster(parameter.i,
|
parametersInsertList.Add(CodegenUtilities.Caster(parameter.i,
|
||||||
@@ -483,7 +496,8 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.DefineParametersType(parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]");
|
invokerTemplate.DefineFuncInvoking(
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]");
|
||||||
invokerTemplate.DefineIsTrusted("true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
@@ -495,7 +509,8 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.DefineParametersType("");
|
invokerTemplate.DefineParametersType("");
|
||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
invokerTemplate.DefineFuncInvoking(
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
||||||
invokerTemplate.DefineIsTrusted("true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
@@ -525,7 +540,8 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.DefineParametersType(parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}");
|
invokerTemplate.DefineFuncInvoking(
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}");
|
||||||
invokerTemplate.DefineIsTrusted("true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
@@ -537,7 +553,8 @@ namespace mROA.Codegen
|
|||||||
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.DefineParametersType($"typeof({method.Parameters.First().Type.ToUnityString()})");
|
invokerTemplate.DefineParametersType($"typeof({method.Parameters.First().Type.ToUnityString()})");
|
||||||
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {CodegenUtilities.Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
invokerTemplate.DefineFuncInvoking(
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {CodegenUtilities.Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
||||||
invokerTemplate.DefineIsTrusted("true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
@@ -576,7 +593,9 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
public static string ToFullString(IParameterSymbol parameter)
|
public static string ToFullString(IParameterSymbol parameter)
|
||||||
{
|
{
|
||||||
return parameter.Type.ToUnityString() + " " + parameter.Name;
|
var coreString = $"{parameter.Type.ToUnityString()} {parameter.Name}";
|
||||||
|
if (parameter.RefKind == RefKind.In) coreString = $"in {coreString}";
|
||||||
|
return coreString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToFullString(ITypeSymbol type)
|
public static string ToFullString(ITypeSymbol type)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using mROA.Benchmark;
|
||||||
|
|
||||||
|
namespace mROA.Test;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class BenchmarkTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Benchmark()
|
||||||
|
{
|
||||||
|
var bench = new TaskWaiting();
|
||||||
|
var x = bench.DefaultJob();
|
||||||
|
var y = bench.DefaultJobAsync();
|
||||||
|
y.Wait();
|
||||||
|
if (x == y.Result)
|
||||||
|
{
|
||||||
|
Assert.Pass();
|
||||||
|
}
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Test;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class ConcurrentTest
|
||||||
|
{
|
||||||
|
private CircularMemoryManager _cmm;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_cmm = new CircularMemoryManager(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ParallelAlloc()
|
||||||
|
{
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,4 +20,28 @@ public class Identifier
|
|||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void RequestIdTest()
|
||||||
|
{
|
||||||
|
var id = RequestId.Generate();
|
||||||
|
Assert.Pass(id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EqualsTest()
|
||||||
|
{
|
||||||
|
var id = RequestId.Generate();
|
||||||
|
var id2 = new RequestId { P0 = id.P0, P1 = id.P1 };
|
||||||
|
Assert.That(id2, Is.EqualTo(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ByteString()
|
||||||
|
{
|
||||||
|
var id = RequestId.Generate();
|
||||||
|
var binary = id.ToByteArray();
|
||||||
|
var reverced = new RequestId(binary);
|
||||||
|
Assert.That(reverced, Is.EqualTo(id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\mROA.Benchmark\mROA.Benchmark.csproj" />
|
||||||
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj" />
|
<ProjectReference Include="..\mROA.Cbor\mROA.Cbor.csproj" />
|
||||||
<ProjectReference Include="..\mROA\mROA.csproj" />
|
<ProjectReference Include="..\mROA\mROA.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Shared", "Example.S
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Frontend", "Example.Frontend\Example.Frontend.csproj", "{9BD25A13-3165-47C0-9EAA-5C59EC490E32}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Frontend", "Example.Frontend\Example.Frontend.csproj", "{9BD25A13-3165-47C0-9EAA-5C59EC490E32}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mROA.Benchmark", "mROA.Benchmark\mROA.Benchmark.csproj", "{6868F42B-E30D-4040-AD4A-BC2A2E76D03A}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mROA.Cbor", "mROA.Cbor\mROA.Cbor.csproj", "{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mROA.Cbor", "mROA.Cbor\mROA.Cbor.csproj", "{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TotalDemo", "TotalDemo", "{FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TotalDemo", "TotalDemo", "{FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}"
|
||||||
@@ -27,9 +25,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mROA.CodegenTools", "mROA.C
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Load", "Example.Load\Example.Load.csproj", "{930B236B-BDAA-4B8C-8054-5B992BAE6622}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Load", "Example.Load\Example.Load.csproj", "{930B236B-BDAA-4B8C-8054-5B992BAE6622}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Functionality.Shared", "Functionality.Shared\Functionality.Shared.csproj", "{D9D28596-E10C-4A98-A2AA-573219467506}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mROA.Benchmark", "mROA.Benchmark\mROA.Benchmark.csproj", "{E021E8B3-56C2-400E-A05E-523CF7831189}"
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{8C20901F-B416-4ABC-8AA4-9059646B081B}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -61,10 +57,6 @@ Global
|
|||||||
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Release|Any CPU.Build.0 = Release|Any CPU
|
{9BD25A13-3165-47C0-9EAA-5C59EC490E32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{6868F42B-E30D-4040-AD4A-BC2A2E76D03A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{6868F42B-E30D-4040-AD4A-BC2A2E76D03A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{6868F42B-E30D-4040-AD4A-BC2A2E76D03A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{6868F42B-E30D-4040-AD4A-BC2A2E76D03A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6211E4EA-13FD-4EB1-8E6A-C0173DD0784A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -77,10 +69,10 @@ Global
|
|||||||
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Release|Any CPU.Build.0 = Release|Any CPU
|
{930B236B-BDAA-4B8C-8054-5B992BAE6622}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{D9D28596-E10C-4A98-A2AA-573219467506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{E021E8B3-56C2-400E-A05E-523CF7831189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{D9D28596-E10C-4A98-A2AA-573219467506}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{E021E8B3-56C2-400E-A05E-523CF7831189}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D9D28596-E10C-4A98-A2AA-573219467506}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E021E8B3-56C2-400E-A05E-523CF7831189}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D9D28596-E10C-4A98-A2AA-573219467506}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E021E8B3-56C2-400E-A05E-523CF7831189}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -91,7 +83,5 @@ Global
|
|||||||
{9BD25A13-3165-47C0-9EAA-5C59EC490E32} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
{9BD25A13-3165-47C0-9EAA-5C59EC490E32} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
||||||
{E7703F5B-F2A6-4A88-AA57-EBB1E38D533E} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
{E7703F5B-F2A6-4A88-AA57-EBB1E38D533E} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
||||||
{930B236B-BDAA-4B8C-8054-5B992BAE6622} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
{930B236B-BDAA-4B8C-8054-5B992BAE6622} = {FC4FA752-10A7-4D78-A7C2-9BCD8A81FB5E}
|
||||||
{8C20901F-B416-4ABC-8AA4-9059646B081B} = {EAE92F5A-664C-41AB-8811-5885524B5347}
|
|
||||||
{D9D28596-E10C-4A98-A2AA-573219467506} = {8C20901F-B416-4ABC-8AA4-9059646B081B}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Abstract
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
public interface ICancellationRepository
|
public interface ICancellationRepository
|
||||||
{
|
{
|
||||||
void RegisterCancellation(Guid id, CancellationTokenSource cts);
|
void RegisterCancellation(RequestId id, CancellationTokenSource cts);
|
||||||
CancellationTokenSource? GetCancellation(Guid id);
|
CancellationTokenSource? GetCancellation(RequestId id);
|
||||||
void FreeCancelation(Guid id);
|
void FreeCancellation(RequestId id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,13 +9,13 @@ namespace mROA.Abstract
|
|||||||
{
|
{
|
||||||
int ConnectionId { get; set; }
|
int ConnectionId { get; set; }
|
||||||
IEndPointContext Context { get; set; }
|
IEndPointContext Context { get; set; }
|
||||||
Channel<NetworkMessageHeader> ReceiveChanel { get; }
|
Channel<NetworkMessage> ReceiveChanel { get; }
|
||||||
ChannelReader<NetworkMessageHeader> TrustedPostChanel { get; }
|
ChannelReader<NetworkMessage> TrustedPostChanel { get; }
|
||||||
ChannelReader<NetworkMessageHeader> UntrustedPostChanel { get; }
|
ChannelReader<NetworkMessage> UntrustedPostChanel { get; }
|
||||||
Func<bool> IsConnected { get; set; }
|
Func<bool> IsConnected { get; set; }
|
||||||
ValueTask<NetworkMessageHeader> GetNextMessageReceiving(bool infinite = true);
|
ValueTask<NetworkMessage> GetNextMessageReceiving();
|
||||||
Task PostMessageAsync(NetworkMessageHeader messageHeader);
|
Task PostMessageAsync(NetworkMessage message);
|
||||||
Task PostMessageUntrustedAsync(NetworkMessageHeader messageHeader);
|
Task PostMessageUntrustedAsync(NetworkMessage message);
|
||||||
event Action<int> OnDisconnected;
|
event Action<int> OnDisconnected;
|
||||||
Task Restart(bool sendRecovery);
|
Task Restart(bool sendRecovery);
|
||||||
void PassReconnection();
|
void PassReconnection();
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ namespace mROA.Abstract
|
|||||||
{
|
{
|
||||||
public interface ICommandExecution : INetworkMessage
|
public interface ICommandExecution : INetworkMessage
|
||||||
{
|
{
|
||||||
Guid Id { get; set; }
|
RequestId Id { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,8 @@
|
|||||||
namespace mROA.Abstract
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
public delegate void ConnectionHandler(IRepresentationModule representationModule);
|
|
||||||
|
|
||||||
public delegate void DisconnectionHandler(IRepresentationModule representationModule);
|
|
||||||
|
|
||||||
public interface IConnectionHub
|
public interface IConnectionHub
|
||||||
{
|
{
|
||||||
void RegisterInteraction(IChannelInteractionModule interaction);
|
void RegisterInteraction(IChannelInteractionModule interaction);
|
||||||
IChannelInteractionModule GetInteraction(int id);
|
IChannelInteractionModule GetInteraction(int id);
|
||||||
event ConnectionHandler? OnConnected;
|
|
||||||
event DisconnectionHandler? OnDisconnected;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,7 @@ namespace mROA.Abstract
|
|||||||
T Deserialize<T>(byte[] rawData, IEndPointContext? context);
|
T Deserialize<T>(byte[] rawData, IEndPointContext? context);
|
||||||
object? Deserialize(byte[] rawData, Type type, IEndPointContext? context);
|
object? Deserialize(byte[] rawData, Type type, IEndPointContext? context);
|
||||||
T Deserialize<T>(ReadOnlyMemory<byte> rawMemory, IEndPointContext? context);
|
T Deserialize<T>(ReadOnlyMemory<byte> rawMemory, IEndPointContext? context);
|
||||||
object? Deserialize(ReadOnlyMemory<byte> rawMemory, Type type, IEndPointContext? context);
|
|
||||||
T Cast<T>(object nonCasted, IEndPointContext? context);
|
|
||||||
object? Cast(object? nonCasted, Type type, IEndPointContext? context);
|
object? Cast(object? nonCasted, Type type, IEndPointContext? context);
|
||||||
|
IContextualSerializationToolKit Clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
|
namespace mROA.Abstract
|
||||||
|
{
|
||||||
|
public interface IDistributionModule
|
||||||
|
{
|
||||||
|
Action<NetworkMessage> GetDistributionAction(int clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace mROA.Abstract
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
public interface IEventBinder<T> : IEventBinder
|
public interface IEventBinder<in T> : IEventBinder
|
||||||
{
|
{
|
||||||
public void BindEvents(T source, IEndPointContext context,
|
public void BindEvents(T source, IEndPointContext context,
|
||||||
IRepresentationModuleProducer representationModuleProducer, int index);
|
IRepresentationModuleProducer representationModuleProducer, int index);
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
using mROA.Implementation;
|
using mROA.Implementation;
|
||||||
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
namespace mROA.Abstract
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
public interface IExecuteModule
|
public interface IExecuteModule
|
||||||
{
|
{
|
||||||
ICommandExecution Execute(ICallRequest command, IInstanceRepository instanceRepository,
|
ICommandExecution? Execute(CallRequest command, IInstanceRepository instanceRepository,
|
||||||
IRepresentationModule representationModule, IEndPointContext context);
|
IRepresentationModule representationModule, IEndPointContext context);
|
||||||
|
|
||||||
|
ICommandExecution Cancel(CancelRequest command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace mROA.Abstract
|
|
||||||
{
|
|
||||||
public interface IOwnershipRepository
|
|
||||||
{
|
|
||||||
int GetOwnershipId();
|
|
||||||
int GetHostOwnershipId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,5 @@ namespace mROA.Abstract
|
|||||||
{
|
{
|
||||||
public interface IRealStoreInstanceRepository : IInstanceRepository
|
public interface IRealStoreInstanceRepository : IInstanceRepository
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using mROA.Implementation;
|
|
||||||
|
|
||||||
namespace mROA.Abstract
|
|
||||||
{
|
|
||||||
public interface IRemoteObjectFactory
|
|
||||||
{
|
|
||||||
T Produce<T>(ComplexObjectIdentifier id, IEndPointContext context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,21 +11,22 @@ namespace mROA.Abstract
|
|||||||
int Id { get; }
|
int Id { get; }
|
||||||
IEndPointContext Context { get; }
|
IEndPointContext Context { get; }
|
||||||
|
|
||||||
Task<(object? Deserialized, EMessageType MessageType)> GetSingle(Predicate<NetworkMessageHeader> rule,
|
Task<(object? Deserialized, EMessageType MessageType)> GetSingle(Predicate<NetworkMessage> rule,
|
||||||
IEndPointContext? context, CancellationToken token = default,
|
IEndPointContext? context, CancellationToken token = default,
|
||||||
params Func<NetworkMessageHeader, Type?>[] converter);
|
params Func<NetworkMessage, Type?>[] converter);
|
||||||
|
|
||||||
IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(Predicate<NetworkMessageHeader> rule,
|
IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(Predicate<NetworkMessage> rule,
|
||||||
IEndPointContext? context, CancellationToken token = default,
|
IEndPointContext? context, CancellationToken token = default,
|
||||||
params Func<NetworkMessageHeader, Type?>[] converter);
|
params Func<NetworkMessage, Type?>[] converter);
|
||||||
|
|
||||||
Task PostCallMessageAsync<T>(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
Task PostCallMessageAsync<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
||||||
where T : notnull;
|
where T : notnull;
|
||||||
|
|
||||||
void PostCallMessage<T>(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
void PostCallMessage<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
||||||
where T : notnull;
|
where T : notnull;
|
||||||
|
|
||||||
Task PostCallMessageUntrustedAsync<T>(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
Task PostCallMessageUntrustedAsync<T>(RequestId id, EMessageType eMessageType, T payload,
|
||||||
|
IEndPointContext? context)
|
||||||
where T : notnull;
|
where T : notnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Implementation;
|
||||||
|
|
||||||
namespace mROA.Abstract
|
namespace mROA.Abstract
|
||||||
{
|
{
|
||||||
public interface IRequestExtractor
|
public interface IRequestExtractor
|
||||||
{
|
{
|
||||||
Task StartExtraction();
|
Task StartExtraction();
|
||||||
|
void PushMessage(object parsed, EMessageType originalType);
|
||||||
|
Predicate<NetworkMessage> Rule { get; }
|
||||||
|
Func<NetworkMessage, Type?>[] Converters { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,32 +10,25 @@ 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;
|
||||||
|
public BasicExecutionModule(ICancellationRepository cancellationRepo, IMethodRepository methodRepo,
|
||||||
public BasicExecutionModule(ICancellationRepository cancellationRepo, IMethodRepository methodRepo, IContextualSerializationToolKit serialization)
|
IContextualSerializationToolKit serialization)
|
||||||
{
|
{
|
||||||
_cancellationRepo = cancellationRepo;
|
_cancellationRepo = cancellationRepo;
|
||||||
_methodRepo = methodRepo;
|
_methodRepo = methodRepo;
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
}
|
}
|
||||||
|
public ICommandExecution? Execute(CallRequest command, IInstanceRepository instanceRepository,
|
||||||
public ICommandExecution Execute(ICallRequest command, IInstanceRepository instanceRepository,
|
|
||||||
IRepresentationModule representationModule, IEndPointContext endPointContext)
|
IRepresentationModule representationModule, IEndPointContext endPointContext)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ThrowIfNotInjected(instanceRepository);
|
|
||||||
if (command is CancelRequest)
|
|
||||||
{
|
|
||||||
return CancelExecution(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
var invoker = _methodRepo.GetMethod(command.CommandId);
|
var invoker = _methodRepo.GetMethod(command.CommandId);
|
||||||
if (invoker == null)
|
if (invoker == null)
|
||||||
throw new Exception($"Command {command.CommandId} not found");
|
throw new Exception($"Command {command.CommandId} not found");
|
||||||
|
|
||||||
var context = GetContext(command, instanceRepository, invoker, endPointContext);
|
var instance = GetInstance(command, instanceRepository, invoker, endPointContext);
|
||||||
|
|
||||||
if (context == null)
|
if (instance is null)
|
||||||
throw new NullReferenceException("Instance can't be null");
|
throw new NullReferenceException("Instance can't be null");
|
||||||
|
|
||||||
|
|
||||||
@@ -47,24 +40,10 @@ namespace mROA.Implementation.Backend
|
|||||||
|
|
||||||
var execContext = new RequestContext(command.Id, representationModule.Id);
|
var execContext = new RequestContext(command.Id, representationModule.Id);
|
||||||
|
|
||||||
switch (invoker)
|
var executionResult = ExecuteRequest(command, instanceRepository, representationModule, endPointContext,
|
||||||
{
|
invoker,
|
||||||
case AsyncMethodInvoker { IsVoid: false } asyncNonVoidMethodInvoker:
|
instance, castedParams, execContext);
|
||||||
return TypedExecuteAsync(asyncNonVoidMethodInvoker, context, castedParams, command,
|
return executionResult;
|
||||||
_cancellationRepo,
|
|
||||||
representationModule, execContext, endPointContext);
|
|
||||||
case AsyncMethodInvoker asyncMethodInvoker:
|
|
||||||
return ExecuteAsync(asyncMethodInvoker, context, castedParams, command, _cancellationRepo,
|
|
||||||
representationModule, execContext, endPointContext);
|
|
||||||
default:
|
|
||||||
var result = Execute((invoker as MethodInvoker)!, context, castedParams!, command, execContext);
|
|
||||||
if (command.CommandId == -1)
|
|
||||||
{
|
|
||||||
instanceRepository.ClearObject(command.ObjectId, endPointContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -75,17 +54,39 @@ namespace mROA.Implementation.Backend
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private ICommandExecution? ExecuteRequest(CallRequest command, IInstanceRepository instanceRepository,
|
||||||
|
IRepresentationModule representationModule, IEndPointContext endPointContext, IMethodInvoker invoker,
|
||||||
|
object context, object?[]? castedParams, RequestContext execContext)
|
||||||
|
{
|
||||||
|
switch (invoker)
|
||||||
|
{
|
||||||
|
case AsyncMethodInvoker { IsVoid: false } asyncNonVoidMethodInvoker:
|
||||||
|
return TypedExecuteAsync(asyncNonVoidMethodInvoker, context, castedParams, command,
|
||||||
|
_cancellationRepo,
|
||||||
|
representationModule, execContext, endPointContext);
|
||||||
|
case AsyncMethodInvoker asyncMethodInvoker:
|
||||||
|
return ExecuteAsync(asyncMethodInvoker, context, castedParams, command, _cancellationRepo,
|
||||||
|
representationModule, execContext, endPointContext);
|
||||||
|
default:
|
||||||
|
var result = Execute((invoker as MethodInvoker)!, context, castedParams!, command, execContext);
|
||||||
|
if (command.CommandId == -1)
|
||||||
|
{
|
||||||
|
instanceRepository.ClearObject(command.ObjectId, endPointContext);
|
||||||
|
}
|
||||||
|
|
||||||
private static object GetContext(ICallRequest command, IInstanceRepository instanceRepository,
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static object GetInstance(CallRequest command, IInstanceRepository instanceRepository,
|
||||||
IMethodInvoker invoker, IEndPointContext endPointContext)
|
IMethodInvoker invoker, IEndPointContext endPointContext)
|
||||||
{
|
{
|
||||||
var context = command.ObjectId.ContextId != -1
|
var context = command.ObjectId.ContextId != -1
|
||||||
? instanceRepository.GetObject<object>(command.ObjectId, endPointContext)
|
? instanceRepository.GetObject<object>(command.ObjectId, endPointContext)
|
||||||
: instanceRepository.GetSingletonObject(invoker.SuitableType, endPointContext);
|
: instanceRepository.GetSingletonObject(invoker.SuitableType, endPointContext);
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
private object?[] CastedParams(CallRequest command, IMethodInvoker invoker, IEndPointContext context)
|
||||||
private object?[] CastedParams(ICallRequest command, IMethodInvoker invoker, IEndPointContext context)
|
|
||||||
{
|
{
|
||||||
object?[] castedParams = new object[invoker.ParameterTypes.Length];
|
object?[] castedParams = new object[invoker.ParameterTypes.Length];
|
||||||
for (var i = 0; i < castedParams.Length; i++)
|
for (var i = 0; i < castedParams.Length; i++)
|
||||||
@@ -95,158 +96,115 @@ namespace mROA.Implementation.Backend
|
|||||||
|
|
||||||
return castedParams;
|
return castedParams;
|
||||||
}
|
}
|
||||||
|
public ICommandExecution Cancel(CancelRequest command)
|
||||||
private void ThrowIfNotInjected(IInstanceRepository instanceRepository)
|
|
||||||
{
|
|
||||||
if (_cancellationRepo is null)
|
|
||||||
throw new NullReferenceException("Method repository was not defined");
|
|
||||||
|
|
||||||
if (_methodRepo is null)
|
|
||||||
throw new NullReferenceException("Method repository was not defined");
|
|
||||||
|
|
||||||
if (instanceRepository is null)
|
|
||||||
throw new NullReferenceException("Context repository was not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
private FinalCommandExecution CancelExecution(ICallRequest command)
|
|
||||||
{
|
{
|
||||||
var cts = _cancellationRepo.GetCancellation(command.Id);
|
var cts = _cancellationRepo.GetCancellation(command.Id);
|
||||||
if (cts == null)
|
if (cts == null)
|
||||||
throw new NullReferenceException("Can't find cancellation for this request");
|
throw new NullReferenceException("Can't find cancellation for this request");
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
_cancellationRepo.FreeCancelation(command.Id);
|
_cancellationRepo.FreeCancellation(command.Id);
|
||||||
|
|
||||||
return new FinalCommandExecution
|
return new FinalCommandExecution
|
||||||
{
|
{
|
||||||
Id = command.Id
|
Id = command.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
private static ICommandExecution? Execute(MethodInvoker invoker, object instance, object?[] parameter,
|
||||||
private static ICommandExecution Execute(MethodInvoker invoker, object instance, object?[] parameter,
|
CallRequest command, RequestContext executionContext)
|
||||||
ICallRequest command, RequestContext executionContext)
|
|
||||||
{
|
{
|
||||||
try
|
var finalResult = invoker.Invoke(instance, parameter, new object[] { executionContext });
|
||||||
|
|
||||||
|
if (!invoker.IsTrusted)
|
||||||
{
|
{
|
||||||
var finalResult = invoker.Invoke(instance, parameter, new object[] { executionContext });
|
return null;
|
||||||
|
|
||||||
if (!invoker.IsTrusted)
|
|
||||||
{
|
|
||||||
return new AsyncCommandExecution();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invoker.IsVoid)
|
|
||||||
{
|
|
||||||
return new FinalCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FinalCommandExecution<object>
|
|
||||||
{
|
|
||||||
Result = finalResult,
|
|
||||||
Id = command.Id
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
|
if (invoker.IsVoid)
|
||||||
{
|
{
|
||||||
if (invoker.IsTrusted)
|
return new FinalCommandExecution
|
||||||
return new ExceptionCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id,
|
|
||||||
Exception = e.ToString()
|
|
||||||
};
|
|
||||||
return new AsyncCommandExecution
|
|
||||||
{
|
{
|
||||||
Id = command.Id
|
Id = command.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new FinalCommandExecution<object>
|
||||||
|
{
|
||||||
|
Result = finalResult,
|
||||||
|
Id = command.Id
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
private ICommandExecution? ExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
|
||||||
private ICommandExecution ExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
|
CallRequest command, ICancellationRepository cancellationRepository,
|
||||||
ICallRequest command, ICancellationRepository cancellationRepository,
|
|
||||||
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
CancellationToken? token = null;
|
||||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
if (invoker.RequireCancellation)
|
||||||
var token = tokenSource.Token;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
invoker.Invoke(instance, parameters, new object[] { executionContext, token }, _ =>
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
|
|
||||||
|
token = tokenSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
invoker.Invoke(instance, parameters, new object[] { executionContext, token }, _ =>
|
||||||
|
{
|
||||||
|
if (invoker.RequireCancellation)
|
||||||
{
|
{
|
||||||
if (token.IsCancellationRequested)
|
_cancellationRepo.FreeCancellation(command.Id);
|
||||||
|
|
||||||
|
if (token.Value.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var payload = new FinalCommandExecution
|
var payload = new FinalCommandExecution
|
||||||
|
{
|
||||||
|
Id = command.Id
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (invoker.IsTrusted)
|
||||||
|
representationModule.PostCallMessageAsync(command.Id, EMessageType.FinishedCommandExecution,
|
||||||
|
payload, context);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private ICommandExecution? TypedExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
|
||||||
|
CallRequest command, ICancellationRepository cancellationRepository,
|
||||||
|
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
||||||
|
{
|
||||||
|
CancellationToken? token = null;
|
||||||
|
if (invoker.RequireCancellation)
|
||||||
|
{
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
|
|
||||||
|
token = tokenSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
invoker.Invoke(instance, parameters, new object[] { executionContext, token },
|
||||||
|
finalResult =>
|
||||||
|
{
|
||||||
|
if (invoker.RequireCancellation)
|
||||||
{
|
{
|
||||||
Id = command.Id
|
_cancellationRepo.FreeCancellation(command.Id);
|
||||||
|
|
||||||
|
if (token.Value.IsCancellationRequested)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload = new FinalCommandExecution<object>
|
||||||
|
{
|
||||||
|
Id = command.Id,
|
||||||
|
Result = finalResult
|
||||||
};
|
};
|
||||||
_cancellationRepo?.FreeCancelation(command.Id);
|
|
||||||
|
|
||||||
|
representationModule.PostCallMessageAsync(command.Id, EMessageType.FinishedCommandExecution,
|
||||||
if (invoker.IsTrusted)
|
payload, context);
|
||||||
representationModule.PostCallMessage(command.Id, EMessageType.FinishedCommandExecution,
|
|
||||||
payload, context);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return new AsyncCommandExecution
|
return null;
|
||||||
{
|
|
||||||
Id = command.Id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (invoker.IsTrusted)
|
|
||||||
return new ExceptionCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id,
|
|
||||||
Exception = e.ToString()
|
|
||||||
};
|
|
||||||
return new AsyncCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ICommandExecution TypedExecuteAsync(AsyncMethodInvoker invoker, object instance, object?[]? parameters,
|
|
||||||
ICallRequest command, ICancellationRepository cancellationRepository,
|
|
||||||
IRepresentationModule representationModule, RequestContext executionContext, IEndPointContext context)
|
|
||||||
{
|
|
||||||
var tokenSource = new CancellationTokenSource();
|
|
||||||
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
|
||||||
|
|
||||||
var token = tokenSource.Token;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
invoker.Invoke(instance, parameters, new object[] { executionContext, token },
|
|
||||||
finalResult =>
|
|
||||||
{
|
|
||||||
var payload = new FinalCommandExecution<object>
|
|
||||||
{
|
|
||||||
Id = command.Id,
|
|
||||||
Result = finalResult
|
|
||||||
};
|
|
||||||
_cancellationRepo.FreeCancelation(command.Id);
|
|
||||||
|
|
||||||
representationModule.PostCallMessage(command.Id, EMessageType.FinishedCommandExecution,
|
|
||||||
payload, context);
|
|
||||||
});
|
|
||||||
|
|
||||||
return new AsyncCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return new ExceptionCommandExecution
|
|
||||||
{
|
|
||||||
Id = command.Id,
|
|
||||||
Exception = e.ToString()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
@@ -26,8 +18,5 @@ namespace mROA.Implementation.Backend
|
|||||||
return _connections!.GetValueOrDefault(id, null) ?? _connections!.GetValueOrDefault(-id, null) ??
|
return _connections!.GetValueOrDefault(id, null) ?? _connections!.GetValueOrDefault(-id, null) ??
|
||||||
throw new Exception("No connection found");
|
throw new Exception("No connection found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public event ConnectionHandler? OnConnected;
|
|
||||||
public event DisconnectionHandler? OnDisconnected;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,28 +7,34 @@ 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 readonly 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 representationModule)
|
||||||
{
|
{
|
||||||
var extractor = CreateExtractor(interaction);
|
var extractor = CreateExtractor(representationModule);
|
||||||
extractor.StartExtraction().ContinueWith(_ => OnDisconnected(interaction));
|
if (_mode.DistributionType == EDistributionType.Channeled)
|
||||||
|
{
|
||||||
|
extractor.StartExtraction().ContinueWith(_ => OnDisconnected(representationModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
_producedExtractors[representationModule.Id] = extractor;
|
||||||
|
return extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDisconnected(IRepresentationModule representationModule)
|
private void OnDisconnected(IRepresentationModule representationModule)
|
||||||
@@ -37,7 +45,7 @@ namespace mROA.Implementation.Backend
|
|||||||
|
|
||||||
private IRequestExtractor CreateExtractor(IRepresentationModule interaction)
|
private IRequestExtractor CreateExtractor(IRepresentationModule interaction)
|
||||||
{
|
{
|
||||||
var extractor = new RequestExtractor(_executeModule, _methodRepository, interaction, _serializationToolkit, interaction.Context);
|
var extractor = new RequestExtractor(_executeModule, interaction, interaction.Context);
|
||||||
var context = interaction.Context;
|
var context = interaction.Context;
|
||||||
if (_contextRepository is IContextRepositoryHub contextHub)
|
if (_contextRepository is IContextRepositoryHub contextHub)
|
||||||
context.RealRepository = contextHub.GetRepository(interaction.Id);
|
context.RealRepository = contextHub.GetRepository(interaction.Id);
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -22,8 +22,6 @@ namespace mROA.Implementation.Backend
|
|||||||
_storage = new ExtensibleStorage<object>();
|
_storage = new ExtensibleStorage<object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int HostId { get; set; }
|
|
||||||
|
|
||||||
public int ResisterObject<T>(object o, IEndPointContext context)
|
public int ResisterObject<T>(object o, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var last = _storage.Place(o);
|
var last = _storage.Place(o);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
namespace mROA.Implementation.Backend
|
namespace mROA.Implementation.Backend
|
||||||
@@ -14,8 +15,6 @@ namespace mROA.Implementation.Backend
|
|||||||
_produceRepository = produceRepository;
|
_produceRepository = produceRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int HostId { get; set; }
|
|
||||||
|
|
||||||
public int ResisterObject<T>(object o, IEndPointContext context)
|
public int ResisterObject<T>(object o, IEndPointContext context)
|
||||||
{
|
{
|
||||||
var repository = GetRepositoryByClientId(context.OwnerId);
|
var repository = GetRepositoryByClientId(context.OwnerId);
|
||||||
|
|||||||
@@ -11,21 +11,25 @@ namespace mROA.Implementation.Backend
|
|||||||
{
|
{
|
||||||
public class NetworkGatewayModule : IGatewayModule
|
public class NetworkGatewayModule : IGatewayModule
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private readonly TcpListener _tcpListener;
|
private readonly TcpListener _tcpListener;
|
||||||
private readonly IConnectionHub _hub;
|
private readonly IConnectionHub _hub;
|
||||||
|
private readonly HubRequestExtractor _hre;
|
||||||
|
private readonly IDistributionModule _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;
|
||||||
public NetworkGatewayModule(IOptions<GatewayOptions> options, IServiceProvider service, IIdentityGenerator identityGenerator, IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub)
|
|
||||||
|
public NetworkGatewayModule(IOptions<GatewayOptions> options, IIdentityGenerator identityGenerator,
|
||||||
|
IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub, HubRequestExtractor hre, IDistributionModule distribution)
|
||||||
{
|
{
|
||||||
_tcpListener = new(options.Value.Endpoint);
|
_tcpListener = new(options.Value.Endpoint);
|
||||||
_serviceProvider = service;
|
|
||||||
_identityGenerator = identityGenerator;
|
_identityGenerator = identityGenerator;
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
_callIndexProvider = callIndexProvider;
|
_callIndexProvider = callIndexProvider;
|
||||||
_hub = hub;
|
_hub = hub;
|
||||||
|
_hre = hre;
|
||||||
|
_distribution = distribution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
@@ -47,67 +51,119 @@ namespace mROA.Implementation.Backend
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var client = await _tcpListener.AcceptTcpClientAsync();
|
var client = await _tcpListener.AcceptTcpClientAsync();
|
||||||
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
|
_ = HandleConnection(client);
|
||||||
var interaction = new ChannelInteractionModule(_serialization, _identityGenerator);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var context = new EndPointContext(null, null);
|
private async Task HandleConnection(TcpClient client)
|
||||||
context.CallIndexProvider = _callIndexProvider;
|
{
|
||||||
var streamExtractor =
|
client.NoDelay = true;
|
||||||
new ChannelInteractionModule.StreamExtractor(client.GetStream(), _serialization, context);
|
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
|
||||||
interaction.IsConnected = () => streamExtractor.IsConnected;
|
var interaction = new ChannelInteractionModule(_serialization, _identityGenerator);
|
||||||
streamExtractor.MessageReceived = async message =>
|
|
||||||
{
|
|
||||||
await interaction.ReceiveChanel.Writer.WriteAsync(message);
|
|
||||||
};
|
|
||||||
_ = Task.Run(() => streamExtractor.SingleReceive());
|
|
||||||
var connectionRequest = await interaction.ReceiveChanel.Reader.ReadAsync();
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
switch (connectionRequest.MessageType)
|
var context = new EndPointContext(null, null)
|
||||||
|
{
|
||||||
|
CallIndexProvider = _callIndexProvider
|
||||||
|
};
|
||||||
|
var streamExtractor =
|
||||||
|
new ChannelInteractionModule.StreamExtractor(client.GetStream());
|
||||||
|
interaction.IsConnected = () => streamExtractor.IsConnected;
|
||||||
|
streamExtractor.MessageReceived = async message =>
|
||||||
|
{
|
||||||
|
await interaction.ReceiveChanel.Writer.WriteAsync(message).ConfigureAwait(false);
|
||||||
|
};
|
||||||
|
_ = Task.Run(() => streamExtractor.SingleReceive());
|
||||||
|
var connectionRequest = await interaction.ReceiveChanel.Reader.ReadAsync();
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
switch (connectionRequest.MessageType)
|
||||||
|
{
|
||||||
|
case EMessageType.ClientConnect:
|
||||||
|
|
||||||
|
HandleNewClient(context, interaction, streamExtractor, cts, connectionRequest);
|
||||||
|
break;
|
||||||
|
case EMessageType.ClientRecovery:
|
||||||
{
|
{
|
||||||
case EMessageType.ClientConnect:
|
RecoverDisconnectedClient(connectionRequest, streamExtractor, cts);
|
||||||
context.HostId = 0;
|
break;
|
||||||
context.OwnerId = -interaction.ConnectionId;
|
}
|
||||||
interaction.Context = context;
|
default:
|
||||||
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token));
|
client.Close();
|
||||||
_ = streamExtractor.SendFromChannel(interaction.TrustedPostChanel, cts.Token);
|
break;
|
||||||
interaction.PostMessageAsync(new NetworkMessageHeader(_serialization!,
|
}
|
||||||
new IdAssignment { Id = interaction.ConnectionId }, null));
|
}
|
||||||
_extractorsCTS[interaction.ConnectionId] = cts;
|
|
||||||
_hub!.RegisterInteraction(interaction);
|
private void HandleNewClient(EndPointContext context, ChannelInteractionModule interaction,
|
||||||
Console.WriteLine("Client registered");
|
ChannelInteractionModule.StreamExtractor streamExtractor, CancellationTokenSource cts,
|
||||||
break;
|
NetworkMessage connection)
|
||||||
case EMessageType.ClientRecovery:
|
{
|
||||||
|
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 NetworkMessage(_serialization,
|
||||||
|
new IdAssignment { Id = interaction.ConnectionId }, null));
|
||||||
|
_extractorsTokenSources[interaction.ConnectionId] = cts;
|
||||||
|
|
||||||
|
_hub.RegisterInteraction(interaction);
|
||||||
|
_hre.HubOnOnConnected(new RepresentationModule(interaction, _serialization.Clone()));
|
||||||
|
|
||||||
|
streamExtractor.MessageReceived = _distribution.GetDistributionAction(interaction.ConnectionId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindRequestFirstDistribution(IEndPointContext context, IChannelInteractionModule interaction,
|
||||||
|
ChannelInteractionModule.StreamExtractor streamExtractor, IRequestExtractor requestExtractor)
|
||||||
|
{
|
||||||
|
var converters = requestExtractor.Converters;
|
||||||
|
streamExtractor.MessageReceived = message =>
|
||||||
|
{
|
||||||
|
if (requestExtractor.Rule(message))
|
||||||
|
{
|
||||||
|
for (var i = 0; i < converters.Length; i++)
|
||||||
{
|
{
|
||||||
var recoveryRequest = _serialization!.Deserialize<ClientRecovery>(connectionRequest.Data, null);
|
var func = converters[i];
|
||||||
var recoveryInteraction = _hub.GetInteraction(recoveryRequest.Id);
|
if (func(message) is not { } t) continue;
|
||||||
|
|
||||||
_extractorsCTS[-recoveryRequest.Id].Cancel();
|
var deserialized = _serialization.Deserialize(message.Data, t, context)!;
|
||||||
|
Task.Run(() => requestExtractor.PushMessage(deserialized, message.MessageType));
|
||||||
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:
|
|
||||||
client.Close();
|
return;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
interaction.ReceiveChanel.Writer.WriteAsync(message).ConfigureAwait(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecoverDisconnectedClient(NetworkMessage 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);
|
||||||
|
|
||||||
|
streamExtractor.MessageReceived = _distribution.GetDistributionAction(recoveryInteraction.ConnectionId);
|
||||||
|
|
||||||
|
Task.Run(async () => await streamExtractor.LoopedReceive(cts.Token).ConfigureAwait(false));
|
||||||
|
|
||||||
|
recoveryInteraction.Restart(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GatewayOptions
|
public class GatewayOptions
|
||||||
{
|
{
|
||||||
public IPEndPoint Endpoint { get; set; }
|
public IPEndPoint Endpoint { get; set; }
|
||||||
public Type InteractionModuleType { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,16 +12,19 @@ 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, Action<NetworkMessage>> _distributionActions = new();
|
||||||
private CancellationTokenSource _tokenSource = new();
|
private readonly CancellationTokenSource _tokenSource = new();
|
||||||
private IContextualSerializationToolKit _serializationToolkit;
|
private readonly IContextualSerializationToolKit _serializationToolkit;
|
||||||
|
private readonly IDistributionModule _distribution;
|
||||||
|
|
||||||
public UdpGateway(IOptions<GatewayOptions> options, IConnectionHub hub, IContextualSerializationToolKit serializationToolkit)
|
public UdpGateway(IOptions<GatewayOptions> options, IConnectionHub hub,
|
||||||
|
IContextualSerializationToolKit serializationToolkit, IDistributionModule distribution)
|
||||||
{
|
{
|
||||||
_hub = hub;
|
_hub = hub;
|
||||||
_serializationToolkit = serializationToolkit;
|
_serializationToolkit = serializationToolkit;
|
||||||
|
_distribution = distribution;
|
||||||
_client = new UdpClient(options.Value.Endpoint);
|
_client = new UdpClient(options.Value.Endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +43,7 @@ namespace mROA.Implementation.Backend
|
|||||||
while (token.IsCancellationRequested == false)
|
while (token.IsCancellationRequested == false)
|
||||||
{
|
{
|
||||||
var incoming = await _client.ReceiveAsync();
|
var incoming = await _client.ReceiveAsync();
|
||||||
var parsed = _serializationToolkit.Deserialize<NetworkMessageHeader>(incoming.Buffer, null);
|
var parsed = _serializationToolkit.Deserialize<NetworkMessage>(incoming.Buffer, null);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int channelId;
|
int channelId;
|
||||||
@@ -48,13 +51,12 @@ namespace mROA.Implementation.Backend
|
|||||||
{
|
{
|
||||||
case UntrustedConnect:
|
case UntrustedConnect:
|
||||||
channelId = BitConverter.ToInt32(parsed.Data);
|
channelId = BitConverter.ToInt32(parsed.Data);
|
||||||
_reservedPorts[incoming.RemoteEndPoint] = channelId;
|
_distributionActions[incoming.RemoteEndPoint] = _distribution.GetDistributionAction(channelId);
|
||||||
_ = UntrustedSend(_hub.GetInteraction(channelId), incoming.RemoteEndPoint);
|
_ = UntrustedSend(_hub.GetInteraction(channelId), incoming.RemoteEndPoint);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
channelId = _reservedPorts[incoming.RemoteEndPoint];
|
_distributionActions[incoming.RemoteEndPoint].Invoke(parsed);
|
||||||
var interaction = _hub.GetInteraction(channelId);
|
|
||||||
await interaction.ReceiveChanel.Writer.WriteAsync(parsed, token);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +74,7 @@ namespace mROA.Implementation.Backend
|
|||||||
{
|
{
|
||||||
await foreach (var post in interaction.UntrustedPostChanel.ReadAllAsync())
|
await foreach (var post in interaction.UntrustedPostChanel.ReadAllAsync())
|
||||||
{
|
{
|
||||||
if (post.MessageType is not (CallRequest or EMessageType.CancelRequest
|
if (post.MessageType is not (EMessageType.CallRequest or EMessageType.CancelRequest
|
||||||
or EventRequest))
|
or EventRequest))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
|
||||||
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
|
|
||||||
|
|
||||||
namespace mROA.Implementation
|
namespace mROA.Implementation
|
||||||
{
|
{
|
||||||
public interface ICallRequest
|
public struct CallRequest
|
||||||
{
|
{
|
||||||
Guid Id { get; }
|
public RequestId Id { get; set; }
|
||||||
int CommandId { get; }
|
|
||||||
ComplexObjectIdentifier ObjectId { get; }
|
|
||||||
object?[]? Parameters { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct DefaultCallRequest : ICallRequest
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public int CommandId { get; set; }
|
public int CommandId { get; set; }
|
||||||
public ComplexObjectIdentifier ObjectId { get; set; }
|
public ComplexObjectIdentifier ObjectId { get; set; }
|
||||||
|
|
||||||
@@ -27,16 +16,8 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CancelRequest : ICallRequest
|
public struct CancelRequest
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public RequestId Id { get; set; }
|
||||||
public int CommandId { get; set; } = -2;
|
|
||||||
public ComplexObjectIdentifier ObjectId { get; set; } = ComplexObjectIdentifier.Null;
|
|
||||||
public object?[]? Parameters { get; set; } = null;
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"Cancel request {{ Id : {Id}, CommandId : {CommandId}, ObjectId : {ObjectId} }}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,19 +8,19 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
public class CancellationRepository : ICancellationRepository
|
public class CancellationRepository : ICancellationRepository
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<Guid, CancellationTokenSource> _cancellations = new();
|
private readonly ConcurrentDictionary<RequestId, CancellationTokenSource> _cancellations = new();
|
||||||
|
|
||||||
public void RegisterCancellation(Guid id, CancellationTokenSource cts)
|
public void RegisterCancellation(RequestId id, CancellationTokenSource cts)
|
||||||
{
|
{
|
||||||
_cancellations.TryAdd(id, cts);
|
_cancellations.TryAdd(id, cts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CancellationTokenSource? GetCancellation(Guid id)
|
public CancellationTokenSource? GetCancellation(RequestId id)
|
||||||
{
|
{
|
||||||
return _cancellations.GetValueOrDefault(id);
|
return _cancellations.GetValueOrDefault(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FreeCancelation(Guid id)
|
public void FreeCancellation(RequestId id)
|
||||||
{
|
{
|
||||||
_cancellations.Remove(id, out _);
|
_cancellations.Remove(id, out _);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -10,11 +10,11 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
public class ChannelInteractionModule : IChannelInteractionModule
|
public class ChannelInteractionModule : IChannelInteractionModule
|
||||||
{
|
{
|
||||||
private readonly ChannelReader<NetworkMessageHeader> _receiveReader;
|
private readonly ChannelReader<NetworkMessage> _receiveReader;
|
||||||
private readonly ChannelWriter<NetworkMessageHeader> _trustedWriter;
|
private readonly ChannelWriter<NetworkMessage> _trustedWriter;
|
||||||
private readonly ChannelWriter<NetworkMessageHeader> _untrustedWriter;
|
private readonly ChannelWriter<NetworkMessage> _untrustedWriter;
|
||||||
private readonly Channel<NetworkMessageHeader> _outputTrustedChannel;
|
private readonly Channel<NetworkMessage> _outputTrustedChannel;
|
||||||
private readonly Channel<NetworkMessageHeader> _outputUntrustedChannel;
|
private readonly Channel<NetworkMessage> _outputUntrustedChannel;
|
||||||
private readonly IContextualSerializationToolKit _serialization;
|
private readonly IContextualSerializationToolKit _serialization;
|
||||||
private bool _isConnected = true;
|
private bool _isConnected = true;
|
||||||
private bool _isActive = true;
|
private bool _isActive = true;
|
||||||
@@ -29,19 +29,19 @@ namespace mROA.Implementation
|
|||||||
public ChannelInteractionModule(IContextualSerializationToolKit serialization)
|
public ChannelInteractionModule(IContextualSerializationToolKit serialization)
|
||||||
{
|
{
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
ReceiveChanel = Channel.CreateUnbounded<NetworkMessageHeader>(new UnboundedChannelOptions
|
ReceiveChanel = Channel.CreateUnbounded<NetworkMessage>(new UnboundedChannelOptions
|
||||||
{
|
{
|
||||||
SingleReader = false,
|
SingleReader = false,
|
||||||
SingleWriter = false,
|
SingleWriter = false,
|
||||||
});
|
});
|
||||||
_receiveReader = ReceiveChanel.Reader;
|
_receiveReader = ReceiveChanel.Reader;
|
||||||
_outputTrustedChannel = Channel.CreateUnbounded<NetworkMessageHeader>(new UnboundedChannelOptions
|
_outputTrustedChannel = Channel.CreateUnbounded<NetworkMessage>(new UnboundedChannelOptions
|
||||||
{
|
{
|
||||||
SingleReader = true,
|
SingleReader = true,
|
||||||
SingleWriter = true
|
SingleWriter = true
|
||||||
});
|
});
|
||||||
_trustedWriter = _outputTrustedChannel.Writer;
|
_trustedWriter = _outputTrustedChannel.Writer;
|
||||||
_outputUntrustedChannel = Channel.CreateUnbounded<NetworkMessageHeader>(new UnboundedChannelOptions
|
_outputUntrustedChannel = Channel.CreateUnbounded<NetworkMessage>(new UnboundedChannelOptions
|
||||||
{
|
{
|
||||||
SingleReader = true,
|
SingleReader = true,
|
||||||
SingleWriter = true,
|
SingleWriter = true,
|
||||||
@@ -53,41 +53,33 @@ namespace mROA.Implementation
|
|||||||
public int ConnectionId { get; set; }
|
public int ConnectionId { get; set; }
|
||||||
|
|
||||||
public IEndPointContext Context { get; set; }
|
public IEndPointContext Context { get; set; }
|
||||||
public Channel<NetworkMessageHeader> ReceiveChanel { get; }
|
public Channel<NetworkMessage> ReceiveChanel { get; }
|
||||||
|
|
||||||
public ChannelReader<NetworkMessageHeader> TrustedPostChanel => _outputTrustedChannel.Reader;
|
public ChannelReader<NetworkMessage> TrustedPostChanel => _outputTrustedChannel.Reader;
|
||||||
public ChannelReader<NetworkMessageHeader> UntrustedPostChanel => _outputUntrustedChannel.Reader;
|
public ChannelReader<NetworkMessage> UntrustedPostChanel => _outputUntrustedChannel.Reader;
|
||||||
public Func<bool> IsConnected { get; set; } = () => false;
|
public Func<bool> IsConnected { get; set; } = () => false;
|
||||||
|
|
||||||
public ValueTask<NetworkMessageHeader> GetNextMessageReceiving(bool infinite = true)
|
public ValueTask<NetworkMessage> GetNextMessageReceiving()
|
||||||
{
|
{
|
||||||
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(NetworkMessage message)
|
||||||
{
|
{
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _trustedWriter.WriteAsync(messageHeader);
|
await _trustedWriter.WriteAsync(message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#pragma warning restore CS8602 // Dereference of a possibly null reference.
|
|
||||||
|
|
||||||
|
public async Task PostMessageAsync(NetworkMessage message)
|
||||||
public async Task PostMessageAsync(NetworkMessageHeader messageHeader)
|
|
||||||
{
|
{
|
||||||
if (_serialization == null)
|
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (await PostMessageInternal(messageHeader))
|
if (await PostMessageInternal(message))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!_isActive)
|
if (!_isActive)
|
||||||
@@ -100,9 +92,9 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PostMessageUntrustedAsync(NetworkMessageHeader messageHeader)
|
public async Task PostMessageUntrustedAsync(NetworkMessage message)
|
||||||
{
|
{
|
||||||
await _untrustedWriter.WriteAsync(messageHeader);
|
await _untrustedWriter.WriteAsync(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Action<int>? OnDisconnected;
|
public event Action<int>? OnDisconnected;
|
||||||
@@ -112,12 +104,12 @@ namespace mROA.Implementation
|
|||||||
if (sendRecovery)
|
if (sendRecovery)
|
||||||
{
|
{
|
||||||
await PostMessageAsync(
|
await PostMessageAsync(
|
||||||
new NetworkMessageHeader(_serialization, new ClientRecovery(Math.Abs(ConnectionId)), Context));
|
new NetworkMessage(_serialization, new ClientRecovery(Math.Abs(ConnectionId)), Context));
|
||||||
await ReceiveChanel.Reader.ReadAsync();
|
await ReceiveChanel.Reader.ReadAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _trustedWriter.WriteAsync(new NetworkMessageHeader());
|
await _trustedWriter.WriteAsync(new NetworkMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
PassReconnection();
|
PassReconnection();
|
||||||
@@ -150,42 +142,35 @@ namespace mROA.Implementation
|
|||||||
|
|
||||||
public class StreamExtractor
|
public class StreamExtractor
|
||||||
{
|
{
|
||||||
private const int BufferSize = ushort.MaxValue;
|
private const int BufferSize = ushort.MaxValue + 19;
|
||||||
|
|
||||||
private readonly Stream _ioStream;
|
private readonly Stream _ioStream;
|
||||||
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 byte[] _lenBuffer;
|
|
||||||
|
|
||||||
public StreamExtractor(Stream ioStream, IContextualSerializationToolKit serializationToolkit,
|
public StreamExtractor(Stream ioStream)
|
||||||
IEndPointContext context)
|
|
||||||
{
|
{
|
||||||
_ioStream = ioStream;
|
_ioStream = ioStream;
|
||||||
_serializationToolkit = serializationToolkit;
|
|
||||||
_context = context;
|
|
||||||
_lenBuffer = new byte[2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<NetworkMessageHeader> MessageReceived = _ => { };
|
public Action<NetworkMessage> MessageReceived = _ => { };
|
||||||
|
|
||||||
private async Task<ushort> ReadMessageLength()
|
|
||||||
{
|
|
||||||
await _ioStream.ReadAsync(_lenBuffer);
|
|
||||||
|
|
||||||
var len = BitConverter.ToUInt16(_lenBuffer);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SingleReceive(CancellationToken token = default)
|
public async Task SingleReceive(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var len = await ReadMessageLength();
|
|
||||||
var localSpan = _buffer[..len];
|
|
||||||
|
|
||||||
await _ioStream.ReadExactlyAsync(localSpan, cancellationToken: token);
|
_ = await _ioStream.ReadExactlyAsync(_buffer[..19], token);
|
||||||
var message = _serializationToolkit.Deserialize<NetworkMessageHeader>(localSpan, _context);
|
|
||||||
MessageReceived(message);
|
var meta = MemoryMarshal.Read<NetworkMessage.NetworkMessageMeta>(_buffer.Span);
|
||||||
|
|
||||||
|
var len = meta.BodyLength;
|
||||||
|
|
||||||
|
var range = 19..(len + 19);
|
||||||
|
// Console.WriteLine($"{range} {_buffer.Length}");
|
||||||
|
var lastPart = _buffer[range];
|
||||||
|
await _ioStream.ReadExactlyAsync(lastPart, cancellationToken: token);
|
||||||
|
|
||||||
|
var message = meta.ToMessage(_buffer.Span);
|
||||||
|
// Console.WriteLine("RECV " + message);
|
||||||
|
|
||||||
|
MessageReceived(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoopedReceive(CancellationToken token = default)
|
public async Task LoopedReceive(CancellationToken token = default)
|
||||||
@@ -196,17 +181,17 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Send(NetworkMessageHeader message, CancellationToken token = default)
|
private async Task Send(NetworkMessage message, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var bodySpan = _buffer[2..];
|
var meta = message.ToMeta();
|
||||||
var len = _serializationToolkit.Serialize(message, bodySpan.Span, _context);
|
MemoryMarshal.Write(_buffer.Span, ref meta);
|
||||||
var header = BitConverter.GetBytes((ushort)len);
|
message.Data.CopyTo(_buffer.Span[19..]);
|
||||||
header.CopyTo(_buffer);
|
var sendingSpan = _buffer[..(19 + meta.BodyLength)];
|
||||||
var sendingSpan = _buffer[..(len + 2)];
|
// Console.WriteLine("SEND " + message);
|
||||||
await _ioStream.WriteAsync(sendingSpan, token);
|
await _ioStream.WriteAsync(sendingSpan, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendFromChannel(ChannelReader<NetworkMessageHeader> channel,
|
public async Task SendFromChannel(ChannelReader<NetworkMessage> channel,
|
||||||
CancellationToken token = default)
|
CancellationToken token = default)
|
||||||
{
|
{
|
||||||
while (token.IsCancellationRequested == false && IsConnected)
|
while (token.IsCancellationRequested == false && IsConnected)
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class CircularMemoryManager
|
||||||
|
{
|
||||||
|
private readonly Memory<byte> _buffer;
|
||||||
|
private Memory<byte> _current;
|
||||||
|
private SpinLock _spinLock = new(false);
|
||||||
|
|
||||||
|
public CircularMemoryManager(int size)
|
||||||
|
{
|
||||||
|
_buffer = new Memory<byte>(new byte[size]);
|
||||||
|
_current = _buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<byte> AllocSlice(int size)
|
||||||
|
{
|
||||||
|
Span<byte> order;
|
||||||
|
var lockTaken = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_spinLock.Enter(ref lockTaken);
|
||||||
|
if (_current.Length < size)
|
||||||
|
_current = _buffer;
|
||||||
|
|
||||||
|
order = _current.Span[..size];
|
||||||
|
_current = _current[size..];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (lockTaken) _spinLock.Exit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Memory<byte> AllocMemory(int size)
|
||||||
|
{
|
||||||
|
Memory<byte> order;
|
||||||
|
var lockTaken = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_spinLock.Enter(ref lockTaken);
|
||||||
|
if (_current.Length < size)
|
||||||
|
_current = _buffer;
|
||||||
|
|
||||||
|
order = _current[..size];
|
||||||
|
_current = _current[size..];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (lockTaken) _spinLock.Exit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
@@ -5,19 +6,16 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
public class CollectableMethodRepository : IMethodRepository
|
public class CollectableMethodRepository : IMethodRepository
|
||||||
{
|
{
|
||||||
private List<IMethodInvoker> _methods = new();
|
private readonly List<IMethodInvoker> _methods = new() { MethodInvoker.Dispose };
|
||||||
|
private IMethodInvoker[] _baked = Array.Empty<IMethodInvoker>();
|
||||||
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
|
public void AppendInvokers(IEnumerable<IMethodInvoker> methodInvokers)
|
||||||
{
|
{
|
||||||
_methods.AddRange(methodInvokers);
|
_methods.AddRange(methodInvokers);
|
||||||
|
_baked = _methods.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethodInvoker GetMethod(int id)
|
public IMethodInvoker GetMethod(int id)
|
||||||
{
|
{
|
||||||
if (id == -1)
|
return _baked[++id];
|
||||||
return MethodInvoker.Dispose;
|
|
||||||
|
|
||||||
return _methods[id];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace mROA.Implementation.CommandExecution
|
|||||||
{
|
{
|
||||||
public class AsyncCommandExecution : ICommandExecution
|
public class AsyncCommandExecution : ICommandExecution
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public RequestId Id { get; set; }
|
||||||
public EMessageType MessageType => EMessageType.Unknown;
|
public EMessageType MessageType => EMessageType.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace mROA.Implementation.CommandExecution
|
|||||||
{
|
{
|
||||||
public class ExceptionCommandExecution : ICommandExecution
|
public class ExceptionCommandExecution : ICommandExecution
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public RequestId Id { get; set; }
|
||||||
public EMessageType MessageType => EMessageType.ExceptionCommandExecution;
|
public EMessageType MessageType => EMessageType.ExceptionCommandExecution;
|
||||||
public string Exception { get; set; }
|
public string Exception { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
|
||||||
|
|
||||||
namespace mROA.Implementation.CommandExecution
|
namespace mROA.Implementation.CommandExecution
|
||||||
{
|
{
|
||||||
public struct FinalCommandExecution : ICommandExecution
|
public struct FinalCommandExecution : ICommandExecution
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public RequestId Id { get; set; }
|
||||||
public EMessageType MessageType => EMessageType.FinishedCommandExecution;
|
public EMessageType MessageType => EMessageType.FinishedCommandExecution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct FinalCommandExecution<T> : ICommandExecution
|
public struct FinalCommandExecution<T> : ICommandExecution
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public RequestId Id { get; set; }
|
||||||
public EMessageType MessageType => EMessageType.FinishedCommandExecution;
|
public EMessageType MessageType => EMessageType.FinishedCommandExecution;
|
||||||
public T? Result { get; set; }
|
public T? Result { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System;
|
|||||||
|
|
||||||
namespace mROA.Implementation
|
namespace mROA.Implementation
|
||||||
{
|
{
|
||||||
#pragma warning disable CS8618, CS9264
|
|
||||||
public struct ComplexObjectIdentifier : IEquatable<ComplexObjectIdentifier>
|
public struct ComplexObjectIdentifier : IEquatable<ComplexObjectIdentifier>
|
||||||
{
|
{
|
||||||
public int ContextId;
|
public int ContextId;
|
||||||
@@ -14,14 +13,9 @@ namespace mROA.Implementation
|
|||||||
OwnerId = ownerId;
|
OwnerId = ownerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ComplexObjectIdentifier Singleton(int ownerId) => new() { ContextId = -1, OwnerId = ownerId };
|
public static ComplexObjectIdentifier Null = new() { ContextId = -2, OwnerId = 0 };
|
||||||
|
|
||||||
public static ComplexObjectIdentifier Null = new ComplexObjectIdentifier { ContextId = -2, OwnerId = 0 };
|
|
||||||
public static ComplexObjectIdentifier FromFlat(ulong flat) => new() { Flat = flat };
|
public static ComplexObjectIdentifier FromFlat(ulong flat) => new() { Flat = flat };
|
||||||
|
|
||||||
public int ClientId => Math.Abs(OwnerId);
|
|
||||||
public bool IsSererStored => OwnerId > 0;
|
|
||||||
public bool IsClientStored => OwnerId < 0;
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,29 +1,23 @@
|
|||||||
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(IServiceProvider creationModules, IConnectionHub hub, IContextualSerializationToolKit serialization)
|
public CreativeRepresentationModuleProducer(IConnectionHub hub, IContextualSerializationToolKit serialization)
|
||||||
{
|
{
|
||||||
_creationModules = creationModules;
|
|
||||||
_hub = hub;
|
_hub = hub;
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IRepresentationModule Produce(int id)
|
public IRepresentationModule Produce(int id)
|
||||||
{
|
{
|
||||||
if (_hub == null)
|
|
||||||
throw new NullReferenceException("Interaction module is null");
|
|
||||||
|
|
||||||
var interaction = _hub.GetInteraction(id);
|
var interaction = _hub.GetInteraction(id);
|
||||||
|
|
||||||
var produced = new RepresentationModule(interaction, _serialization);
|
var produced = new RepresentationModule(interaction, _serialization.Clone());
|
||||||
|
|
||||||
return produced;
|
return produced;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Abstract;
|
||||||
|
using mROA.Implementation.Backend;
|
||||||
|
|
||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class ChannelDistributionModule : IDistributionModule
|
||||||
|
{
|
||||||
|
private readonly IConnectionHub _hub;
|
||||||
|
|
||||||
|
public ChannelDistributionModule(IConnectionHub hub)
|
||||||
|
{
|
||||||
|
_hub = hub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<NetworkMessage> GetDistributionAction(int clientId)
|
||||||
|
{
|
||||||
|
var writer = _hub.GetInteraction(clientId).ReceiveChanel.Writer;
|
||||||
|
return message =>
|
||||||
|
{
|
||||||
|
writer.TryWrite(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtractorFirstDistributionModule : IDistributionModule
|
||||||
|
{
|
||||||
|
private readonly IConnectionHub _hub;
|
||||||
|
private readonly IContextualSerializationToolKit _serialization;
|
||||||
|
private readonly HubRequestExtractor _extractorHub;
|
||||||
|
|
||||||
|
public ExtractorFirstDistributionModule(HubRequestExtractor extractorHub, IConnectionHub hub, IContextualSerializationToolKit serialization)
|
||||||
|
{
|
||||||
|
_extractorHub = extractorHub;
|
||||||
|
_hub = hub;
|
||||||
|
_serialization = serialization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<NetworkMessage> GetDistributionAction(int clientId)
|
||||||
|
{
|
||||||
|
var interaction = _hub.GetInteraction(clientId);
|
||||||
|
var writer = interaction.ReceiveChanel.Writer;
|
||||||
|
var context = interaction.Context;
|
||||||
|
var requestExtractor = _extractorHub[clientId];
|
||||||
|
var converters = requestExtractor.Converters;
|
||||||
|
var serialization = _serialization.Clone();
|
||||||
|
return message =>
|
||||||
|
{
|
||||||
|
if (requestExtractor.Rule(message))
|
||||||
|
{
|
||||||
|
for (var i = 0; i < converters.Length; i++)
|
||||||
|
{
|
||||||
|
var func = converters[i];
|
||||||
|
if (func(message) is not { } t) continue;
|
||||||
|
|
||||||
|
var deserialized = serialization.Deserialize(message.Data, t, context)!;
|
||||||
|
Task.Run(() => requestExtractor.PushMessage(deserialized, message.MessageType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteAsync(message).ConfigureAwait(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class DistributionOptions
|
||||||
|
{
|
||||||
|
public EDistributionType DistributionType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EDistributionType
|
||||||
|
{
|
||||||
|
Channeled,
|
||||||
|
ExtractorFirst
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace mROA.Implementation
|
namespace mROA.Implementation
|
||||||
{
|
{
|
||||||
public enum EMessageType
|
public enum EMessageType : byte
|
||||||
{
|
{
|
||||||
Unknown,
|
Unknown,
|
||||||
FinishedCommandExecution,
|
FinishedCommandExecution,
|
||||||
@@ -12,6 +12,6 @@ namespace mROA.Implementation
|
|||||||
ClientRecovery,
|
ClientRecovery,
|
||||||
ClientConnect,
|
ClientConnect,
|
||||||
ClientDisconnect,
|
ClientDisconnect,
|
||||||
UntrustedConnect,
|
UntrustedConnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,8 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
public EndPointContext()
|
public EndPointContext()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EndPointContext(IRealStoreInstanceRepository realRepository, IInstanceRepository remoteRepository)
|
public EndPointContext(IRealStoreInstanceRepository realRepository, IInstanceRepository remoteRepository)
|
||||||
{
|
{
|
||||||
RealRepository = realRepository;
|
RealRepository = realRepository;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace mROA.Implementation
|
|||||||
public void Free(int index)
|
public void Free(int index)
|
||||||
{
|
{
|
||||||
_freePlaces.AddFirst(index);
|
_freePlaces.AddFirst(index);
|
||||||
_array[index] = default;
|
_array[index] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -14,39 +14,36 @@ 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 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)
|
||||||
{
|
{
|
||||||
_serverEndPoint = options.Value.Endpoint;
|
_serverEndPoint = options.Value.Endpoint;
|
||||||
_context = context;
|
_context = context;
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
_interactionModule = interactionModule;
|
_interactionModule = interactionModule;
|
||||||
_rawExtractorCancellation = new CancellationTokenSource();
|
_rawExtractorCancellation = new CancellationTokenSource();
|
||||||
|
_currentExtractor = new ChannelInteractionModule.StreamExtractor(Stream.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Connect()
|
public async Task Connect()
|
||||||
{
|
{
|
||||||
if (_interactionModule is null)
|
|
||||||
throw new Exception("Interaction module was not injected");
|
|
||||||
if (_serialization == null)
|
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
|
||||||
|
|
||||||
_tcpClient.Connect(_serverEndPoint);
|
_tcpClient.Connect(_serverEndPoint);
|
||||||
_tcpClient.NoDelay = true;
|
_tcpClient.NoDelay = true;
|
||||||
PrepareExtractor();
|
PrepareExtractor();
|
||||||
_interactionModule.IsConnected = () => _currentExtractor.IsConnected;
|
_interactionModule.IsConnected = () => _currentExtractor.IsConnected;
|
||||||
_interactionModule.OnDisconnected += _ => { Reconnect(); };
|
_interactionModule.OnDisconnected += _ => { Reconnect().ConfigureAwait(false); };
|
||||||
|
|
||||||
_interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientConnect(), _context))
|
_interactionModule.PostMessageAsync(new NetworkMessage(_serialization, new ClientConnect(), _context))
|
||||||
.Wait();
|
.Wait();
|
||||||
|
|
||||||
_currentExtractor.SingleReceive();
|
_ = _currentExtractor.SingleReceive().ConfigureAwait(false);
|
||||||
var idMessage = await _interactionModule.GetNextMessageReceiving(false);
|
var idMessage = await _interactionModule.GetNextMessageReceiving();
|
||||||
|
|
||||||
if (idMessage.MessageType != EMessageType.IdAssigning)
|
if (idMessage.MessageType != EMessageType.IdAssigning)
|
||||||
{
|
{
|
||||||
@@ -54,8 +51,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
$"Incorrect message type. Must be IdAssigning, current : {idMessage.MessageType.ToString()}");
|
$"Incorrect message type. Must be IdAssigning, current : {idMessage.MessageType.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
||||||
Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
|
||||||
|
|
||||||
var assignment = _serialization.Deserialize<IdAssignment>(idMessage.Data, _context);
|
var assignment = _serialization.Deserialize<IdAssignment>(idMessage.Data, _context);
|
||||||
_interactionModule.ConnectionId = -assignment.Id;
|
_interactionModule.ConnectionId = -assignment.Id;
|
||||||
@@ -66,9 +62,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());
|
||||||
|
|
||||||
_ = _currentExtractor.SendFromChannel(_interactionModule!.TrustedPostChanel,
|
_ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel,
|
||||||
_rawExtractorCancellation.Token);
|
_rawExtractorCancellation.Token);
|
||||||
_currentExtractor.MessageReceived = message =>
|
_currentExtractor.MessageReceived = message =>
|
||||||
{
|
{
|
||||||
@@ -86,7 +82,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
|
|
||||||
PrepareExtractor();
|
PrepareExtractor();
|
||||||
|
|
||||||
Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
_ = Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
||||||
|
|
||||||
await _interactionModule.Restart(true);
|
await _interactionModule.Restart(true);
|
||||||
}
|
}
|
||||||
@@ -98,7 +94,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
|
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
_ = _interactionModule!.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientDisconnect(),
|
_ = _interactionModule.PostMessageAsync(new NetworkMessage(_serialization, new ClientDisconnect(),
|
||||||
_context));
|
_context));
|
||||||
_interactionModule.Dispose();
|
_interactionModule.Dispose();
|
||||||
_tcpClient.Dispose();
|
_tcpClient.Dispose();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
{
|
{
|
||||||
public class RemoteException : Exception
|
public class RemoteException : Exception
|
||||||
{
|
{
|
||||||
public Guid CallRequestId;
|
public RequestId CallRequestId;
|
||||||
private readonly string _error;
|
private readonly string _error;
|
||||||
|
|
||||||
public RemoteException(string error)
|
public RemoteException(string error)
|
||||||
|
|||||||
@@ -3,98 +3,90 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
// ReSharper disable MethodHasAsyncOverload
|
|
||||||
|
|
||||||
namespace mROA.Implementation.Frontend
|
namespace mROA.Implementation.Frontend
|
||||||
{
|
{
|
||||||
public class RequestExtractor : IRequestExtractor
|
public class RequestExtractor : IRequestExtractor
|
||||||
{
|
{
|
||||||
private IExecuteModule _executeModule;
|
private readonly IExecuteModule _executeModule;
|
||||||
|
|
||||||
private IMethodRepository _methodRepository;
|
private readonly IRepresentationModule _representationModule;
|
||||||
|
private readonly IEndPointContext _context;
|
||||||
|
|
||||||
private IRepresentationModule _representationModule;
|
public RequestExtractor(IExecuteModule executeModule, IRepresentationModule representationModule,
|
||||||
private IContextualSerializationToolKit _serializationToolkit;
|
IEndPointContext context)
|
||||||
private IEndPointContext _context;
|
|
||||||
|
|
||||||
public RequestExtractor(IExecuteModule executeModule, IMethodRepository methodRepository, IRepresentationModule representationModule, IContextualSerializationToolKit serializationToolkit, IEndPointContext context)
|
|
||||||
{
|
{
|
||||||
_executeModule = executeModule;
|
_executeModule = executeModule;
|
||||||
_methodRepository = methodRepository;
|
|
||||||
_representationModule = representationModule;
|
_representationModule = representationModule;
|
||||||
_serializationToolkit = serializationToolkit;
|
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartExtraction()
|
public async Task StartExtraction()
|
||||||
{
|
{
|
||||||
ThrowIfNotInjected();
|
|
||||||
|
|
||||||
var streamTokenSource = new CancellationTokenSource();
|
var streamTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
var query = _representationModule.GetStream(m =>
|
var query = _representationModule.GetStream(Rule, _context,
|
||||||
m.MessageType is EMessageType.CallRequest or EMessageType.CancelRequest
|
|
||||||
or EMessageType.EventRequest or EMessageType.ClientDisconnect, _context,
|
|
||||||
streamTokenSource.Token,
|
streamTokenSource.Token,
|
||||||
m => m.MessageType == EMessageType.CallRequest ? typeof(DefaultCallRequest) : null,
|
Converters);
|
||||||
m => m.MessageType == EMessageType.CancelRequest ? typeof(CancelRequest) : null,
|
|
||||||
m => m.MessageType == EMessageType.EventRequest ? typeof(DefaultCallRequest) : null,
|
|
||||||
m => m.MessageType == EMessageType.ClientDisconnect ? typeof(ClientDisconnect) : null);
|
|
||||||
|
|
||||||
|
|
||||||
await foreach (var command in query)
|
await foreach (var command in query)
|
||||||
{
|
{
|
||||||
switch (command.originalType)
|
PushMessage(command.parced, command.originalType);
|
||||||
{
|
|
||||||
case EMessageType.CallRequest:
|
|
||||||
HandleCallRequest((DefaultCallRequest)command.parced);
|
|
||||||
break;
|
|
||||||
case EMessageType.ClientDisconnect:
|
|
||||||
return;
|
|
||||||
case EMessageType.EventRequest:
|
|
||||||
HandleEventRequest((DefaultCallRequest)command.parced);
|
|
||||||
break;
|
|
||||||
case EMessageType.CancelRequest:
|
|
||||||
HandleCancelRequest((command.parced as CancelRequest)!);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowIfNotInjected()
|
public void PushMessage(object parsed, EMessageType originalType)
|
||||||
{
|
{
|
||||||
if (_serializationToolkit == null)
|
switch (originalType)
|
||||||
throw new NullReferenceException("Serializing toolkit is null.");
|
{
|
||||||
if (_executeModule == null)
|
case EMessageType.CallRequest:
|
||||||
throw new NullReferenceException("Execute module is null.");
|
HandleCallRequest((CallRequest)parsed);
|
||||||
if (_representationModule == null)
|
break;
|
||||||
throw new NullReferenceException("Representation module is null.");
|
case EMessageType.ClientDisconnect:
|
||||||
if (_methodRepository == null)
|
return;
|
||||||
throw new NullReferenceException("Method repository is null.");
|
case EMessageType.EventRequest:
|
||||||
|
HandleEventRequest((CallRequest)parsed);
|
||||||
|
break;
|
||||||
|
case EMessageType.CancelRequest:
|
||||||
|
HandleCancelRequest((CancelRequest)parsed);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Predicate<NetworkMessage> Rule { get; } = m =>
|
||||||
|
m.MessageType is EMessageType.CallRequest or EMessageType.CancelRequest
|
||||||
|
or EMessageType.EventRequest or EMessageType.ClientDisconnect;
|
||||||
|
|
||||||
|
public Func<NetworkMessage, Type?>[] Converters { get; } =
|
||||||
|
{
|
||||||
|
m => m.MessageType == EMessageType.CallRequest ? typeof(CallRequest) : null,
|
||||||
|
m => m.MessageType == EMessageType.CancelRequest ? typeof(CancelRequest) : null,
|
||||||
|
m => m.MessageType == EMessageType.EventRequest ? typeof(CallRequest) : null,
|
||||||
|
m => m.MessageType == EMessageType.ClientDisconnect ? typeof(ClientDisconnect) : null
|
||||||
|
};
|
||||||
|
|
||||||
private void HandleCancelRequest(CancelRequest req)
|
private void HandleCancelRequest(CancelRequest req)
|
||||||
{
|
{
|
||||||
_executeModule.Execute(req, _context.RealRepository, _representationModule, _context);
|
_executeModule.Cancel(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleCallRequest(DefaultCallRequest request)
|
private void HandleCallRequest(CallRequest request)
|
||||||
{
|
{
|
||||||
var result = _executeModule.Execute(request, _context.RealRepository, _representationModule, _context);
|
var result = _executeModule.Execute(request, _context.RealRepository, _representationModule, _context);
|
||||||
|
|
||||||
var resultType = result.MessageType;
|
if (result is null)
|
||||||
|
|
||||||
if (resultType == EMessageType.Unknown)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_representationModule.PostCallMessage(request.Id, resultType, result, _context);
|
var resultType = result.MessageType;
|
||||||
|
_representationModule.PostCallMessageAsync(request.Id, resultType, result, _context).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleEventRequest(DefaultCallRequest request)
|
private void HandleEventRequest(CallRequest request)
|
||||||
{
|
{
|
||||||
_executeModule.Execute(request, _context.RemoteRepository, _representationModule, _context);
|
_executeModule.Execute(request, _context.RemoteRepository, _representationModule, _context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using mROA.Abstract;
|
|
||||||
|
|
||||||
namespace mROA.Implementation.Frontend
|
|
||||||
{
|
|
||||||
public class StaticOwnershipRepository : IOwnershipRepository
|
|
||||||
{
|
|
||||||
private readonly int _id;
|
|
||||||
|
|
||||||
public StaticOwnershipRepository(int id)
|
|
||||||
{
|
|
||||||
_id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetOwnershipId()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHostOwnershipId()
|
|
||||||
{
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,8 @@ namespace mROA.Implementation.Frontend
|
|||||||
private readonly CancellationTokenSource _tokenSource = new();
|
private readonly CancellationTokenSource _tokenSource = new();
|
||||||
private readonly IEndPointContext _context;
|
private readonly IEndPointContext _context;
|
||||||
|
|
||||||
public UdpUntrustedInteraction(IContextualSerializationToolKit serializationToolkit, IChannelInteractionModule channelInteractionModule, IEndPointContext context)
|
public UdpUntrustedInteraction(IContextualSerializationToolKit serializationToolkit,
|
||||||
|
IChannelInteractionModule channelInteractionModule, IEndPointContext context)
|
||||||
{
|
{
|
||||||
_serializationToolkit = serializationToolkit;
|
_serializationToolkit = serializationToolkit;
|
||||||
_channelInteractionModule = channelInteractionModule;
|
_channelInteractionModule = channelInteractionModule;
|
||||||
@@ -43,7 +44,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
while (token.IsCancellationRequested == false)
|
while (token.IsCancellationRequested == false)
|
||||||
{
|
{
|
||||||
var message = new Memory<byte>((await udpClient.ReceiveAsync()).Buffer);
|
var message = new Memory<byte>((await udpClient.ReceiveAsync()).Buffer);
|
||||||
var parsed = _serializationToolkit.Deserialize<NetworkMessageHeader>(message, _context);
|
var parsed = _serializationToolkit.Deserialize<NetworkMessage>(message, _context);
|
||||||
|
|
||||||
await writer.WriteAsync(parsed, token);
|
await writer.WriteAsync(parsed, token);
|
||||||
}
|
}
|
||||||
@@ -51,10 +52,10 @@ namespace mROA.Implementation.Frontend
|
|||||||
|
|
||||||
private async Task Posting(UdpClient udpClient, CancellationToken token)
|
private async Task Posting(UdpClient udpClient, CancellationToken token)
|
||||||
{
|
{
|
||||||
var initMessage = new NetworkMessageHeader
|
var initMessage = new NetworkMessage
|
||||||
{
|
{
|
||||||
MessageType = EMessageType.UntrustedConnect, Id = Guid.NewGuid(),
|
MessageType = EMessageType.UntrustedConnect, Id = RequestId.Generate(),
|
||||||
Data = BitConverter.GetBytes(_channelInteractionModule.ConnectionId)
|
Data = BitConverter.GetBytes(-_channelInteractionModule.ConnectionId)
|
||||||
};
|
};
|
||||||
|
|
||||||
var initParsed = _serializationToolkit.Serialize(initMessage, _context);
|
var initParsed = _serializationToolkit.Serialize(initMessage, _context);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace mROA.Implementation
|
|||||||
|
|
||||||
public class ClientRecovery : INetworkMessage
|
public class ClientRecovery : INetworkMessage
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once UnusedMember.Global
|
||||||
public ClientRecovery()
|
public ClientRecovery()
|
||||||
{
|
{
|
||||||
Id = 0;
|
Id = 0;
|
||||||
@@ -26,5 +27,6 @@ namespace mROA.Implementation
|
|||||||
public class ClientConnect : INetworkMessage
|
public class ClientConnect : INetworkMessage
|
||||||
{
|
{
|
||||||
public EMessageType MessageType => EMessageType.ClientConnect;
|
public EMessageType MessageType => EMessageType.ClientConnect;
|
||||||
|
public string[]? Config { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ namespace mROA.Implementation
|
|||||||
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
|
public Type[] ParameterTypes { get; set; } = Type.EmptyTypes;
|
||||||
public Type? ReturnType { get; set; }
|
public Type? ReturnType { get; set; }
|
||||||
public Type SuitableType { get; set; } = typeof(object);
|
public Type SuitableType { get; set; } = typeof(object);
|
||||||
|
public bool RequireCancellation { get; set; } = true;
|
||||||
public Action<object, object?[]?, object[], Action<object?>> Invoking { get; set; } =
|
public Action<object, object?[]?, object[], Action<object?>> Invoking { get; set; } =
|
||||||
(_, _, _, post) => { post.Invoke(null); };
|
(_, _, _, post) => { post.Invoke(null); };
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class NetworkMessage
|
||||||
|
{
|
||||||
|
private bool Equals(NetworkMessage other)
|
||||||
|
{
|
||||||
|
return Id.Equals(other.Id) && MessageType == other.MessageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (obj is null) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
return obj.GetType() == GetType() && Equals((NetworkMessage)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkMessage()
|
||||||
|
{
|
||||||
|
Data = Array.Empty<byte>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkMessage(IContextualSerializationToolKit serializationToolkit,
|
||||||
|
INetworkMessage networkMessage, IEndPointContext? context)
|
||||||
|
{
|
||||||
|
MessageType = networkMessage.MessageType;
|
||||||
|
Data = serializationToolkit.Serialize(networkMessage, context);
|
||||||
|
Id = RequestId.Generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequestId Id { get; set; }
|
||||||
|
|
||||||
|
public EMessageType MessageType { get; set; }
|
||||||
|
|
||||||
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $" {Id}:{MessageType} [{Data.Length}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkMessageMeta ToMeta()
|
||||||
|
{
|
||||||
|
return new NetworkMessageMeta
|
||||||
|
{
|
||||||
|
BodyLength = (ushort)(Data == null ? 0 : Data.Length),
|
||||||
|
Type = (byte)MessageType,
|
||||||
|
Id = Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct NetworkMessageMeta
|
||||||
|
{
|
||||||
|
public RequestId Id;
|
||||||
|
public ushort BodyLength;
|
||||||
|
public byte Type;
|
||||||
|
|
||||||
|
public NetworkMessage ToMessage(Span<byte> memory)
|
||||||
|
{
|
||||||
|
var data = memory[19..][..BodyLength];
|
||||||
|
return new NetworkMessage
|
||||||
|
{
|
||||||
|
Data = data.ToArray(),
|
||||||
|
Id = Id,
|
||||||
|
MessageType = (EMessageType)Type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
using System;
|
|
||||||
using mROA.Abstract;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace mROA.Implementation
|
|
||||||
{
|
|
||||||
public class NetworkMessageHeader
|
|
||||||
{
|
|
||||||
private bool Equals(NetworkMessageHeader other)
|
|
||||||
{
|
|
||||||
return Id.Equals(other.Id) && MessageType == other.MessageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
|
||||||
{
|
|
||||||
if (obj is null) return false;
|
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
|
||||||
if (obj.GetType() != GetType()) return false;
|
|
||||||
return Equals((NetworkMessageHeader)obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly NetworkMessageHeader Null = new();
|
|
||||||
|
|
||||||
public NetworkMessageHeader()
|
|
||||||
{
|
|
||||||
Data = Array.Empty<byte>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetworkMessageHeader(IContextualSerializationToolKit serializationToolkit,
|
|
||||||
INetworkMessage networkMessage, IEndPointContext? context)
|
|
||||||
{
|
|
||||||
MessageType = networkMessage.MessageType;
|
|
||||||
Data = serializationToolkit.Serialize(networkMessage, context);
|
|
||||||
Id = Guid.NewGuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
public EMessageType MessageType { get; set; }
|
|
||||||
|
|
||||||
public byte[] Data { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $" {Id}:{MessageType} [{Data.Length}]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,12 +7,14 @@ 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 List<RemoteObjectBase> _producedSingletonProxies = new();
|
||||||
|
private readonly ICallIndexProvider _callIndexProvider;
|
||||||
|
|
||||||
private IRepresentationModuleProducer _representationProducer;
|
private readonly IRepresentationModuleProducer _representationProducer;
|
||||||
|
|
||||||
public RemoteInstanceRepository(ICallIndexProvider callIndexProvider, IRepresentationModuleProducer representationProducer)
|
public RemoteInstanceRepository(ICallIndexProvider callIndexProvider,
|
||||||
|
IRepresentationModuleProducer representationProducer)
|
||||||
{
|
{
|
||||||
_callIndexProvider = callIndexProvider;
|
_callIndexProvider = callIndexProvider;
|
||||||
_representationProducer = representationProducer;
|
_representationProducer = representationProducer;
|
||||||
@@ -31,11 +33,9 @@ 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 existing = _producedProxies.Find(i => i.Identifier.Equals(id));
|
||||||
if (index is not null)
|
if (existing is not null)
|
||||||
return (T)(index as object);
|
return (T)(existing as object);
|
||||||
if (_representationProducer == null)
|
|
||||||
throw new NullReferenceException("representation producer is not initialized");
|
|
||||||
|
|
||||||
if (!_callIndexProvider.Activators.TryGetValue(typeof(T), out var remoteType))
|
if (!_callIndexProvider.Activators.TryGetValue(typeof(T), out var remoteType))
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
@@ -44,7 +44,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)!;
|
||||||
}
|
}
|
||||||
@@ -56,8 +56,9 @@ namespace mROA.Implementation
|
|||||||
|
|
||||||
public object GetSingletonObject(Type type, IEndPointContext context)
|
public object GetSingletonObject(Type type, IEndPointContext context)
|
||||||
{
|
{
|
||||||
if (_representationProducer == null)
|
var existing = _producedSingletonProxies.Find(i => i.GetType() == type);
|
||||||
throw new NullReferenceException("representation producer is not initialized");
|
if (existing is not null)
|
||||||
|
return existing;
|
||||||
|
|
||||||
var representationModule =
|
var representationModule =
|
||||||
_representationProducer.Produce(context.OwnerId);
|
_representationProducer.Produce(context.OwnerId);
|
||||||
@@ -65,11 +66,10 @@ namespace mROA.Implementation
|
|||||||
var instance = _callIndexProvider.Activators[type](-1, representationModule, context,
|
var instance = _callIndexProvider.Activators[type](-1, representationModule, context,
|
||||||
_callIndexProvider.GetIndices(type))!;
|
_callIndexProvider.GetIndices(type))!;
|
||||||
|
|
||||||
var remoteObjectBase = instance;
|
_producedProxies.Add(instance);
|
||||||
|
_producedSingletonProxies.Add(instance);
|
||||||
|
|
||||||
_producedProxys.Add(remoteObjectBase);
|
return _producedProxies.Last();
|
||||||
|
|
||||||
return _producedProxys.Last();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetObjectIndex<T>(object o, IEndPointContext context)
|
public int GetObjectIndex<T>(object o, IEndPointContext context)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Threading.Tasks;
|
|||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
using mROA.Implementation.CommandExecution;
|
using mROA.Implementation.CommandExecution;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace mROA.Implementation
|
namespace mROA.Implementation
|
||||||
{
|
{
|
||||||
@@ -21,8 +20,7 @@ namespace mROA.Implementation
|
|||||||
{
|
{
|
||||||
if (obj is null) return false;
|
if (obj is null) return false;
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
if (obj.GetType() != GetType()) return false;
|
return obj.GetType() == GetType() && Equals((RemoteObjectBase)obj);
|
||||||
return Equals((RemoteObjectBase)obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
@@ -57,9 +55,9 @@ namespace mROA.Implementation
|
|||||||
protected async Task<T> GetResultAsync<T>(int methodId, object?[]? parameters = null,
|
protected async Task<T> GetResultAsync<T>(int methodId, object?[]? parameters = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var request = new DefaultCallRequest
|
var request = new CallRequest
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
Id = RequestId.Generate(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
||||||
};
|
};
|
||||||
|
|
||||||
await _representationModule.PostCallMessageAsync(request.Id, EMessageType.CallRequest, request, _context);
|
await _representationModule.PostCallMessageAsync(request.Id, EMessageType.CallRequest, request, _context);
|
||||||
@@ -102,9 +100,9 @@ namespace mROA.Implementation
|
|||||||
protected async Task CallAsync(int methodId, object?[]? parameters = null,
|
protected async Task CallAsync(int methodId, object?[]? parameters = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var request = new DefaultCallRequest
|
var request = new CallRequest
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
Id = RequestId.Generate(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
||||||
};
|
};
|
||||||
await _representationModule.PostCallMessageAsync(request.Id, EMessageType.CallRequest, request, _context);
|
await _representationModule.PostCallMessageAsync(request.Id, EMessageType.CallRequest, request, _context);
|
||||||
|
|
||||||
@@ -142,14 +140,16 @@ namespace mROA.Implementation
|
|||||||
return;
|
return;
|
||||||
case EMessageType.ExceptionCommandExecution:
|
case EMessageType.ExceptionCommandExecution:
|
||||||
throw (responseRequest.Deserialized as ExceptionCommandExecution)!.GetException();
|
throw (responseRequest.Deserialized as ExceptionCommandExecution)!.GetException();
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task CallUntrustedAsync(int methodId, object?[]? parameters = null)
|
protected async Task CallUntrustedAsync(int methodId, object?[]? parameters = null)
|
||||||
{
|
{
|
||||||
var request = new DefaultCallRequest
|
var request = new CallRequest
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
Id = RequestId.Generate(), CommandId = methodId, ObjectId = _identifier, Parameters = parameters
|
||||||
};
|
};
|
||||||
await _representationModule.PostCallMessageUntrustedAsync(request.Id, EMessageType.CallRequest, request,
|
await _representationModule.PostCallMessageUntrustedAsync(request.Id, EMessageType.CallRequest, request,
|
||||||
_context);
|
_context);
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using mROA.Abstract;
|
using mROA.Abstract;
|
||||||
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
|
||||||
|
|
||||||
namespace mROA.Implementation
|
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)
|
||||||
{
|
{
|
||||||
_interaction = interaction;
|
_interaction = interaction;
|
||||||
_serialization = serialization;
|
_serialization = serialization;
|
||||||
@@ -28,13 +28,12 @@ namespace mROA.Implementation
|
|||||||
public IEndPointContext Context => _interaction.Context;
|
public IEndPointContext Context => _interaction.Context;
|
||||||
|
|
||||||
public async Task<(object? Deserialized, EMessageType MessageType)> GetSingle(
|
public async Task<(object? Deserialized, EMessageType MessageType)> GetSingle(
|
||||||
Predicate<NetworkMessageHeader> rule, IEndPointContext? context,
|
Predicate<NetworkMessage> rule, IEndPointContext? context,
|
||||||
CancellationToken token = default, params Func<NetworkMessageHeader, Type?>[] converter)
|
CancellationToken token = default, params Func<NetworkMessage, Type?>[] converter)
|
||||||
{
|
{
|
||||||
var writer = _interaction.ReceiveChanel.Writer;
|
var writer = _interaction.ReceiveChanel.Writer;
|
||||||
var reader = _interaction.ReceiveChanel.Reader;
|
var reader = _interaction.ReceiveChanel.Reader;
|
||||||
|
|
||||||
|
|
||||||
await foreach (var message in reader.ReadAllAsync(token))
|
await foreach (var message in reader.ReadAllAsync(token))
|
||||||
{
|
{
|
||||||
if (!rule(message))
|
if (!rule(message))
|
||||||
@@ -52,11 +51,11 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(
|
public async IAsyncEnumerable<(object parced, EMessageType originalType)> GetStream(
|
||||||
Predicate<NetworkMessageHeader> rule, IEndPointContext? context,
|
Predicate<NetworkMessage> rule, IEndPointContext? context,
|
||||||
[EnumeratorCancellation] CancellationToken token = default,
|
[EnumeratorCancellation] CancellationToken token = default,
|
||||||
params Func<NetworkMessageHeader, Type?>[] converter)
|
params Func<NetworkMessage, Type?>[] converter)
|
||||||
{
|
{
|
||||||
var writer = _interaction?.ReceiveChanel.Writer;
|
var writer = _interaction.ReceiveChanel.Writer;
|
||||||
await foreach (var message in _interaction.ReceiveChanel.Reader.ReadAllAsync(token))
|
await foreach (var message in _interaction.ReceiveChanel.Reader.ReadAllAsync(token))
|
||||||
{
|
{
|
||||||
if (!rule(message))
|
if (!rule(message))
|
||||||
@@ -66,7 +65,7 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < converter.Length; i++)
|
for (var i = 0; i < converter.Length; i++)
|
||||||
{
|
{
|
||||||
var func = converter[i];
|
var func = converter[i];
|
||||||
if (func(message) is { } t)
|
if (func(message) is { } t)
|
||||||
@@ -79,30 +78,25 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PostCallMessageAsync<T>(Guid id, EMessageType eMessageType, T payload,
|
public async Task PostCallMessageAsync<T>(RequestId id, EMessageType eMessageType, T payload,
|
||||||
IEndPointContext? context) where T : notnull
|
IEndPointContext? context) where T : notnull
|
||||||
{
|
{
|
||||||
if (_interaction == null)
|
|
||||||
throw new NullReferenceException("Interaction toolkit is not initialized");
|
|
||||||
if (_serialization == null)
|
|
||||||
throw new NullReferenceException("Serialization toolkit is not initialized");
|
|
||||||
|
|
||||||
var serialized = _serialization.Serialize(payload, context);
|
var serialized = _serialization.Serialize(payload, context);
|
||||||
await _interaction.PostMessageAsync(new NetworkMessageHeader
|
await _interaction.PostMessageAsync(new NetworkMessage
|
||||||
{ Id = id, MessageType = eMessageType, Data = serialized });
|
{ Id = id, MessageType = eMessageType, Data = serialized });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostCallMessage<T>(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
public void PostCallMessage<T>(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context)
|
||||||
where T : notnull
|
where T : notnull
|
||||||
{
|
{
|
||||||
PostCallMessageAsync(id, eMessageType, payload, context).GetAwaiter().GetResult();
|
PostCallMessageAsync(id, eMessageType, payload, context).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task PostCallMessageUntrustedAsync<T>(Guid id, EMessageType eMessageType, T payload,
|
public async Task PostCallMessageUntrustedAsync<T>(RequestId id, EMessageType eMessageType, T payload,
|
||||||
IEndPointContext? context) where T : notnull
|
IEndPointContext? context) where T : notnull
|
||||||
{
|
{
|
||||||
var serialized = _serialization.Serialize(payload, context);
|
var serialized = _serialization.Serialize(payload, context);
|
||||||
await _interaction.PostMessageUntrustedAsync(new NetworkMessageHeader
|
await _interaction.PostMessageUntrustedAsync(new NetworkMessage
|
||||||
{ Id = id, MessageType = eMessageType, Data = serialized });
|
{ Id = id, MessageType = eMessageType, Data = serialized });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user