110 lines
4.0 KiB
C#
110 lines
4.0 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using mROA.Abstract;
|
|
using mROA.Implementation.Backend;
|
|
using Exception = System.Exception;
|
|
|
|
namespace mROA.Implementation.Frontend
|
|
{
|
|
public class NetworkFrontendBridge : IFrontendBridge
|
|
{
|
|
private readonly IPEndPoint _serverEndPoint;
|
|
private TcpClient _tcpClient = new();
|
|
private readonly IChannelInteractionModule _interactionModule;
|
|
private readonly ILogger _logger;
|
|
private readonly IContextualSerializationToolKit _serialization;
|
|
private ChannelInteractionModule.StreamExtractor? _currentExtractor;
|
|
private CancellationTokenSource _rawExtractorCancellation;
|
|
private readonly IEndPointContext _context;
|
|
|
|
public NetworkFrontendBridge(IOptions<GatewayOptions> options, IEndPointContext context, IContextualSerializationToolKit serialization, IChannelInteractionModule interactionModule, ILogger<ChannelInteractionModule.StreamExtractor> logger)
|
|
{
|
|
_serverEndPoint = options.Value.Endpoint;
|
|
_context = context;
|
|
_serialization = serialization;
|
|
_interactionModule = interactionModule;
|
|
_logger = logger;
|
|
_rawExtractorCancellation = new CancellationTokenSource();
|
|
}
|
|
|
|
public async Task Connect()
|
|
{
|
|
_tcpClient.Connect(_serverEndPoint);
|
|
_tcpClient.NoDelay = true;
|
|
PrepareExtractor();
|
|
_interactionModule.IsConnected = () => _currentExtractor.IsConnected;
|
|
_interactionModule.OnDisconnected += _ => { Reconnect(); };
|
|
|
|
_interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientConnect(), _context))
|
|
.Wait();
|
|
|
|
_currentExtractor.SingleReceive();
|
|
var idMessage = await _interactionModule.GetNextMessageReceiving(false);
|
|
|
|
if (idMessage.MessageType != EMessageType.IdAssigning)
|
|
{
|
|
throw new Exception(
|
|
$"Incorrect message type. Must be IdAssigning, current : {idMessage.MessageType.ToString()}");
|
|
}
|
|
|
|
|
|
Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
|
|
|
var assignment = _serialization.Deserialize<IdAssignment>(idMessage.Data, _context);
|
|
_interactionModule.ConnectionId = -assignment.Id;
|
|
_context.HostId = assignment.Id;
|
|
_context.OwnerId = assignment.Id;
|
|
}
|
|
|
|
private void PrepareExtractor()
|
|
{
|
|
_currentExtractor =
|
|
new ChannelInteractionModule.StreamExtractor(_tcpClient.GetStream(), _serialization, _context, _logger);
|
|
|
|
_ = _currentExtractor.SendFromChannel(_interactionModule.TrustedPostChanel,
|
|
_rawExtractorCancellation.Token);
|
|
_currentExtractor.MessageReceived = message =>
|
|
{
|
|
_interactionModule.ReceiveChanel.Writer.WriteAsync(message);
|
|
};
|
|
}
|
|
|
|
private async Task Reconnect()
|
|
{
|
|
_tcpClient = new TcpClient();
|
|
_tcpClient.Connect(_serverEndPoint);
|
|
|
|
_rawExtractorCancellation.Cancel();
|
|
_rawExtractorCancellation = new CancellationTokenSource();
|
|
|
|
PrepareExtractor();
|
|
|
|
Task.Run(async () => await _currentExtractor.LoopedReceive(_rawExtractorCancellation.Token));
|
|
|
|
await _interactionModule.Restart(true);
|
|
}
|
|
|
|
public void Obstacle()
|
|
{
|
|
_tcpClient.Dispose();
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
_ = _interactionModule.PostMessageAsync(new NetworkMessageHeader(_serialization, new ClientDisconnect(),
|
|
_context));
|
|
_interactionModule.Dispose();
|
|
_tcpClient.Dispose();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Disconnect();
|
|
}
|
|
}
|
|
} |