using System.Net; using System.Text; using FinalFactory.Rendezvous.TestClient; using LiteNetLib; namespace FinalFactory.Rendezvous.Tests.TestClient; public sealed class DirectEchoProtocolTests { [Fact] public async Task HostReleasesPendingNonceWhenPeerDisconnectsBeforeAcknowledgement() { using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(3)); EventBasedNetListener hostEvents = new(); EventBasedNetListener clientEvents = new(); hostEvents.ConnectionRequestEvent += request => request.Accept(); NetPeer? clientPeer = null; clientEvents.PeerConnectedEvent += peer => clientPeer = peer; NetManager hostManager = new(hostEvents); NetManager clientManager = new(clientEvents); try { Assert.True(hostManager.Start(0)); Assert.True(clientManager.Start(0)); clientManager.Connect( new IPEndPoint(IPAddress.Loopback, hostManager.LocalPort), "echo-test"); await PumpUntilAsync( () => clientPeer is not null, hostManager, clientManager, clientManager, timeout.Token); using DirectEchoProtocol host = new(hostEvents, host: true); clientPeer!.Send( Encoding.ASCII.GetBytes("rv1-ping:00112233445566778899aabbccddeeff"), DeliveryMethod.ReliableOrdered); await PumpUntilAsync( () => host.PendingHostExchangeCount == 1, hostManager, clientManager, clientManager, timeout.Token); clientPeer.Disconnect(); await PumpUntilAsync( () => host.PendingHostExchangeCount == 0, hostManager, clientManager, clientManager, timeout.Token); Assert.Equal(0, host.PendingHostExchangeCount); } finally { clientManager.Stop(); hostManager.Stop(); } } [Fact] public async Task HostVerifiesOverlappingPeersAgainstTheirOwnNonces() { using CancellationTokenSource timeout = new(TimeSpan.FromSeconds(3)); EventBasedNetListener hostEvents = new(); EventBasedNetListener firstEvents = new(); EventBasedNetListener secondEvents = new(); hostEvents.ConnectionRequestEvent += request => request.Accept(); NetPeer? firstPeer = null; NetPeer? secondPeer = null; firstEvents.PeerConnectedEvent += peer => firstPeer = peer; secondEvents.PeerConnectedEvent += peer => secondPeer = peer; NetManager hostManager = new(hostEvents); NetManager firstManager = new(firstEvents); NetManager secondManager = new(secondEvents); try { Assert.True(hostManager.Start(0)); Assert.True(firstManager.Start(0)); Assert.True(secondManager.Start(0)); IPEndPoint hostEndpoint = new(IPAddress.Loopback, hostManager.LocalPort); firstManager.Connect(hostEndpoint, "echo-test"); secondManager.Connect(hostEndpoint, "echo-test"); await PumpUntilAsync( () => firstPeer is not null && secondPeer is not null, hostManager, firstManager, secondManager, timeout.Token); using DirectEchoProtocol host = new(hostEvents, host: true); using DirectEchoProtocol first = new(firstEvents, host: false); using DirectEchoProtocol second = new(secondEvents, host: false); int hostCompletions = 0; host.ExchangeCompleted += _ => hostCompletions++; first.BeginJoin(firstPeer!); second.BeginJoin(secondPeer!); await PumpUntilAsync( () => first.Completion.IsCompleted && second.Completion.IsCompleted && hostCompletions == 2, hostManager, firstManager, secondManager, timeout.Token); Assert.Equal(2, hostCompletions); } finally { firstManager.Stop(); secondManager.Stop(); hostManager.Stop(); } } private static async Task PumpUntilAsync( Func predicate, NetManager host, NetManager first, NetManager second, CancellationToken cancellationToken) { while (!predicate()) { cancellationToken.ThrowIfCancellationRequested(); host.PollEvents(); first.PollEvents(); second.PollEvents(); await Task.Delay(2, cancellationToken); } } }