public async Task ProcessWebSocketRequestAsync(WebSocket webSocket, Option <EndPoint> localEndPoint, EndPoint remoteEndPoint, string correlationId, Option <X509Certificate2> clientCert, Option <IList <X509Certificate2> > clientCertChain) { try { DeviceIdentityProvider identityProvider = new DeviceIdentityProvider(this.authenticator, this.clientCredentialsFactory, true); var serverChannel = new ServerWebSocketChannel( webSocket, remoteEndPoint ); clientCert.Map(cert => { return(identityProvider.RemoteCertificateValidationCallback(cert, clientCertChain.Expect(() => new ArgumentException("Certificate chain was found to be null")))); }); serverChannel .Option(ChannelOption.Allocator, this.byteBufferAllocator) .Option(ChannelOption.AutoRead, this.autoRead) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, this.mqttDecoderMaxMessageSize), new MqttAdapter( this.settings, this.sessionProviderFactory(), identityProvider, null, this.messagingBridgeFactoryFunc)); await this.workerGroup.GetNext().RegisterAsync(serverChannel); Events.Established(correlationId); await serverChannel.WebSocketClosed.Task; // This will wait until the websocket is closed } catch (Exception ex) when(!ex.IsFatal()) { Events.Exception(correlationId, ex); throw; } }
ServerBootstrap SetupServerBootstrap() { int maxInboundMessageSize = this.settingsProvider.GetIntegerSetting("MaxInboundMessageSize", DefaultMaxInboundMessageSize); int threadCount = this.settingsProvider.GetIntegerSetting("ThreadCount", DefaultThreadCount); int listenBacklogSize = this.settingsProvider.GetIntegerSetting("ListenBacklogSize", DefaultListenBacklogSize); int parentEventLoopCount = this.settingsProvider.GetIntegerSetting("EventLoopCount", DefaultParentEventLoopCount); var settings = new Settings(this.settingsProvider); MessagingBridgeFactoryFunc bridgeFactory = this.mqttConnectionProvider.Connect; var bootstrap = new ServerBootstrap(); // multithreaded event loop that handles the incoming connection IEventLoopGroup parentEventLoopGroup = new MultithreadEventLoopGroup(parentEventLoopCount); // multithreaded event loop (worker) that handles the traffic of the accepted connections this.eventLoopGroup = new MultithreadEventLoopGroup(threadCount); bootstrap.Group(parentEventLoopGroup, this.eventLoopGroup) .Option(ChannelOption.SoBacklog, listenBacklogSize) // Allow listening socket to force bind to port if previous socket is still in TIME_WAIT // Fixes "address is already in use" errors .Option(ChannelOption.SoReuseaddr, true) .ChildOption(ChannelOption.Allocator, this.byteBufferAllocator) .ChildOption(ChannelOption.AutoRead, AutoRead) // channel that accepts incoming connections .Channel <TcpServerSocketChannel>() // Channel initializer, it is handler that is purposed to help configure a new channel .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { DeviceIdentityProvider identityProvider = new DeviceIdentityProvider(this.authenticator, this.clientCredentialsFactory, this.clientCertAuthAllowed); // configure the channel pipeline of the new Channel by adding handlers TlsSettings serverSettings = new ServerTlsSettings( certificate: this.tlsCertificate, negotiateClientCertificate: this.clientCertAuthAllowed ); channel.Pipeline.AddLast(new TlsHandler(stream => new SslStream(stream, true, (sender, remoteCertificate, remoteChain, sslPolicyErrors) => this.clientCertAuthAllowed ? identityProvider.RemoteCertificateValidationCallback(remoteCertificate, remoteChain) : true), serverSettings)); channel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, maxInboundMessageSize), new MqttAdapter( settings, this.sessionProvider, identityProvider, null, bridgeFactory)); })); var mqttWebSocketListener = new MqttWebSocketListener( settings, bridgeFactory, this.authenticator, this.clientCredentialsFactory, () => this.sessionProvider, new MultithreadEventLoopGroup(Environment.ProcessorCount), this.byteBufferAllocator, AutoRead, maxInboundMessageSize); this.webSocketListenerRegistry.TryRegister(mqttWebSocketListener); return(bootstrap); }