Exemplo n.º 1
0
        async Task DoContexts(string url)
        {
            const int NumSurveyors        = 1;
            const int NumResponders       = 2;
            var       readyToDial         = new AsyncBarrier(NumSurveyors + NumResponders);
            var       readyToSend         = new AsyncBarrier(NumSurveyors + NumResponders);
            var       ready               = readyToSend.WaitAsync();
            var       numSurveyorReceive  = new AsyncCountdownEvent(NumSurveyors);
            var       numResponderReceive = new AsyncCountdownEvent(NumSurveyors);

            using (var surveySocket = Factory.SurveyorOpen().ThenListen(url).Unwrap())
                using (var respondSocket = Factory.RespondentOpen().ThenDial(url).Unwrap())
                {
                    var duration = new nng_duration {
                        TimeMs = DefaultTimeoutMs
                    };
                    // Send() is not cancelable so need it to timeout
                    surveySocket.SetOpt(nng.Native.Defines.NNG_OPT_SENDTIMEO, new nng_duration {
                        TimeMs = 50
                    });
                    surveySocket.SetOpt(nng.Native.Defines.NNG_OPT_RECVTIMEO, nng_duration.Infinite);
                    surveySocket.SetOpt(Native.Defines.NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration.Infinite);
                    respondSocket.SetOpt(nng.Native.Defines.NNG_OPT_SENDTIMEO, new nng_duration {
                        TimeMs = 50
                    });

                    var cts   = new CancellationTokenSource();
                    var tasks = new List <Task>();
                    for (var i = 0; i < NumSurveyors; ++i)
                    {
                        var id   = i;
                        var task = Task.Run(async() =>
                        {
                            using (var ctx = surveySocket.CreateAsyncContext(Factory).Unwrap())
                            {
                                ctx.Ctx.SetOpt(Native.Defines.NNG_OPT_RECVTIMEO, nng_duration.Infinite);
                                ctx.Ctx.SetOpt(Native.Defines.NNG_OPT_SURVEYOR_SURVEYTIME, nng_duration.Infinite);

                                await readyToDial.SignalAndWait();
                                await readyToSend.SignalAndWait();

                                // Send survey and receive responses
                                var survey = Factory.CreateMessage();
                                var val    = (uint)rng.Next();
                                survey.Append(val);
                                //Assert.Equal(0, survey.Header.Append((uint)(0x8000000 | i))); // Protocol header contains "survey ID"
                                (await ctx.Send(survey)).Unwrap();
                                while (!cts.IsCancellationRequested)
                                {
                                    try
                                    {
                                        var response = (await ctx.Receive(cts.Token)).Unwrap();
                                        response.Trim(out uint respVal);
                                        Assert.Equal(val, respVal);
                                        if (numSurveyorReceive.Signal() == 0)
                                        {
                                            break;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.Error.WriteLine(ex.ToString());
                                        throw ex;
                                    }
                                }
                            }
                        });
                        tasks.Add(task);
                    }

                    for (var i = 0; i < NumResponders; ++i)
                    {
                        var id   = i;
                        var task = Task.Run(async() =>
                        {
                            await readyToDial.SignalAndWait();
                            using (var ctx = respondSocket.CreateAsyncContext(Factory).Unwrap())
                            {
                                // Receive survey and send response
                                try
                                {
                                    // Receive is async, give it a chance to start before signaling we are ready.
                                    // This to avoid race where surveyor sends before it actually starts receiving
                                    var recvFuture = ctx.Receive(cts.Token);
                                    await WaitShort();
                                    await readyToSend.SignalAndWait();
                                    var survey = (await recvFuture).Unwrap();
                                    await Task.Delay(10); // Make sure surveyor has a chance to start receiving
                                    (await ctx.Send(survey)).Unwrap();
                                    numResponderReceive.Signal();
                                    await numSurveyorReceive.WaitAsync();
                                    cts.Cancel(); // Cancel any responders still receiving
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                    throw ex;
                                }
                            }
                        });
                        tasks.Add(task);
                    }
                    await Task.WhenAny(ready, Task.WhenAll(tasks));

                    await Util.CancelAfterAssertwait(tasks, cts);

                    Assert.Equal(0, numSurveyorReceive.Count);
                    Assert.Equal(0, numResponderReceive.Count);
                }
        }
Exemplo n.º 2
0
        public void TestBasicFunctionality()
        {
            const int PORT = 1234;

            EndpointManager endpointManager = new();

            BufferBlock <TcpClient> block = new();

            block.LinkTo(endpointManager.IncomingClientBlock);

            using TcpClientListener listener = new TcpClientListener();
            listener.StartListeningForConnections(PORT);
            listener.ConnectingClientBlock.LinkTo(endpointManager.IncomingClientBlock);

            //
            // add unconnected client
            // add client -> multiple clients
            // disconnect client (extern)
            // disconnect client (local, null)
            // disconnect client (local, unregistered)
            // disconnect client (local)
            // add 2 clients
            // send message via client 1
            // send message via client 2
            //

            AsyncBarrier barrier = null;

            EndpointEventType expectedType = new();

            TcpClient clientUnconnected      = new();
            TcpClient client1                = new();
            TcpClient client2                = new();
            TcpClient client3                = new();
            TcpClient clientRemoteDisconnect = new();
            TcpClient clientLocalDisconnect  = new();
            IEndpoint ep = new Endpoint(new PacketSocket(clientUnconnected));
            IEndpoint localDisconnectEp = null;
            bool      local             = false;

            bool remoteDisconnect = false;

            List <IEndpoint> epList = new List <IEndpoint>();

            SemaphoreSlim sem = new(1);

            endpointManager.EndpointConnectedHandler = async ep =>
            {
                Assert.IsTrue(expectedType == EndpointEventType.Connect);

                await sem.WaitAsync();

                epList.Add(ep);

                if (local)
                {
                    localDisconnectEp = ep;
                }

                TestUtils.AssertTask(barrier.SignalAsync());
                sem.Release();
            };
            endpointManager.EndpointDisconnectedHandler = async(ep, remote) =>
            {
                Assert.AreEqual(remoteDisconnect, remote);
                Assert.IsTrue(expectedType == EndpointEventType.Disconnect);

                await sem.WaitAsync();

                Assert.IsTrue(epList.Remove(ep));

                TestUtils.AssertTask(barrier.SignalAsync());
                sem.Release();
            };

            expectedType = EndpointEventType.Connect;
            barrier      = new(4, false);

            // add unconnected client
            TestUtils.AssertTask(block.SendAsync(clientUnconnected));

            var tasks = new List <Task>();

            // add client -> multiple clients
            tasks.Add(Task.Run(() => client1.Connect("localhost", PORT)));
            tasks.Add(Task.Run(() => client2.Connect("localhost", PORT)));
            tasks.Add(Task.Run(() => client3.Connect("localhost", PORT)));
            tasks.Add(Task.Run(() => clientRemoteDisconnect.Connect("localhost", PORT)));
            TestUtils.AssertTask(barrier.WaitAsync(), 3000);

            local   = true;
            barrier = new(1, false);
            tasks.Add(Task.Run(() => clientLocalDisconnect.Connect("localhost", PORT)));
            TestUtils.AssertTask(barrier.WaitAsync(), 3000);
            local = false;

            CollectionAssert.Contains(epList, localDisconnectEp);
            CollectionAssert.Contains(endpointManager.ConnectedEndpoints, localDisconnectEp);
            Assert.AreEqual(5, endpointManager.ConnectedEndpoints.Count);
            CollectionAssert.AreEquivalent(epList, endpointManager.ConnectedEndpoints);
            Assert.IsNotNull(localDisconnectEp);

            // disconnect client (remote)
            expectedType     = EndpointEventType.Disconnect;
            remoteDisconnect = true;
            barrier          = new(1, false);
            clientRemoteDisconnect.Close();
            TestUtils.AssertTask(barrier.WaitAsync());
            Assert.AreEqual(4, endpointManager.ConnectedEndpoints.Count);
            Assert.AreEqual(4, epList.Count);
            CollectionAssert.AreEquivalent(epList, endpointManager.ConnectedEndpoints);
            CollectionAssert.Contains(epList, localDisconnectEp);
            CollectionAssert.Contains(endpointManager.ConnectedEndpoints, localDisconnectEp);

            // disconnect client (local, null)
            remoteDisconnect = false;
            TestUtils.AssertException <ArgumentNullException>(endpointManager.DisconnectEndpointAsync(null));

            // disconnect client (local, unregistered)
            TestUtils.AssertException <ArgumentException>(endpointManager.DisconnectEndpointAsync(ep));

            CollectionAssert.AreEquivalent(epList, endpointManager.ConnectedEndpoints);
            // disconnect client (local)
            barrier = new(1, false);
            CollectionAssert.Contains(endpointManager.ConnectedEndpoints, localDisconnectEp);
            TestUtils.AssertTask(endpointManager.DisconnectEndpointAsync(localDisconnectEp));
            TestUtils.AssertTask(barrier.WaitAsync());
            CollectionAssert.AreEquivalent(epList, endpointManager.ConnectedEndpoints);
            CollectionAssert.DoesNotContain(endpointManager.ConnectedEndpoints, localDisconnectEp);

            barrier = new(1, false);

            byte[] buffer = Encoding.ASCII.GetBytes("Hello World!");

            ActionBlock <RawMessage> aB = new(m =>
            {
                CollectionAssert.AreEqual(buffer, m.Data);
                _ = barrier.SignalAsync();
            });

            foreach (var e in endpointManager.ConnectedEndpoints)
            {
                Assert.IsTrue(e.Socket.IsConnected);
            }
            Assert.IsTrue(client1.Connected);

            PacketSocket socket1 = new PacketSocket(client1);


            Assert.IsTrue(socket1.IsReceiving);

            Assert.IsTrue(socket1.IsConnected);


            endpointManager.RawMessageBlock.LinkTo(aB);

            Assert.IsTrue(TestUtils.AssertTask(socket1.SendAsync(buffer)));
            TestUtils.AssertTask(barrier.WaitAsync());
        }
Exemplo n.º 3
0
        public void TestIncomingConnections()
        {
            const int     COUNT   = 10;
            ModuleManager manager = new();

            MockBaseModule   baseModule       = new();
            ConnectionModule connectionModule = new();


            //register modules and get interface
            TestUtils.AssertTask(manager.RegisterModuleAsync(baseModule.Header));
            TestUtils.AssertTask(manager.RegisterModuleAsync(connectionModule.Header));

            var connectionControl = TestUtils.AssertTask(manager.GetInterfaceAsync <IConnectionControl>(null));

            //connect endpoints
            AsyncBarrier barrier = new(COUNT);

            baseModule.MockProtocol.NewConnection = (connection) =>
            {
                Assert.AreEqual(ConnectionState.Connecting, connection.State);
                return(Task.CompletedTask);
            };
            baseModule.MockProtocol.SynchronizingConnection = (connection) =>
            {
                Assert.AreEqual(ConnectionState.Synchronizing, connection.State);
                return(Task.CompletedTask);
            };
            baseModule.MockProtocol.EstablishedConnection = async(connection) =>
            {
                Assert.AreEqual(ConnectionState.Established, connection.State);
                await barrier.SignalAsync();
            };

            List <Task>         tasks     = new();
            List <MockEndpoint> endpoints = new();

            for (int i = 0; i < COUNT; i++)
            {
                var endpoint = new MockEndpoint();
                endpoints.Add(endpoint);
                tasks.Add(Task.Run(() => baseModule.ConnectEndpoint(endpoint)));
            }
            Task.WhenAll(tasks).Wait();

            TestUtils.AssertTask(barrier.WaitAsync(), 500);

            Assert.AreEqual(endpoints.Count, baseModule.ConnectedEndpoints.Count);
            Assert.AreEqual(endpoints.Count, connectionControl.Connections.Count);
            for (int i = 0; i < COUNT; i++)
            {
                var connection = (Connection)endpoints[i].ConnectionData;

                Assert.IsTrue(connectionControl.Connections.Contains(connection));
                Assert.IsNotNull(connection);
                Assert.AreEqual(endpoints[i], connection.Endpoint);
            }

            //disconnect local
            barrier = new AsyncBarrier(2, false);
            baseModule.MockProtocol.ClosingConnection = async(connection, reason, msg) =>
            {
                //only called for local disconnect
                Assert.AreEqual(ConnectionState.Established, connection.State);
                await barrier.SignalAsync();
            };
            baseModule.MockProtocol.DisconnectedConnection = async(connection) =>
            {
                Assert.AreEqual(ConnectionState.Disconnected, connection.State);
                await barrier.SignalAsync();
            };
            connectionControl.CloseConnectionAsync((Connection)endpoints[0].ConnectionData, DisconnectReason.Kick, "test");

            TestUtils.AssertTask(barrier.WaitAsync(), 500);

            Assert.IsFalse(endpoints[0].Socket.IsConnected);

            endpoints.RemoveAt(0);

            foreach (var ep in endpoints)
            {
                Assert.IsTrue(ep.Socket.IsConnected);
            }

            Assert.AreEqual(endpoints.Count, baseModule.ConnectedEndpoints.Count);
            Assert.AreEqual(endpoints.Count, connectionControl.Connections.Count);

            //disconnect remote
            barrier = new AsyncBarrier(1, false);
            endpoints[0].Disconnect(true);

            TestUtils.AssertTask(barrier.WaitAsync(), 500);

            Assert.IsFalse(endpoints[0].Socket.IsConnected);

            endpoints.RemoveAt(0);

            foreach (var ep in endpoints)
            {
                Assert.IsTrue(ep.Socket.IsConnected);
            }

            Task.Delay(1000);

            barrier = new AsyncBarrier(2 * endpoints.Count, false);

            Assert.AreEqual(endpoints.Count, baseModule.ConnectedEndpoints.Count);
            Assert.AreEqual(endpoints.Count, connectionControl.Connections.Count);

            //disconnect all
            TestUtils.AssertTask(connectionControl.CloseAllConnectionsAsync());

            foreach (var ep in endpoints)
            {
                Assert.IsFalse(ep.Socket.IsConnected);
            }
        }