Merge pull request #938 from chkr1011/interceptor-undelivered

Added interceptor for undelivered messages.
This commit is contained in:
Christian
2020-06-15 23:13:06 +02:00
committed by GitHub
7 changed files with 63 additions and 3 deletions
+1
View File
@@ -18,6 +18,7 @@
* [Server] Added state checks (throw if not started etc.) for most server APIs. * [Server] Added state checks (throw if not started etc.) for most server APIs.
* [Server] Exposed real X509Certificate2 (instead byte array) to TLS options (thanks to @borigas). * [Server] Exposed real X509Certificate2 (instead byte array) to TLS options (thanks to @borigas).
* [Core] Fixed a null reference exception in the MqttTcpChannel with WriteAsync and ReadAsync. * [Core] Fixed a null reference exception in the MqttTcpChannel with WriteAsync and ReadAsync.
* [Core] Added server interceptor for undelivered messages (Thanks to @cshark-inator).
</releaseNotes> </releaseNotes>
<copyright>Copyright Christian Kratky 2016-2020</copyright> <copyright>Copyright Christian Kratky 2016-2020</copyright>
<tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags> <tags>MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor</tags>
@@ -25,5 +25,7 @@ namespace MQTTnet.Server
IMqttServerStorage Storage { get; } IMqttServerStorage Storage { get; }
IMqttRetainedMessagesManager RetainedMessagesManager { get; } IMqttRetainedMessagesManager RetainedMessagesManager { get; }
IMqttServerApplicationMessageInterceptor UndeliveredMessageInterceptor { get; set; }
} }
} }
+4 -2
View File
@@ -46,17 +46,19 @@ namespace MQTTnet.Server
/// </summary> /// </summary>
public IDictionary<object, object> Items { get; } public IDictionary<object, object> Items { get; }
public void EnqueueApplicationMessage(MqttApplicationMessage applicationMessage, string senderClientId, bool isRetainedApplicationMessage) public bool EnqueueApplicationMessage(MqttApplicationMessage applicationMessage, string senderClientId, bool isRetainedApplicationMessage)
{ {
var checkSubscriptionsResult = SubscriptionsManager.CheckSubscriptions(applicationMessage.Topic, applicationMessage.QualityOfServiceLevel); var checkSubscriptionsResult = SubscriptionsManager.CheckSubscriptions(applicationMessage.Topic, applicationMessage.QualityOfServiceLevel);
if (!checkSubscriptionsResult.IsSubscribed) if (!checkSubscriptionsResult.IsSubscribed)
{ {
return; return true;
} }
_logger.Verbose("Queued application message with topic '{0}' (ClientId: {1}).", applicationMessage.Topic, ClientId); _logger.Verbose("Queued application message with topic '{0}' (ClientId: {1}).", applicationMessage.Topic, ClientId);
ApplicationMessagesQueue.Enqueue(applicationMessage, senderClientId, checkSubscriptionsResult.QualityOfServiceLevel, isRetainedApplicationMessage); ApplicationMessagesQueue.Enqueue(applicationMessage, senderClientId, checkSubscriptionsResult.QualityOfServiceLevel, isRetainedApplicationMessage);
return false;
} }
public async Task SubscribeAsync(ICollection<MqttTopicFilter> topicFilters) public async Task SubscribeAsync(ICollection<MqttTopicFilter> topicFilters)
@@ -220,12 +220,31 @@ namespace MQTTnet.Server
await _retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false); await _retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false);
} }
var deliveryCount = 0;
foreach (var clientSession in _sessions.Values) foreach (var clientSession in _sessions.Values)
{ {
clientSession.EnqueueApplicationMessage( var isSubscribed = clientSession.EnqueueApplicationMessage(
applicationMessage, applicationMessage,
sender?.ClientId, sender?.ClientId,
false); false);
if (isSubscribed)
{
deliveryCount++;
}
}
if (deliveryCount == 0)
{
var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor;
if (undeliveredMessageInterceptor == null)
{
return;
}
await undeliveredMessageInterceptor.InterceptApplicationMessagePublishAsync(new MqttApplicationMessageInterceptorContext(sender?.ClientId, sender?.Session?.Items, applicationMessage));
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@@ -31,5 +31,7 @@ namespace MQTTnet.Server
public IMqttServerStorage Storage { get; set; } public IMqttServerStorage Storage { get; set; }
public IMqttRetainedMessagesManager RetainedMessagesManager { get; set; } = new MqttRetainedMessagesManager(); public IMqttRetainedMessagesManager RetainedMessagesManager { get; set; } = new MqttRetainedMessagesManager();
public IMqttServerApplicationMessageInterceptor UndeliveredMessageInterceptor { get; set; }
} }
} }
@@ -212,5 +212,11 @@ namespace MQTTnet.Server
{ {
return _options; return _options;
} }
public MqttServerOptionsBuilder WithUndeliveredMessageInterceptor(Action<MqttApplicationMessageInterceptorContext> value)
{
_options.UndeliveredMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
return this;
}
} }
} }
+28
View File
@@ -1384,5 +1384,33 @@ namespace MQTTnet.Tests
Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount); Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
} }
} }
[TestMethod]
public async Task Intercept_Undelivered()
{
using (var testEnvironment = new TestEnvironment())
{
var undeliverd = string.Empty;
var svr = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithUndeliveredMessageInterceptor(
context =>
{
undeliverd = context.ApplicationMessage.Topic;
}));
var topicAReceived = false;
var topicBReceived = false;
var client = await testEnvironment.ConnectClientAsync();
await client.SubscribeAsync("b");
await client.PublishAsync("a", null, MqttQualityOfServiceLevel.ExactlyOnce);
await Task.Delay(500);
Assert.AreEqual(undeliverd, "a");
}
}
} }
} }