public Task ProcessWebSocketRequestAsync( WebSocket webSocket, Option <EndPoint> localEndPoint, EndPoint remoteEndPoint, string correlationId, X509Certificate2 clientCert, IList <X509Certificate2> clientCertChain) { var identityProvider = new DeviceIdentityProvider(this.authenticator, this.clientCredentialsFactory, this.clientCertAuthAllowed); identityProvider.RegisterConnectionCertificate(clientCert, clientCertChain); return(this.ProcessWebSocketRequestAsyncInternal(identityProvider, webSocket, localEndPoint, remoteEndPoint, correlationId)); }
bool RemoteCertificateValidationCallback(DeviceIdentityProvider identityProvider, X509Certificate certificate, X509Chain chain) { if (this.clientCertAuthAllowed && certificate != null) { IList <X509Certificate2> certChain = chain?.ChainElements? .Cast <X509ChainElement>() .Select(element => element.Certificate) .ToList() ?? new List <X509Certificate2>(); identityProvider.RegisterConnectionCertificate(new X509Certificate2(certificate), certChain); } return(true); }
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; } }
public async Task ProcessWebSocketRequestAsyncInternal( DeviceIdentityProvider identityProvider, WebSocket webSocket, Option <EndPoint> localEndPoint, EndPoint remoteEndPoint, string correlationId) { try { var serverChannel = new ServerWebSocketChannel(webSocket, remoteEndPoint); 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; } }
public Task ProcessWebSocketRequestAsync(WebSocket webSocket, Option <EndPoint> localEndPoint, EndPoint remoteEndPoint, string correlationId) { var identityProvider = new DeviceIdentityProvider(this.authenticator, this.usernameParser, this.clientCredentialsFactory, this.metadataStore, this.clientCertAuthAllowed); return(this.ProcessWebSocketRequestAsyncInternal(identityProvider, webSocket, localEndPoint, remoteEndPoint, correlationId)); }
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 => { var 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.RemoteCertificateValidationCallback(identityProvider, remoteCertificate, remoteChain)), 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.clientCertAuthAllowed); this.webSocketListenerRegistry.TryRegister(mqttWebSocketListener); return(bootstrap); }