public async Task MqttWebSocketClientAndServerScenario() { var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); Uri uri = new Uri("ws://" + IotHubName + ":" + Port + WebSocketConstants.UriSuffix); await websocket.ConnectAsync(uri, CancellationToken.None); var clientReadListener = new ReadListeningHandler(); var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default); clientChannel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), clientReadListener); var clientWorkerGroup = new MultithreadEventLoopGroup(); await clientWorkerGroup.GetNext().RegisterAsync(clientChannel); await Task.WhenAll(RunMqttClientScenarioAsync(clientChannel, clientReadListener), RunMqttServerScenarioAsync(serverWebSocketChannel, serverListener)); done = true; }
private async Task <RegistrationOperationStatus> ProvisionOverWssCommonAsync( ProvisioningTransportRegisterMessage message, X509Certificate2 clientCertificate, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <RegistrationOperationStatus>(); var uriBuilder = new UriBuilder(WsScheme, message.GlobalDeviceEndpoint, Port); Uri websocketUri = uriBuilder.Uri; using var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WsMqttSubprotocol); if (clientCertificate != null) { websocket.Options.ClientCertificates.Add(clientCertificate); } //Check if we're configured to use a proxy server try { if (Proxy != DefaultWebProxySettings.Instance) { // Configure proxy server websocket.Options.Proxy = Proxy; if (Logging.IsEnabled) { Logging.Info(this, $"{nameof(ProvisionOverWssUsingX509CertificateAsync)} Setting ClientWebSocket.Options.Proxy: {Proxy}"); } } } catch (PlatformNotSupportedException) { // .NET Core 2.0 doesn't support WebProxy configuration - ignore this setting. if (Logging.IsEnabled) { Logging.Error(this, $"{nameof(ProvisionOverWssUsingX509CertificateAsync)} PlatformNotSupportedException thrown as .NET Core 2.0 doesn't support proxy"); } } await websocket.ConnectAsync(websocketUri, cancellationToken).ConfigureAwait(false); var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( new ReadTimeoutHandler(ReadTimeoutSeconds), MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), new LoggingHandler(LogLevel.DEBUG), new ProvisioningChannelHandlerAdapter(message, tcs, cancellationToken)); await s_eventLoopGroup.RegisterAsync(clientChannel).ConfigureAwait(false); return(await tcs.Task.ConfigureAwait(false)); }
private async Task <RegistrationOperationStatus> ProvisionOverWssUsingX509CertificateAsync( ProvisioningTransportRegisterMessage message, CancellationToken cancellationToken) { Debug.Assert(message.Security is SecurityProviderX509); cancellationToken.ThrowIfCancellationRequested(); X509Certificate2 clientCertificate = ((SecurityProviderX509)message.Security).GetAuthenticationCertificate(); var tcs = new TaskCompletionSource <RegistrationOperationStatus>(); UriBuilder uriBuilder = new UriBuilder(WsScheme, message.GlobalDeviceEndpoint, Port); Uri websocketUri = uriBuilder.Uri; // TODO properly dispose of the ws. var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WsMqttSubprotocol); websocket.Options.ClientCertificates.Add(clientCertificate); await websocket.ConnectAsync(websocketUri, cancellationToken).ConfigureAwait(false); // TODO: use ClientWebSocketChannel. var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( new ReadTimeoutHandler(ReadTimeoutSeconds), MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), new ProvisioningChannelHandlerAdapter(message, tcs, cancellationToken)); await s_eventLoopGroup.RegisterAsync(clientChannel).ConfigureAwait(false); return(await tcs.Task.ConfigureAwait(false)); }
public async Task ClientWebSocketChannelReadAfterCloseTest() { var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); var uri = new Uri("ws://" + IotHubName + ":" + Port + WebSocketConstants.UriSuffix); await websocket.ConnectAsync(uri, CancellationToken.None); var clientReadListener = new ReadListeningHandler(); var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, true) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default); clientChannel.Pipeline.AddLast( clientReadListener); var threadLoop = new SingleThreadEventLoop("MQTTExecutionThread", TimeSpan.FromSeconds(1)); await threadLoop.RegisterAsync(clientChannel); await clientChannel.CloseAsync(); // Test Read API try { await clientReadListener.ReceiveAsync(DefaultTimeout); Assert.Fail("Should have thrown InvalidOperationException"); } catch (InvalidOperationException e) { Assert.IsTrue(e.Message.Contains("Channel is closed")); } done = true; }
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; }; }