More options for disconnect (#1557)

* Expose more options in disconnect options.

* Expose more options in disconnect API.

* Refactor code.

* Expose user properties in disconnected event.

* Expose more disconnect options in server.

* Fix build errors

* Add new samples.

* Fix client cleanup

* Fix merge conflicts
This commit is contained in:
Christian
2022-12-23 17:09:02 +01:00
committed by GitHub
parent abe7bbda15
commit fdf00f1b18
28 changed files with 752 additions and 366 deletions
@@ -4,17 +4,30 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MQTTnet.Packets;
using MQTTnet.Protocol;
namespace MQTTnet.Server
{
public sealed class ClientDisconnectedEventArgs : EventArgs
{
public ClientDisconnectedEventArgs(string clientId, MqttClientDisconnectType disconnectType, string endpoint, IDictionary sessionItems)
readonly MqttDisconnectPacket _disconnectPacket;
public ClientDisconnectedEventArgs(
string clientId,
MqttDisconnectPacket disconnectPacket,
MqttClientDisconnectType disconnectType,
string endpoint,
IDictionary sessionItems)
{
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
DisconnectType = disconnectType;
Endpoint = endpoint;
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
// The DISCONNECT packet can be null in case of a non clean disconnect or session takeover.
_disconnectPacket = disconnectPacket;
}
/// <summary>
@@ -27,9 +40,37 @@ namespace MQTTnet.Server
public string Endpoint { get; }
/// <summary>
/// Gets the reason code sent by the client.
/// Only available for clean disconnects.
/// <remarks>MQTT 5.0.0+ feature.</remarks>
/// </summary>
public MqttDisconnectReasonCode? ReasonCode => _disconnectPacket?.ReasonCode;
/// <summary>
/// Gets the reason string sent by the client.
/// Only available for clean disconnects.
/// <remarks>MQTT 5.0.0+ feature.</remarks>
/// </summary>
public string ReasonString => _disconnectPacket?.ReasonString;
/// <summary>
/// Gets the session expiry interval sent by the client.
/// Only available for clean disconnects.
/// <remarks>MQTT 5.0.0+ feature.</remarks>
/// </summary>
public uint SessionExpiryInterval => _disconnectPacket?.SessionExpiryInterval ?? 0;
/// <summary>
/// Gets or sets a key/value collection that can be used to share data within the scope of this session.
/// </summary>
public IDictionary SessionItems { get; }
/// <summary>
/// Gets the user properties sent by the client.
/// Only available for clean disconnects.
/// <remarks>MQTT 5.0.0+ feature.</remarks>
/// </summary>
public List<MqttUserProperty> UserProperties => _disconnectPacket?.UserProperties;
}
}
+8 -7
View File
@@ -57,12 +57,12 @@ namespace MQTTnet.Server
public IMqttChannelAdapter ChannelAdapter { get; }
public MqttDisconnectPacket DisconnectPacket { get; set; }
public string Endpoint { get; }
public string Id => _connectPacket.ClientId;
public bool IsCleanDisconnect { get; private set; }
public bool IsRunning { get; private set; }
public bool IsTakenOver { get; set; }
@@ -95,8 +95,7 @@ namespace MQTTnet.Server
{
var cancellationToken = _cancellationToken.Token;
_ = Task.Factory.StartNew(() => SendPacketsLoop(cancellationToken), cancellationToken, TaskCreationOptions.PreferFairness, TaskScheduler.Default)
.ConfigureAwait(false);
_ = Task.Factory.StartNew(() => SendPacketsLoop(cancellationToken), cancellationToken, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false);
IsRunning = true;
@@ -111,7 +110,9 @@ namespace MQTTnet.Server
_cancellationToken = null;
}
if (!IsTakenOver && !IsCleanDisconnect && Session.LatestConnectPacket.WillFlag && !Session.WillMessageSent)
var isCleanDisconnect = DisconnectPacket != null;
if (!IsTakenOver && !isCleanDisconnect && Session.LatestConnectPacket.WillFlag && !Session.WillMessageSent)
{
var willPublishPacket = MqttPacketFactories.Publish.Create(Session.LatestConnectPacket);
var willApplicationMessage = MqttApplicationMessageFactory.Create(willPublishPacket);
@@ -431,9 +432,9 @@ namespace MQTTnet.Server
{
throw new MqttProtocolViolationException("A PINGRESP Packet is sent by the Server to the Client in response to a PINGREQ Packet only.");
}
else if (currentPacket is MqttDisconnectPacket)
else if (currentPacket is MqttDisconnectPacket disconnectPacket)
{
IsCleanDisconnect = true;
DisconnectPacket = disconnectPacket;
return;
}
else
@@ -387,8 +387,8 @@ namespace MQTTnet.Server
if (client.Id != null && !client.IsTakenOver && _eventContainer.ClientDisconnectedEvent.HasHandlers)
{
var disconnectType = client.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean;
var eventArgs = new ClientDisconnectedEventArgs(client.Id, disconnectType, endpoint, client.Session.Items);
var disconnectType = client.DisconnectPacket != null ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean;
var eventArgs = new ClientDisconnectedEventArgs(client.Id, client.DisconnectPacket, disconnectType, endpoint, client.Session.Items);
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
}
@@ -592,8 +592,13 @@ namespace MQTTnet.Server
if (_eventContainer.ClientDisconnectedEvent.HasHandlers)
{
var eventArgs = new ClientDisconnectedEventArgs(oldClient.Id, MqttClientDisconnectType.Takeover, oldClient.Endpoint, oldClient.Session.Items);
var eventArgs = new ClientDisconnectedEventArgs(
oldClient.Id,
null,
MqttClientDisconnectType.Takeover,
oldClient.Endpoint,
oldClient.Session.Items);
await _eventContainer.ClientDisconnectedEvent.TryInvokeAsync(eventArgs, _logger).ConfigureAwait(false);
}
}