protected override void InitChannel(IChannel channel)
        {
            var pipeline = channel.Pipeline;

            if (_cert is object)
            {
                var tlsSettings = new ClientTlsSettings(_targetHost)
                {
                    ApplicationProtocols = new List <SslApplicationProtocol>(new[]
                    {
                        SslApplicationProtocol.Http2,
                        SslApplicationProtocol.Http11
                    })
                }.AllowAnyServerCertificate();
                pipeline.AddLast("tls", new TlsHandler(tlsSettings));
            }

            var build = Http2FrameCodecBuilder.ForClient();

            build.InitialSettings = Http2Settings.DefaultSettings(); // this is the default, but shows it can be changed.
            Http2FrameCodec http2FrameCodec = build.Build();

            pipeline.AddLast(http2FrameCodec);
            pipeline.AddLast(new Http2MultiplexHandler(new SimpleChannelInboundHandler0()));
        }
Ejemplo n.º 2
0
        public async void MqttServerAndClient()
        {
            var testPromise = new TaskCompletionSource();

            var         tlsCertificate  = new X509Certificate2("dotnetty.com.pfx", "password");
            Func <Task> closeServerFunc = await this.StartServerAsync(true, ch =>
            {
                ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER"));
                ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate));
                ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***"));
                ch.Pipeline.AddLast(
                    MqttEncoder.Instance,
                    new MqttDecoder(true, 256 * 1024),
                    new TestScenarioRunner(this.GetMqttServerScenario, testPromise));
            }, testPromise);

            var       group = new MultithreadEventLoopGroup();
            Bootstrap b     = new Bootstrap()
                              .Group(group)
                              .Channel <TcpSocketChannel>()
                              .Option(ChannelOption.TcpNodelay, true)
                              .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                string targetHost     = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
                var clientTlsSettings = new ClientTlsSettings(targetHost);

                ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT"));
                ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings));
                ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***"));
                ch.Pipeline.AddLast(
                    MqttEncoder.Instance,
                    new MqttDecoder(false, 256 * 1024),
                    new TestScenarioRunner(this.GetMqttClientScenario, testPromise));
            }));

            this.Output.WriteLine("Configured Bootstrap: {0}", b);

            IChannel clientChannel = null;

            try
            {
                clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port);

                this.Output.WriteLine("Connected channel: {0}", clientChannel);

                await Task.WhenAny(testPromise.Task, Task.Delay(TimeSpan.FromSeconds(30)));

                Assert.True(testPromise.Task.IsCompleted);
            }
            finally
            {
                Task serverCloseTask = closeServerFunc();
                clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5));
                group.ShutdownGracefullyAsync();
                if (!serverCloseTask.Wait(ShutdownTimeout))
                {
                    this.Output.WriteLine("Didn't stop in time.");
                }
            }
        }
Ejemplo n.º 3
0
        public async void EchoServerAndClient()
        {
            var testPromise = new TaskCompletionSource();
            var tlsCertificate = new X509Certificate2("dotnetty.com.pfx", "password");
            Func<Task> closeServerFunc = await this.StartServerAsync(true, ch =>
            {
                ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER"));
                ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate));
                ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***"));
                ch.Pipeline.AddLast("server prepender", new LengthFieldPrepender(2));
                ch.Pipeline.AddLast("server decoder", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2));
                ch.Pipeline.AddLast(new EchoChannelHandler());
            }, testPromise);

            var group = new MultithreadEventLoopGroup();
            Bootstrap b = new Bootstrap()
                .Group(group)
                .Channel<TcpSocketChannel>()
                .Option(ChannelOption.TcpNodelay, true)
                .Handler(new ActionChannelInitializer<ISocketChannel>(ch =>
                {
                    string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
                    var clientTlsSettings = new ClientTlsSettings(targetHost);
                    ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT"));
                    ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings));
                    ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***"));
                    ch.Pipeline.AddLast("client prepender", new LengthFieldPrepender(2));
                    ch.Pipeline.AddLast("client decoder", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2));
                    ch.Pipeline.AddLast(new TestScenarioRunner(this.GetEchoClientScenario, testPromise));
                }));

            this.Output.WriteLine("Configured Bootstrap: {0}", b);

            IChannel clientChannel = null;
            try
            {
                clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port);

                this.Output.WriteLine("Connected channel: {0}", clientChannel);

                await Task.WhenAny(testPromise.Task, Task.Delay(TimeSpan.FromSeconds(30)));
                Assert.True(testPromise.Task.IsCompleted, "timed out");
                testPromise.Task.Wait();
            }
            finally
            {
                Task serverCloseTask = closeServerFunc();
                clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5));
                group.ShutdownGracefullyAsync();
                if (!serverCloseTask.Wait(ShutdownTimeout))
                {
                    this.Output.WriteLine("Didn't stop in time.");
                }
            }
        }
        private Task <RegistrationOperationStatus> ProvisionOverTcpUsingSymmetricKeyAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            Debug.Assert(message.Security is SecurityProviderSymmetricKey);
            cancellationToken.ThrowIfCancellationRequested();

            var tlsSettings = new ClientTlsSettings(
                message.GlobalDeviceEndpoint);

            return(ProvisionOverTcpCommonAsync(message, tlsSettings, cancellationToken));
        }
        /// <summary>
        /// Configure the pipeline for TLS NPN negotiation to HTTP/2.
        /// </summary>
        /// <param name="ch"></param>
        void ConfigureSsl(IChannel ch)
        {
            var pipeline    = ch.Pipeline;
            var tlsSettings = new ClientTlsSettings(_targetHost)
            {
                ApplicationProtocols = new List <SslApplicationProtocol>(new[]
                {
                    SslApplicationProtocol.Http2,
                    SslApplicationProtocol.Http11
                })
            }.AllowAnyServerCertificate();

            pipeline.AddLast("tls", new TlsHandler(tlsSettings));

            // We must wait for the handshake to finish and the protocol to be negotiated before configuring
            // the HTTP/2 components of the pipeline.
            pipeline.AddLast(new ClientApplicationProtocolNegotiationHandler(this));
        }
        private Task <RegistrationOperationStatus> ProvisionOverTcpUsingX509CertificateAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            Debug.Assert(message.Security is SecurityProviderX509);
            cancellationToken.ThrowIfCancellationRequested();

            X509Certificate2 clientCertificate =
                ((SecurityProviderX509)message.Security).GetAuthenticationCertificate();

            var tlsSettings = new ClientTlsSettings(
                message.GlobalDeviceEndpoint,
                new List <X509Certificate> {
                clientCertificate
            });

            return(ProvisionOverTcpCommonAsync(message, tlsSettings, cancellationToken));
        }
Ejemplo n.º 7
0
        private async Task <RegistrationOperationStatus> ProvisionOverTcpCommonAsync(
            ProvisioningTransportRegisterMessage message,
            ClientTlsSettings tlsSettings,
            CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <RegistrationOperationStatus>();

            Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, RemoteCertificateValidationCallback);

            Bootstrap bootstrap = new Bootstrap()
                                  .Group(s_eventLoopGroup)
                                  .Channel <TcpSocketChannel>()
                                  .Option(ChannelOption.TcpNodelay, true)
                                  .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
                                  .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                ch.Pipeline.AddLast(
                    new ReadTimeoutHandler(ReadTimeoutSeconds),
                    new TlsHandler(streamFactory, tlsSettings),
                    MqttEncoder.Instance,
                    new MqttDecoder(isServer: false, maxMessageSize: MaxMessageSize),
                    new LoggingHandler(LogLevel.DEBUG),
                    new ProvisioningChannelHandlerAdapter(message, tcs, cancellationToken));
            }));

            if (Logging.IsEnabled)
            {
                Logging.Associate(bootstrap, this);
            }

            IPAddress[] addresses = await Dns.GetHostAddressesAsync(message.GlobalDeviceEndpoint).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Info(this, $"DNS resolved {addresses.Length} addresses.");
            }

            IChannel  channel       = null;
            Exception lastException = null;

            foreach (IPAddress address in addresses)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"Connecting to {address.ToString()}.");
                    }

                    channel = await bootstrap.ConnectAsync(address, Port).ConfigureAwait(false);

                    break;
                }
                catch (AggregateException ae)
                {
                    ae.Handle((ex) =>
                    {
                        if (ex is ConnectException)     // We will handle DotNetty.Transport.Channels.ConnectException
                        {
                            lastException = ex;
                            if (Logging.IsEnabled)
                            {
                                Logging.Info(
                                    this,
                                    $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}");
                            }

                            return(true);
                        }

                        return(false); // Let anything else stop the application.
                    });
                }
            }

            if (channel == null)
            {
                string errorMessage = "Cannot connect to Provisioning Service.";
                if (Logging.IsEnabled)
                {
                    Logging.Error(this, errorMessage);
                }

                ExceptionDispatchInfo.Capture(lastException).Throw();
            }

            return(await tcs.Task.ConfigureAwait(false));
        }
Ejemplo n.º 8
0
        public async Task EchoServerAndClient()
        {
            var         testPromise     = new DefaultPromise();
            var         tlsCertificate  = TestResourceHelper.GetTestCertificate();
            Func <Task> closeServerFunc = await this.StartServerAsync(true, ch =>
            {
                ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER"));
                ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate));
                ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***"));
                ch.Pipeline.AddLast("server prepender", new LengthFieldPrepender2(2));
                ch.Pipeline.AddLast("server decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2));
                ch.Pipeline.AddLast(new EchoChannelHandler());
            }, testPromise);

            var       group        = new MultithreadEventLoopGroup();
            var       readListener = new ReadListeningHandler(DefaultTimeout);
            Bootstrap b            = new Bootstrap()
                                     .Group(group)
                                     .Channel <TcpSocketChannel>()
                                     .Option(ChannelOption.TcpNodelay, true)
                                     .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                string targetHost     = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
                var clientTlsSettings = new ClientTlsSettings(targetHost);
                ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT"));
                ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings));
                ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***"));
                ch.Pipeline.AddLast("client prepender", new LengthFieldPrepender2(2));
                ch.Pipeline.AddLast("client decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2));
                ch.Pipeline.AddLast(readListener);
            }));

            this.Output.WriteLine("Configured Bootstrap: {0}", b);

            IChannel clientChannel = null;

            try
            {
                clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port);

                this.Output.WriteLine("Connected channel: {0}", clientChannel);

                string[] messages = { "message 1", string.Join(",", Enumerable.Range(1, 300)) };
                foreach (string message in messages)
                {
                    await clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(message))).WithTimeout(DefaultTimeout);

                    var responseMessage = Assert.IsAssignableFrom <IByteBuffer>(await readListener.ReceiveAsync());
                    Assert.Equal(message, responseMessage.ToString(Encoding.UTF8));
                }

                testPromise.TryComplete();
                await testPromise.Task.WithTimeout(TimeSpan.FromMinutes(5));
            }
            finally
            {
                Task serverCloseTask = closeServerFunc();
                clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5));
                group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10));
                if (!serverCloseTask.Wait(ShutdownTimeout))
                {
                    this.Output.WriteLine("Didn't stop in time.");
                }
            }
        }
Ejemplo n.º 9
0
        public async Task MqttServerAndClient()
        {
            var testPromise = new DefaultPromise();

            var         tlsCertificate     = TestResourceHelper.GetTestCertificate();
            var         serverReadListener = new ReadListeningHandler();
            IChannel    serverChannel      = null;
            Func <Task> closeServerFunc    = await this.StartServerAsync(true, ch =>
            {
                serverChannel = ch;
                ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER"));
                ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate));
                ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***"));
                ch.Pipeline.AddLast(
                    MqttEncoder.Instance,
                    new MqttDecoder(true, 256 * 1024),
                    serverReadListener);
            }, testPromise);

            var       group = new MultithreadEventLoopGroup();
            var       clientReadListener = new ReadListeningHandler();
            Bootstrap b = new Bootstrap()
                          .Group(group)
                          .Channel <TcpSocketChannel>()
                          .Option(ChannelOption.TcpNodelay, true)
                          .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                string targetHost     = tlsCertificate.GetNameInfo(X509NameType.DnsName, false);
                var clientTlsSettings = new ClientTlsSettings(targetHost);

                ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT"));
                ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings));
                ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***"));
                ch.Pipeline.AddLast(
                    MqttEncoder.Instance,
                    new MqttDecoder(false, 256 * 1024),
                    clientReadListener);
            }));

            this.Output.WriteLine("Configured Bootstrap: {0}", b);

            IChannel clientChannel = null;

            try
            {
                clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port);

                this.Output.WriteLine("Connected channel: {0}", clientChannel);

                await Task.WhenAll(this.RunMqttClientScenarioAsync(clientChannel, clientReadListener), this.RunMqttServerScenarioAsync(serverChannel, serverReadListener))
                .WithTimeout(TimeSpan.FromMinutes(5));

                testPromise.TryComplete();
                await testPromise.Task;
            }
            finally
            {
                Task serverCloseTask = closeServerFunc();
                clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5));
                group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10));
                if (!serverCloseTask.Wait(ShutdownTimeout))
                {
                    this.Output.WriteLine("Didn't stop in time.");
                }
            }
        }
Ejemplo n.º 10
0
        private async Task <RegistrationOperationStatus> ProvisionOverTcpUsingX509CertificateAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            Debug.Assert(message.Security is SecurityProviderX509);
            cancellationToken.ThrowIfCancellationRequested();

            X509Certificate2 clientCertificate =
                ((SecurityProviderX509)message.Security).GetAuthenticationCertificate();

            var tlsSettings = new ClientTlsSettings(
                message.GlobalDeviceEndpoint,
                new List <X509Certificate> {
                clientCertificate
            });

            var tcs = new TaskCompletionSource <RegistrationOperationStatus>();

            Bootstrap bootstrap = new Bootstrap()
                                  .Group(s_eventLoopGroup)
                                  .Channel <TcpSocketChannel>()
                                  .Option(ChannelOption.TcpNodelay, true)
                                  .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
                                  .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                ch.Pipeline.AddLast(
                    new ReadTimeoutHandler(ReadTimeoutSeconds),
                    new TlsHandler(tlsSettings),     //TODO: Ensure SystemDefault is used.
                    MqttEncoder.Instance,
                    new MqttDecoder(isServer: false, maxMessageSize: MaxMessageSize),
                    new ProvisioningChannelHandlerAdapter(message, tcs, cancellationToken));
            }));

            if (Logging.IsEnabled)
            {
                Logging.Associate(bootstrap, this);
            }

            IPAddress[] addresses = await Dns.GetHostAddressesAsync(message.GlobalDeviceEndpoint);

            if (Logging.IsEnabled)
            {
                Logging.Info(this, $"DNS resolved {addresses.Length} addresses.");
            }

            IChannel  channel       = null;
            Exception lastException = null;

            foreach (IPAddress address in addresses)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"Connecting to {address.ToString()}.");
                    }
                    channel = await bootstrap.ConnectAsync(address, this.Port);

                    break;
                }
                catch (AggregateException ae)
                {
                    ae.Handle((ex) =>
                    {
                        if (ex is ConnectException)     // We will handle DotNetty.Transport.Channels.ConnectException
                        {
                            lastException = ex;
                            if (Logging.IsEnabled)
                            {
                                Logging.Info(
                                    this,
                                    $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}");
                            }
                            return(true);
                        }

                        return(false); // Let anything else stop the application.
                    });
                }
            }

            if (channel == null)
            {
                string errorMessage = "Cannot connect to Provisioning Service.";
                if (Logging.IsEnabled)
                {
                    Logging.Error(this, errorMessage);
                }
                ExceptionDispatchInfo.Capture(lastException).Throw();
            }

            return(await tcs.Task);
        }
        private Func <IPAddress[], int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, ProductInfo productInfo)
        {
            return(async(addresses, port) =>
            {
                IChannel channel = null;

                Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback);

                var certs = settings.ClientCertificate == null
                    ? new List <X509Certificate>(0)
                    : new List <X509Certificate> {
                    settings.ClientCertificate
                };

                SslProtocols protocols = TlsVersions.Instance.Preferred;
#if NET451
                // Requires hardcoding in NET451 otherwise yields error:
                //    Microsoft.Azure.Devices.Client.Exceptions.IotHubCommunicationException: Transient network error occurred, please retry.
                //    DotNetty.Transport.Channels.ClosedChannelException: I/O error occurred.
                if (settings.GetTransportType() == TransportType.Mqtt_Tcp_Only &&
                    protocols == SslProtocols.None)
                {
                    protocols = TlsVersions.Instance.MinimumTlsVersions;
                }
#endif

                var clientTlsSettings = new ClientTlsSettings(
                    protocols,
                    settings.CertificateRevocationCheck,
                    certs,
                    iotHubConnectionString.HostName);

                Bootstrap bootstrap = new Bootstrap()
                                      .Group(s_eventLoopGroup.Value)
                                      .Channel <TcpSocketChannel>()
                                      .Option(ChannelOption.TcpNodelay, true)
                                      .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
                                      .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
                {
                    var tlsHandler = new TlsHandler(streamFactory, clientTlsSettings);

                    ch.Pipeline
                    .AddLast(
                        tlsHandler,
                        MqttEncoder.Instance,
                        new MqttDecoder(false, MaxMessageSize),
                        new LoggingHandler(LogLevel.DEBUG),
                        this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings, productInfo));
                }));

                foreach (IPAddress address in addresses)
                {
                    try
                    {
                        if (Logging.IsEnabled)
                        {
                            Logging.Info(this, $"Connecting to {address.ToString()}", nameof(CreateChannelFactory));
                        }
                        channel = await bootstrap.ConnectAsync(address, port).ConfigureAwait(true);

                        break;
                    }
                    catch (AggregateException ae)
                    {
                        ae.Handle((ex) =>
                        {
                            if (ex is ConnectException)     // We will handle DotNetty.Transport.Channels.ConnectException
                            {
                                if (Logging.IsEnabled)
                                {
                                    Logging.Error(this, $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}", nameof(CreateChannelFactory));
                                }
                                return true;
                            }

                            return false; // Let anything else stop the application.
                        });
                    }
                    catch (ConnectException ex)
                    {
                        //same as above, we will handle DotNetty.Transport.Channels.ConnectException
                        if (Logging.IsEnabled)
                        {
                            Logging.Error(this, $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}", nameof(CreateChannelFactory));
                        }
                    }
                }

                if (channel == null)
                {
                    throw new IotHubCommunicationException("MQTT channel open failed.");
                }
                return channel;
            });
        }