114 lines
3.9 KiB
C#
114 lines
3.9 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.Threading.Channels;
|
|
using System.Threading.Tasks;
|
|
using mROA.Abstract;
|
|
using Exception = System.Exception;
|
|
|
|
namespace mROA.Implementation.Frontend
|
|
{
|
|
public class NetworkFrontendBridge : IFrontendBridge
|
|
{
|
|
private readonly IPEndPoint _serverEndPoint;
|
|
private TcpClient _tcpClient = new();
|
|
private IChannelInteractionModule? _interactionModule;
|
|
private ISerializationToolkit? _serialization;
|
|
private StreamExtractor _currentExtractor;
|
|
private CancellationTokenSource _rawExtractorCancellation;
|
|
|
|
public NetworkFrontendBridge(IPEndPoint serverEndPoint)
|
|
{
|
|
_serverEndPoint = serverEndPoint;
|
|
_rawExtractorCancellation = new CancellationTokenSource();
|
|
}
|
|
|
|
public void Inject<T>(T dependency)
|
|
{
|
|
switch (dependency)
|
|
{
|
|
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");
|
|
|
|
_tcpClient.Connect(_serverEndPoint);
|
|
|
|
PrepareExtractor();
|
|
_interactionModule.IsConnected = () => _currentExtractor.IsConnected;
|
|
_interactionModule.OnDisconnected += id => { Reconnect(); };
|
|
|
|
_interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientConnect())).Wait();
|
|
|
|
_currentExtractor.SingleReceive();
|
|
var idMessage = _interactionModule.GetNextMessageReceiving(false).GetAwaiter().GetResult();
|
|
|
|
if (idMessage.MessageType != EMessageType.IdAssigning)
|
|
{
|
|
throw new Exception(
|
|
$"Incorrect message type. Must be IdAssigning, current : {idMessage.MessageType.ToString()}");
|
|
}
|
|
|
|
|
|
var stopToken = _rawExtractorCancellation.Token;
|
|
Task.Run(async () => await _currentExtractor.LoopedReceive(stopToken));
|
|
|
|
var assignment = _serialization.Deserialize<IdAssignment>(idMessage.Data)!;
|
|
_interactionModule.ConnectionId = -assignment.Id;
|
|
TransmissionConfig.OwnershipRepository = new StaticOwnershipRepository(assignment.Id);
|
|
}
|
|
|
|
private void PrepareExtractor()
|
|
{
|
|
_currentExtractor = new StreamExtractor(_tcpClient.GetStream(), _serialization);
|
|
|
|
_ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel,
|
|
_rawExtractorCancellation.Token);
|
|
_currentExtractor.MessageReceived += message => _interactionModule.ReceiveChanel.WriteAsync(message);
|
|
}
|
|
|
|
private async Task Reconnect()
|
|
{
|
|
_tcpClient = new TcpClient();
|
|
_tcpClient.Connect(_serverEndPoint);
|
|
|
|
_rawExtractorCancellation.Cancel();
|
|
_rawExtractorCancellation = new CancellationTokenSource();
|
|
|
|
PrepareExtractor();
|
|
|
|
_ = _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token);
|
|
|
|
await _interactionModule.Restart(true);
|
|
}
|
|
|
|
public void Obstacle()
|
|
{
|
|
_tcpClient.Dispose();
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
_ = _interactionModule!.PostMessageAsync(new NetworkMessageHeader(_serialization!, new ClientDisconnect()));
|
|
_interactionModule.Dispose();
|
|
_tcpClient.Dispose();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Disconnect();
|
|
}
|
|
}
|
|
} |