Esempio n. 1
0
        public async Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            ThrowIfDisposed();

            try
            {
                _disconnectReason         = MqttClientDisconnectReason.NormalDisconnection;
                _cleanDisconnectInitiated = true;

                if (IsConnected)
                {
                    var disconnectPacket = _adapter.PacketFormatterAdapter.DataConverter.CreateDisconnectPacket(options);
                    await SendAsync(disconnectPacket, cancellationToken).ConfigureAwait(false);
                }
            }
            finally
            {
                if (!DisconnectIsPending())
                {
                    await DisconnectInternalAsync(null, null, null).ConfigureAwait(false);
                }
            }
        }
Esempio n. 2
0
        /// <inheritdoc cref="IMqttClient.DisconnectAsync" />
        public Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken)
        {
            _broker.Disconnect(ClientId);

            IsConnected = false;

            return(Task.CompletedTask);
        }
Esempio n. 3
0
        public MqttDisconnectPacket CreateDisconnectPacket(MqttClientDisconnectOptions options)
        {
            if (options != null)
            {
                throw new MqttProtocolViolationException("Reason codes for disconnect are only supported for MQTTv5.");
            }

            return(new MqttDisconnectPacket());
        }
Esempio n. 4
0
        public MqttDisconnectPacket CreateDisconnectPacket(MqttClientDisconnectOptions options)
        {
            if (options.ReasonCode != MqttClientDisconnectReason.NormalDisconnection || options.ReasonString != null)
            {
                throw new MqttProtocolViolationException("Reason codes and reason string for disconnect are only supported for MQTTv5.");
            }

            return(new MqttDisconnectPacket());
        }
Esempio n. 5
0
        public static Task DisconnectAsync(this IMqttClient client, MqttClientDisconnectOptions options)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            return(client.DisconnectAsync(options, CancellationToken.None));
        }
Esempio n. 6
0
        public async Task DisconnectAsync(CancellationToken cancellationToken)
        {
            var cancelToken       = cancellationToken != null ? cancellationToken : CancellationToken.None;
            var disconnectOptions = new MqttClientDisconnectOptions {
                ReasonString = "Bridge disconnect"
            };
            await PrimaryClient.DisconnectAsync(disconnectOptions, cancelToken);

            await SecondaryClient.DisconnectAsync(disconnectOptions, cancelToken);
        }
Esempio n. 7
0
        public async Task DisconnectAsync(CancellationToken cancellationToken)
        {
            var cancelToken       = cancellationToken != null ? cancellationToken : CancellationToken.None;
            var disconnectOptions = new MqttClientDisconnectOptions {
                ReasonString = "Bridge disconnect"
            };
            await LocalClient.DisconnectAsync(disconnectOptions, cancelToken);

            await DeviceClient.CloseAsync(cancelToken);
        }
Esempio n. 8
0
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            var disconnectOptions = new MqttClientDisconnectOptions
            {
                ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                ReasonString = "Diconnection"
            };

            await this.client.DisconnectAsync(disconnectOptions, cancellationToken);
        }
Esempio n. 9
0
 public async Task StopAsync(CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         var disconnectOption = new MqttClientDisconnectOptions {
             ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
             ReasonString = "NormalDiconnection"
         };
         await mqttClient.DisconnectAsync(disconnectOption, cancellationToken);
     }
     await mqttClient.DisconnectAsync();
 }
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            this.logger.LogInformation("MQTT Service Stop!");

            if (cancellationToken.IsCancellationRequested)
            {
                var disconnectOption = new MqttClientDisconnectOptions
                {
                    ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                    ReasonString = "NormalDiconnection"
                };
                await this.mqttClient.DisconnectAsync(disconnectOption, cancellationToken);
            }
            await this.mqttClient.DisconnectAsync(cancellationToken);
        }
Esempio n. 11
0
        public MqttDisconnectPacket CreateDisconnectPacket(MqttClientDisconnectOptions options)
        {
            var packet = new MqttDisconnectPacket();

            if (options == null)
            {
                packet.ReasonCode = MqttDisconnectReasonCode.NormalDisconnection;
            }
            else
            {
                packet.ReasonCode = (MqttDisconnectReasonCode)options.ReasonCode;
            }

            return(packet);
        }
Esempio n. 12
0
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            // o app ser encerrado

            if (cancellationToken.IsCancellationRequested)
            {
                var disconnectOption = new MqttClientDisconnectOptions
                {
                    ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                    ReasonString = "NormalDisconnection"
                };
                await mqttClient.DisconnectAsync(disconnectOption, cancellationToken);
            }
            await mqttClient.DisconnectAsync();

            _logger.LogInformation("Encerrando...");
        }
Esempio n. 13
0
        async Task TrySendDisconnectPacket(MqttClientDisconnectReason reason)
        {
            try
            {
                var disconnectOptions = new MqttClientDisconnectOptions
                {
                    ReasonCode   = reason,
                    ReasonString = reason.ToString()
                };

                var disconnectPacket = _channelAdapter.PacketFormatterAdapter.DataConverter.CreateDisconnectPacket(disconnectOptions);

                using (var timeout = new CancellationTokenSource(_serverOptions.DefaultCommunicationTimeout))
                {
                    await SendPacketAsync(disconnectPacket, timeout.Token).ConfigureAwait(false);
                }
            }
            catch (Exception exception)
            {
                _logger.Warning(exception, "Client '{{0}}': Error while sending DISCONNECT packet (Reason = {1}).", ClientId, reason);
            }
        }
Esempio n. 14
0
        public async Task StopAsync(MqttClientDisconnectReason reason)
        {
            Status            = MqttClientConnectionStatus.Finalizing;
            _disconnectReason = reason;

            if (reason == MqttClientDisconnectReason.SessionTakenOver || reason == MqttClientDisconnectReason.KeepAliveTimeout)
            {
                // Is is very important to send the DISCONNECT packet here BEFORE cancelling the
                // token because the entire connection is closed (disposed) as soon as the cancellation
                // token is cancelled. To there is no chance that the DISCONNECT packet will ever arrive
                // at the client!
                try
                {
                    var disconnectOptions = new MqttClientDisconnectOptions
                    {
                        ReasonCode   = reason,
                        ReasonString = reason.ToString()
                    };

                    var disconnectPacket = _channelAdapter.PacketFormatterAdapter.DataConverter.CreateDisconnectPacket(disconnectOptions);

                    using (var timeout = new CancellationTokenSource(_serverOptions.DefaultCommunicationTimeout))
                    {
                        await _channelAdapter.SendPacketAsync(disconnectPacket, timeout.Token).ConfigureAwait(false);
                    }
                }
                catch (Exception exception)
                {
                    _logger.Warning(exception, "Client '{0}': Error while sending DISCONNECT packet after takeover.", ClientId);
                }
            }

            StopInternal();

            await(_packageReceiverTask ?? PlatformAbstractionLayer.CompletedTask);
        }
Esempio n. 15
0
        public RemoteMqttBroker(
            ILogger <RemoteMqttBroker> logger,
            IEventIdCreationSource eventIdCreationSource,
            IOptions <MqttNetworkOptions>?options = null)
        {
            _logger = logger;
            _eventIdCreationSource = eventIdCreationSource;

            EventId eventId = GetNextEventId();

            _logger.LogInformation(eventId, $"Creating Mqtt Client (Id: {ClientId}).");

            MqttNetworkOptions mqttNetworkOptions = options?.Value ?? MqttNetworkOptions.Default;

            mqttNetworkOptions.Host ??= MqttNetworkOptions.Default.Host !;

            if (mqttNetworkOptions.Port < 0x0000)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Port), mqttNetworkOptions.Port, "Port number too small.");
            }
            else if (mqttNetworkOptions.Port > 0xffff)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Port), mqttNetworkOptions.Port, "Port number too large.");
            }

            if (mqttNetworkOptions.Timeout < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Timeout), mqttNetworkOptions.Timeout, "Timeout timespan too small.");
            }
            else if (mqttNetworkOptions.Timeout > 99999)
            {
                throw new ArgumentOutOfRangeException(nameof(mqttNetworkOptions.Timeout), mqttNetworkOptions.Timeout, "Timeout timespan too large.");
            }

            _logger.LogInformation(eventId, $"MQTT Client Communication Timeout: {mqttNetworkOptions.Timeout} ms.");

            var clientOptionsBuilder = new MqttClientOptionsBuilder()
                                       .WithClientId(ClientId)
                                       .WithCommunicationTimeout(TimeSpan.FromSeconds(60))
                                       .WithTcpServer(mqttNetworkOptions.Host, mqttNetworkOptions.Port);

            _mqttClient = new MqttFactory().CreateMqttClient();
            _mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(eventArgs =>
            {
                _logger.LogDebug("Client Connected. Reason: " + (eventArgs.AuthenticateResult?.ReasonString ?? "null"));
            });

            _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(eventArgs =>
            {
                _logger.LogDebug(eventArgs.Exception, "Client Disconnected. Reason: " + (eventArgs.AuthenticateResult?.ReasonString ?? "null"));
            });

            CancellationTokenSource?cancellationTokenSource = null;

            #region Connecting to remote Mqtt Broker

            try
            {
                _logger.LogInformation(eventId, $"Connecting to remote Mqtt-Broker (mqtt://{mqttNetworkOptions.Host}:{mqttNetworkOptions.Port}).");

                cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan);
                var result = _mqttClient.ConnectAsync(clientOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                if (result.ResultCode != MqttClientConnectResultCode.Success)
                {
                    throw new Exception("Mqtt-Client ConnectResultCode Success expected. Actual: " + result.ResultCode);
                }
            }
            catch (OperationCanceledException)
            {
                string errorMessage = "Connect to remote Mqtt-Broker timed out.";
                _logger.LogCritical(eventId, errorMessage);
                throw new Exception(errorMessage);
            }
            catch (Exception exception)
            {
                string errorMessage = "Failed to connect to remote Mqtt-Broker.";
                _logger.LogCritical(eventId, exception, errorMessage);
                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion

            #region Subscribing to relevant Events

            try
            {
                _logger.LogInformation(eventId, $"Subscribing to relevant events.");

                MqttQualityOfServiceLevel     mqttQualityOfServiceLevel   = MqttQualityOfServiceLevel.AtLeastOnce;
                MqttClientSubscribeResultCode expectedSubscribeResultCode = MqttClientSubscribeResultCode.GrantedQoS1;

                MqttClientSubscribeOptionsBuilder subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder()
                                                                            .WithTopicFilter(MqttTopics.TrackerHello, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.TrackerGoodbye, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinAccepted, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinDenied, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientRegistered, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientGoodbye, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FileInfoPublished, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionStarted, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionDelivered, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionEnded, mqttQualityOfServiceLevel);

                cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan); //timeout
                MqttClientSubscribeResult result = _mqttClient.SubscribeAsync(subscribeOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                foreach (MqttClientSubscribeResultItem item in result.Items)
                {
                    if (item.ResultCode != expectedSubscribeResultCode)
                    {
                        throw new Exception($"Expected SubscribeResultCode {expectedSubscribeResultCode} for topic \"{item.TopicFilter.Topic}\". Actual: {item.ResultCode}");
                    }
                }
            }
            catch (Exception exception)
            {
                string errorMessage;

                if (exception is OperationCanceledException)
                {
                    errorMessage = "Subscribing to all relevant Events to remote Mqtt-Broker timed out.";
                    _logger.LogCritical(eventId, errorMessage);
                }
                else
                {
                    errorMessage = "Failed to subscribe to all relevant topics with expected SubscribeResultCode.";
                    _logger.LogCritical(eventId, exception, errorMessage);
                }

                try
                {
                    _logger.LogInformation("Disconnecting from remote Mqtt-Broker");
                    MqttClientDisconnectOptions disconnectOptions = new MqttClientDisconnectOptions()
                    {
                        ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                        ReasonString = errorMessage
                    };

                    cancellationTokenSource = new CancellationTokenSource(TimeoutTimeSpan);
                    _mqttClient.DisconnectAsync(disconnectOptions, cancellationTokenSource.Token).GetAwaiter().GetResult();
                }
                catch (OperationCanceledException)
                {
                    _logger.LogError(eventId, "Disconnecting from remote Mqtt-Broker timed out.");
                }
                catch (Exception disconnectException)
                {
                    _logger.LogError(eventId, disconnectException, "Disconnecting from remote Mqtt-Broker failed.");
                }
                finally
                {
                    cancellationTokenSource?.Dispose();
                }

                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion
        }
Esempio n. 16
0
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            _disposed = true;

            EventId eventId = GetNextEventId();

            CancellationTokenSource?cancellationTokenSource = null;

            try
            {
                try
                {
                    MqttClientUnsubscribeOptions mqttClientUnsubscribeOptions = new MqttClientUnsubscribeOptions
                    {
                        TopicFilters = new List <string>
                        {
                            MqttTopics.ClientJoinRequested,
                            MqttTopics.ClientJoinSucceeded,
                            MqttTopics.ClientJoinFailed,
                            MqttTopics.ClientGoodbye,
                            MqttTopics.FragmentDistributionRequested,
                            MqttTopics.FragmentDistributionObtained,
                            MqttTopics.FragmentDistributionFailed
                        }
                    };

                    _logger.LogInformation(eventId, "Unsubscribing from all events from remote Mqtt-Broker.");
                    cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                    var result = _mqttClient.UnsubscribeAsync(mqttClientUnsubscribeOptions, cancellationTokenSource.Token).GetAwaiter().GetResult();

                    foreach (MqttClientUnsubscribeResultItem item in result.Items)
                    {
                        if (item.ReasonCode != MqttClientUnsubscribeResultCode.Success)
                        {
                            throw new Exception($"Expected UnsubscribeResultCode Success for topic \"{item.TopicFilter}\". Actual: {item.ReasonCode}");
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    _logger.LogError(eventId, "Unsubscribing from all events from remote Mqtt-Broker timed out.");
                }
                catch (Exception exception)
                {
                    _logger.LogError(eventId, exception, "Unsubscribing from all events from remote Mqtt-Broker failed.");
                }
                finally
                {
                    cancellationTokenSource?.Dispose();
                }

                _logger.LogInformation(eventId, "Disconnecting from remote Mqtt-Broker.");
                MqttClientDisconnectOptions disconnectOptions = new MqttClientDisconnectOptions()
                {
                    ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                    ReasonString = "Client Disposed"
                };

                cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                _mqttClient.DisconnectAsync(disconnectOptions, cancellationTokenSource.Token).GetAwaiter().GetResult();
            }
            catch (OperationCanceledException)
            {
                _logger.LogError(eventId, "Disconnecting from remote Mqtt-Broker timed out.");
            }
            catch (Exception exception)
            {
                _logger.LogError(eventId, exception, "Disconnecting from remote Mqtt-Broker failed.");
            }
            finally
            {
                _mqttClient.Dispose();
                cancellationTokenSource?.Dispose();
            }
        }
Esempio n. 17
0
 public MqttDisconnectPacket CreateDisconnectPacket(MqttClientDisconnectOptions options)
 {
     return(new MqttDisconnectPacket());
 }
Esempio n. 18
0
        public RemoteMqttBroker(
            ILogger <RemoteMqttBroker> logger,
            IEventIdCreationSource eventIdCreationSource,
            string host,
            int port,
            int timeout)
        {
            _logger = logger;
            _eventIdCreationSource = eventIdCreationSource;

            EventId eventId = GetNextEventId();

#if DEBUG
            _logger.LogDebug(eventId, "Creating Mqtt Client.");
#endif
            if (port < 0x0000)
            {
                throw new ArgumentOutOfRangeException(nameof(port), port, "Port number too small.");
            }
            else if (timeout > 0xffff)
            {
                throw new ArgumentOutOfRangeException(nameof(port), port, "Port number too large.");
            }

            if (timeout < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), timeout, "Timeout timespan too small.");
            }
            else if (timeout > 99999)
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), timeout, "Timeout timespan too large.");
            }

            _logger.LogInformation(eventId, $"MQTT Client Communication Timeout: {timeout} ms.");

            var clientOptionsBuilder = new MqttClientOptionsBuilder()
                                       .WithClientId(ClientId)
                                       .WithCommunicationTimeout(TimeSpan.FromMilliseconds(timeout))
                                       .WithTcpServer(host, port);

            _mqttClient = new MqttFactory().CreateMqttClient();

            CancellationTokenSource?cancellationTokenSource = null;

            #region Connecting to remote Mqtt Broker

            try
            {
                _logger.LogInformation(eventId, $"Connecting to remote Mqtt-Broker (mqtt://{host}:{port}).");

                cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)); //timeout
                var result = _mqttClient.ConnectAsync(clientOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                if (result.ResultCode != MqttClientConnectResultCode.Success)
                {
                    throw new Exception("Mqtt-Client ConnectResultCode Success expected. Actual: " + result.ResultCode);
                }
            }
            catch (OperationCanceledException)
            {
                string errorMessage = "Connect to remote Mqtt-Broker timed out.";
                _logger.LogCritical(eventId, errorMessage);
                throw new Exception(errorMessage);
            }
            catch (Exception exception)
            {
                string errorMessage = "Failed to connect to remote Mqtt-Broker.";
                _logger.LogCritical(eventId, exception, errorMessage);
                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion

            #region Subscribing to relevant Events

            try
            {
                _logger.LogInformation(eventId, $"Subscribing to relevant events.");

                MqttQualityOfServiceLevel     mqttQualityOfServiceLevel   = MqttQualityOfServiceLevel.AtLeastOnce;
                MqttClientSubscribeResultCode expectedSubscribeResultCode = MqttClientSubscribeResultCode.GrantedQoS1;

                MqttClientSubscribeOptionsBuilder subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder()
                                                                            .WithTopicFilter(MqttTopics.ClientJoinRequested, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinSucceeded, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientJoinFailed, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.ClientGoodbye, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionRequested, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionObtained, mqttQualityOfServiceLevel)
                                                                            .WithTopicFilter(MqttTopics.FragmentDistributionFailed, mqttQualityOfServiceLevel);

                cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)); //timeout
                MqttClientSubscribeResult result = _mqttClient.SubscribeAsync(subscribeOptionsBuilder.Build(), cancellationTokenSource.Token).GetAwaiter().GetResult();

                foreach (MqttClientSubscribeResultItem item in result.Items)
                {
                    if (item.ResultCode != expectedSubscribeResultCode)
                    {
                        throw new Exception($"Expected SubscribeResultCode {expectedSubscribeResultCode} for topic \"{item.TopicFilter.Topic}\". Actual: {item.ResultCode}");
                    }
                }
            }
            catch (OperationCanceledException)
            {
                string errorMessage = "Subscribing to all relevant Events to remote Mqtt-Broker timed out.";
                _logger.LogCritical(eventId, errorMessage);

                DisconnectOnError(errorMessage);

                throw new Exception(errorMessage);
            }
            catch (Exception exception)
            {
                string errorMessage = "Failed to subscribe to all relevant topics with expected SubscribeResultCode.";
                _logger.LogCritical(eventId, exception, errorMessage);

                DisconnectOnError(errorMessage);

                throw new Exception(errorMessage);
            }
            finally
            {
                cancellationTokenSource?.Dispose();
            }

            #endregion

            void DisconnectOnError(string reasonString)
            {
                try
                {
                    _logger.LogInformation("Disconnecting from remote Mqtt-Broker");
                    MqttClientDisconnectOptions disconnectOptions = new MqttClientDisconnectOptions()
                    {
                        ReasonCode   = MqttClientDisconnectReason.NormalDisconnection,
                        ReasonString = reasonString
                    };

                    cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                    _mqttClient.DisconnectAsync(disconnectOptions, cancellationTokenSource.Token).GetAwaiter().GetResult();
                }
                catch (OperationCanceledException)
                {
                    _logger.LogError(eventId, "Disconnecting from remote Mqtt-Broker timed out.");
                }
                catch (Exception exception)
                {
                    _logger.LogError(eventId, exception, "Disconnecting from remote Mqtt-Broker failed.");
                }
                finally
                {
                    cancellationTokenSource?.Dispose();
                }
            }
        }