dotnet / MQTTnet

MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from http://mqtt.org/.
MIT License
4.5k stars 1.07k forks source link

Server subscriber sessions hash set can contain sessions with no subscriptions #2062

Open sidhoda-nortech opened 3 months ago

sidhoda-nortech commented 3 months ago

Describe the bug

In the server implementation, MqttClientSessionsManager keeps an internal hash set of "subscriber sessions" that have one or more subscriptions.

However, there is a bug that can result in this hash set containing sessions that have no subscriptions. If a subscribe message is intercepted and ProcessSubscription = false is set for all topic filters, then there will be no subscriptions to add. MqttClientSubscriptionsManager.Subscribe will still call MqttClientSessionsManager.OnSubscriptionsAdded with an empty topics list. This method will blindly add the session to _subscriberSessions.

https://github.com/dotnet/MQTTnet/blob/master/Source/MQTTnet/Server/Internal/MqttClientSubscriptionsManager.cs#L215 https://github.com/dotnet/MQTTnet/blob/master/Source/MQTTnet/Server/Internal/MqttClientSessionsManager.cs#L455

As a result, the server will need to check the session for subscriptions for every subsequent application message received which incurs some performance overhead for locking. There may also be other side effects due to this inconsistency.

Which component is your bug related to?

Server

To Reproduce

Steps to reproduce the behavior:

Expected behavior

Session should only be added to the _subscriberSessions if there was at least one subscription added. This then also avoids taking the _sessionsManagementLock when there is no work to do and avoids any other potential side effects.

if (addedSubscriptions.Count > 0)
{
    _subscriptionChangedNotification?.OnSubscriptionsAdded(_session, addedSubscriptions);
}