public void SimpleSend(IByteBuffer source, bool bindClient, IByteBufferAllocator allocator, AddressFamily addressFamily, byte[] expectedData, int count)
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return;
            }
            SocketDatagramChannel serverChannel = null;
            IChannel clientChannel = null;
            var      serverGroup   = new MultithreadEventLoopGroup(1);
            var      clientGroup   = new MultithreadEventLoopGroup(1);

            try
            {
                var handler         = new TestHandler(expectedData);
                var serverBootstrap = new Bootstrap();
                serverBootstrap
                .Group(serverGroup)
                .ChannelFactory(() => new SocketDatagramChannel(addressFamily))
                .Option(ChannelOption.Allocator, allocator)
                .Option(ChannelOption.SoBroadcast, true)
                .Option(ChannelOption.IpMulticastLoopDisabled, false)
                .Handler(new ActionChannelInitializer <IChannel>(channel =>
                {
                    channel.Pipeline.AddLast(nameof(SocketDatagramChannelUnicastTest), handler);
                }));

                IPAddress address = NetUtil.GetLoopbackAddress(addressFamily);
                this.Output.WriteLine($"Unicast server binding to:({addressFamily}){address}");
                Task <IChannel> task = serverBootstrap.BindAsync(address, IPEndPoint.MinPort);

                Assert.True(task.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                            $"Unicast server binding to:({addressFamily}){address} timed out!");

                serverChannel = (SocketDatagramChannel)task.Result;
                var endPoint = (IPEndPoint)serverChannel.LocalAddress;

                var clientBootstrap = new Bootstrap();
                clientBootstrap
                .Group(clientGroup)
                .ChannelFactory(() => new SocketDatagramChannel(addressFamily))
                .Option(ChannelOption.Allocator, allocator)
                .Option(ChannelOption.SoBroadcast, true)
                .Option(ChannelOption.IpMulticastLoopDisabled, false)
                .Handler(new ActionChannelInitializer <IChannel>(channel =>
                {
                    channel.Pipeline.AddLast("Dummy", new NetUtil.DummyHandler());
                }));

                var clientEndPoint = new IPEndPoint(
                    addressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,
                    IPEndPoint.MinPort);

                clientBootstrap
                .LocalAddress(clientEndPoint)
                .RemoteAddress(new IPEndPoint(address, endPoint.Port));

                if (bindClient)
                {
                    this.Output.WriteLine($"Unicast client binding to:({addressFamily}){address}");
                    task = clientBootstrap.BindAsync(clientEndPoint);

                    Assert.True(task.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                                $"Unicast client binding to:({clientEndPoint}) timed out!");
                    clientChannel = task.Result;
                }
                else
                {
                    this.Output.WriteLine($"Register client binding to:({addressFamily}){address}");
                    task = (Task <IChannel>)clientBootstrap.RegisterAsync();
                    Assert.True(task.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds)), "Unicast client register timed out!");
                    clientChannel = task.Result;
                }

                for (int i = 0; i < count; i++)
                {
                    var packet = new DatagramPacket((IByteBuffer)source.Retain(), new IPEndPoint(address, endPoint.Port));
                    clientChannel.WriteAndFlushAsync(packet).Wait();
                    Assert.True(handler.WaitForResult());

                    var duplicatedPacket = (DatagramPacket)packet.Duplicate();
                    duplicatedPacket.Retain();
                    clientChannel.WriteAndFlushAsync(duplicatedPacket).Wait();
                    Assert.True(handler.WaitForResult());
                }
            }
            finally
            {
                serverChannel?.CloseAsync().Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds));
                clientChannel?.CloseAsync().Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds));

                source.Release();
                Task.WaitAll(
                    serverGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)),
                    clientGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)));
            }
        }
        public void Multicast(AddressFamily addressFamily, IByteBufferAllocator allocator)
        {
            SocketDatagramChannel serverChannel = null;
            IChannel         clientChannel      = null;
            var              serverGroup        = new MultithreadEventLoopGroup(1);
            var              clientGroup        = new MultithreadEventLoopGroup(1);
            NetworkInterface loopback           = NetUtil.LoopbackInterface(addressFamily);

            try
            {
                var multicastHandler = new MulticastTestHandler();
                var serverBootstrap  = new Bootstrap();
                serverBootstrap
                .Group(serverGroup)
                .ChannelFactory(() => new SocketDatagramChannel(addressFamily))
                .Option(ChannelOption.Allocator, allocator)
                .Option(ChannelOption.SoReuseaddr, true)
                .Option(ChannelOption.IpMulticastLoopDisabled, false)
                .Handler(new ActionChannelInitializer <IChannel>(channel =>
                {
                    channel.Pipeline.AddLast(nameof(SocketDatagramChannelMulticastTest), multicastHandler);
                }));

                IPAddress address = addressFamily == AddressFamily.InterNetwork
                    ? IPAddress.Loopback : IPAddress.IPv6Loopback;

                this.Output.WriteLine($"Multicast server binding to:({addressFamily}){address}");
                Task <IChannel> task = serverBootstrap.BindAsync(address, IPEndPoint.MinPort);
                Assert.True(task.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                            $"Multicast server binding to:({addressFamily}){address} timed out!");

                serverChannel = (SocketDatagramChannel)task.Result;
                var serverEndPoint = (IPEndPoint)serverChannel.LocalAddress;

                var clientBootstrap = new Bootstrap();
                clientBootstrap
                .Group(clientGroup)
                .ChannelFactory(() => new SocketDatagramChannel(addressFamily))
                .Option(ChannelOption.Allocator, allocator)
                .Option(ChannelOption.SoReuseaddr, true)
                .Option(ChannelOption.IpMulticastLoopDisabled, false)
                .Handler(new ActionChannelInitializer <IChannel>(channel =>
                {
                    channel.Pipeline.AddLast("Dummy", new NetUtil.DummyHandler());
                }));

                this.Output.WriteLine($"Multicast client binding to:({addressFamily}){address}");

                task = clientBootstrap.BindAsync(address, IPEndPoint.MinPort);
                Assert.True(task.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                            $"Multicast client binding to:({addressFamily}){address} timed out!");

                clientChannel = (SocketDatagramChannel)task.Result;

                IPAddress multicastAddress = addressFamily == AddressFamily.InterNetwork
                    ? IPAddress.Parse("230.0.0.1") : IPAddress.Parse("ff12::1");
                var  groupAddress = new IPEndPoint(multicastAddress, serverEndPoint.Port);
                Task joinTask     = serverChannel.JoinGroup(groupAddress, loopback);
                Assert.True(joinTask.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                            $"Multicast server join group {groupAddress} timed out!");

                clientChannel.WriteAndFlushAsync(new DatagramPacket(Unpooled.Buffer().WriteInt(1), groupAddress)).Wait();
                Assert.True(multicastHandler.WaitForResult(), "Multicast server should have receivied the message.");

                Task leaveTask = serverChannel.LeaveGroup(groupAddress, loopback);
                Assert.True(leaveTask.Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds * 5)),
                            $"Multicast server leave group {groupAddress} timed out!");

                // sleep half a second to make sure we left the group
                Task.Delay(DefaultTimeOutInMilliseconds).Wait();

                // we should not receive a message anymore as we left the group before
                clientChannel.WriteAndFlushAsync(new DatagramPacket(Unpooled.Buffer().WriteInt(1), groupAddress)).Wait();
                Assert.False(multicastHandler.WaitForResult(), "Multicast server should not receive the message.");
            }
            finally
            {
                serverChannel?.CloseAsync().Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds));
                clientChannel?.CloseAsync().Wait(TimeSpan.FromMilliseconds(DefaultTimeOutInMilliseconds));

                Task.WaitAll(
                    serverGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)),
                    clientGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)));
            }
        }
Esempio n. 3
0
        public IObservable <IPEndPoint[]> MakeObservable()
        {
            return(Observable.Create <IPEndPoint[]>(async(observer, cancellationToken) =>
            {
                try
                {
                    Bootstrap clientBootstrap = new Bootstrap();
                    MultithreadEventLoopGroup clientGroup = new MultithreadEventLoopGroup(1);
                    try
                    {
                        clientBootstrap
                        .Group(clientGroup)
                        .ChannelFactory(() => new SocketDatagramChannel(_addressFamily))
                        .Option(ChannelOption.Allocator, PooledByteBufferAllocator.Default)
                        .Option(ChannelOption.SoReuseaddr, true)
                        .Option(ChannelOption.IpMulticastLoopDisabled, false)
                        .Handler(new ActionChannelInitializer <IChannel>(channel =>
                        {
                            channel.Pipeline.AddLast(new SimpleChannelInboundHandler(_endPoints));
                        }));

                        SocketDatagramChannel clientChannel = (SocketDatagramChannel)await clientBootstrap
                                                              .BindAsync(IPAddress.Any, IPEndPoint.MinPort)
                                                              .ConfigureAwait(false);
                        try
                        {
                            IPEndPoint multicastEndPoint = new IPEndPoint(_multicastAddress, _disconveryServerPort);
                            byte[] groupBytes = Encoding.UTF8.GetBytes(_group);
                            IByteBuffer message = PooledByteBufferAllocator.Default
                                                  .Buffer()
                                                  .WriteInt(groupBytes.Length)
                                                  .WriteBytes(groupBytes);
                            DatagramPacket dataGram = new DatagramPacket(message, multicastEndPoint);
                            while (!cancellationToken.IsCancellationRequested)
                            {
                                _endPoints.Clear();
                                await clientChannel
                                .WriteAndFlushAsync(dataGram.Copy())
                                .ConfigureAwait(false);
                                await Task
                                .Delay(_replyWaitTimeout, cancellationToken)
                                .ConfigureAwait(false);
                                observer.OnNext(_endPoints.ToArray());
                                await Task
                                .Delay(_pollingInterval, cancellationToken)
                                .ConfigureAwait(false);
                            }
                        }
                        finally
                        {
                            await clientChannel
                            .CloseAsync()
                            .ConfigureAwait(false);
                        }
                    }
                    finally
                    {
                        await clientGroup
                        .ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))
                        .ConfigureAwait(false);
                    }

                    observer.OnCompleted();
                }
                catch (OperationCanceledException)
                {
                    observer.OnCompleted();
                }
                catch (Exception exception)
                {
                    observer.OnError(exception);
                }
            })
                   .DistinctUntilChanged(endPoints => string.Join(";", endPoints.Select(endPoint => endPoint.ToString()))));
        }
Esempio n. 4
0
        public IDisposable Run()
        {
            ManualResetEvent resetEvent = new ManualResetEvent(false);
            var subscription            = Observable
                                          .Create <object>(async(observer, cancellationToken) =>
            {
                try
                {
                    Bootstrap serverBootstrap             = new Bootstrap();
                    MultithreadEventLoopGroup serverGroup = new MultithreadEventLoopGroup(1);
                    try
                    {
                        serverBootstrap
                        .Group(serverGroup)
                        .ChannelFactory(() => new SocketDatagramChannel(_addressFamily))
                        .Option(ChannelOption.Allocator, PooledByteBufferAllocator.Default)
                        .Option(ChannelOption.SoReuseaddr, true)
                        .Option(ChannelOption.IpMulticastLoopDisabled, false)
                        .Handler(new ActionChannelInitializer <IChannel>(channel => { channel.Pipeline.AddLast(this); }));

                        SocketDatagramChannel serverChannel = (SocketDatagramChannel)await serverBootstrap
                                                              .BindAsync(IPAddress.Any, _discoveryServerPort)
                                                              .ConfigureAwait(false);

                        try
                        {
                            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>();
                            using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken), false))
                            {
                                resetEvent.Set();
                                await tcs.Task.ConfigureAwait(false);
                            }
                        }
                        finally
                        {
                            await serverChannel
                            .CloseAsync()
                            .ConfigureAwait(false);
                        }
                    }
                    finally
                    {
                        await serverGroup
                        .ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))
                        .ConfigureAwait(false);
                    }

                    observer.OnCompleted();
                }
                catch (OperationCanceledException)
                {
                    observer.OnCompleted();
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }
            })
                                          .Subscribe();

            resetEvent.WaitOne();
            return(subscription);
        }