From bb3c4887df827501d50653c9b54700cc8b4c4666 Mon Sep 17 00:00:00 2001 From: Mitrofanov Mikhail Date: Sun, 27 Jul 2025 00:14:15 +0300 Subject: [PATCH] Works, but slow for many connections --- Example.Load/Program.cs | 98 ++++++++++--------- mROA.Cbor/CborSerializationToolkit.cs | 10 +- mROA.Cbor/IOrdinaryStructureParser.cs | 8 +- mROA.Codegen/RemoteTypeBinder.cstmpl | 2 +- mROA.Test/Identifier.cs | 24 +++++ mROA/Abstract/ICancellationRepository.cs | 7 +- mROA/Abstract/ICommandExecution.cs | 2 +- mROA/Abstract/IRepresentationModule.cs | 6 +- .../Backend/BasicExecutionModule.cs | 6 +- .../Backend/NetworkGatewayModule.cs | 4 +- mROA/Implementation/CallRequest.cs | 6 +- mROA/Implementation/CancellationRepository.cs | 8 +- .../ChannelInteractionModule.cs | 41 ++++---- .../CommandExecution/AsyncCommandExecution.cs | 2 +- .../ExceptionCommandExecution.cs | 2 +- .../CommandExecution/FinalCommandExecution.cs | 4 +- .../Frontend/NetworkFrontendBridge.cs | 4 +- .../Frontend/RemoteException.cs | 2 +- .../Frontend/UdpUntrustedInteraction.cs | 2 +- mROA/Implementation/NetworkMessage.cs | 25 ++--- mROA/Implementation/RemoteObjectBase.cs | 6 +- mROA/Implementation/RepresentationModule.cs | 6 +- mROA/Implementation/RequestContext.cs | 4 +- mROA/Implementation/RequestId.cs | 60 ++++++++++-- 24 files changed, 209 insertions(+), 130 deletions(-) diff --git a/Example.Load/Program.cs b/Example.Load/Program.cs index 295fb0f..160e454 100644 --- a/Example.Load/Program.cs +++ b/Example.Load/Program.cs @@ -35,65 +35,75 @@ File.AppendAllText("results.txt", $"[SINGLE CBOR WRITER ALLOC] {totalRequests}\r async Task> GetLoadEndpoints(int count) { - var loads = new List(); - for (int i = 0; i < count; i++) + try { - var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true }); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(provider => + var loads = new List(); + for (int i = 0; i < count; i++) { - var repo = new InstanceRepository(provider.GetService()); - repo.FillSingletons(typeof(Program).Assembly); - return repo; - }); + Console.WriteLine($"Initializing {i}"); + var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings { DisableDefaults = true }); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(provider => + { + var repo = new InstanceRepository(provider.GetService()); + repo.FillSingletons(typeof(Program).Assembly); + return repo; + }); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - // builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567); - builder.Services.AddSingleton(); - builder.Services.AddOptions(); - builder.Services.Configure(options => options.Endpoint = serverEndPoint); - builder.Services.AddSingleton(); - // builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + // builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 4567); + builder.Services.AddSingleton(); + builder.Services.AddOptions(); + builder.Services.Configure(options => options.Endpoint = serverEndPoint); + builder.Services.AddSingleton(); + // builder.Services.AddSingleton(); + builder.Services.AddSingleton(); - builder.Services.AddSingleton(p => - { - var methodRepo = new CollectableMethodRepository(); - methodRepo.AppendInvokers(new GeneratedInvokersCollection()); - return methodRepo; - }); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(p => + { + var methodRepo = new CollectableMethodRepository(); + methodRepo.AppendInvokers(new GeneratedInvokersCollection()); + return methodRepo; + }); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); - var app = builder.Build(); + var app = builder.Build(); - var frontendBridge = app.Services.GetService()!; - await frontendBridge.Connect(); - // _ = app.Services.GetService()!.StartExtraction(); - // _ = app.Services.GetService().Start(serverEndPoint); - var context = app.Services.GetService(); + Console.WriteLine($"Connecting {i}"); + var frontendBridge = app.Services.GetService()!; + await frontendBridge.Connect(); + // _ = app.Services.GetService()!.StartExtraction(); + // _ = app.Services.GetService().Start(serverEndPoint); + var context = app.Services.GetService(); + Console.WriteLine($"Connected {i}"); + var singletonObject = + context.GetSingletonObject( + app.Services.GetService()); + loads.Add(singletonObject); + } - var singletonObject = - context.GetSingletonObject( - app.Services.GetService()); - loads.Add(singletonObject); + return loads; + } + catch (Exception e) + { + Console.WriteLine(e); + throw; } - return loads; } async Task Requests(CancellationToken token, int id, ILoadTest load) { try { - - int count = 0; - while (true){ + while (true) + { if (token.IsCancellationRequested) { break; @@ -101,7 +111,7 @@ async Task Requests(CancellationToken token, int id, ILoadTest load) await load.Next(2); count++; - } + } Console.WriteLine(id); return count; diff --git a/mROA.Cbor/CborSerializationToolkit.cs b/mROA.Cbor/CborSerializationToolkit.cs index f50fe7c..0506e65 100644 --- a/mROA.Cbor/CborSerializationToolkit.cs +++ b/mROA.Cbor/CborSerializationToolkit.cs @@ -116,9 +116,9 @@ namespace mROA.Cbor return preParsed.ToObject(type, context); - if (type == typeof(Guid)) + if (type == typeof(RequestId)) { - return new Guid((byte[])nonCasted); + return new RequestId((byte[])nonCasted); } return Convert.ChangeType(nonCasted, type); @@ -164,7 +164,7 @@ namespace mROA.Cbor case DateTimeOffset dto: writer.WriteDateTimeOffset(dto); break; - case Guid g: + case RequestId g: writer.WriteByteString(g.ToByteArray()); break; case byte[] bytes: @@ -270,8 +270,8 @@ namespace mROA.Cbor return reader.ReadUInt64(); case CborReaderState.ByteString: - if (type == typeof(Guid)) - return new Guid(reader.ReadByteString()); + if (type == typeof(RequestId)) + return new RequestId(reader.ReadByteString()); return reader.ReadByteString(); case CborReaderState.TextString: return reader.ReadTextString(); diff --git a/mROA.Cbor/IOrdinaryStructureParser.cs b/mROA.Cbor/IOrdinaryStructureParser.cs index 2d3711a..10ff38d 100644 --- a/mROA.Cbor/IOrdinaryStructureParser.cs +++ b/mROA.Cbor/IOrdinaryStructureParser.cs @@ -29,7 +29,7 @@ namespace mROA.Cbor reader.ReadStartArray(); var value = new NetworkMessage { - Id = new Guid(reader.ReadByteString()), + Id = new RequestId(reader.ReadByteString()), MessageType = (EMessageType)reader.ReadInt32(), Data = reader.ReadByteString() }; @@ -57,7 +57,7 @@ namespace mROA.Cbor reader.ReadStartArray(); var value = new DefaultCallRequest { - Id = new Guid(reader.ReadByteString()), + Id = new RequestId(reader.ReadByteString()), CommandId = reader.ReadInt32(), ObjectId = (ComplexObjectIdentifier)ComplexObjectIdentifierParser.Instance.Read(reader, context, serialization), Parameters = serialization.ReadData(reader, typeof(object[]), context) as object[] @@ -102,7 +102,7 @@ namespace mROA.Cbor reader.ReadStartArray(); var result = new FinalCommandExecution { - Id = new Guid(reader.ReadByteString()), + Id = new RequestId(reader.ReadByteString()), Result = serialization.ReadData(reader, typeof(object), context), }; reader.ReadEndArray(); @@ -125,7 +125,7 @@ namespace mROA.Cbor reader.ReadStartArray(); var result = new FinalCommandExecution { - Id = new Guid(reader.ReadByteString()) + Id = new RequestId(reader.ReadByteString()) }; reader.ReadEndArray(); return result; diff --git a/mROA.Codegen/RemoteTypeBinder.cstmpl b/mROA.Codegen/RemoteTypeBinder.cstmpl index 8735464..78df6c3 100644 --- a/mROA.Codegen/RemoteTypeBinder.cstmpl +++ b/mROA.Codegen/RemoteTypeBinder.cstmpl @@ -31,7 +31,7 @@ namespace mROA.Codegen Console.WriteLine("Sending event..."); var request = new DefaultCallRequest { - Id = Guid.NewGuid(), + Id = RequestId.Generate(), CommandId = , ObjectId = new ComplexObjectIdentifier(index, ownerId), Parameters = new object[] { } diff --git a/mROA.Test/Identifier.cs b/mROA.Test/Identifier.cs index 6b929bc..333ca33 100644 --- a/mROA.Test/Identifier.cs +++ b/mROA.Test/Identifier.cs @@ -20,4 +20,28 @@ public class Identifier 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)); + } } \ No newline at end of file diff --git a/mROA/Abstract/ICancellationRepository.cs b/mROA/Abstract/ICancellationRepository.cs index 22189cb..502d1ea 100644 --- a/mROA/Abstract/ICancellationRepository.cs +++ b/mROA/Abstract/ICancellationRepository.cs @@ -1,12 +1,13 @@ using System; using System.Threading; +using mROA.Implementation; namespace mROA.Abstract { public interface ICancellationRepository { - void RegisterCancellation(Guid id, CancellationTokenSource cts); - CancellationTokenSource? GetCancellation(Guid id); - void FreeCancelation(Guid id); + void RegisterCancellation(RequestId id, CancellationTokenSource cts); + CancellationTokenSource? GetCancellation(RequestId id); + void FreeCancellation(RequestId id); } } \ No newline at end of file diff --git a/mROA/Abstract/ICommandExecution.cs b/mROA/Abstract/ICommandExecution.cs index e546c68..cf4ec0b 100644 --- a/mROA/Abstract/ICommandExecution.cs +++ b/mROA/Abstract/ICommandExecution.cs @@ -5,6 +5,6 @@ namespace mROA.Abstract { public interface ICommandExecution : INetworkMessage { - Guid Id { get; set; } + RequestId Id { get; set; } } } \ No newline at end of file diff --git a/mROA/Abstract/IRepresentationModule.cs b/mROA/Abstract/IRepresentationModule.cs index 45d44d3..3446380 100644 --- a/mROA/Abstract/IRepresentationModule.cs +++ b/mROA/Abstract/IRepresentationModule.cs @@ -19,13 +19,13 @@ namespace mROA.Abstract IEndPointContext? context, CancellationToken token = default, params Func[] converter); - Task PostCallMessageAsync(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context) + Task PostCallMessageAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull; - void PostCallMessage(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context) + void PostCallMessage(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull; - Task PostCallMessageUntrustedAsync(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context) + Task PostCallMessageUntrustedAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull; } } \ No newline at end of file diff --git a/mROA/Implementation/Backend/BasicExecutionModule.cs b/mROA/Implementation/Backend/BasicExecutionModule.cs index 91c5a1d..d72ec7c 100644 --- a/mROA/Implementation/Backend/BasicExecutionModule.cs +++ b/mROA/Implementation/Backend/BasicExecutionModule.cs @@ -114,7 +114,7 @@ namespace mROA.Implementation.Backend if (cts == null) throw new NullReferenceException("Can't find cancellation for this request"); cts.Cancel(); - _cancellationRepo.FreeCancelation(command.Id); + _cancellationRepo.FreeCancellation(command.Id); return new FinalCommandExecution { @@ -164,7 +164,7 @@ namespace mROA.Implementation.Backend { Id = command.Id }; - _cancellationRepo.FreeCancelation(command.Id); + _cancellationRepo.FreeCancellation(command.Id); if (invoker.IsTrusted) @@ -195,7 +195,7 @@ namespace mROA.Implementation.Backend Id = command.Id, Result = finalResult }; - _cancellationRepo.FreeCancelation(command.Id); + _cancellationRepo.FreeCancellation(command.Id); representationModule.PostCallMessage(command.Id, EMessageType.FinishedCommandExecution, payload, context); diff --git a/mROA/Implementation/Backend/NetworkGatewayModule.cs b/mROA/Implementation/Backend/NetworkGatewayModule.cs index 6d4bdfb..e569185 100644 --- a/mROA/Implementation/Backend/NetworkGatewayModule.cs +++ b/mROA/Implementation/Backend/NetworkGatewayModule.cs @@ -56,7 +56,7 @@ namespace mROA.Implementation.Backend while (true) { var client = await _tcpListener.AcceptTcpClientAsync(); - _ = HandleConnection(client).ConfigureAwait(false); + _ = HandleConnection(client); } } @@ -70,7 +70,7 @@ namespace mROA.Implementation.Backend CallIndexProvider = _callIndexProvider }; var streamExtractor = - new ChannelInteractionModule.StreamExtractor(client.GetStream(), _serialization, context); + new ChannelInteractionModule.StreamExtractor(client.GetStream()); interaction.IsConnected = () => streamExtractor.IsConnected; streamExtractor.MessageReceived = async message => { diff --git a/mROA/Implementation/CallRequest.cs b/mROA/Implementation/CallRequest.cs index cf4834b..fcf9131 100644 --- a/mROA/Implementation/CallRequest.cs +++ b/mROA/Implementation/CallRequest.cs @@ -4,7 +4,7 @@ namespace mROA.Implementation { public interface ICallRequest { - Guid Id { get; } + RequestId Id { get; } int CommandId { get; } ComplexObjectIdentifier ObjectId { get; } object?[]? Parameters { get; } @@ -12,7 +12,7 @@ namespace mROA.Implementation public struct DefaultCallRequest : ICallRequest { - public Guid Id { get; set; } + public RequestId Id { get; set; } public int CommandId { get; set; } public ComplexObjectIdentifier ObjectId { get; set; } @@ -26,7 +26,7 @@ namespace mROA.Implementation public class CancelRequest : ICallRequest { - 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; diff --git a/mROA/Implementation/CancellationRepository.cs b/mROA/Implementation/CancellationRepository.cs index 92db694..9b6be1b 100644 --- a/mROA/Implementation/CancellationRepository.cs +++ b/mROA/Implementation/CancellationRepository.cs @@ -8,19 +8,19 @@ namespace mROA.Implementation { public class CancellationRepository : ICancellationRepository { - private readonly ConcurrentDictionary _cancellations = new(); + private readonly ConcurrentDictionary _cancellations = new(); - public void RegisterCancellation(Guid id, CancellationTokenSource cts) + public void RegisterCancellation(RequestId id, CancellationTokenSource cts) { _cancellations.TryAdd(id, cts); } - public CancellationTokenSource? GetCancellation(Guid id) + public CancellationTokenSource? GetCancellation(RequestId id) { return _cancellations.GetValueOrDefault(id); } - public void FreeCancelation(Guid id) + public void FreeCancellation(RequestId id) { _cancellations.Remove(id, out _); } diff --git a/mROA/Implementation/ChannelInteractionModule.cs b/mROA/Implementation/ChannelInteractionModule.cs index d084ad4..63b4778 100644 --- a/mROA/Implementation/ChannelInteractionModule.cs +++ b/mROA/Implementation/ChannelInteractionModule.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; @@ -141,39 +142,34 @@ namespace mROA.Implementation public class StreamExtractor { - private const int BufferSize = ushort.MaxValue + 2; + private const int BufferSize = ushort.MaxValue + 19; private readonly Stream _ioStream; - private readonly IContextualSerializationToolKit _serializationToolkit; private readonly Memory _buffer = new byte[BufferSize]; - private readonly IEndPointContext _context; - private readonly byte[] _lenBuffer; - public StreamExtractor(Stream ioStream, IContextualSerializationToolKit serializationToolkit, - IEndPointContext context) + public StreamExtractor(Stream ioStream) { _ioStream = ioStream; - _serializationToolkit = serializationToolkit; - _context = context; - _lenBuffer = new byte[2]; } public Action MessageReceived = _ => { }; public async Task SingleReceive(CancellationToken token = default) { - int firstRead = _ioStream.Read(_buffer.Span); - - var metadata = new NetworkMessage.NetworkMessageMeta(_buffer.Span); + var firstRead = _ioStream.Read(_buffer.Span); - var localSpan = _buffer[2..len]; - if (firstRead - 2 != len) + var meta = MemoryMarshal.Read(_buffer.Span); + + var len = meta.BodyLength; + var readLen = firstRead - 19; + + if (readLen != len) { - localSpan = _buffer[(len + 2)..]; - await _ioStream.ReadExactlyAsync(localSpan, cancellationToken: token); + var lastPart = _buffer[firstRead..(len + 19)]; + await _ioStream.ReadExactlyAsync(lastPart, cancellationToken: token); } - - var message = _serializationToolkit.Deserialize(localSpan, _context); + + var message = meta.ToMessage(_buffer.Span); MessageReceived(message); } @@ -187,11 +183,10 @@ namespace mROA.Implementation private async Task Send(NetworkMessage message, CancellationToken token = default) { - var bodySpan = _buffer[2..]; - var len = _serializationToolkit.Serialize(message, bodySpan.Span, _context); - var header = BitConverter.GetBytes((ushort)len); - header.CopyTo(_buffer); - var sendingSpan = _buffer[..(len + 2)]; + var meta = message.ToMeta(); + MemoryMarshal.Write(_buffer.Span, ref meta); + message.Data.CopyTo(_buffer.Span[19..]); + var sendingSpan = _buffer[..(19 + meta.BodyLength)]; await _ioStream.WriteAsync(sendingSpan, token); // _logger.LogTrace("SEND {0}", message.ToString()); } diff --git a/mROA/Implementation/CommandExecution/AsyncCommandExecution.cs b/mROA/Implementation/CommandExecution/AsyncCommandExecution.cs index deb3299..768668a 100644 --- a/mROA/Implementation/CommandExecution/AsyncCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/AsyncCommandExecution.cs @@ -5,7 +5,7 @@ namespace mROA.Implementation.CommandExecution { public class AsyncCommandExecution : ICommandExecution { - public Guid Id { get; set; } + public RequestId Id { get; set; } public EMessageType MessageType => EMessageType.Unknown; } } \ No newline at end of file diff --git a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs index 3199141..29d9144 100644 --- a/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/ExceptionCommandExecution.cs @@ -6,7 +6,7 @@ namespace mROA.Implementation.CommandExecution { public class ExceptionCommandExecution : ICommandExecution { - public Guid Id { get; set; } + public RequestId Id { get; set; } public EMessageType MessageType => EMessageType.ExceptionCommandExecution; public string Exception { get; set; } diff --git a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs index 5911109..cef5580 100644 --- a/mROA/Implementation/CommandExecution/FinalCommandExecution.cs +++ b/mROA/Implementation/CommandExecution/FinalCommandExecution.cs @@ -5,13 +5,13 @@ namespace mROA.Implementation.CommandExecution { public struct FinalCommandExecution : ICommandExecution { - public Guid Id { get; set; } + public RequestId Id { get; set; } public EMessageType MessageType => EMessageType.FinishedCommandExecution; } public struct FinalCommandExecution : ICommandExecution { - public Guid Id { get; set; } + public RequestId Id { get; set; } public EMessageType MessageType => EMessageType.FinishedCommandExecution; public T? Result { get; set; } } diff --git a/mROA/Implementation/Frontend/NetworkFrontendBridge.cs b/mROA/Implementation/Frontend/NetworkFrontendBridge.cs index cfd7f4a..5a8572b 100644 --- a/mROA/Implementation/Frontend/NetworkFrontendBridge.cs +++ b/mROA/Implementation/Frontend/NetworkFrontendBridge.cs @@ -28,7 +28,7 @@ namespace mROA.Implementation.Frontend _serialization = serialization; _interactionModule = interactionModule; _rawExtractorCancellation = new CancellationTokenSource(); - _currentExtractor = new ChannelInteractionModule.StreamExtractor(Stream.Null, _serialization, context); + _currentExtractor = new ChannelInteractionModule.StreamExtractor(Stream.Null); } public async Task Connect() @@ -63,7 +63,7 @@ namespace mROA.Implementation.Frontend private void PrepareExtractor() { _currentExtractor = - new ChannelInteractionModule.StreamExtractor(_tcpClient.GetStream(), _serialization, _context); + new ChannelInteractionModule.StreamExtractor(_tcpClient.GetStream()); _ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel, _rawExtractorCancellation.Token); diff --git a/mROA/Implementation/Frontend/RemoteException.cs b/mROA/Implementation/Frontend/RemoteException.cs index e63e8b3..873c836 100644 --- a/mROA/Implementation/Frontend/RemoteException.cs +++ b/mROA/Implementation/Frontend/RemoteException.cs @@ -4,7 +4,7 @@ namespace mROA.Implementation.Frontend { public class RemoteException : Exception { - public Guid CallRequestId; + public RequestId CallRequestId; private readonly string _error; public RemoteException(string error) diff --git a/mROA/Implementation/Frontend/UdpUntrustedInteraction.cs b/mROA/Implementation/Frontend/UdpUntrustedInteraction.cs index 13a6bce..c3a63ff 100644 --- a/mROA/Implementation/Frontend/UdpUntrustedInteraction.cs +++ b/mROA/Implementation/Frontend/UdpUntrustedInteraction.cs @@ -54,7 +54,7 @@ namespace mROA.Implementation.Frontend { var initMessage = new NetworkMessage { - MessageType = EMessageType.UntrustedConnect, Id = Guid.NewGuid(), + MessageType = EMessageType.UntrustedConnect, Id = RequestId.Generate(), Data = BitConverter.GetBytes(_channelInteractionModule.ConnectionId) }; diff --git a/mROA/Implementation/NetworkMessage.cs b/mROA/Implementation/NetworkMessage.cs index 6053b3e..3a7e5ed 100644 --- a/mROA/Implementation/NetworkMessage.cs +++ b/mROA/Implementation/NetworkMessage.cs @@ -27,10 +27,10 @@ namespace mROA.Implementation { MessageType = networkMessage.MessageType; Data = serializationToolkit.Serialize(networkMessage, context); - Id = Guid.NewGuid(); + Id = RequestId.Generate(); } - public Guid Id { get; set; } + public RequestId Id { get; set; } public EMessageType MessageType { get; set; } @@ -40,19 +40,22 @@ namespace mROA.Implementation { 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 byte Type; - public Guid Id; + public RequestId Id; public ushort BodyLength; - - public NetworkMessageMeta(ReadOnlySpan metadata) - { - Type = metadata[0]; - Id = new Guid(metadata[1..17]); - BodyLength = BitConverter.ToUInt16(metadata[17..]); - } + public byte Type; public NetworkMessage ToMessage(ReadOnlySpan memory) { diff --git a/mROA/Implementation/RemoteObjectBase.cs b/mROA/Implementation/RemoteObjectBase.cs index bc70cf1..9968aea 100644 --- a/mROA/Implementation/RemoteObjectBase.cs +++ b/mROA/Implementation/RemoteObjectBase.cs @@ -57,7 +57,7 @@ namespace mROA.Implementation { var request = new DefaultCallRequest { - 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); @@ -102,7 +102,7 @@ namespace mROA.Implementation { var request = new DefaultCallRequest { - 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); @@ -149,7 +149,7 @@ namespace mROA.Implementation { var request = new DefaultCallRequest { - 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, _context); diff --git a/mROA/Implementation/RepresentationModule.cs b/mROA/Implementation/RepresentationModule.cs index 586cb7e..3452277 100644 --- a/mROA/Implementation/RepresentationModule.cs +++ b/mROA/Implementation/RepresentationModule.cs @@ -79,7 +79,7 @@ namespace mROA.Implementation } } - public async Task PostCallMessageAsync(Guid id, EMessageType eMessageType, T payload, + public async Task PostCallMessageAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull { var serialized = _serialization.Serialize(payload, context); @@ -87,13 +87,13 @@ namespace mROA.Implementation { Id = id, MessageType = eMessageType, Data = serialized }); } - public void PostCallMessage(Guid id, EMessageType eMessageType, T payload, IEndPointContext? context) + public void PostCallMessage(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull { PostCallMessageAsync(id, eMessageType, payload, context).GetAwaiter().GetResult(); } - public async Task PostCallMessageUntrustedAsync(Guid id, EMessageType eMessageType, T payload, + public async Task PostCallMessageUntrustedAsync(RequestId id, EMessageType eMessageType, T payload, IEndPointContext? context) where T : notnull { var serialized = _serialization.Serialize(payload, context); diff --git a/mROA/Implementation/RequestContext.cs b/mROA/Implementation/RequestContext.cs index 81db0d6..8ac4cae 100644 --- a/mROA/Implementation/RequestContext.cs +++ b/mROA/Implementation/RequestContext.cs @@ -5,9 +5,9 @@ namespace mROA.Implementation public struct RequestContext { public int OwnerId { get; } - public Guid RequestId { get; } + public RequestId RequestId { get; } - public RequestContext(Guid requestId, int ownerId) + public RequestContext(RequestId requestId, int ownerId) { RequestId = requestId; OwnerId = ownerId; diff --git a/mROA/Implementation/RequestId.cs b/mROA/Implementation/RequestId.cs index e4b49f7..3f19867 100644 --- a/mROA/Implementation/RequestId.cs +++ b/mROA/Implementation/RequestId.cs @@ -1,18 +1,64 @@ using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace mROA.Implementation { - public struct RequestId + public struct RequestId : IEquatable { + private static Random _random = new(); + public ulong P0; public ulong P1; - public RequestId Generate() + + public static RequestId Generate() { - var guid = Guid.NewGuid(); - var bytes = guid.ToByteArray(); - var high = BitConverter.ToUInt64(bytes, 0); - var low = BitConverter.ToUInt64(bytes, 8); - return new RequestId{ P0 = high, P1 = low}; + var high = (ulong)(ushort)_random.Next() << 32 | (ulong)_random.Next(); + var low = (ulong)(ushort)_random.Next() << 32 | (ulong)_random.Next(); + return new RequestId { P0 = high, P1 = low }; + } + + public RequestId(byte[] bytes) + { + P0 = BitConverter.ToUInt64(bytes); + P1 = BitConverter.ToUInt64(bytes, 8); + } + + public bool Equals(RequestId other) + { + return P0 == other.P0 && P1 == other.P1; + } + + public override bool Equals(object? obj) + { + return obj is RequestId other && Equals(other); + } + + public static bool operator ==(RequestId r1, RequestId r2) + { + return r1.Equals(r2); + } + + public static bool operator !=(RequestId r1, RequestId r2) + { + return !(r1 == r2); + } + + public override string ToString() + { + return $"{P0:X}{P1:X}"; + } + + public override int GetHashCode() + { + return HashCode.Combine(P0, P1); + } + + public byte[] ToByteArray() + { + var array = new byte[16]; + MemoryMarshal.Write(array, ref this); + return array; } } } \ No newline at end of file