mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-19 02:53:06 +08:00
Adds events for delivered and dropped messages. (#1866)
* Adds events for delivered and dropped messages. * Rename new events to match other namings * Update ReleaseNotes.md --------- Co-authored-by: Christian <6939810+chkr1011@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
* [Client] Added support for custom CA chain validation (#1851, thanks to @rido-min).
|
* [Client] Added support for custom CA chain validation (#1851, thanks to @rido-min).
|
||||||
* [Client] Added support for custom CA chain validation (#1851, thanks to @rido-min).
|
|
||||||
* [Client] Fixed handling of unobserved tasks exceptions (#1871).
|
* [Client] Fixed handling of unobserved tasks exceptions (#1871).
|
||||||
* [Client] Fixed not specified ReasonCode when using _SendExtendedAuthenticationExchangeDataAsync_ (#1882, thanks to @rido-min).
|
* [Client] Fixed not specified ReasonCode when using _SendExtendedAuthenticationExchangeDataAsync_ (#1882, thanks to @rido-min).
|
||||||
* [Server] Fixed not working _UpdateRetainedMessageAsync_ public api (#1858, thanks to @kimdiego2098).
|
* [Server] Fixed not working _UpdateRetainedMessageAsync_ public api (#1858, thanks to @kimdiego2098).
|
||||||
* [Server] Added support for custom DISCONNECT packets when stopping the server or disconnect a client (BREAKING CHANGE!, #1846).
|
* [Server] Added support for custom DISCONNECT packets when stopping the server or disconnect a client (BREAKING CHANGE!, #1846).
|
||||||
* [Server] Added new property to stop the server from accepting new connections even if it is running (#1846).
|
* [Server] Added new property to stop the server from accepting new connections even if it is running (#1846).
|
||||||
|
* [Server] Added new events for delivered and dropped messages (#1866, thanks to @kallayj).
|
||||||
@@ -104,17 +104,22 @@ namespace MQTTnet.Internal
|
|||||||
_signal.Dispose();
|
_signal.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DropFirstItem(MqttPacketBusPartition partition)
|
public MqttPacketBusItem DropFirstItem(MqttPacketBusPartition partition)
|
||||||
{
|
{
|
||||||
lock (_syncRoot)
|
lock (_syncRoot)
|
||||||
{
|
{
|
||||||
var partitionInstance = _partitions[(int)partition];
|
var partitionInstance = _partitions[(int)partition];
|
||||||
|
|
||||||
if (partitionInstance.Any())
|
if (partitionInstance.Count > 0)
|
||||||
{
|
{
|
||||||
|
var firstItem = partitionInstance.First.Value;
|
||||||
partitionInstance.RemoveFirst();
|
partitionInstance.RemoveFirst();
|
||||||
|
|
||||||
|
return firstItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnqueueItem(MqttPacketBusItem item, MqttPacketBusPartition partition)
|
public void EnqueueItem(MqttPacketBusItem item, MqttPacketBusPartition partition)
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public sealed class ApplicationMessageEnqueuedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public ApplicationMessageEnqueuedEventArgs(string senderClientId, string receiverClientId, MqttApplicationMessage applicationMessage, bool isDropped)
|
||||||
|
{
|
||||||
|
SenderClientId = senderClientId ?? throw new ArgumentNullException( nameof(senderClientId));
|
||||||
|
ReceiverClientId = receiverClientId ?? throw new ArgumentNullException(nameof(receiverClientId));
|
||||||
|
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
|
||||||
|
IsDropped = isDropped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SenderClientId { get; }
|
||||||
|
|
||||||
|
public string ReceiverClientId { get; }
|
||||||
|
|
||||||
|
public bool IsDropped { get; }
|
||||||
|
|
||||||
|
public MqttApplicationMessage ApplicationMessage { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MQTTnet.Packets;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public sealed class QueueMessageOverwrittenEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public QueueMessageOverwrittenEventArgs(string receiverClientId, MqttPacket packet)
|
||||||
|
{
|
||||||
|
ReceiverClientId = receiverClientId ?? throw new ArgumentNullException(nameof(receiverClientId));
|
||||||
|
Packet = packet ?? throw new ArgumentNullException(nameof(packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MqttPacket Packet { get; }
|
||||||
|
|
||||||
|
public string ReceiverClientId { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public enum EnqueueDataPacketResult
|
||||||
|
{
|
||||||
|
Enqueued,
|
||||||
|
Dropped
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -244,7 +244,14 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
matchingSubscribersCount++;
|
matchingSubscribersCount++;
|
||||||
|
|
||||||
session.EnqueueDataPacket(new MqttPacketBusItem(publishPacketCopy));
|
var result = session.EnqueueDataPacket(new MqttPacketBusItem(publishPacketCopy));
|
||||||
|
|
||||||
|
if (_eventContainer.ApplicationMessageEnqueuedOrDroppedEvent.HasHandlers)
|
||||||
|
{
|
||||||
|
var eventArgs = new ApplicationMessageEnqueuedEventArgs(senderId, session.Id, applicationMessage, result == EnqueueDataPacketResult.Dropped);
|
||||||
|
await _eventContainer.ApplicationMessageEnqueuedOrDroppedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Verbose("Client '{0}': Queued PUBLISH packet with topic '{1}'", session.Id, applicationMessage.Topic);
|
_logger.Verbose("Client '{0}': Queued PUBLISH packet with topic '{1}'", session.Id, applicationMessage.Topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public AsyncEvent<InterceptingClientApplicationMessageEnqueueEventArgs> InterceptingClientEnqueueEvent { get; } = new AsyncEvent<InterceptingClientApplicationMessageEnqueueEventArgs>();
|
public AsyncEvent<InterceptingClientApplicationMessageEnqueueEventArgs> InterceptingClientEnqueueEvent { get; } = new AsyncEvent<InterceptingClientApplicationMessageEnqueueEventArgs>();
|
||||||
|
|
||||||
|
public AsyncEvent<ApplicationMessageEnqueuedEventArgs> ApplicationMessageEnqueuedOrDroppedEvent { get; } = new AsyncEvent<ApplicationMessageEnqueuedEventArgs>();
|
||||||
|
|
||||||
|
public AsyncEvent<QueueMessageOverwrittenEventArgs> QueuedApplicationMessageOverwrittenEvent { get; } = new AsyncEvent<QueueMessageOverwrittenEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<InterceptingPacketEventArgs> InterceptingInboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
public AsyncEvent<InterceptingPacketEventArgs> InterceptingInboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<InterceptingPacketEventArgs> InterceptingOutboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
public AsyncEvent<InterceptingPacketEventArgs> InterceptingOutboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace MQTTnet.Server
|
|||||||
public sealed class MqttSession : IDisposable
|
public sealed class MqttSession : IDisposable
|
||||||
{
|
{
|
||||||
readonly MqttClientSessionsManager _clientSessionsManager;
|
readonly MqttClientSessionsManager _clientSessionsManager;
|
||||||
|
readonly MqttServerEventContainer _eventContainer;
|
||||||
readonly MqttPacketBus _packetBus = new MqttPacketBus();
|
readonly MqttPacketBus _packetBus = new MqttPacketBus();
|
||||||
readonly MqttPacketIdentifierProvider _packetIdentifierProvider = new MqttPacketIdentifierProvider();
|
readonly MqttPacketIdentifierProvider _packetIdentifierProvider = new MqttPacketIdentifierProvider();
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ namespace MQTTnet.Server
|
|||||||
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
||||||
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
||||||
_clientSessionsManager = clientSessionsManager ?? throw new ArgumentNullException(nameof(clientSessionsManager));
|
_clientSessionsManager = clientSessionsManager ?? throw new ArgumentNullException(nameof(clientSessionsManager));
|
||||||
|
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||||
|
|
||||||
_subscriptionsManager = new MqttClientSubscriptionsManager(this, eventContainer, retainedMessagesManager, clientSessionsManager);
|
_subscriptionsManager = new MqttClientSubscriptionsManager(this, eventContainer, retainedMessagesManager, clientSessionsManager);
|
||||||
}
|
}
|
||||||
@@ -117,20 +119,25 @@ namespace MQTTnet.Server
|
|||||||
_packetBus.EnqueueItem(packetBusItem, MqttPacketBusPartition.Control);
|
_packetBus.EnqueueItem(packetBusItem, MqttPacketBusPartition.Control);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnqueueDataPacket(MqttPacketBusItem packetBusItem)
|
public EnqueueDataPacketResult EnqueueDataPacket(MqttPacketBusItem packetBusItem)
|
||||||
{
|
{
|
||||||
if (_packetBus.ItemsCount(MqttPacketBusPartition.Data) >= _serverOptions.MaxPendingMessagesPerClient)
|
if (_packetBus.ItemsCount(MqttPacketBusPartition.Data) >= _serverOptions.MaxPendingMessagesPerClient)
|
||||||
{
|
{
|
||||||
if (_serverOptions.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
|
if (_serverOptions.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
|
||||||
{
|
{
|
||||||
return;
|
return EnqueueDataPacketResult.Dropped;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_serverOptions.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
|
if (_serverOptions.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
|
||||||
{
|
{
|
||||||
// Only drop from the data partition. Dropping from control partition might break the connection
|
// Only drop from the data partition. Dropping from control partition might break the connection
|
||||||
// because the client does not receive PINGREQ packets etc. any longer.
|
// because the client does not receive PINGREQ packets etc. any longer.
|
||||||
_packetBus.DropFirstItem(MqttPacketBusPartition.Data);
|
var firstItem = _packetBus.DropFirstItem(MqttPacketBusPartition.Data);
|
||||||
|
if (firstItem != null && _eventContainer.QueuedApplicationMessageOverwrittenEvent.HasHandlers)
|
||||||
|
{
|
||||||
|
var eventArgs = new QueueMessageOverwrittenEventArgs(Id, firstItem.Packet);
|
||||||
|
_eventContainer.QueuedApplicationMessageOverwrittenEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +154,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
_packetBus.EnqueueItem(packetBusItem, MqttPacketBusPartition.Data);
|
_packetBus.EnqueueItem(packetBusItem, MqttPacketBusPartition.Data);
|
||||||
|
return EnqueueDataPacketResult.Enqueued;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnqueueHealthPacket(MqttPacketBusItem packetBusItem)
|
public void EnqueueHealthPacket(MqttPacketBusItem packetBusItem)
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ namespace MQTTnet.Server
|
|||||||
_keepAliveMonitor = new MqttServerKeepAliveMonitor(options, _clientSessionsManager, _rootLogger);
|
_keepAliveMonitor = new MqttServerKeepAliveMonitor(options, _clientSessionsManager, _rootLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event Func<ApplicationMessageEnqueuedEventArgs, Task> ApplicationMessageEnqueuedOrDroppedAsync
|
||||||
|
{
|
||||||
|
add => _eventContainer.ApplicationMessageEnqueuedOrDroppedEvent.AddHandler(value);
|
||||||
|
remove => _eventContainer.ApplicationMessageEnqueuedOrDroppedEvent.RemoveHandler(value);
|
||||||
|
}
|
||||||
|
|
||||||
public event Func<ApplicationMessageNotConsumedEventArgs, Task> ApplicationMessageNotConsumedAsync
|
public event Func<ApplicationMessageNotConsumedEventArgs, Task> ApplicationMessageNotConsumedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ApplicationMessageNotConsumedEvent.AddHandler(value);
|
add => _eventContainer.ApplicationMessageNotConsumedEvent.AddHandler(value);
|
||||||
@@ -135,6 +141,12 @@ namespace MQTTnet.Server
|
|||||||
remove => _eventContainer.PreparingSessionEvent.RemoveHandler(value);
|
remove => _eventContainer.PreparingSessionEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event Func<QueueMessageOverwrittenEventArgs, Task> QueuedApplicationMessageOverwrittenAsync
|
||||||
|
{
|
||||||
|
add => _eventContainer.QueuedApplicationMessageOverwrittenEvent.AddHandler(value);
|
||||||
|
remove => _eventContainer.QueuedApplicationMessageOverwrittenEvent.RemoveHandler(value);
|
||||||
|
}
|
||||||
|
|
||||||
public event Func<RetainedMessageChangedEventArgs, Task> RetainedMessageChangedAsync
|
public event Func<RetainedMessageChangedEventArgs, Task> RetainedMessageChangedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.RetainedMessageChangedEvent.AddHandler(value);
|
add => _eventContainer.RetainedMessageChangedEvent.AddHandler(value);
|
||||||
|
|||||||
Reference in New Issue
Block a user