Files
mROA/mROA/Implementation/Frontend/NetworkFrontendBridge.cs
T

116 lines
4.0 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
2025-05-02 12:08:31 +03:00
using System.Threading;
using System.Threading.Channels;
2025-04-06 20:51:12 +03:00
using System.Threading.Tasks;
using mROA.Abstract;
using Exception = System.Exception;
namespace mROA.Implementation.Frontend
{
public class NetworkFrontendBridge : IFrontendBridge
{
2025-04-06 21:20:18 +03:00
private readonly IPEndPoint _serverEndPoint;
private TcpClient _tcpClient = new();
2025-04-30 12:25:23 +03:00
private IChannelInteractionModule? _interactionModule;
private ISerializationToolkit? _serialization;
2025-05-02 12:08:31 +03:00
private StreamExtractor _currentExtractor;
private CancellationTokenSource _rawExtractorCancellation;
2025-04-06 21:20:18 +03:00
public NetworkFrontendBridge(IPEndPoint serverEndPoint)
{
2025-04-06 21:20:18 +03:00
_serverEndPoint = serverEndPoint;
2025-05-02 12:08:31 +03:00
_rawExtractorCancellation = new CancellationTokenSource();
}
public void Inject<T>(T dependency)
{
switch (dependency)
{
2025-04-30 12:25:23 +03:00
case ChannelInteractionModule interactionModule:
_interactionModule = interactionModule;
break;
case ISerializationToolkit toolkit:
_serialization = toolkit;
break;
}
}
public void Connect()
{
if (_interactionModule is null)
throw new Exception("Interaction module was not injected");
if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized");
2025-03-13 20:01:17 +03:00
2025-04-06 21:20:18 +03:00
_tcpClient.Connect(_serverEndPoint);
2025-04-06 20:51:12 +03:00
2025-05-02 12:08:31 +03:00
PrepareExtractor();
_interactionModule.IsConnected = () => _currentExtractor.IsConnected;
_interactionModule.OnDisconnected += id => { Reconnect(); };
_interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientConnect())).Wait();
2025-05-02 12:08:31 +03:00
_currentExtractor.SingleReceive();
var idMessage = _interactionModule.GetNextMessageReceiving(false).GetAwaiter().GetResult();
2025-05-02 12:08:31 +03:00
if (idMessage.MessageType != EMessageType.IdAssigning)
{
2025-03-13 20:01:17 +03:00
throw new Exception(
$"Incorrect message type. Must be IdAssigning, current : {idMessage.MessageType.ToString()}");
}
2025-04-06 20:51:12 +03:00
2025-05-02 12:08:31 +03:00
var stopToken = _rawExtractorCancellation.Token;
Task.Run(async () => await _currentExtractor.LoopedReceive(stopToken));
var assignment = _serialization.Deserialize<IdAssignment>(idMessage.Data)!;
_interactionModule.ConnectionId = -assignment.Id;
2025-02-24 18:01:34 +03:00
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(assignment.Id);
}
2025-04-06 20:51:12 +03:00
2025-05-02 12:08:31 +03:00
private void PrepareExtractor()
{
_currentExtractor = new StreamExtractor(_tcpClient.GetStream(), _serialization);
_ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel,
_rawExtractorCancellation.Token);
_currentExtractor.MessageReceived += message => _interactionModule.ReceiveChanel.WriteAsync(message);
}
2025-04-06 21:20:18 +03:00
private async Task Reconnect()
2025-04-06 20:51:12 +03:00
{
2025-04-06 21:20:18 +03:00
_tcpClient = new TcpClient();
_tcpClient.Connect(_serverEndPoint);
2025-05-02 12:08:31 +03:00
_rawExtractorCancellation.Cancel();
_rawExtractorCancellation = new CancellationTokenSource();
PrepareExtractor();
_ = _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token);
await _interactionModule.Restart(true);
2025-04-06 20:51:12 +03:00
}
public void Obstacle()
{
2025-04-08 22:42:00 +03:00
_tcpClient.Dispose();
2025-04-06 20:51:12 +03:00
}
public void Disconnect()
{
_ = _interactionModule!.PostMessageAsync(new NetworkMessageHeader(_serialization!, new ClientDisconnect()));
2025-04-09 14:11:31 +03:00
_interactionModule.Dispose();
2025-04-06 20:51:12 +03:00
_tcpClient.Dispose();
}
public void Dispose()
{
Disconnect();
}
}
}