Esempio n. 1
0
        public IMqttChannelAdapter CreateClientAdapter(IMqttClientOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            IMqttChannel channel;

            switch (options.ChannelOptions)
            {
            case MqttClientTcpOptions _:
            {
                channel = new MqttTcpChannel(options);
                break;
            }

            case MqttClientWebSocketOptions webSocketOptions:
            {
                channel = new MqttWebSocketChannel(webSocketOptions);
                break;
            }

            default:
            {
                throw new NotSupportedException();
            }
            }

            var packetFormatterAdapter = new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttPacketWriter());

            return(new MqttChannelAdapter(channel, packetFormatterAdapter, options.PacketInspector, _logger));
        }
        async void OnConnectionReceivedAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            try
            {
                var clientHandler = ClientHandler;
                if (clientHandler != null)
                {
                    X509Certificate2 clientCertificate = null;

                    if (args.Socket.Control.ClientCertificate != null)
                    {
                        try
                        {
                            clientCertificate = new X509Certificate2(args.Socket.Control.ClientCertificate.GetCertificateBlob().ToArray());
                        }
                        catch (Exception exception)
                        {
                            _logger.Warning(exception, "Unable to convert UWP certificate to X509Certificate2.");
                        }
                    }

                    var bufferWriter           = new MqttBufferWriter(4096, 65535);
                    var packetFormatterAdapter = new MqttPacketFormatterAdapter(bufferWriter);
                    var tcpChannel             = new MqttTcpChannel(args.Socket, clientCertificate, _options);

                    using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, null, _rootLogger))
                    {
                        await clientHandler(clientAdapter).ConfigureAwait(false);
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception is ObjectDisposedException)
                {
                    // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
                    return;
                }

                _logger.Error(exception, "Error while handling client connection.");
            }
            finally
            {
                try
                {
                    args.Socket.Dispose();
                }
                catch (Exception exception)
                {
                    _logger.Error(exception, "Error while cleaning up client connection.");
                }
            }
        }
        private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false);

                    var tcpChannel    = new MqttTcpChannel(clientSocket, null);
                    var clientAdapter = new MqttChannelCommunicationAdapter(tcpChannel, new MqttPacketSerializer());
                    ClientAccepted?.Invoke(clientAdapter);
                }
                catch (Exception exception) when(!(exception is ObjectDisposedException))
                {
                    MqttNetTrace.Error(nameof(MqttServerAdapter), exception, "Error while accepting connection at default endpoint.");

                    //excessive CPU consumed if in endless loop of socket errors
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
                }
            }
        }
        private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    var clientSocket = await Task.Factory.FromAsync(_tlsEndpointSocket.BeginAccept, _tlsEndpointSocket.EndAccept, null).ConfigureAwait(false);

                    var sslStream = new SslStream(new NetworkStream(clientSocket));
                    await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false);

                    var tcpChannel    = new MqttTcpChannel(clientSocket, sslStream);
                    var clientAdapter = new MqttChannelCommunicationAdapter(tcpChannel, new MqttPacketSerializer());
                    ClientAccepted?.Invoke(clientAdapter);
                }
                catch (Exception exception)
                {
                    MqttNetTrace.Error(nameof(MqttServerAdapter), exception, "Error while accepting connection at TLS endpoint.");

                    //excessive CPU consumed if in endless loop of socket errors
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
                }
            }
        }
Esempio n. 5
0
        async Task TryHandleClientConnectionAsync(CrossPlatformSocket clientSocket)
        {
            Stream stream         = null;
            string remoteEndPoint = null;

            try
            {
                remoteEndPoint = clientSocket.RemoteEndPoint.ToString();

                _logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.",
                                remoteEndPoint,
                                _localEndPoint,
                                _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");

                clientSocket.NoDelay = _options.NoDelay;
                stream = clientSocket.GetStream();
                X509Certificate2 clientCertificate = null;

                if (_tlsCertificate != null)
                {
                    var sslStream = new SslStream(stream, false, _tlsOptions.RemoteCertificateValidationCallback);

                    #if NETCOREAPP3_1 || NET5_0_OR_GREATER
                    await sslStream.AuthenticateAsServerAsync(
                        new SslServerAuthenticationOptions()
                    {
                        ServerCertificate              = _tlsCertificate,
                        ClientCertificateRequired      = _tlsOptions.ClientCertificateRequired,
                        EnabledSslProtocols            = _tlsOptions.SslProtocol,
                        CertificateRevocationCheckMode = _tlsOptions.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck,
                        EncryptionPolicy   = EncryptionPolicy.RequireEncryption,
                        CipherSuitesPolicy = _tlsOptions.CipherSuitesPolicy
                    }).ConfigureAwait(false);
                    #else
                    await sslStream.AuthenticateAsServerAsync(
                        _tlsCertificate,
                        _tlsOptions.ClientCertificateRequired,
                        _tlsOptions.SslProtocol,
                        _tlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
                    #endif

                    stream = sslStream;

                    clientCertificate = sslStream.RemoteCertificate as X509Certificate2;

                    if (clientCertificate == null && sslStream.RemoteCertificate != null)
                    {
                        clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert));
                    }
                }

                var clientHandler = ClientHandler;
                if (clientHandler != null)
                {
                    var tcpChannel             = new MqttTcpChannel(stream, remoteEndPoint, clientCertificate);
                    var bufferWriter           = new MqttBufferWriter(_serverOptions.WriterBufferSize, _serverOptions.WriterBufferSizeMax);
                    var packetFormatterAdapter = new MqttPacketFormatterAdapter(bufferWriter);

                    using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, null, _rootLogger))
                    {
                        await clientHandler(clientAdapter).ConfigureAwait(false);
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception is ObjectDisposedException)
                {
                    // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed.
                    return;
                }

                if (exception is SocketException socketException &&
                    socketException.SocketErrorCode == SocketError.OperationAborted)
                {
                    return;
                }

                _logger.Error(exception, "Error while handling client connection.");
            }
            finally
            {
                try
                {
                    stream?.Dispose();
                    clientSocket?.Dispose();
                }
                catch (Exception disposeException)
                {
                    _logger.Error(disposeException, "Error while cleaning up client connection");
                }
            }

            _logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.",
                            remoteEndPoint,
                            _localEndPoint,
                            _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6");
        }