Esempio n. 1
0
        internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, Func <IPAddress, int, Task <IChannel> > channelFactory)
            : base(settings)
        {
            this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings);
            this.messageQueue             = new ConcurrentQueue <Message>();
            this.completionQueue          = new Queue <string>();
            this.serverAddress            = Dns.GetHostEntry(iotHubConnectionString.HostName).AddressList[0];
            this.qos = settings.PublishToServerQoS;
            this.eventLoopGroupKey = iotHubConnectionString.IotHubName + "#" + iotHubConnectionString.DeviceId + "#" + iotHubConnectionString.Audience;

            if (channelFactory == null)
            {
                switch (settings.GetTransportType())
                {
                case TransportType.Mqtt_Tcp_Only:
                    this.channelFactory = this.CreateChannelFactory(iotHubConnectionString, settings);
                    break;

                case TransportType.Mqtt_WebSocket_Only:
                    this.channelFactory = this.CreateWebSocketChannelFactory(iotHubConnectionString, settings);
                    break;

                default:
                    throw new InvalidOperationException("Unsupported Transport Setting {0}".FormatInvariant(settings.GetTransportType()));
                }
            }
            else
            {
                this.channelFactory = channelFactory;
            }

            this.closeRetryPolicy = new RetryPolicy(new TransientErrorIgnoreStrategy(), 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        }
Esempio n. 2
0
        internal MqttTransportHandler(
            IPipelineContext context,
            IotHubConnectionString iotHubConnectionString,
            MqttTransportSettings settings,
            Func <IPAddress[], int, Task <IChannel> > channelFactory,
            Action <object, ConnectionEventArgs> onConnectionOpenedCallback,
            Func <object, ConnectionEventArgs, Task> onConnectionClosedCallback)
            : base(context, settings)
        {
            this.connectionOpenedListener = onConnectionOpenedCallback;
            this.connectionClosedListener = onConnectionClosedCallback;

            this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings);
            this.messageQueue             = new ConcurrentQueue <Message>();
            this.completionQueue          = new Queue <string>();

            this.serverAddresses           = null; // this will be resolved asynchronously in OpenAsync
            this.hostName                  = iotHubConnectionString.HostName;
            this.receiveEventMessageFilter = string.Format(CultureInfo.InvariantCulture, receiveEventMessagePatternFilter, iotHubConnectionString.DeviceId, iotHubConnectionString.ModuleId);
            this.receiveEventMessagePrefix = string.Format(CultureInfo.InvariantCulture, receiveEventMessagePrefixPattern, iotHubConnectionString.DeviceId, iotHubConnectionString.ModuleId);

            this.qos = settings.PublishToServerQoS;
            this.eventLoopGroupKey = iotHubConnectionString.IotHubName + "#" + iotHubConnectionString.DeviceId + "#" + iotHubConnectionString.Audience;

            if (channelFactory == null)
            {
                switch (settings.GetTransportType())
                {
                case TransportType.Mqtt_Tcp_Only:
                    this.channelFactory = this.CreateChannelFactory(iotHubConnectionString, settings, context.Get <ProductInfo>());
                    break;

                case TransportType.Mqtt_WebSocket_Only:
                    this.channelFactory = this.CreateWebSocketChannelFactory(iotHubConnectionString, settings, context.Get <ProductInfo>());
                    break;

                default:
                    throw new InvalidOperationException("Unsupported Transport Setting {0}".FormatInvariant(settings.GetTransportType()));
                }
            }
            else
            {
                this.channelFactory = channelFactory;
            }

            this.closeRetryPolicy = new RetryPolicy(new TransientErrorIgnoreStrategy(), 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        }
        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;
            });
        }
 public void TransportSettingsTest_TransportType_Mqtt_WebSocket_Only()
 {
     var transportSetting = new MqttTransportSettings(TransportType.Mqtt_WebSocket_Only);
     Assert.IsTrue(transportSetting.GetTransportType() == TransportType.Mqtt_WebSocket_Only, "Should be TransportType.Mqtt_WebSocket_Only");
 }
        internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, Func<IPAddress, int, Task<IChannel>> channelFactory)
            : base(settings)
        {
            this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings);
            this.messageQueue = new ConcurrentQueue<Message>();
            this.completionQueue = new Queue<string>();
            this.serverAddress = Dns.GetHostEntry(iotHubConnectionString.HostName).AddressList[0];
            this.qos = settings.PublishToServerQoS;
            this.eventLoopGroupKey = iotHubConnectionString.IotHubName + "#" + iotHubConnectionString.DeviceId + "#" + iotHubConnectionString.Audience;

            if (channelFactory == null)
            {
                switch (settings.GetTransportType())
                {
                    case TransportType.Mqtt_Tcp_Only:
                        this.channelFactory = this.CreateChannelFactory(iotHubConnectionString, settings);
                        break;
                    case TransportType.Mqtt_WebSocket_Only:
                        this.channelFactory = this.CreateWebSocketChannelFactory(iotHubConnectionString, settings);
                        break;
                    default:
                        throw new InvalidOperationException("Unsupported Transport Setting {0}".FormatInvariant(settings.GetTransportType()));
                }
            }
            else
            {
                this.channelFactory = channelFactory;
            }

            this.closeRetryPolicy = new RetryPolicy(new TransientErrorIgnoreStrategy(), 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
        }