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)); }
public MqttIotHubAdapter( string deviceId, string iotHubHostName, string password, MqttTransportSettings mqttTransportSettings, IWillMessage willMessage, Action onConnected, Action<Message> onMessageReceived, Action<Exception> onError) { Contract.Requires(deviceId != null); Contract.Requires(iotHubHostName != null); Contract.Requires(password != null); Contract.Requires(mqttTransportSettings != null); Contract.Requires(!mqttTransportSettings.HasWill || willMessage != null); this.deviceId = deviceId; this.iotHubHostName = iotHubHostName; this.password = password; this.mqttTransportSettings = mqttTransportSettings; this.willMessage = willMessage; this.onConnected = onConnected; this.onError = onError; this.onMessageReceived = onMessageReceived; this.pingRequestInterval = this.mqttTransportSettings.KeepAliveInSeconds > 0 ? TimeSpan.FromSeconds(this.mqttTransportSettings.KeepAliveInSeconds / 2d) : TimeSpan.MaxValue; this.deviceBoundOneWayProcessor = new SimpleWorkQueue<PublishPacket>(this.AcceptMessageAsync); this.deviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue<int, PublishPacket>(this.AcceptMessageAsync, p => p.PacketId, this.SendAckAsync); this.serviceBoundOneWayProcessor = new SimpleWorkQueue<PublishWorkItem>(this.SendMessageToServerAsync); this.serviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue<int, PublishWorkItem>(this.SendMessageToServerAsync, p => p.Value.PacketId, this.ProcessAckAsync); }
public MqttIotHubAdapter( string deviceId, string iotHubHostName, string password, MqttTransportSettings mqttTransportSettings, IWillMessage willMessage, Action onConnected, Action <Message> onMessageReceived, Action <Exception> onError) { Contract.Requires(deviceId != null); Contract.Requires(iotHubHostName != null); Contract.Requires(password != null); Contract.Requires(mqttTransportSettings != null); Contract.Requires(!mqttTransportSettings.HasWill || willMessage != null); this.deviceId = deviceId; this.iotHubHostName = iotHubHostName; this.password = password; this.mqttTransportSettings = mqttTransportSettings; this.willMessage = willMessage; this.onConnected = onConnected; this.onError = onError; this.onMessageReceived = onMessageReceived; this.pingRequestInterval = this.mqttTransportSettings.KeepAliveInSeconds > 0 ? TimeSpan.FromSeconds(this.mqttTransportSettings.KeepAliveInSeconds / 2d) : TimeSpan.MaxValue; this.deviceBoundOneWayProcessor = new SimpleWorkQueue <PublishPacket>(this.AcceptMessageAsync); this.deviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue <int, PublishPacket>(this.AcceptMessageAsync, p => p.PacketId, this.SendAckAsync); this.serviceBoundOneWayProcessor = new SimpleWorkQueue <PublishWorkItem>(this.SendMessageToServerAsync); this.serviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue <int, PublishWorkItem>(this.SendMessageToServerAsync, p => p.Value.PacketId, this.ProcessAckAsync); }
public MqttIotHubAdapter( string deviceId, string iotHubHostName, IAuthorizationProvider passwordProvider, MqttTransportSettings mqttTransportSettings, IWillMessage willMessage, IMqttIotHubEventHandler mqttIotHubEventHandler, ProductInfo productInfo) { Contract.Requires(deviceId != null); Contract.Requires(iotHubHostName != null); Contract.Requires(passwordProvider != null); Contract.Requires(mqttTransportSettings != null); Contract.Requires(!mqttTransportSettings.HasWill || willMessage != null); Contract.Requires(productInfo != null); this.deviceId = deviceId; this.iotHubHostName = iotHubHostName; this.passwordProvider = passwordProvider; this.mqttTransportSettings = mqttTransportSettings; this.willMessage = willMessage; this.mqttIotHubEventHandler = mqttIotHubEventHandler; this.pingRequestInterval = this.mqttTransportSettings.KeepAliveInSeconds > 0 ? TimeSpan.FromSeconds(this.mqttTransportSettings.KeepAliveInSeconds / 4d) : TimeSpan.MaxValue; this.productInfo = productInfo; this.deviceBoundOneWayProcessor = new SimpleWorkQueue <PublishPacket>(this.AcceptMessageAsync); this.deviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue <int, PublishPacket>(this.AcceptMessageAsync, p => p.PacketId, this.SendAckAsync); this.serviceBoundOneWayProcessor = new SimpleWorkQueue <PublishWorkItem>(this.SendMessageToServerAsync); this.serviceBoundTwoWayProcessor = new OrderedTwoPhaseWorkQueue <int, PublishWorkItem>(this.SendMessageToServerAsync, p => p.Value.PacketId, this.ProcessAckAsync); }
public static QualityOfService DeriveQos(Message message, MqttTransportSettings config) { QualityOfService qos; string qosValue; if (message.Properties.TryGetValue(config.QoSPropertyName, out qosValue)) { int qosAsInt; if (int.TryParse(qosValue, out qosAsInt)) { qos = (QualityOfService)qosAsInt; if (qos > QualityOfService.ExactlyOnce) { qos = config.PublishToServerQoS; } } else { qos = config.PublishToServerQoS; } } else { qos = config.PublishToServerQoS; } return(qos); }
internal MqttTransportHandler( IPipelineContext context, IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, Action <object, EventArgs> onConnectionClosedCallback, Func <MethodRequestInternal, Task> onMethodCallback = null, Action <TwinCollection> onReportedStatePatchReceivedCallback = null) : this(context, iotHubConnectionString, settings, null, onConnectionClosedCallback) { this.messageListener = onMethodCallback; this.onReportedStatePatchListener = onReportedStatePatchReceivedCallback; }
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; this.channelFactory = channelFactory ?? this.CreateChannelFactory(iotHubConnectionString, settings); this.closeRetryPolicy = new RetryPolicy(new TransientErrorIgnoreStrategy(), 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); }
internal MqttTransportHandler( IPipelineContext context, IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, Func<MethodRequestInternal, Task> onMethodCallback = null, Action<TwinCollection> onDesiredStatePatchReceivedCallback = null, Func<string, Message, Task> onReceiveCallback = null) : this(context, iotHubConnectionString, settings, null) { this.messageListener = onMethodCallback; this.messageReceivedListener = onReceiveCallback; this.onDesiredStatePatchListener = onDesiredStatePatchReceivedCallback; }
public MqttIotHubAdapter Create( IMqttIotHubEventHandler mqttIotHubEventHandler, IotHubConnectionString iotHubConnectionString, MqttTransportSettings mqttTransportSettings) { IWillMessage willMessage = mqttTransportSettings.HasWill ? this.settings.WillMessage : null; return(new MqttIotHubAdapter( iotHubConnectionString.DeviceId, iotHubConnectionString.HostName, mqttTransportSettings.ClientCertificate != null ? null : iotHubConnectionString.GetPassword(), mqttTransportSettings, willMessage, mqttIotHubEventHandler)); }
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)); }
public MqttIotHubAdapter Create( Action onConnected, Action <Message> onMessageReceived, Action <Exception> onError, IotHubConnectionString iotHubConnectionString, MqttTransportSettings mqttTransportSettings) { IWillMessage willMessage = mqttTransportSettings.HasWill ? this.settings.WillMessage : null; return(new MqttIotHubAdapter( iotHubConnectionString.DeviceId, iotHubConnectionString.HostName, iotHubConnectionString.GetPassword(), mqttTransportSettings, willMessage, onConnected, onMessageReceived, onError)); }
public MqttIotHubAdapter Create( Action onConnected, Action<Message> onMessageReceived, Action<Exception> onError, IotHubConnectionString iotHubConnectionString, MqttTransportSettings mqttTransportSettings) { IWillMessage willMessage = mqttTransportSettings.HasWill ? this.settings.WillMessage : null; return new MqttIotHubAdapter( iotHubConnectionString.DeviceId, iotHubConnectionString.HostName, mqttTransportSettings.ClientCertificate != null ? null : iotHubConnectionString.GetPassword(), mqttTransportSettings, willMessage, onConnected, onMessageReceived, onError); }
public MqttIotHubAdapter Create( IMqttIotHubEventHandler mqttIotHubEventHandler, IotHubConnectionString iotHubConnectionString, MqttTransportSettings mqttTransportSettings, ProductInfo productInfo, ClientOptions options) { IWillMessage willMessage = mqttTransportSettings.HasWill ? this.settings.WillMessage : null; return(new MqttIotHubAdapter( iotHubConnectionString.DeviceId, iotHubConnectionString.ModuleId, iotHubConnectionString.HostName, mqttTransportSettings.ClientCertificate != null ? null : iotHubConnectionString, mqttTransportSettings, willMessage, mqttIotHubEventHandler, productInfo, options)); }
internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { this.DefaultReceiveTimeout = DefaultReceiveTimeoutInSeconds; this.connectCompletion = new TaskCompletionSource(); this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings); this.messageQueue = new ConcurrentQueue<Message>(); this.completionQueue = new Queue<string>(); this.serverAddress = Dns.GetHostEntry(iotHubConnectionString.HostName).AddressList[0]; var group = new SingleInstanceEventLoopGroup(); this.qos = settings.PublishToServerQoS; this.bootstrap = new Bootstrap() .Group(@group) .Channel<TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer<ISocketChannel>(ch => { ch.Pipeline.AddLast( TlsHandler.Client(iotHubConnectionString.HostName, null), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), this.mqttIotHubAdapterFactory.Create( this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(async () => { this.connectCompletion.TrySetCanceled(); await group.ShutdownGracefullyAsync(); }); }
internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { this.DefaultReceiveTimeout = DefaultReceiveTimeoutInSeconds; this.connectCompletion = new TaskCompletionSource(); this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings); this.messageQueue = new ConcurrentQueue <Message>(); this.completionQueue = new Queue <string>(); this.serverAddress = Dns.GetHostEntry(iotHubConnectionString.HostName).AddressList[0]; var group = new SingleInstanceEventLoopGroup(); this.qos = settings.PublishToServerQoS; this.bootstrap = new Bootstrap() .Group(@group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { ch.Pipeline.AddLast( TlsHandler.Client(iotHubConnectionString.HostName, null), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), this.mqttIotHubAdapterFactory.Create( this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(async() => { this.connectCompletion.TrySetCanceled(); await group.ShutdownGracefullyAsync(); }); }
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; }); }
internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) : this(iotHubConnectionString, settings, null) { }
Func <IPAddress, int, Task <IChannel> > CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return(async(address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); // Check if we're configured to use a proxy server IWebProxy webProxy = WebRequest.DefaultWebProxy; Uri proxyAddress = webProxy?.GetProxy(websocketUri); if (!websocketUri.Equals(proxyAddress)) { // Configure proxy server websocket.Options.Proxy = webProxy; } if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } else { websocket.Options.UseDefaultCredentials = true; } using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token); } var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }); }
Func <IPAddress, int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return((address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); var clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List <X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .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), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return bootstrap.ConnectAsync(address, port); }); }
internal MqttTransportHandler(IPipelineContext context, IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, Func <MethodRequestInternal, Task> onMethodCallback = null) : this(context, iotHubConnectionString, settings, null) { this.messageListener = onMethodCallback; }
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 clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List<X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(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)); } } return channel; }; }
Func <IPAddress, int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { #if WINDOWS_UWP return(async(address, port) => { PlatformProvider.Platform = new UWPPlatform(); var eventLoopGroup = new MultithreadEventLoopGroup(); var streamSocket = new StreamSocket(); await streamSocket.ConnectAsync(new HostName(iotHubConnectionString.HostName), port.ToString(), SocketProtectionLevel.PlainSocket); streamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); await streamSocket.UpgradeToSslAsync(SocketProtectionLevel.Tls12, new HostName(iotHubConnectionString.HostName)); var streamSocketChannel = new StreamSocketChannel(streamSocket); streamSocketChannel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); streamSocketChannel.Configuration.SetOption(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default); await eventLoopGroup.GetNext().RegisterAsync(streamSocketChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return streamSocketChannel; }); #else return((address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); var clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List <X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .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), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return bootstrap.ConnectAsync(address, port); }); #endif }
public MqttIotHubAdapterFactory(MqttTransportSettings settings) { this.settings = settings; }
Func<IPAddress, int, Task<IChannel>> CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return async (address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); // Check if we're configured to use a proxy server IWebProxy webProxy = WebRequest.DefaultWebProxy; Uri proxyAddress = webProxy?.GetProxy(websocketUri); if (!websocketUri.Equals(proxyAddress)) { // Configure proxy server websocket.Options.Proxy = webProxy; } if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } else { websocket.Options.UseDefaultCredentials = true; } using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token); } var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }; }
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; this.channelFactory = channelFactory ?? this.CreateChannelFactory(iotHubConnectionString, settings); this.closeRetryPolicy = new RetryPolicy(new TransientErrorIgnoreStrategy(), 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); }
Func<IPAddress, int, Task<IChannel>> CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return (address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Func<Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); ClientTlsSettings clientTlsSettings; clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List<X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .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, 256 * 1024), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return bootstrap.ConnectAsync(address, port); }; }
public static QualityOfService DeriveQos(Message message, MqttTransportSettings config) { QualityOfService qos; string qosValue; if (message.Properties.TryGetValue(config.QoSPropertyName, out qosValue)) { int qosAsInt; if (int.TryParse(qosValue, out qosAsInt)) { qos = (QualityOfService)qosAsInt; if (qos > QualityOfService.ExactlyOnce) { qos = config.PublishToServerQoS; } } else { qos = config.PublishToServerQoS; } } else { qos = config.PublishToServerQoS; } return qos; }
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)); }
Func <IPAddress, int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return((address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { ch.Pipeline .AddLast( TlsHandler.Client(iotHubConnectionString.HostName), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return bootstrap.ConnectAsync(address, port); }); }
Func <IPAddress[], int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, ProductInfo productInfo) { return(async(addresses, port) => { IChannel channel = null; IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); var clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List <X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .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), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings, productInfo)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); foreach (IPAddress address in addresses) { try { Debug.WriteLine("Connecting to {0}.", 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 { Debug.WriteLine("ConnectException trying to connect to {0}: {1}", address.ToString(), ex.ToString()); return true; } return false; // Let anything else stop the application. }); } } return channel; }); }
Func<IPAddress[], int, Task<IChannel>> CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, ProductInfo productInfo) { return async (address, port) => { string additionalQueryParams = ""; #if NETSTANDARD1_3 // NETSTANDARD1_3 implementation doesn't set client certs, so we want to tell the IoT Hub to not ask for them additionalQueryParams = "?iothub-no-client-cert=true"; #endif var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix + additionalQueryParams); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); // Check if we're configured to use a proxy server IWebProxy webProxy = settings.Proxy; try { if (webProxy != DefaultWebProxySettings.Instance) { // Configure proxy server websocket.Options.Proxy = webProxy; if (Logging.IsEnabled) { Logging.Info(this, $"{nameof(CreateWebSocketChannelFactory)} Setting ClientWebSocket.Options.Proxy"); } } } catch (PlatformNotSupportedException) { // .NET Core 2.0 doesn't support proxy. Ignore this setting. if (Logging.IsEnabled) { Logging.Error(this, $"{nameof(CreateWebSocketChannelFactory)} PlatformNotSupportedException thrown as .NET Core 2.0 doesn't support proxy"); } } if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token).ConfigureAwait(true); } var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), new LoggingHandler(LogLevel.DEBUG), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings, productInfo)); await s_eventLoopGroup.Value.RegisterAsync(clientChannel).ConfigureAwait(false); return clientChannel; }; }
public static Message CompleteMessageFromPacket(Message message, PublishPacket packet, MqttTransportSettings mqttTransportSettings) { message.MessageId = Guid.NewGuid().ToString("N"); if (packet.RetainRequested) { message.Properties[mqttTransportSettings.RetainPropertyName] = IotHubTrueString; } if (packet.Duplicate) { message.Properties[mqttTransportSettings.DupPropertyName] = IotHubTrueString; } return message; }
Func <IPAddress, int, Task <IChannel> > CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return(async(address, port) => { string additionalQueryParams = ""; #if WINDOWS_UWP || NETSTANDARD1_3 // UWP and NETSTANDARD1_3 implementation doesn't set client certs, so we want to tell the IoT Hub to not ask for them additionalQueryParams = "?iothub-no-client-cert=true"; #endif IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix + additionalQueryParams); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); #if !WINDOWS_UWP // UWP does not support proxies // Check if we're configured to use a proxy server IWebProxy webProxy = WebRequest.DefaultWebProxy; Uri proxyAddress = null; #if !NETSTANDARD1_3 proxyAddress = webProxy?.GetProxy(websocketUri); #endif if (!websocketUri.Equals(proxyAddress)) { // Configure proxy server websocket.Options.Proxy = webProxy; } #endif if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } #if !WINDOWS_UWP && !NETSTANDARD1_3 // UseDefaultCredentials is not in UWP and NetStandard else { websocket.Options.UseDefaultCredentials = true; } #endif using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token); } #if WINDOWS_UWP PlatformProvider.Platform = new UWPPlatform(); #endif var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }); }
public static Message CompleteMessageFromPacket(Message message, PublishPacket packet, MqttTransportSettings mqttTransportSettings) { message.MessageId = Guid.NewGuid().ToString("N"); if (packet.RetainRequested) { message.Properties[mqttTransportSettings.RetainPropertyName] = IotHubTrueString; } if (packet.Duplicate) { message.Properties[mqttTransportSettings.DupPropertyName] = IotHubTrueString; } return(message); }
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"); }