From 42402fba04faa6e2b60f4ae61d68de8804211a3c Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 31 Jul 2022 10:22:23 +0200 Subject: [PATCH] Allow interception of injected application messages. --- .github/workflows/ReleaseNotes.md | 3 +- .../Internal/MqttServerEventContainer.cs | 1 + Source/MQTTnet/Server/MqttServer.cs | 31 +++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ReleaseNotes.md b/.github/workflows/ReleaseNotes.md index 67631049..883446ea 100644 --- a/.github/workflows/ReleaseNotes.md +++ b/.github/workflows/ReleaseNotes.md @@ -1,4 +1,5 @@ -* [Client] Added support for passing the local endpoint which should be used (network card). +* [Client] Added support for passing the local endpoint (network card) which should be used (#1311). * [Client] Exposed _PackageIdentifier_ in _MqttApplicationMessageReceivedEventArgs_ (thanks to @koepalex, #1466). * [Server] Added a new event (_ClientAcknowledgedPublishPacketAsync_) which is fired whenever a client acknowledges a PUBLISH packet (QoS 1 and 2, #487). * [Server] Exposed channel adapter (HTTP context etc.) in connection validation (#1125). +* [Server] The event _InterceptingPublishAsync_ is now also called for injected application messages (#Jeanot-Zubler). diff --git a/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs b/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs index d363ca54..e60a15e8 100644 --- a/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs +++ b/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs @@ -26,6 +26,7 @@ namespace MQTTnet.Server public AsyncEvent InterceptingOutboundPacketEvent { get; } = new AsyncEvent(); public AsyncEvent InterceptingPublishEvent { get; } = new AsyncEvent(); + public AsyncEvent InterceptingSubscriptionEvent { get; } = new AsyncEvent(); public AsyncEvent InterceptingUnsubscriptionEvent { get; } = new AsyncEvent(); diff --git a/Source/MQTTnet/Server/MqttServer.cs b/Source/MQTTnet/Server/MqttServer.cs index 9903be8a..f14ade4e 100644 --- a/Source/MQTTnet/Server/MqttServer.cs +++ b/Source/MQTTnet/Server/MqttServer.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -19,7 +21,8 @@ namespace MQTTnet.Server public class MqttServer : Disposable { readonly MqttServerEventContainer _eventContainer = new MqttServerEventContainer(); - + + readonly IDictionary _sessionItems = new ConcurrentDictionary(); readonly ICollection _adapters; readonly MqttNetSourceLogger _logger; readonly MqttServerOptions _options; @@ -205,7 +208,7 @@ namespace MQTTnet.Server return _clientSessionsManager.GetSessionStatusAsync(); } - public Task InjectApplicationMessage(InjectedMqttApplicationMessage injectedApplicationMessage) + public async Task InjectApplicationMessage(InjectedMqttApplicationMessage injectedApplicationMessage) { if (injectedApplicationMessage == null) { @@ -221,7 +224,29 @@ namespace MQTTnet.Server ThrowIfNotStarted(); - return _clientSessionsManager.DispatchApplicationMessage(injectedApplicationMessage.SenderClientId, injectedApplicationMessage.ApplicationMessage); + var processPublish = true; + var applicationMessage = injectedApplicationMessage.ApplicationMessage; + + if (_eventContainer.InterceptingPublishEvent.HasHandlers) + { + var interceptingPublishEventArgs = new InterceptingPublishEventArgs(applicationMessage, _cancellationTokenSource.Token, injectedApplicationMessage.SenderClientId, _sessionItems); + await _eventContainer.InterceptingPublishEvent.InvokeAsync(interceptingPublishEventArgs).ConfigureAwait(false); + + applicationMessage = interceptingPublishEventArgs.ApplicationMessage; + processPublish = interceptingPublishEventArgs.ProcessPublish; + } + + if (!processPublish) + { + return; + } + + if (string.IsNullOrEmpty(applicationMessage.Topic)) + { + throw new NotSupportedException("Injected application messages must contain a topic. Topic alias is not supported."); + } + + await _clientSessionsManager.DispatchApplicationMessage(injectedApplicationMessage.SenderClientId, applicationMessage).ConfigureAwait(false); } public async Task StartAsync()