From 24bd06b3d02cc64d957d8fd36c64ef43e41ab725 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Tue, 8 Apr 2025 13:08:29 +0300 Subject: [PATCH] Reconnection does not work now, but part of deep reconnection logic written --- Example.Frontend/Program.cs | 2 +- .../Backend/NetworkGatewayModule.cs | 7 +- .../NextGenerationInteractionModule.cs | 71 +++++++++++++++---- 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index ea7090d..8ecc3f4 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -58,7 +58,7 @@ class Program Console.WriteLine("Printer created"); Thread.Sleep(100); - // frontendBridge.Obstacle(); + frontendBridge.Obstacle(); var name = disposingPrinter.GetName(); DemoCheck.BasicNonParamsCall = true; Console.WriteLine("Printer name : {0}", name); diff --git a/mROA/Implementation/Backend/NetworkGatewayModule.cs b/mROA/Implementation/Backend/NetworkGatewayModule.cs index 6bb8cda..8e7106c 100644 --- a/mROA/Implementation/Backend/NetworkGatewayModule.cs +++ b/mROA/Implementation/Backend/NetworkGatewayModule.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using mROA.Abstract; +using static System.Byte; namespace mROA.Implementation.Backend { @@ -66,7 +67,7 @@ namespace mROA.Implementation.Backend while (true) { var client = _tcpListener.AcceptTcpClient(); - + Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}"); var interaction = Activator.CreateInstance(_interactionModuleType!) as INextGenerationInteractionModule; foreach (var injectableModule in _injectableModules!) @@ -75,7 +76,7 @@ namespace mROA.Implementation.Backend interaction!.Inject(_serialization); interaction.BaseStream = client.GetStream(); - + var connectionRequest = interaction.GetNextMessageReceiving().GetAwaiter().GetResult()!; switch (connectionRequest.MessageType) @@ -91,6 +92,8 @@ namespace mROA.Implementation.Backend var recoveryRequest = _serialization!.Deserialize(connectionRequest.Data)!; var recoveryInteraction = _hub.GetInteraction(recoveryRequest.Id); recoveryInteraction.BaseStream = client.GetStream(); + + recoveryInteraction.Restart(false); Console.WriteLine($"Client {recoveryRequest.Id} reconnected"); break; diff --git a/mROA/Implementation/NextGenerationInteractionModule.cs b/mROA/Implementation/NextGenerationInteractionModule.cs index 3e5d854..f3816c1 100644 --- a/mROA/Implementation/NextGenerationInteractionModule.cs +++ b/mROA/Implementation/NextGenerationInteractionModule.cs @@ -17,15 +17,13 @@ namespace mROA.Implementation private Task? _currentReceiving; private ISerializationToolkit? _serialization; private Stream? _baseStream; - private bool _isRecovering; - private event Action OnReconnected; - - private TaskCompletionSource _reconection; + private bool _isConnected = true; + private bool _isInReconnectionState; + private TaskCompletionSource _reconnection; public NextGenerationInteractionModule() { - _reconection = new TaskCompletionSource(); - _reconection.SetResult(Stream.Null); + _reconnection = new TaskCompletionSource(); } public int ConnectionId { get; set; } @@ -104,6 +102,8 @@ namespace mROA.Implementation if (await PostMessageInternal(messageHeader)) break; + _isConnected = false; + await MakeRecovery("OUT"); // Console.WriteLine("Try to get lock from post"); // lock (_reconection) // { @@ -159,8 +159,9 @@ namespace mROA.Implementation { return await Receive(); } - catch (Exception) + catch (Exception ex) { + await MakeRecovery("IN"); // Console.WriteLine("Try to get lock from receive"); // lock (_reconection) // { @@ -186,10 +187,18 @@ namespace mROA.Implementation private ushort ReadMessageLength() { - var firstBit = (byte)BaseStream.ReadByte(); + + var firstBit = BaseStream.ReadByte(); + if (firstBit == -1) + { + _isConnected = false; + throw new EndOfStreamException(); + } + + _isConnected = true; var secondBit = (byte)BaseStream.ReadByte(); - var len = BitConverter.ToUInt16(new[] { firstBit, secondBit }); + var len = BitConverter.ToUInt16(new[] { (byte)firstBit, secondBit }); return len; } @@ -216,12 +225,50 @@ namespace mROA.Implementation public async Task Restart(bool sendRecovery) { if (sendRecovery) + { await PostMessageAsync( new NetworkMessageHeader(_serialization!, new ClientRecovery(Math.Abs(ConnectionId)))); - _isRecovering = false; - _reconection.SetResult(BaseStream!); - _reconection = new TaskCompletionSource(); + + var confirmByte = BaseStream.ReadByte(); + Console.WriteLine("Reconnection byte {0}", confirmByte); + } + else + { + BaseStream.WriteByte(byte.MaxValue); + } + Console.WriteLine("Setting result for reconnection"); + _reconnection.SetResult(BaseStream!); + Console.WriteLine("Set result for reconnection successfull"); + + _reconnection = new TaskCompletionSource(); + } + + private async Task MakeRecovery(string source) + { + + Console.WriteLine("Staring recovery from {0}", source); + lock (_reconnection) + { + Console.WriteLine("Got lock from {0}", source); + if (_isConnected || _isInReconnectionState) + { + Console.WriteLine($"{_isConnected} {_isInReconnectionState} {!_baseStream.CanRead} {!_baseStream.CanWrite}"); + return; + } + + Console.WriteLine("Call OnDisconnected from {0}", source); + _isInReconnectionState = true; + OnDisconected?.Invoke(ConnectionId); + } + + Console.WriteLine("Waiting for reconnect from {0}", source); + await _reconnection.Task; + Console.WriteLine("Reconnect finished from {0}", source); + lock (_reconnection) + { + _isInReconnectionState = false; + } } } } \ No newline at end of file