private async Task TryProcessNextQueuedApplicationMessageAsync(CancellationToken cancellationToken) { try { if (cancellationToken.IsCancellationRequested) { return; } var dequeueResult = await _messageQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false); var queuedApplicationMessage = dequeueResult.Item; var sender = queuedApplicationMessage.Sender; var applicationMessage = queuedApplicationMessage.ApplicationMessage; var interceptorContext = await InterceptApplicationMessageAsync(sender, applicationMessage).ConfigureAwait(false); if (interceptorContext != null) { if (interceptorContext.CloseConnection) { if (sender != null) { await sender.StopAsync().ConfigureAwait(false); } } if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish) { return; } applicationMessage = interceptorContext.ApplicationMessage; } await _eventDispatcher.HandleApplicationMessageReceivedAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false); if (applicationMessage.Retain) { await _retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false); } foreach (var clientSession in _sessions.Values) { clientSession.EnqueueApplicationMessage( applicationMessage, sender?.ClientId, false); } } catch (OperationCanceledException) { } catch (Exception exception) { _logger.Error(exception, "Unhandled exception while processing next queued application message."); } }
async Task TryProcessNextQueuedApplicationMessage() { try { MqttPendingApplicationMessage pendingApplicationMessage; try { pendingApplicationMessage = _messageQueue.Take(); } catch (ArgumentNullException) { return; } catch (ObjectDisposedException) { return; } var clientConnection = pendingApplicationMessage.Sender; var senderClientId = clientConnection?.ClientId ?? _options.ClientId; var applicationMessage = pendingApplicationMessage.ApplicationMessage; var interceptor = _options.ApplicationMessageInterceptor; if (interceptor != null) { var interceptorContext = await InterceptApplicationMessageAsync(interceptor, clientConnection, applicationMessage) .ConfigureAwait(false); if (interceptorContext != null) { if (interceptorContext.CloseConnection) { if (clientConnection != null) { await clientConnection.StopAsync(MqttClientDisconnectReason.NormalDisconnection) .ConfigureAwait(false); } } if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish) { return; } applicationMessage = interceptorContext.ApplicationMessage; } } await _eventDispatcher.SafeNotifyApplicationMessageReceivedAsync(senderClientId, applicationMessage) .ConfigureAwait(false); if (applicationMessage.Retain) { await _retainedMessagesManager.HandleMessageAsync(senderClientId, applicationMessage) .ConfigureAwait(false); } var deliveryCount = 0; List <MqttClientSession> sessions; lock (_clientSessions) { sessions = _clientSessions.Values.ToList(); } foreach (var clientSession in sessions) { var checkSubscriptionsResult = clientSession.SubscriptionsManager.CheckSubscriptions( applicationMessage.Topic, applicationMessage.QualityOfServiceLevel, senderClientId); if (!checkSubscriptionsResult.IsSubscribed) { continue; } _logger.Verbose("Client '{0}': Queued application message with topic '{1}'.", clientSession.ClientId, applicationMessage.Topic); var queuedApplicationMessage = new MqttQueuedApplicationMessage { ApplicationMessage = applicationMessage, SubscriptionQualityOfServiceLevel = checkSubscriptionsResult.QualityOfServiceLevel, SubscriptionIdentifiers = checkSubscriptionsResult.SubscriptionIdentifiers }; if (checkSubscriptionsResult.RetainAsPublished) { // Transfer the original retain state from the publisher. // This is a MQTTv5 feature. queuedApplicationMessage.IsRetainedMessage = applicationMessage.Retain; } clientSession.ApplicationMessagesQueue.Enqueue(queuedApplicationMessage); deliveryCount++; } if (deliveryCount == 0) { var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor; if (undeliveredMessageInterceptor == null) { return; } // The delegate signature is the same as for regular message interceptor. So the call is fine and just uses a different interceptor. await InterceptApplicationMessageAsync(undeliveredMessageInterceptor, clientConnection, applicationMessage).ConfigureAwait(false); } } catch (Exception exception) { _logger.Error(exception, "Unhandled exception while processing next queued application message."); } }
async Task TryProcessNextQueuedApplicationMessageAsync(CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); MqttPendingApplicationMessage queuedApplicationMessage; try { queuedApplicationMessage = _messageQueue.Take(cancellationToken); } catch (ArgumentNullException) { return; } catch (ObjectDisposedException) { return; } var clientConnection = queuedApplicationMessage.Sender; var senderClientId = clientConnection?.ClientId ?? _options.ClientId; var applicationMessage = queuedApplicationMessage.ApplicationMessage; var interceptor = _options.ApplicationMessageInterceptor; if (interceptor != null) { var interceptorContext = await InterceptApplicationMessageAsync(interceptor, clientConnection, applicationMessage).ConfigureAwait(false); if (interceptorContext != null) { if (interceptorContext.CloseConnection) { if (clientConnection != null) { await clientConnection.StopAsync(MqttClientDisconnectReason.NormalDisconnection).ConfigureAwait(false); } } if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish) { return; } applicationMessage = interceptorContext.ApplicationMessage; } } await _eventDispatcher.SafeNotifyApplicationMessageReceivedAsync(senderClientId, applicationMessage).ConfigureAwait(false); if (applicationMessage.Retain) { await _retainedMessagesManager.HandleMessageAsync(senderClientId, applicationMessage).ConfigureAwait(false); } var deliveryCount = 0; List <MqttClientSession> sessions; lock (_sessions) { sessions = _sessions.Values.ToList(); } foreach (var clientSession in sessions) { var isSubscribed = clientSession.EnqueueApplicationMessage(applicationMessage, senderClientId, false); if (isSubscribed) { deliveryCount++; } } if (deliveryCount == 0) { var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor; if (undeliveredMessageInterceptor == null) { return; } // The delegate signature is the same as for regular message interceptor. So the call is fine and just uses a different interceptor. await InterceptApplicationMessageAsync(undeliveredMessageInterceptor, clientConnection, applicationMessage).ConfigureAwait(false); } } catch (OperationCanceledException) { } catch (Exception exception) { _logger.Error(exception, "Unhandled exception while processing next queued application message."); } }
async Task TryProcessNextQueuedApplicationMessageAsync(CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); var queuedApplicationMessage = _messageQueue.Take(cancellationToken); var sender = queuedApplicationMessage.Sender; var senderClientId = sender?.ClientId ?? _options.ClientId; var applicationMessage = queuedApplicationMessage.ApplicationMessage; var interceptor = _options.ApplicationMessageInterceptor; if (interceptor != null) { var interceptorContext = await InterceptApplicationMessageAsync(interceptor, sender, applicationMessage).ConfigureAwait(false); if (interceptorContext != null) { if (interceptorContext.CloseConnection) { if (sender != null) { await sender.StopAsync(MqttDisconnectReasonCode.NormalDisconnection).ConfigureAwait(false); } } if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish) { return; } applicationMessage = interceptorContext.ApplicationMessage; } } await _eventDispatcher.SafeNotifyApplicationMessageReceivedAsync(senderClientId, applicationMessage).ConfigureAwait(false); if (applicationMessage.Retain) { await _retainedMessagesManager.HandleMessageAsync(senderClientId, applicationMessage).ConfigureAwait(false); } var deliveryCount = 0; lock (_sessions) { foreach (var clientSession in _sessions.Values) { var isSubscribed = clientSession.EnqueueApplicationMessage(applicationMessage, senderClientId, false); if (isSubscribed) { deliveryCount++; } } } if (deliveryCount == 0) { var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor; if (undeliveredMessageInterceptor == null) { return; } await undeliveredMessageInterceptor.InterceptApplicationMessagePublishAsync(new MqttApplicationMessageInterceptorContext(senderClientId, sender?.Session?.Items, applicationMessage)); } } catch (OperationCanceledException) { } catch (Exception exception) { _logger.Error(exception, "Unhandled exception while processing next queued application message."); } }