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)); }
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)); }