From 981ea021491b4bc11dfec815c1dffeded40b5b3b Mon Sep 17 00:00:00 2001
From: Victornor <1-1@hotmail.dk>
Date: Tue, 10 Dec 2024 19:37:29 +0100
Subject: [PATCH 1/2] Unused parameter in WithTryPrivate causing client to send
incorrect version byte in header. (#2125)
* fix: unused tryPrivate parameter in WithTryPrivate
* Fix wrong usage of try private
---------
Co-authored-by: christian <6939810+chkr1011@users.noreply.github.com>
---
.../Formatter/V3/MqttV3PacketFormatter.cs | 37 +++++++++----------
Source/MQTTnet/Options/MqttClientOptions.cs | 2 +-
.../Options/MqttClientOptionsBuilder.cs | 4 +-
.../Options/MqttClientOptionsValidator.cs | 6 ++-
4 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/Source/MQTTnet/Formatter/V3/MqttV3PacketFormatter.cs b/Source/MQTTnet/Formatter/V3/MqttV3PacketFormatter.cs
index 5e5a2f150..20dd59f49 100644
--- a/Source/MQTTnet/Formatter/V3/MqttV3PacketFormatter.cs
+++ b/Source/MQTTnet/Formatter/V3/MqttV3PacketFormatter.cs
@@ -18,9 +18,9 @@ public sealed class MqttV3PacketFormatter : IMqttPacketFormatter
{
const int FixedHeaderSize = 1;
- static readonly MqttDisconnectPacket DisconnectPacket = new MqttDisconnectPacket();
+ static readonly MqttDisconnectPacket DisconnectPacket = new();
- readonly MqttBufferReader _bufferReader = new MqttBufferReader();
+ readonly MqttBufferReader _bufferReader = new();
readonly MqttBufferWriter _bufferWriter;
readonly MqttProtocolVersion _mqttProtocolVersion;
@@ -68,10 +68,8 @@ public MqttPacket Decode(ReceivedMqttPacket receivedMqttPacket)
{
return DecodeConnAckPacketV311(receivedMqttPacket.Body);
}
- else
- {
- return DecodeConnAckPacket(receivedMqttPacket.Body);
- }
+
+ return DecodeConnAckPacket(receivedMqttPacket.Body);
case MqttControlPacketType.Disconnect:
return DisconnectPacket;
@@ -106,10 +104,6 @@ public MqttPacketBuffer Encode(MqttPacket packet)
payload = publishPacket.Payload;
remainingLength += (uint)payload.Length;
}
- else
- {
- publishPacket = null;
- }
var remainingLengthSize = MqttBufferWriter.GetVariableByteIntegerSize(remainingLength);
@@ -481,7 +475,16 @@ byte EncodeConnectPacketV311(MqttConnectPacket packet, MqttBufferWriter bufferWr
ValidateConnectPacket(packet);
bufferWriter.WriteString("MQTT");
- bufferWriter.WriteByte(4); // 3.1.2.2 Protocol Level 4
+
+ // 3.1.2.2 Protocol Level 4
+ var protocolVersion = 4;
+
+ if (packet.TryPrivate)
+ {
+ protocolVersion |= 0x80;
+ }
+
+ bufferWriter.WriteByte((byte)protocolVersion);
byte connectFlags = 0x0;
if (packet.CleanSession)
@@ -552,19 +555,15 @@ byte EncodePacket(MqttPacket packet, MqttBufferWriter bufferWriter)
{
return EncodeConnectPacketV311(connectPacket, bufferWriter);
}
- else
- {
- return EncodeConnectPacket(connectPacket, bufferWriter);
- }
+
+ return EncodeConnectPacket(connectPacket, bufferWriter);
case MqttConnAckPacket connAckPacket:
if (_mqttProtocolVersion == MqttProtocolVersion.V311)
{
return EncodeConnAckPacketV311(connAckPacket, bufferWriter);
}
- else
- {
- return EncodeConnAckPacket(connAckPacket, bufferWriter);
- }
+
+ return EncodeConnAckPacket(connAckPacket, bufferWriter);
case MqttDisconnectPacket _:
return EncodeEmptyPacket(MqttControlPacketType.Disconnect);
case MqttPingReqPacket _:
diff --git a/Source/MQTTnet/Options/MqttClientOptions.cs b/Source/MQTTnet/Options/MqttClientOptions.cs
index d337ea0e8..d17dd0548 100644
--- a/Source/MQTTnet/Options/MqttClientOptions.cs
+++ b/Source/MQTTnet/Options/MqttClientOptions.cs
@@ -127,7 +127,7 @@ public sealed class MqttClientOptions
/// connect properly.
///
///
- public bool TryPrivate { get; set; } = true;
+ public bool TryPrivate { get; set; } // Implementation in Mosquitto: https://github.com/eclipse-mosquitto/mosquitto/blob/3cbe805e71ac41a2a20cc9b2ea6b3b619f49554a/lib/send_connect.c#L153
///
/// Gets or sets the user properties.
diff --git a/Source/MQTTnet/Options/MqttClientOptionsBuilder.cs b/Source/MQTTnet/Options/MqttClientOptionsBuilder.cs
index a4dedff97..b1e14a797 100644
--- a/Source/MQTTnet/Options/MqttClientOptionsBuilder.cs
+++ b/Source/MQTTnet/Options/MqttClientOptionsBuilder.cs
@@ -361,9 +361,9 @@ public MqttClientOptionsBuilder WithTopicAliasMaximum(ushort topicAliasMaximum)
/// Not all brokers support this feature so it may be necessary to set it to false if your bridge does not connect
/// properly.
///
- public MqttClientOptionsBuilder WithTryPrivate(bool tryPrivate = true)
+ public MqttClientOptionsBuilder WithTryPrivate(bool value = true)
{
- _options.TryPrivate = true;
+ _options.TryPrivate = value;
return this;
}
diff --git a/Source/MQTTnet/Options/MqttClientOptionsValidator.cs b/Source/MQTTnet/Options/MqttClientOptionsValidator.cs
index 6e9c09f9b..19b2c91c3 100644
--- a/Source/MQTTnet/Options/MqttClientOptionsValidator.cs
+++ b/Source/MQTTnet/Options/MqttClientOptionsValidator.cs
@@ -17,7 +17,11 @@ public static void ThrowIfNotSupported(MqttClientOptions options)
if (options.ProtocolVersion == MqttProtocolVersion.V500)
{
- // Everything is supported.
+ if (options.TryPrivate)
+ {
+ throw new NotSupportedException("Feature TryPrivate only works with MQTT version 3.1 and 3.1.1.");
+ }
+
return;
}
From e2f8d0f0ac15b01eeebdef3821df3a5a46560641 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=80=81=E4=B9=9D?= <366193849@qq.com>
Date: Wed, 11 Dec 2024 02:44:38 +0800
Subject: [PATCH 2/2] Added UserName property to various Server EventArgs.
(#2123)
* Added UserName property to various Server EventArgs.
* InjectedMqttApplicationMessage: Add SenderUserName property.
* Reformat code
* Reformat code
---------
Co-authored-by: christian <6939810+chkr1011@users.noreply.github.com>
---
...ClientAcknowledgedPublishPacketEventArgs.cs | 8 +++++++-
.../Events/ClientConnectedEventArgs.cs | 6 ++++++
.../Events/ClientDisconnectedEventArgs.cs | 18 +++++++++++++++---
.../Events/ClientSubscribedTopicEventArgs.cs | 8 +++++++-
.../Events/ClientUnsubscribedTopicEventArgs.cs | 8 +++++++-
.../Events/InterceptingPacketEventArgs.cs | 8 +++++++-
.../Events/InterceptingPublishEventArgs.cs | 8 +++++++-
.../InterceptingSubscriptionEventArgs.cs | 7 +++++++
.../InterceptingUnsubscriptionEventArgs.cs | 8 +++++++-
.../Events/SessionDeletedEventArgs.cs | 8 +++++++-
.../InjectedMqttApplicationMessage.cs | 2 ++
.../Internal/MqttClientSessionsManager.cs | 14 ++++++++++----
.../Internal/MqttClientSubscriptionsManager.cs | 8 ++++----
.../Internal/MqttConnectedClient.cs | 13 ++++++++-----
Source/MQTTnet.Server/Internal/MqttSession.cs | 2 ++
Source/MQTTnet.Server/MqttServer.cs | 1 +
Source/MQTTnet.Tests/Server/Events_Tests.cs | 17 ++++++++++++-----
17 files changed, 116 insertions(+), 28 deletions(-)
diff --git a/Source/MQTTnet.Server/Events/ClientAcknowledgedPublishPacketEventArgs.cs b/Source/MQTTnet.Server/Events/ClientAcknowledgedPublishPacketEventArgs.cs
index 5b126060c..8a206cc2f 100644
--- a/Source/MQTTnet.Server/Events/ClientAcknowledgedPublishPacketEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/ClientAcknowledgedPublishPacketEventArgs.cs
@@ -10,9 +10,10 @@ namespace MQTTnet.Server
{
public sealed class ClientAcknowledgedPublishPacketEventArgs : EventArgs
{
- public ClientAcknowledgedPublishPacketEventArgs(string clientId, IDictionary sessionItems, MqttPublishPacket publishPacket, MqttPacketWithIdentifier acknowledgePacket)
+ public ClientAcknowledgedPublishPacketEventArgs(string clientId, string userName, IDictionary sessionItems, MqttPublishPacket publishPacket, MqttPacketWithIdentifier acknowledgePacket)
{
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
+ UserName = userName;
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
PublishPacket = publishPacket ?? throw new ArgumentNullException(nameof(publishPacket));
AcknowledgePacket = acknowledgePacket ?? throw new ArgumentNullException(nameof(acknowledgePacket));
@@ -28,6 +29,11 @@ public ClientAcknowledgedPublishPacketEventArgs(string clientId, IDictionary ses
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets whether the PUBLISH packet is fully acknowledged. This is the case for PUBACK (QoS 1) and PUBCOMP (QoS 2.
///
diff --git a/Source/MQTTnet.Server/Events/ClientConnectedEventArgs.cs b/Source/MQTTnet.Server/Events/ClientConnectedEventArgs.cs
index 27701db6f..4249eea6f 100644
--- a/Source/MQTTnet.Server/Events/ClientConnectedEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/ClientConnectedEventArgs.cs
@@ -6,6 +6,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Net;
+using System.Text;
using MQTTnet.Formatter;
using MQTTnet.Packets;
@@ -56,6 +57,11 @@ public ClientConnectedEventArgs(MqttConnectPacket connectPacket, MqttProtocolVer
///
public string UserName => _connectPacket.Username;
+ ///
+ /// Gets the password of the connected client.
+ ///
+ public string Password => Encoding.UTF8.GetString(_connectPacket.Password.AsSpan());
+
///
/// Gets the user properties sent by the client.
/// MQTT 5.0.0+ feature.
diff --git a/Source/MQTTnet.Server/Events/ClientDisconnectedEventArgs.cs b/Source/MQTTnet.Server/Events/ClientDisconnectedEventArgs.cs
index b552e4e96..f64a2f3bd 100644
--- a/Source/MQTTnet.Server/Events/ClientDisconnectedEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/ClientDisconnectedEventArgs.cs
@@ -6,6 +6,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Net;
+using System.Text;
using MQTTnet.Packets;
using MQTTnet.Protocol;
@@ -13,20 +14,21 @@ namespace MQTTnet.Server
{
public sealed class ClientDisconnectedEventArgs : EventArgs
{
+ readonly MqttConnectPacket _connectPacket;
readonly MqttDisconnectPacket _disconnectPacket;
public ClientDisconnectedEventArgs(
- string clientId,
+ MqttConnectPacket connectPacket,
MqttDisconnectPacket disconnectPacket,
MqttClientDisconnectType disconnectType,
EndPoint remoteEndPoint,
IDictionary sessionItems)
{
- ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
DisconnectType = disconnectType;
RemoteEndPoint = remoteEndPoint;
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
+ _connectPacket = connectPacket;
// The DISCONNECT packet can be null in case of a non clean disconnect or session takeover.
_disconnectPacket = disconnectPacket;
}
@@ -35,7 +37,17 @@ public ClientDisconnectedEventArgs(
/// Gets the client identifier.
/// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues.
///
- public string ClientId { get; }
+ public string ClientId => _connectPacket.ClientId;
+
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName => _connectPacket.Username;
+
+ ///
+ /// Gets the password of the client.
+ ///
+ public string Password => Encoding.UTF8.GetString(_connectPacket.Password.AsSpan());
public MqttClientDisconnectType DisconnectType { get; }
diff --git a/Source/MQTTnet.Server/Events/ClientSubscribedTopicEventArgs.cs b/Source/MQTTnet.Server/Events/ClientSubscribedTopicEventArgs.cs
index 639ad98e3..2f5246835 100644
--- a/Source/MQTTnet.Server/Events/ClientSubscribedTopicEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/ClientSubscribedTopicEventArgs.cs
@@ -10,9 +10,10 @@ namespace MQTTnet.Server
{
public sealed class ClientSubscribedTopicEventArgs : EventArgs
{
- public ClientSubscribedTopicEventArgs(string clientId, MqttTopicFilter topicFilter, IDictionary sessionItems)
+ public ClientSubscribedTopicEventArgs(string clientId, string userName, MqttTopicFilter topicFilter, IDictionary sessionItems)
{
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
+ UserName = userName;
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
}
@@ -23,6 +24,11 @@ public ClientSubscribedTopicEventArgs(string clientId, MqttTopicFilter topicFilt
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets or sets a key/value collection that can be used to share data within the scope of this session.
///
diff --git a/Source/MQTTnet.Server/Events/ClientUnsubscribedTopicEventArgs.cs b/Source/MQTTnet.Server/Events/ClientUnsubscribedTopicEventArgs.cs
index d521b857e..677236b37 100644
--- a/Source/MQTTnet.Server/Events/ClientUnsubscribedTopicEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/ClientUnsubscribedTopicEventArgs.cs
@@ -9,9 +9,10 @@ namespace MQTTnet.Server
{
public sealed class ClientUnsubscribedTopicEventArgs : EventArgs
{
- public ClientUnsubscribedTopicEventArgs(string clientId, string topicFilter, IDictionary sessionItems)
+ public ClientUnsubscribedTopicEventArgs(string clientId, string userName, string topicFilter, IDictionary sessionItems)
{
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
+ UserName = userName;
TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter));
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
}
@@ -22,6 +23,11 @@ public ClientUnsubscribedTopicEventArgs(string clientId, string topicFilter, IDi
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets or sets a key/value collection that can be used to share data within the scope of this session.
///
diff --git a/Source/MQTTnet.Server/Events/InterceptingPacketEventArgs.cs b/Source/MQTTnet.Server/Events/InterceptingPacketEventArgs.cs
index 0b1eef2e8..6067a17e4 100644
--- a/Source/MQTTnet.Server/Events/InterceptingPacketEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/InterceptingPacketEventArgs.cs
@@ -12,10 +12,11 @@ namespace MQTTnet.Server
{
public sealed class InterceptingPacketEventArgs : EventArgs
{
- public InterceptingPacketEventArgs(CancellationToken cancellationToken, string clientId, EndPoint remoteEndPoint, MqttPacket packet, IDictionary sessionItems)
+ public InterceptingPacketEventArgs(CancellationToken cancellationToken, string clientId, string userName, EndPoint remoteEndPoint, MqttPacket packet, IDictionary sessionItems)
{
CancellationToken = cancellationToken;
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
+ UserName = userName;
RemoteEndPoint = remoteEndPoint;
Packet = packet ?? throw new ArgumentNullException(nameof(packet));
SessionItems = sessionItems;
@@ -32,6 +33,11 @@ public InterceptingPacketEventArgs(CancellationToken cancellationToken, string c
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets the endpoint of the sending or receiving client.
///
diff --git a/Source/MQTTnet.Server/Events/InterceptingPublishEventArgs.cs b/Source/MQTTnet.Server/Events/InterceptingPublishEventArgs.cs
index 34b12b565..b20961049 100644
--- a/Source/MQTTnet.Server/Events/InterceptingPublishEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/InterceptingPublishEventArgs.cs
@@ -10,11 +10,12 @@ namespace MQTTnet.Server
{
public sealed class InterceptingPublishEventArgs : EventArgs
{
- public InterceptingPublishEventArgs(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken, string clientId, IDictionary sessionItems)
+ public InterceptingPublishEventArgs(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken, string clientId, string userName, IDictionary sessionItems)
{
ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage));
CancellationToken = cancellationToken;
ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
+ UserName = userName;
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
}
@@ -31,6 +32,11 @@ public InterceptingPublishEventArgs(MqttApplicationMessage applicationMessage, C
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
public bool CloseConnection { get; set; }
///
diff --git a/Source/MQTTnet.Server/Events/InterceptingSubscriptionEventArgs.cs b/Source/MQTTnet.Server/Events/InterceptingSubscriptionEventArgs.cs
index fa26d13e8..7f62d68e9 100644
--- a/Source/MQTTnet.Server/Events/InterceptingSubscriptionEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/InterceptingSubscriptionEventArgs.cs
@@ -15,12 +15,14 @@ public sealed class InterceptingSubscriptionEventArgs : EventArgs
public InterceptingSubscriptionEventArgs(
CancellationToken cancellationToken,
string clientId,
+ string userName,
MqttSessionStatus session,
MqttTopicFilter topicFilter,
List userProperties)
{
CancellationToken = cancellationToken;
ClientId = clientId;
+ UserName = userName;
Session = session;
TopicFilter = topicFilter;
UserProperties = userProperties;
@@ -37,6 +39,11 @@ public InterceptingSubscriptionEventArgs(
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets or sets whether the broker should close the client connection.
///
diff --git a/Source/MQTTnet.Server/Events/InterceptingUnsubscriptionEventArgs.cs b/Source/MQTTnet.Server/Events/InterceptingUnsubscriptionEventArgs.cs
index 36d08df3d..5838aadcb 100644
--- a/Source/MQTTnet.Server/Events/InterceptingUnsubscriptionEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/InterceptingUnsubscriptionEventArgs.cs
@@ -12,10 +12,11 @@ namespace MQTTnet.Server
{
public sealed class InterceptingUnsubscriptionEventArgs : EventArgs
{
- public InterceptingUnsubscriptionEventArgs(CancellationToken cancellationToken, string clientId, IDictionary sessionItems, string topic, List userProperties)
+ public InterceptingUnsubscriptionEventArgs(CancellationToken cancellationToken, string clientId, string userName, IDictionary sessionItems, string topic, List userProperties)
{
CancellationToken = cancellationToken;
ClientId = clientId;
+ UserName = userName;
SessionItems = sessionItems;
Topic = topic;
UserProperties = userProperties;
@@ -32,6 +33,11 @@ public InterceptingUnsubscriptionEventArgs(CancellationToken cancellationToken,
///
public string ClientId { get; }
+ ///
+ /// Gets the user name of the client.
+ ///
+ public string UserName { get; }
+
///
/// Gets or sets whether the broker should close the client connection.
///
diff --git a/Source/MQTTnet.Server/Events/SessionDeletedEventArgs.cs b/Source/MQTTnet.Server/Events/SessionDeletedEventArgs.cs
index 3d27036c7..dd9037239 100644
--- a/Source/MQTTnet.Server/Events/SessionDeletedEventArgs.cs
+++ b/Source/MQTTnet.Server/Events/SessionDeletedEventArgs.cs
@@ -9,9 +9,10 @@ namespace MQTTnet.Server
{
public sealed class SessionDeletedEventArgs : EventArgs
{
- public SessionDeletedEventArgs(string id, IDictionary sessionItems)
+ public SessionDeletedEventArgs(string id, string userName, IDictionary sessionItems)
{
Id = id ?? throw new ArgumentNullException(nameof(id));
+ UserName = userName;
SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
}
@@ -20,6 +21,11 @@ public SessionDeletedEventArgs(string id, IDictionary sessionItems)
///
public string Id { get; }
+ ///
+ /// Gets the user name of the session.
+ ///
+ public string UserName { get; }
+
///
/// Gets or sets a key/value collection that can be used to share data within the scope of this session.
///
diff --git a/Source/MQTTnet.Server/InjectedMqttApplicationMessage.cs b/Source/MQTTnet.Server/InjectedMqttApplicationMessage.cs
index 3a9add06a..56929dd42 100644
--- a/Source/MQTTnet.Server/InjectedMqttApplicationMessage.cs
+++ b/Source/MQTTnet.Server/InjectedMqttApplicationMessage.cs
@@ -23,4 +23,6 @@ public InjectedMqttApplicationMessage(MqttApplicationMessage applicationMessage)
public IDictionary CustomSessionItems { get; set; }
public string SenderClientId { get; set; } = string.Empty;
+
+ public string SenderUserName { get; set; }
}
\ No newline at end of file
diff --git a/Source/MQTTnet.Server/Internal/MqttClientSessionsManager.cs b/Source/MQTTnet.Server/Internal/MqttClientSessionsManager.cs
index 67728a8d3..b99fa8e03 100644
--- a/Source/MQTTnet.Server/Internal/MqttClientSessionsManager.cs
+++ b/Source/MQTTnet.Server/Internal/MqttClientSessionsManager.cs
@@ -101,7 +101,7 @@ public async Task DeleteSessionAsync(string clientId)
{
if (_eventContainer.SessionDeletedEvent.HasHandlers && session != null)
{
- var eventArgs = new SessionDeletedEventArgs(clientId, session.Items);
+ var eventArgs = new SessionDeletedEventArgs(clientId, session.UserName, session.Items);
await _eventContainer.SessionDeletedEvent.TryInvokeAsync(eventArgs, _logger).ConfigureAwait(false);
}
}
@@ -117,6 +117,7 @@ public async Task DeleteSessionAsync(string clientId)
public async Task DispatchApplicationMessage(
string senderId,
+ string senderUserName,
IDictionary senderSessionItems,
MqttApplicationMessage applicationMessage,
CancellationToken cancellationToken)
@@ -130,7 +131,7 @@ public async Task DispatchApplicationMessage(
// Allow the user to intercept application message...
if (_eventContainer.InterceptingPublishEvent.HasHandlers)
{
- var interceptingPublishEventArgs = new InterceptingPublishEventArgs(applicationMessage, cancellationToken, senderId, senderSessionItems);
+ var interceptingPublishEventArgs = new InterceptingPublishEventArgs(applicationMessage, cancellationToken, senderId, senderUserName, senderSessionItems);
if (string.IsNullOrEmpty(interceptingPublishEventArgs.ApplicationMessage.Topic))
{
// This can happen if a topic alias us used but the topic is
@@ -408,7 +409,12 @@ public async Task HandleClientConnectionAsync(IMqttChannelAdapter channelAdapter
if (connectedClient.Id != null && !connectedClient.IsTakenOver && _eventContainer.ClientDisconnectedEvent.HasHandlers)
{
var disconnectType = connectedClient.DisconnectPacket != null ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean;
- var eventArgs = new ClientDisconnectedEventArgs(connectedClient.Id, connectedClient.DisconnectPacket, disconnectType, endpoint, connectedClient.Session.Items);
+ var eventArgs = new ClientDisconnectedEventArgs(
+ connectedClient.ConnectPacket,
+ connectedClient.DisconnectPacket,
+ disconnectType,
+ endpoint,
+ connectedClient.Session.Items);
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
}
@@ -592,7 +598,7 @@ async Task CreateClientConnection(
if (_eventContainer.ClientDisconnectedEvent.HasHandlers)
{
var eventArgs = new ClientDisconnectedEventArgs(
- oldConnectedClient.Id,
+ oldConnectedClient.ConnectPacket,
null,
MqttClientDisconnectType.Takeover,
oldConnectedClient.RemoteEndPoint,
diff --git a/Source/MQTTnet.Server/Internal/MqttClientSubscriptionsManager.cs b/Source/MQTTnet.Server/Internal/MqttClientSubscriptionsManager.cs
index 4413755ad..7c1023e52 100644
--- a/Source/MQTTnet.Server/Internal/MqttClientSubscriptionsManager.cs
+++ b/Source/MQTTnet.Server/Internal/MqttClientSubscriptionsManager.cs
@@ -209,7 +209,7 @@ public async Task Subscribe(MqttSubscribePacket subscribePacket
{
foreach (var finalTopicFilter in finalTopicFilters)
{
- var eventArgs = new ClientSubscribedTopicEventArgs(_session.Id, finalTopicFilter, _session.Items);
+ var eventArgs = new ClientSubscribedTopicEventArgs(_session.Id, _session.UserName, finalTopicFilter, _session.Items);
await _eventContainer.ClientSubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
}
}
@@ -297,7 +297,7 @@ public async Task Unsubscribe(MqttUnsubscribePacket unsubscri
{
foreach (var topicFilter in unsubscribePacket.TopicFilters)
{
- var eventArgs = new ClientUnsubscribedTopicEventArgs(_session.Id, topicFilter, _session.Items);
+ var eventArgs = new ClientUnsubscribedTopicEventArgs(_session.Id, _session.UserName, topicFilter, _session.Items);
await _eventContainer.ClientUnsubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
}
}
@@ -460,7 +460,7 @@ async Task InterceptSubscribe(
List userProperties,
CancellationToken cancellationToken)
{
- var eventArgs = new InterceptingSubscriptionEventArgs(cancellationToken, _session.Id, new MqttSessionStatus(_session), topicFilter, userProperties);
+ var eventArgs = new InterceptingSubscriptionEventArgs(cancellationToken, _session.Id, _session.UserName, new MqttSessionStatus(_session), topicFilter, userProperties);
if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
{
@@ -493,7 +493,7 @@ async Task InterceptUnsubscribe(
List userProperties,
CancellationToken cancellationToken)
{
- var clientUnsubscribingTopicEventArgs = new InterceptingUnsubscriptionEventArgs(cancellationToken, _session.Id, _session.Items, topicFilter, userProperties)
+ var clientUnsubscribingTopicEventArgs = new InterceptingUnsubscriptionEventArgs(cancellationToken, _session.Id, _session.UserName, _session.Items, topicFilter, userProperties)
{
Response =
{
diff --git a/Source/MQTTnet.Server/Internal/MqttConnectedClient.cs b/Source/MQTTnet.Server/Internal/MqttConnectedClient.cs
index 84f26570d..bfdb21307 100644
--- a/Source/MQTTnet.Server/Internal/MqttConnectedClient.cs
+++ b/Source/MQTTnet.Server/Internal/MqttConnectedClient.cs
@@ -72,6 +72,8 @@ public MqttConnectedClient(
public MqttClientStatistics Statistics { get; } = new();
+ public string UserName => ConnectPacket.Username;
+
public void Dispose()
{
_cancellationToken?.Dispose();
@@ -117,7 +119,7 @@ public async Task RunAsync()
var willPublishPacket = MqttPublishPacketFactory.Create(Session.LatestConnectPacket);
var willApplicationMessage = MqttApplicationMessageFactory.Create(willPublishPacket);
- _ = _sessionsManager.DispatchApplicationMessage(Id, Session.Items, willApplicationMessage, CancellationToken.None);
+ _ = _sessionsManager.DispatchApplicationMessage(Id, UserName, Session.Items, willApplicationMessage, CancellationToken.None);
Session.WillMessageSent = true;
_logger.Info("Client '{0}': Published will message", Id);
@@ -174,7 +176,7 @@ Task ClientAcknowledgedPublishPacket(MqttPublishPacket publishPacket, MqttPacket
{
if (_eventContainer.ClientAcknowledgedPublishPacketEvent.HasHandlers)
{
- var eventArgs = new ClientAcknowledgedPublishPacketEventArgs(Id, Session.Items, publishPacket, acknowledgePacket);
+ var eventArgs = new ClientAcknowledgedPublishPacketEventArgs(Id, UserName, Session.Items, publishPacket, acknowledgePacket);
return _eventContainer.ClientAcknowledgedPublishPacketEvent.TryInvokeAsync(eventArgs, _logger);
}
@@ -217,7 +219,8 @@ async Task HandleIncomingPublishPacket(MqttPublishPacket publishPacket, Cancella
var applicationMessage = MqttApplicationMessageFactory.Create(publishPacket);
- var dispatchApplicationMessageResult = await _sessionsManager.DispatchApplicationMessage(Id, Session.Items, applicationMessage, cancellationToken).ConfigureAwait(false);
+ var dispatchApplicationMessageResult =
+ await _sessionsManager.DispatchApplicationMessage(Id, UserName, Session.Items, applicationMessage, cancellationToken).ConfigureAwait(false);
if (dispatchApplicationMessageResult.CloseConnection)
{
@@ -339,7 +342,7 @@ async Task InterceptPacketAsync(MqttPacket packet, CancellationToken
return packet;
}
- var interceptingPacketEventArgs = new InterceptingPacketEventArgs(cancellationToken, Id, RemoteEndPoint, packet, Session.Items);
+ var interceptingPacketEventArgs = new InterceptingPacketEventArgs(cancellationToken, Id, UserName, RemoteEndPoint, packet, Session.Items);
await _eventContainer.InterceptingOutboundPacketEvent.InvokeAsync(interceptingPacketEventArgs).ConfigureAwait(false);
if (!interceptingPacketEventArgs.ProcessPacket || packet == null)
@@ -385,7 +388,7 @@ async Task ReceivePackagesLoop(CancellationToken cancellationToken)
if (_eventContainer.InterceptingInboundPacketEvent.HasHandlers)
{
- var interceptingPacketEventArgs = new InterceptingPacketEventArgs(cancellationToken, Id, RemoteEndPoint, currentPacket, Session.Items);
+ var interceptingPacketEventArgs = new InterceptingPacketEventArgs(cancellationToken, Id, UserName, RemoteEndPoint, currentPacket, Session.Items);
await _eventContainer.InterceptingInboundPacketEvent.InvokeAsync(interceptingPacketEventArgs).ConfigureAwait(false);
currentPacket = interceptingPacketEventArgs.Packet;
processPacket = interceptingPacketEventArgs.ProcessPacket;
diff --git a/Source/MQTTnet.Server/Internal/MqttSession.cs b/Source/MQTTnet.Server/Internal/MqttSession.cs
index 0aea7d803..55814b849 100644
--- a/Source/MQTTnet.Server/Internal/MqttSession.cs
+++ b/Source/MQTTnet.Server/Internal/MqttSession.cs
@@ -53,6 +53,8 @@ public MqttSession(
public string Id => _connectPacket.ClientId;
+ public string UserName => _connectPacket.Username;
+
public IDictionary Items { get; }
public MqttConnectPacket LatestConnectPacket { get; set; }
diff --git a/Source/MQTTnet.Server/MqttServer.cs b/Source/MQTTnet.Server/MqttServer.cs
index dc30ac93f..f0f423f0e 100644
--- a/Source/MQTTnet.Server/MqttServer.cs
+++ b/Source/MQTTnet.Server/MqttServer.cs
@@ -255,6 +255,7 @@ public Task InjectApplicationMessage(InjectedMqttApplicationMessage injectedAppl
return _clientSessionsManager.DispatchApplicationMessage(
injectedApplicationMessage.SenderClientId,
+ injectedApplicationMessage.SenderUserName,
sessionItems,
injectedApplicationMessage.ApplicationMessage,
cancellationToken);
diff --git a/Source/MQTTnet.Tests/Server/Events_Tests.cs b/Source/MQTTnet.Tests/Server/Events_Tests.cs
index 415a2a2d2..bce9197ed 100644
--- a/Source/MQTTnet.Tests/Server/Events_Tests.cs
+++ b/Source/MQTTnet.Tests/Server/Events_Tests.cs
@@ -29,7 +29,7 @@ public async Task Fire_Client_Connected_Event()
return CompletedTask.Instance;
};
- await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
+ await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser", "ThePassword"));
await LongTestDelay();
@@ -39,6 +39,7 @@ public async Task Fire_Client_Connected_Event()
Assert.IsTrue(eventArgs.RemoteEndPoint.ToString().Contains("127.0.0.1"));
Assert.AreEqual(MqttProtocolVersion.V311, eventArgs.ProtocolVersion);
Assert.AreEqual("TheUser", eventArgs.UserName);
+ Assert.AreEqual("ThePassword", eventArgs.Password);
}
}
@@ -56,7 +57,7 @@ public async Task Fire_Client_Disconnected_Event()
return CompletedTask.Instance;
};
- var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
+ var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser", "ThePassword"));
await client.DisconnectAsync();
await LongTestDelay();
@@ -66,6 +67,9 @@ public async Task Fire_Client_Disconnected_Event()
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Disconnected_Event)));
Assert.IsTrue(eventArgs.RemoteEndPoint.ToString().Contains("127.0.0.1"));
Assert.AreEqual(MqttClientDisconnectType.Clean, eventArgs.DisconnectType);
+
+ Assert.AreEqual("TheUser", eventArgs.UserName);
+ Assert.AreEqual("ThePassword", eventArgs.Password);
}
}
@@ -83,7 +87,7 @@ public async Task Fire_Client_Subscribed_Event()
return CompletedTask.Instance;
};
- var client = await testEnvironment.ConnectClient();
+ var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
await client.SubscribeAsync("The/Topic", MqttQualityOfServiceLevel.AtLeastOnce);
await LongTestDelay();
@@ -93,6 +97,7 @@ public async Task Fire_Client_Subscribed_Event()
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Subscribed_Event)));
Assert.AreEqual("The/Topic", eventArgs.TopicFilter.Topic);
Assert.AreEqual(MqttQualityOfServiceLevel.AtLeastOnce, eventArgs.TopicFilter.QualityOfServiceLevel);
+ Assert.AreEqual("TheUser", eventArgs.UserName);
}
}
@@ -110,7 +115,7 @@ public async Task Fire_Client_Unsubscribed_Event()
return CompletedTask.Instance;
};
- var client = await testEnvironment.ConnectClient();
+ var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
await client.UnsubscribeAsync("The/Topic");
await LongTestDelay();
@@ -119,6 +124,7 @@ public async Task Fire_Client_Unsubscribed_Event()
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Client_Unsubscribed_Event)));
Assert.AreEqual("The/Topic", eventArgs.TopicFilter);
+ Assert.AreEqual("TheUser", eventArgs.UserName);
}
}
@@ -136,7 +142,7 @@ public async Task Fire_Application_Message_Received_Event()
return CompletedTask.Instance;
};
- var client = await testEnvironment.ConnectClient();
+ var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
await client.PublishStringAsync("The_Topic", "The_Payload");
await LongTestDelay();
@@ -146,6 +152,7 @@ public async Task Fire_Application_Message_Received_Event()
Assert.IsTrue(eventArgs.ClientId.StartsWith(nameof(Fire_Application_Message_Received_Event)));
Assert.AreEqual("The_Topic", eventArgs.ApplicationMessage.Topic);
Assert.AreEqual("The_Payload", eventArgs.ApplicationMessage.ConvertPayloadToString());
+ Assert.AreEqual("TheUser", eventArgs.UserName);
}
}