Пример #1
0
        /// <summary>
        /// Connect the client to the AR. The given options suit the testcases but have to be reviewed for a production environment regarding reconnecting for example.
        /// </summary>
        /// <param name="mqttClient">-</param>
        /// <param name="onboardResponse">-</param>
        /// <returns>No dedicated response.</returns>
        public static async Task ConnectMqttClient(IMqttClient mqttClient, OnboardResponse onboardResponse)
        {
            var tlsParameters = new MqttClientOptionsBuilderTlsParameters
            {
                Certificates = new[] { ReadRootCertificates(), ReadClientCertificate(onboardResponse) },
                UseTls       = true
            };

            var options = new MqttClientOptionsBuilder()
                          .WithClientId(onboardResponse.ConnectionCriteria.ClientId)
                          .WithTcpServer(onboardResponse.ConnectionCriteria.Host,
                                         int.Parse(onboardResponse.ConnectionCriteria.Port))
                          .WithTls(tlsParameters)
                          .WithCommunicationTimeout(TimeSpan.FromSeconds(20))
                          .Build();

            await mqttClient.ConnectAsync(options);
        }
Пример #2
0
        private IMqttClientOptions GetMqttOption(string clientId)
        {
            var builder = new MqttClientOptionsBuilder()
                          .WithProtocolVersion(MqttProtocolVersion.V311)
                          .WithKeepAlivePeriod(TimeSpan.FromSeconds(5))
                          .WithCommunicationTimeout(TimeSpan.FromSeconds(15))
                          .WithClientId(clientId)
                          // this message will be sent to all clients
                          // subscribed to <clientId>/status topic
                          // if this client gets disconnected
                          .WithWillMessage(new MqttApplicationMessage
            {
                Payload = Encoding.UTF8.GetBytes("disconnected"),
                Topic   = String.Format("/{0}/status", clientId),
                Retain  = true,
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
            });

            // TODO: ?
            // .WithCleanSession();
            if (usingWebSockets)
            {
                builder.WithWebSocketServer(endPoint.Address + ":" + endPoint.Port + "/mqtt");
            }
            else
            {
                builder.WithTcpServer(endPoint.Address, endPoint.Port);
            }
            if (networkCredential != null)
            {
                builder.WithCredentials(networkCredential.UserName, networkCredential.Password);
            }
            if (useSsl)
            {
                var tlsParameters = new MqttClientOptionsBuilderTlsParameters {
                    UseTls = true
                };
                builder.WithTls(tlsParameters);
            }
            return(builder.Build());
        }
Пример #3
0
        public void Start(string certPath)
        {
            X509Certificate2 certificate  = new X509Certificate2(certPath);
            List <byte[]>    certificates = new List <byte[]>();

            certificates.Add(certificate.Export(X509ContentType.SerializedCert));

            //setup connection options
            MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters
            {
                Certificates = certificates,
                SslProtocol  = SslProtocols.Tls12,
                UseTls       = true
            };

            tlsOptions.CertificateValidationCallback += CertificateValidationCallback;

            // Create TCP based options using the builder.
            var options = new MqttClientOptionsBuilder()
                          .WithClientId($"Test_C#_Client_{Guid.NewGuid()}")
                          .WithTcpServer(MqttServer, MqttPort)
                          .WithTls(tlsOptions)
                          .WithCleanSession()
                          .WithKeepAlivePeriod(TimeSpan.FromSeconds(90))
                          .WithKeepAliveSendInterval(TimeSpan.FromSeconds(60))
                          .Build();

            var factory = new MqttFactory();

            mqttClient = factory.CreateMqttClient();

            mqttClient.UseApplicationMessageReceivedHandler(DataHandler);
            mqttClient.UseConnectedHandler(ConnectedHandler);
            mqttClient.UseDisconnectedHandler(DisconnectedHandler);
            Console.WriteLine($"Connecting to mqtt.cloud.yandex.net...");
            mqttClient.ConnectAsync(options, CancellationToken.None);
        }
Пример #4
0
        private static int _iLastUpdateThreshold      = 5;    // Minutes

        public static async void StartMQTT(string strMQTTServer, bool bMQTTTLS, string strClientId, string strUser, string strPassword, MessageHandler messageHandler)
        {
            IManagedMqttClientOptions             options;
            MqttClientOptionsBuilder              clientOptions;
            MqttClientOptionsBuilderTlsParameters optionsTLS;
            int iPort = 0;

            string[] strMQTTServerArray;
            string   strMQTTBroker;

            Logging.WriteDebugLog("MQTT.StartMQTT()");

            if (strMQTTServer == null || strMQTTServer == "")
            {
                return;
            }

            _timerMQTT = new Timer(Update, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));

            _strClientId    = strClientId;
            _messageHandler = messageHandler;

            if (strMQTTServer.Contains(":"))
            {
                strMQTTServerArray = strMQTTServer.Split(new char[] { ':' });
                if (strMQTTServerArray.Length != 2)
                {
                    Logging.WriteDebugLog("MQTT.StartMQTT() MQTTBroker field has incorrect syntax (host or host:port)");
                    return;
                }

                if (!int.TryParse(strMQTTServerArray[1], out iPort) || iPort == 0)
                {
                    Logging.WriteDebugLog("MQTT.StartMQTT() MQTTBroker field has incorrect syntax - port not non-zero numeric (host or host:port)");
                    return;
                }

                if (strMQTTServerArray[0].Length == 0)
                {
                    Logging.WriteDebugLog("MQTT.StartMQTT() MQTTBroker field has incorrect syntax - missing host (host or host:port)");
                    return;
                }

                strMQTTBroker = strMQTTServerArray[0];

                Logging.WriteDebugLog("MQTT.StartMQTT() Host: {0}, Port: {1}", strMQTTBroker, iPort);
            }
            else
            {
                strMQTTBroker = strMQTTServer;

                Logging.WriteDebugLog("MQTT.StartMQTT() Host: {0}", strMQTTBroker);
            }

            clientOptions = new MqttClientOptionsBuilder().WithClientId(_strClientId).WithTcpServer(strMQTTBroker, (iPort == 0 ? null : iPort));
            if (strUser != "")
            {
                clientOptions = clientOptions.WithCredentials(strUser, strPassword);
            }
            if (bMQTTTLS)
            {
                optionsTLS = new MqttClientOptionsBuilderTlsParameters
                {
                    IgnoreCertificateChainErrors = true,
                    UseTls = true,
                    IgnoreCertificateRevocationErrors = true,
                    AllowUntrustedCertificates        = true,
                    SslProtocol = System.Security.Authentication.SslProtocols.Tls12
                };

                clientOptions = clientOptions.WithTls(optionsTLS);
            }

            options = new ManagedMqttClientOptionsBuilder().WithAutoReconnectDelay(TimeSpan.FromSeconds(5)).WithClientOptions(clientOptions.Build()).Build();

            _mqtt = new MqttFactory().CreateManagedMqttClient();

            _mqtt.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(MessageProcessor);

            await _mqtt.StartAsync(options);
        }
Пример #5
0
        public static async Task RunAsync()
        {
            // MqttNetConsoleLogger.ForwardToConsole();

            // For most of these connections to work, set output target to Net5.0.

#if NET5_0_OR_GREATER
            // TLS13 is only available in Net5.0
            var unsafeTls13 = new MqttClientOptionsBuilderTlsParameters
            {
                UseTls      = true,
                SslProtocol = SslProtocols.Tls13,
                // Don't use this in production code. This handler simply allows any invalid certificate to work.
                CertificateValidationHandler = w => true
            };
#endif

            // Also defining TLS12 for servers that don't seem no to support TLS13.
            var unsafeTls12 = new MqttClientOptionsBuilderTlsParameters
            {
                UseTls      = true,
                SslProtocol = SslProtocols.Tls12,
                // Don't use this in production code. This handler simply allows any invalid certificate to work.
                CertificateValidationHandler = w => true
            };

            // mqtt.eclipseprojects.io
            await ExecuteTestAsync("mqtt.eclipseprojects.io TCP",
                                   new MqttClientOptionsBuilder().WithTcpServer("mqtt.eclipseprojects.io", 1883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("mqtt.eclipseprojects.io WS",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("mqtt.eclipseprojects.io:80/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

#if NET5_0_OR_GREATER
            await ExecuteTestAsync("mqtt.eclipseprojects.io WS TLS13",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("mqtt.eclipseprojects.io:443/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls13).Build());
#endif

            // test.mosquitto.org
            await ExecuteTestAsync("test.mosquitto.org TCP",
                                   new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 1883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("test.mosquitto.org TCP - Authenticated",
                                   new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 1884)
                                   .WithCredentials("rw", "readwrite")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("test.mosquitto.org TCP TLS12",
                                   new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls12).Build());

#if NET5_0_OR_GREATER
            await ExecuteTestAsync("test.mosquitto.org TCP TLS13",
                                   new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls13).Build());
#endif

            await ExecuteTestAsync("test.mosquitto.org TCP TLS12 - Authenticated",
                                   new MqttClientOptionsBuilder().WithTcpServer("test.mosquitto.org", 8885)
                                   .WithCredentials("rw", "readwrite")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls12).Build());

            await ExecuteTestAsync("test.mosquitto.org WS",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("test.mosquitto.org:8080/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("test.mosquitto.org WS TLS12",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("test.mosquitto.org:8081/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls12).Build());

            // broker.emqx.io
            await ExecuteTestAsync("broker.emqx.io TCP",
                                   new MqttClientOptionsBuilder().WithTcpServer("broker.emqx.io", 1883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("broker.emqx.io TCP TLS12",
                                   new MqttClientOptionsBuilder().WithTcpServer("broker.emqx.io", 8883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls12).Build());

#if NET5_0_OR_GREATER
            await ExecuteTestAsync("broker.emqx.io TCP TLS13",
                                   new MqttClientOptionsBuilder().WithTcpServer("broker.emqx.io", 8883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls13).Build());
#endif

            await ExecuteTestAsync("broker.emqx.io WS",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("broker.emqx.io:8083/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("broker.emqx.io WS TLS12",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("broker.emqx.io:8084/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).WithTls(unsafeTls12).Build());


            // broker.hivemq.com
            await ExecuteTestAsync("broker.hivemq.com TCP",
                                   new MqttClientOptionsBuilder().WithTcpServer("broker.hivemq.com", 1883)
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            await ExecuteTestAsync("broker.hivemq.com WS",
                                   new MqttClientOptionsBuilder().WithWebSocketServer("broker.hivemq.com:8000/mqtt")
                                   .WithProtocolVersion(MqttProtocolVersion.V311).Build());

            // mqtt.swifitch.cz: Does not seem to operate any more

            // cloudmqtt.com: Cannot test because it does not offer a free plan any more.

            Write("Finished.", ConsoleColor.White);
            Console.ReadLine();
        }
Пример #6
0
 public MqttClientOptionsBuilder WithTls(MqttClientOptionsBuilderTlsParameters parameters)
 {
     _tlsParameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
     return(this);
 }
Пример #7
0
        private MqttClientOptionsBuilder CreateOptionsBuilder(ClientCredentials credentials = null)
        {
            MqttClientOptionsBuilder clientOptionsBuilder       = new MqttClientOptionsBuilder();
            MqttClientOptionsBuilderTlsParameters tlsParameters = null;
            string hostName = Settings.Client.BrokerHostname;
            int    portNum  = Settings.Client.BrokerPort;

            //check if broker endpoint for local connections is defined in environment, only possible for connections without credentials
            if (credentials == null)
            {
                string brokerEndpoint = Environment.GetEnvironmentVariable("GE_BROKER_CONNECTION_ENDPOINT");
                if (!string.IsNullOrEmpty(brokerEndpoint))
                {
                    string[] tokens = brokerEndpoint.Split(':');
                    if (tokens.Length == 2)
                    {
                        hostName = tokens[0];
                        portNum  = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture);
                    }
                }
            }
            clientOptionsBuilder.WithCleanSession();
            clientOptionsBuilder.WithClientId(ClientId);
            if (portNum == 443)
            {
                clientOptionsBuilder.WithWebSocketServer(hostName);
            }
            else
            {
                clientOptionsBuilder.WithTcpServer(hostName, portNum);
            }
            if (credentials != null)
            {
                if (credentials.HasCertificates())
                {
                    tlsParameters = new MqttClientOptionsBuilderTlsParameters
                    {
                        UseTls = true,
                        AllowUntrustedCertificates        = Settings.Client.AllowUntrustedCertificates,
                        IgnoreCertificateChainErrors      = Settings.Client.IgnoreCertificateChainErrors,
                        IgnoreCertificateRevocationErrors = Settings.Client.IgnoreCertificateRevocationErrors,
                        CertificateValidationHandler      = CertificateValidationCallback,
                        Certificates = credentials.ClientCertAndCaChain,
                        SslProtocol  = SslProtocols.Tls12
                    };
                    clientOptionsBuilder.WithTls(tlsParameters);
                }
                if (credentials.IsUserNameAndPasswordRequired())
                {
                    credentials.GetUserNameAndPassword(ClientId, out string username, out string password);
                    clientOptionsBuilder.WithCredentials(username, password);
                }
            }

            // settings for connection timeout and MQTT kepp alive interval, given in seconds
            // (defaults in MQTTnet stack are CommunicationTimeout = 10 sec and KeepAlivePeriod = 15 sec.,
            //  see in MqttClientOptions.cs of MQTTnet)
            clientOptionsBuilder.WithCommunicationTimeout(new TimeSpan(0, 0, Settings.Client.CommunicationTimeout));
            clientOptionsBuilder.WithKeepAlivePeriod(new TimeSpan(0, 0, Settings.Client.MqttKeepAlivePeriod));
            return(clientOptionsBuilder);
        }
Пример #8
0
        public async Task ConnectAsync(Options options, TaskCompletionSource <int> closedPromise)
        {
            if (options.Verbose)
            {
                MqttNetGlobalLogger.LogMessagePublished += (s, e) =>
                {
                    var trace = $">> [{e.LogMessage.Timestamp:O}] [{e.LogMessage.ThreadId}] [{e.LogMessage.Source}] [{e.LogMessage.Level}]: {e.LogMessage.Message}";
                    if (e.LogMessage.Exception != null)
                    {
                        trace += Environment.NewLine + e.LogMessage.Exception.ToString();
                    }

                    Console.WriteLine(trace);
                };
            }

            var factory = new MqttFactory();
            var client  = factory.CreateMqttClient();

            client.UseApplicationMessageReceivedHandler(msg => this.HandleMessageAsync(msg));

            var tlsOptions = new MqttClientOptionsBuilderTlsParameters();

            tlsOptions.UseTls = true;

            var clientOptions = new MqttClientOptionsBuilder()
                                .WithTcpServer(opt => opt.NoDelay = true)
                                .WithClientId(options.ClientId)
                                .WithTcpServer(options.Hostname, 8883)
                                .WithTls(tlsOptions)
                                .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
                                // .WithUserProperty("host", hostName) // normally it is not needed as SNI is added by most TLS implementations.
                                .WithUserProperty("api-version", "2020-10-01-preview")
                                .WithCommunicationTimeout(TimeSpan.FromSeconds(30))
                                .WithKeepAlivePeriod(TimeSpan.FromSeconds(300))
                                .WithCleanSession(false); // keep existing subscriptions

            if (string.IsNullOrEmpty(options.SasKey))
            {
                tlsOptions.Certificates = new[] { new X509Certificate(options.ClientCertificatePath, options.ClientCertificatePassword) };
                clientOptions.WithAuthentication("X509", null);
            }
            else
            {
                var    at           = DateTimeOffset.UtcNow;
                var    atString     = at.ToUnixTimeMilliseconds().ToString();
                var    expiry       = at.AddMinutes(40);
                var    expiryString = expiry.ToUnixTimeMilliseconds().ToString();
                string toSign       = $"{options.Hostname}\n{options.ClientId}\n{options.SasPolicy}\n{atString}\n{expiryString}\n";
                var    hmac         = new HMACSHA256(Convert.FromBase64String(options.SasKey));
                var    sas          = hmac.ComputeHash(Encoding.UTF8.GetBytes(toSign));

                clientOptions
                .WithAuthentication("SAS", sas)
                .WithUserProperty("sas-at", atString)
                .WithUserProperty("sas-expiry", expiryString);
                if (!string.IsNullOrEmpty(options.SasPolicy))
                {
                    // include only if using SAS policy
                    clientOptions.WithUserProperty("sas-policy", options.SasPolicy);
                }
            }

            // Set up disconnection handling: print out details and allow process to close
            client.UseDisconnectedHandler(disconnectArgs =>
            {
                Console.WriteLine($"Disconnected: {disconnectArgs.ReasonCode}");
                if (disconnectArgs.AuthenticateResult?.UserProperties != null)
                {
                    foreach (var prop in disconnectArgs.AuthenticateResult.UserProperties)
                    {
                        Console.WriteLine($"{prop.Name}: {prop.Value}");
                    }
                }
                closedPromise.SetResult(1);
            });

            try
            {
                // once connection is established, we may start receiving messages based on subscriptions
                // from previous connections - better set client before connection.
                this.client = client;

                var connectResult = await client.ConnectAsync(clientOptions.Build(), CancellationToken.None);

                if (connectResult.ResultCode != MqttClientConnectResultCode.Success)
                {
                    var status = GetStatus(connectResult.UserProperties)?.ToString("x4");
                    throw new Exception($"Connect failed. Status: {connectResult.ResultCode}; status: {status}");
                }

                if (!connectResult.IsSessionPresent)
                {
                    // only subscribe if haven't subscribed already.
                    // This optimization only works of a single SUBSCRIBE is used to subscribe to everything at once or
                    // if app keeps track of what has been successfully acknowledged by server.
                    var subscribeResult = await client.SubscribeAsync(
                        new MqttTopicFilter
                    {
                        Topic = "$iothub/methods/+",
                        QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
                    },
                        new MqttTopicFilter
                    {
                        Topic = "$iothub/commands",
                        QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce
                    },
                        new MqttTopicFilter
                    {
                        Topic = "$iothub/twin/patch/desired",
                        QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
                    });

                    // make sure subscriptions were successful
                    if (subscribeResult.Items.Count != 3 ||
                        subscribeResult.Items[0].ResultCode != MqttClientSubscribeResultCode.GrantedQoS0 ||
                        subscribeResult.Items[1].ResultCode != MqttClientSubscribeResultCode.GrantedQoS1 ||
                        subscribeResult.Items[2].ResultCode != MqttClientSubscribeResultCode.GrantedQoS0)
                    {
                        throw new ApplicationException("Failed to subscribe");
                    }
                }
            }
            catch (MqttConnectingFailedException ex)
            {
                Console.WriteLine($"Failed to connect, reason code: {ex.ResultCode}");
                if (ex.Result?.UserProperties != null)
                {
                    foreach (var prop in ex.Result.UserProperties)
                    {
                        Console.WriteLine($"{prop.Name}: {prop.Value}");
                    }
                }
                throw;
            }
        }
Пример #9
0
        private void Start(string brokerUrl, int port, string clientId, string username, string password, X509Certificate2 serverRootCa, X509Certificate clientCertificate, string[] topics)
        {
            _brokerUrl    = brokerUrl;
            _port         = port;
            Topics        = topics;
            _serverRootCa = serverRootCa;

            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                $"Start MQTT Client..."
            }, LogRecordLevel.Info));

            try
            {
                lock (_lockObject)
                {
                    var optionsBuilder = new MqttClientOptionsBuilder()
                                         .WithClientId(clientId)
                                         .WithTcpServer(brokerUrl, port)
                                         .WithCleanSession()
                                                                                                                 //.WithKeepAliveSendInterval(TimeSpan.FromSeconds(KeepAliveIntervalSec)) // Keep alive send interval
                                         .WithKeepAlivePeriod(TimeSpan.FromSeconds(KeepAliveIntervalSec * 1.5)); // Time after last keep alive when IoT Core will disconnect the client

                    if (clientCertificate == null)
                    {
                        //auth by username and password
                        optionsBuilder.WithCredentials(username, password);

                        if (serverRootCa != null)
                        {
                            MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters();
                            tlsOptions.UseTls = true;
                            tlsOptions.AllowUntrustedCertificates = true;
                            //tlsOptions.IgnoreCertificateChainErrors = true;
                            //tlsOptions.IgnoreCertificateRevocationErrors = true;
                            tlsOptions.CertificateValidationCallback += MqttClient_CertificateValidationCallback;

                            optionsBuilder.WithTls(tlsOptions);
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Setup connection with username and password over TLS"
                            }, LogRecordLevel.Info));
                        }
                        else
                        {
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Setup connection with username and password"
                            }, LogRecordLevel.Info));
                        }
                    }
                    else
                    {
                        // Auth by client certificate
                        List <X509Certificate> certificates = new List <X509Certificate>();
                        certificates.Add(clientCertificate);

                        MqttClientOptionsBuilderTlsParameters tlsOptions = new MqttClientOptionsBuilderTlsParameters();
                        tlsOptions.Certificates = certificates;
                        tlsOptions.UseTls       = true;
                        tlsOptions.AllowUntrustedCertificates = true;
                        //tlsOptions.IgnoreCertificateChainErrors = true;
                        //tlsOptions.IgnoreCertificateRevocationErrors = true;

                        if (serverRootCa != null)
                        {
                            tlsOptions.AllowUntrustedCertificates     = true;
                            tlsOptions.CertificateValidationCallback += MqttClient_CertificateValidationCallback;
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Setup connection with client and server certificate over TLS"
                            }, LogRecordLevel.Info));
                        }
                        else
                        {
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Setup connection with client certificate over TLC"
                            }, LogRecordLevel.Info));
                        }

                        optionsBuilder.WithTls(tlsOptions);
                    }

                    _options = optionsBuilder.Build();

                    while (true)
                    {
                        try
                        {
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Connecting to MQTT server ..."
                            }, LogRecordLevel.Info));
                            _mqttClient.ConnectAsync(_options).Wait(new TimeSpan(Timeout));
                            break;
                        }
                        catch (Exception ex)
                        {
                            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                                $"Can't connect to MQTT server: {ex.Message}"
                            }, LogRecordLevel.Error));
                            Thread.Sleep(Timeout);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                    $"MQTT Client start was failed: {ex.Message}"
                }, LogRecordLevel.Error));
            }

            Logger.Instance.AppendLog(new LogRecord(DateTime.Now, new List <string> {
                $"MQTT Client started"
            }, LogRecordLevel.Info));
        }
Пример #10
0
        public static async void exec()
        {
            Console.WriteLine("Enter ClientID");
            string ClientID = Console.ReadLine();

            Console.WriteLine("Chat with:");
            string Friend = Console.ReadLine();

            IManagedMqttClient mqttClient = new MqttFactory().CreateManagedMqttClient();

            try
            {
                MqttClientOptionsBuilderTlsParameters TlsOptions = new MqttClientOptionsBuilderTlsParameters
                {
                    UseTls = false
                };

                var options = new MqttClientOptionsBuilder()
                              .WithClientId(Guid.NewGuid().ToString("N"))
                              .WithTcpServer("localhost")
                              .WithTls(TlsOptions);

                var moptions = new ManagedMqttClientOptionsBuilder()
                               .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
                               .WithClientOptions(options)
                               .Build();

                await mqttClient.StartAsync(moptions);
            }
            catch (Exception ex)
            {
                throw ex;
            }


            mqttClient.ApplicationMessageReceived += (s, e) =>
            {
                //Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
                Console.WriteLine($"{e.ApplicationMessage.Topic}: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");

                //Console.WriteLine($"+ Payload = ");
                //Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
                //Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
                Console.WriteLine();
            };

            mqttClient.Connected += async(s, e) =>
            {
                Console.WriteLine("### CONNECTED WITH SERVER ###");

                // Subscribe to a topic
                await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"chat/{Friend}").Build());

                Console.WriteLine("### SUBSCRIBED ###");
            };

            while (true)
            {
                string msg     = Console.ReadLine();
                var    message = new MqttApplicationMessageBuilder()
                                 .WithTopic($"chat/{ClientID}")
                                 .WithPayload(msg)
                                 .Build();

                await mqttClient.PublishAsync(message);
            }
        }
Пример #11
0
        public static MqttStatus Connect(string url, MqttConfig config)
        {
            Guid key = Guid.NewGuid();

            try
            {
#if DEBUG
                IMqttClient client = new MqttFactory().CreateMqttClient(new ConsoleLogger());
#else
                IMqttClient client = new MqttFactory().CreateMqttClient();
#endif

                var b = new MqttClientOptionsBuilder()
                        .WithTcpServer(url, config.Port)
                        .WithKeepAlivePeriod(TimeSpan.FromSeconds(config.KeepAlive))
                        .WithMaximumPacketSize(Convert.ToUInt32(config.BufferSize))
                        .WithCommunicationTimeout(TimeSpan.FromSeconds(config.ConnectionTimeout))
                        .WithCleanSession(config.CleanSession);

                if (config.SessionExpiryInterval > 0)
                {
                    b = b.WithSessionExpiryInterval((uint)config.SessionExpiryInterval);
                }

                if (!string.IsNullOrEmpty(config.ClientId))
                {
                    b = b.WithClientId(config.ClientId);
                }

                if (!config.SSLConnection)
                {
                    b = b.WithCredentials(config.UserName, config.Password);
                }

                switch (config.ProtocolVersion)
                {
                case 310:
                    b = b.WithProtocolVersion(MqttProtocolVersion.V310);
                    break;

                case 311:
                    b = b.WithProtocolVersion(MqttProtocolVersion.V311);
                    break;

                case 500:
                    b = b.WithProtocolVersion(MqttProtocolVersion.V500);
                    break;

                default:
                    throw new InvalidDataException("Invalid protocol versions. Valid versions are 310, 311 or 500");
                }


                if (config.SSLConnection)
                {
                    string           base64CACert = RSAKeys.GetPlainBase64(config.CAcertificate);
                    X509Certificate2 caCert       = new X509Certificate2(Convert.FromBase64String(base64CACert));
                    byte[]           caBytes      = caCert.Export(X509ContentType.Cert);

                    string           base64Client = RSAKeys.GetPlainBase64(config.ClientCertificate);
                    X509Certificate2 cliCert      = new X509Certificate2(Convert.FromBase64String(base64Client), config.ClientCerificatePassphrase);
                    cliCert = cliCert.CopyWithPrivateKey(RSAKeys.ImportPrivateKey(config.PrivateKey, new PasswordFinder(config.ClientCerificatePassphrase)));
                    byte[] cliBytes = cliCert.Export(X509ContentType.Pfx);

                    try
                    {
                        var tls = new MqttClientOptionsBuilderTlsParameters
                        {
                            SslProtocol = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
                            UseTls      = true,
                            AllowUntrustedCertificates        = true,
                            IgnoreCertificateChainErrors      = true,
                            IgnoreCertificateRevocationErrors = true,

                            Certificates = new List <X509Certificate>()
                            {
                                caCert, cliCert
                            },
                            //CertificateValidationHandler = context => true
                            CertificateValidationCallback = (certificate, chain, sslError, opts) => true
                        };

                        b = b.WithTls(tls);
                    }
                    finally
                    {
                        caCert.Dispose();
                        cliCert.Dispose();
                    }
                }


                client.UseDisconnectedHandler(async e =>
                {
                    try
                    {
                        if (Connections.ContainsKey(key))
                        {
                            await Task.Delay(TimeSpan.FromSeconds(config.AutoReconnectDelay));
                            MqttClientAuthenticateResult reconnectResult = await client.ConnectAsync(b.Build());
                            SubscribePreviousConnection(key, reconnectResult);
                        }
                    }
                    catch
                    {
                        Connections.Remove(key);
                        client.Dispose();
                    }
                });

                MqttClientAuthenticateResult result = client.ConnectAsync(b.Build()).GetAwaiter().GetResult();

                MqttClient mqtt = new MqttClient(client, config);

                Connections[key] = mqtt;

                SubscribePreviousConnection(key, result);
            }
            catch (Exception ex)
            {
                return(MqttStatus.Fail(Guid.Empty, ex));
            }

            return(MqttStatus.Success(key));
        }
Пример #12
0
        /// <summary>
        /// Service Start action. Do not call this directly.
        /// </summary>
        /// <param name="cancellationToken">Cancelation token.</param>
        /// <returns>Awaitable <see cref="Task" />.</returns>
        public async Task StartAsync(CancellationToken cancellationToken = default)
        {
            _serviceLog.LogInformation("Service start initiated");
            _stopping = false;

            // MQTT will message
            var willMessage = new MqttApplicationMessageBuilder()
                              .WithTopic($"{TopicRoot}/connected")
                              .WithPayload(((int)ConnectionStatus.Disconnected).ToString())
                              .WithAtLeastOnceQoS()
                              .WithRetainFlag()
                              .Build();

            // MQTT client options
            var optionsBuilder = new MqttClientOptionsBuilder()
                                 .WithTcpServer(_brokerSettings.BrokerIp, _brokerSettings.BrokerPort)
                                 .WithClientId(MqttClientId.ToString())
                                 .WithCleanSession()
                                 .WithWillMessage(willMessage);

            // MQTT TLS support
            if (_brokerSettings.BrokerUseTls)
            {
                if (_brokerSettings.BrokerTlsSettings == null)
                {
                    throw new ArgumentNullException(nameof(_brokerSettings.BrokerTlsSettings));
                }

                var tlsOptions = new MqttClientOptionsBuilderTlsParameters
                {
                    UseTls = _brokerSettings.BrokerUseTls,
                    AllowUntrustedCertificates        = _brokerSettings.BrokerTlsSettings.AllowUntrustedCertificates,
                    IgnoreCertificateChainErrors      = _brokerSettings.BrokerTlsSettings.IgnoreCertificateChainErrors,
                    IgnoreCertificateRevocationErrors = _brokerSettings.BrokerTlsSettings.IgnoreCertificateRevocationErrors,
                    SslProtocol  = _brokerSettings.BrokerTlsSettings.SslProtocol,
                    Certificates = _brokerSettings.BrokerTlsSettings.Certificates
                };

                optionsBuilder.WithTls(tlsOptions);
            }

            // MQTT credentials
            if (!string.IsNullOrEmpty(_brokerSettings.BrokerUsername) && !string.IsNullOrEmpty(_brokerSettings.BrokerPassword))
            {
                optionsBuilder.WithCredentials(_brokerSettings.BrokerUsername, _brokerSettings.BrokerPassword);
            }

            var managedOptions = new ManagedMqttClientOptionsBuilder()
                                 .WithAutoReconnectDelay(TimeSpan.FromSeconds(_brokerSettings.BrokerReconnectDelay))
                                 .WithClientOptions(optionsBuilder.Build())
                                 .Build();

            // Subscribe to MQTT messages
            await SubscribeAsync(cancellationToken)
            .ConfigureAwait(false);

            // Connect to MQTT
            await MqttClient.StartAsync(managedOptions)
            .ConfigureAwait(false);

            // Call startup on inheriting service class
            await StartServiceAsync(cancellationToken)
            .ConfigureAwait(false);

            _serviceLog.LogInformation("Service started successfully");
        }