mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-19 02:53:06 +08:00
Migrate retained messages to the event based approach.
This commit is contained in:
@@ -6,7 +6,7 @@ namespace MQTTnet.Formatter
|
|||||||
{
|
{
|
||||||
public sealed class MqttConnAckPacketFactory
|
public sealed class MqttConnAckPacketFactory
|
||||||
{
|
{
|
||||||
public MqttConnAckPacket Create(ValidatingMqttClientConnectionEventArgs clientConnectionValidationEventArgs)
|
public MqttConnAckPacket Create(ValidatingConnectionEventArgs clientConnectionValidationEventArgs)
|
||||||
{
|
{
|
||||||
if (clientConnectionValidationEventArgs == null) throw new ArgumentNullException(nameof(clientConnectionValidationEventArgs));
|
if (clientConnectionValidationEventArgs == null) throw new ArgumentNullException(nameof(clientConnectionValidationEventArgs));
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace MQTTnet.Formatter
|
|||||||
{
|
{
|
||||||
public sealed class MqttPubAckPacketFactory
|
public sealed class MqttPubAckPacketFactory
|
||||||
{
|
{
|
||||||
public MqttPubAckPacket Create(MqttPublishPacket publishPacket, MqttApplicationMessageResponse applicationMessageResponse)
|
public MqttPubAckPacket Create(MqttPublishPacket publishPacket, PublishResponse applicationMessageResponse)
|
||||||
{
|
{
|
||||||
if (applicationMessageResponse == null) throw new ArgumentNullException(nameof(applicationMessageResponse));
|
if (applicationMessageResponse == null) throw new ArgumentNullException(nameof(applicationMessageResponse));
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace MQTTnet.Formatter
|
|||||||
return pubRecPacket;
|
return pubRecPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttBasePacket Create(MqttPublishPacket publishPacket, MqttApplicationMessageResponse applicationMessageResponse)
|
public MqttBasePacket Create(MqttPublishPacket publishPacket, PublishResponse applicationMessageResponse)
|
||||||
{
|
{
|
||||||
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
|
||||||
|
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ namespace MQTTnet.Formatter
|
|||||||
{
|
{
|
||||||
public sealed class MqttSubAckPacketFactory
|
public sealed class MqttSubAckPacketFactory
|
||||||
{
|
{
|
||||||
public MqttSubAckPacket Create(MqttSubscribePacket subscribePacket, MqttSubscribeResult mqttSubscribeResult)
|
public MqttSubAckPacket Create(MqttSubscribePacket subscribePacket, SubscribeResult subscribeResult)
|
||||||
{
|
{
|
||||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||||
if (mqttSubscribeResult == null) throw new ArgumentNullException(nameof(mqttSubscribeResult));
|
if (subscribeResult == null) throw new ArgumentNullException(nameof(subscribeResult));
|
||||||
|
|
||||||
var subAckPacket = new MqttSubAckPacket
|
var subAckPacket = new MqttSubAckPacket
|
||||||
{
|
{
|
||||||
PacketIdentifier = subscribePacket.PacketIdentifier
|
PacketIdentifier = subscribePacket.PacketIdentifier
|
||||||
};
|
};
|
||||||
|
|
||||||
subAckPacket.ReasonCodes.AddRange(mqttSubscribeResult.ReasonCodes);
|
subAckPacket.ReasonCodes.AddRange(subscribeResult.ReasonCodes);
|
||||||
|
|
||||||
return subAckPacket;
|
return subAckPacket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
|
using MqttClient = MQTTnet.Client.MqttClient;
|
||||||
|
|
||||||
namespace MQTTnet
|
namespace MQTTnet
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttApplicationMessageNotConsumedEventArgs : EventArgs
|
public sealed class ApplicationMessageNotConsumedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the application message which was not consumed by any client.
|
/// Gets the application message which was not consumed by any client.
|
||||||
+1
-1
@@ -3,7 +3,7 @@ using MQTTnet.Formatter;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttServerClientConnectedEventArgs : EventArgs
|
public sealed class ClientConnectedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier of the connected client.
|
/// Gets the client identifier of the connected client.
|
||||||
+1
-1
@@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttServerClientDisconnectedEventArgs : EventArgs
|
public sealed class ClientDisconnectedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
+1
-1
@@ -3,7 +3,7 @@ using MQTTnet.Packets;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttServerClientSubscribedTopicEventArgs : EventArgs
|
public sealed class ClientSubscribedTopicEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttServerClientUnsubscribedTopicEventArgs : EventArgs
|
public sealed class ClientUnsubscribedTopicEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
+2
-2
@@ -4,7 +4,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class InterceptingMqttClientPublishEventArgs : EventArgs
|
public sealed class InterceptingPublishEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
@@ -22,7 +22,7 @@ namespace MQTTnet.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the response which will be sent to the client via the PUBACK etc. packets.
|
/// Gets the response which will be sent to the client via the PUBACK etc. packets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttApplicationMessageResponse Response { get; } = new MqttApplicationMessageResponse();
|
public PublishResponse Response { get; } = new PublishResponse();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether the publish should be processed internally.
|
/// Gets or sets whether the publish should be processed internally.
|
||||||
+2
-2
@@ -5,7 +5,7 @@ using MQTTnet.Packets;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class InterceptingMqttClientSubscriptionEventArgs : EventArgs
|
public sealed class InterceptingSubscriptionEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
@@ -44,7 +44,7 @@ namespace MQTTnet.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the response which will be sent to the client via the SUBACK packet.
|
/// Gets the response which will be sent to the client via the SUBACK packet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttSubscribeResponse Response { get; } = new MqttSubscribeResponse();
|
public SubscribeResponse Response { get; } = new SubscribeResponse();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the cancellation token which can indicate that the client connection gets down.
|
/// Gets the cancellation token which can indicate that the client connection gets down.
|
||||||
+2
-2
@@ -4,7 +4,7 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class InterceptingMqttClientUnsubscriptionEventArgs : EventArgs
|
public sealed class InterceptingUnsubscriptionEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the client identifier.
|
/// Gets the client identifier.
|
||||||
@@ -27,7 +27,7 @@ namespace MQTTnet.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the response which will be sent to the client via the UNSUBACK pocket.
|
/// Gets the response which will be sent to the client via the UNSUBACK pocket.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttUnsubscribeResponse Response { get; } = new MqttUnsubscribeResponse();
|
public UnsubscribeResponse Response { get; } = new UnsubscribeResponse();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether the broker should remove an internal subscription for the client.
|
/// Gets or sets whether the broker should remove an internal subscription for the client.
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public sealed class LoadingRetainedMessagesEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public List<MqttApplicationMessage> StoredRetainedMessages { get; set; } = new List<MqttApplicationMessage>();
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-2
@@ -4,9 +4,9 @@ using MQTTnet.Packets;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class PreparingMqttClientSessionEventArgs : EventArgs
|
public sealed class PreparingSessionEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public string ClientId { get; internal set; }
|
public string Id { get; internal set; }
|
||||||
|
|
||||||
// TODO: Allow adding of packets to the queue etc.
|
// TODO: Allow adding of packets to the queue etc.
|
||||||
|
|
||||||
@@ -25,5 +25,21 @@ namespace MQTTnet.Server
|
|||||||
public List<MqttSubscription> Subscriptions { get; } = new List<MqttSubscription>();
|
public List<MqttSubscription> Subscriptions { get; } = new List<MqttSubscription>();
|
||||||
|
|
||||||
public List<MqttPublishPacket> PublishPackets { get; } = new List<MqttPublishPacket>();
|
public List<MqttPublishPacket> PublishPackets { get; } = new List<MqttPublishPacket>();
|
||||||
|
|
||||||
|
IDictionary<object, object> Items { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the last will message.
|
||||||
|
/// In MQTT, you use the last will message feature to notify other clients about an ungracefully disconnected client.
|
||||||
|
/// </summary>
|
||||||
|
MqttApplicationMessage WillMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the will delay interval.
|
||||||
|
/// This is the time between the client disconnect and the time the will message will be sent.
|
||||||
|
/// </summary>
|
||||||
|
uint? WillDelayInterval { get; set; }
|
||||||
|
|
||||||
|
DateTime? SessionExpiryTimestamp { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MQTTnet.Server
|
||||||
|
{
|
||||||
|
public sealed class RetainedMessageChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public string ClientId { get; internal set; }
|
||||||
|
|
||||||
|
public MqttApplicationMessage ChangedRetainedMessage { get; internal set; }
|
||||||
|
|
||||||
|
public List<MqttApplicationMessage> StoredRetainedMessages { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -10,12 +10,12 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class ValidatingMqttClientConnectionEventArgs : EventArgs
|
public sealed class ValidatingConnectionEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
readonly MqttConnectPacket _connectPacket;
|
readonly MqttConnectPacket _connectPacket;
|
||||||
readonly IMqttChannelAdapter _clientAdapter;
|
readonly IMqttChannelAdapter _clientAdapter;
|
||||||
|
|
||||||
public ValidatingMqttClientConnectionEventArgs(MqttConnectPacket connectPacket, IMqttChannelAdapter clientAdapter)
|
public ValidatingConnectionEventArgs(MqttConnectPacket connectPacket, IMqttChannelAdapter clientAdapter)
|
||||||
{
|
{
|
||||||
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
||||||
_clientAdapter = clientAdapter ?? throw new ArgumentNullException(nameof(clientAdapter));
|
_clientAdapter = clientAdapter ?? throw new ArgumentNullException(nameof(clientAdapter));
|
||||||
@@ -20,7 +20,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public MqttApplicationMessage ApplicationMessage { get; private set; }
|
public MqttApplicationMessage ApplicationMessage { get; private set; }
|
||||||
|
|
||||||
public MqttApplicationMessageResponse Response { get; private set; } = new MqttApplicationMessageResponse();
|
public PublishResponse Response { get; private set; } = new PublishResponse();
|
||||||
|
|
||||||
public bool ProcessPublish { get; private set; } = true;
|
public bool ProcessPublish { get; private set; } = true;
|
||||||
|
|
||||||
@@ -29,13 +29,13 @@ namespace MQTTnet.Server
|
|||||||
public async Task Invoke(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
public async Task Invoke(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Reset to defaults.
|
// Reset to defaults.
|
||||||
Response = new MqttApplicationMessageResponse();
|
Response = new PublishResponse();
|
||||||
ProcessPublish = true;
|
ProcessPublish = true;
|
||||||
CloseConnection = false;
|
CloseConnection = false;
|
||||||
ApplicationMessage = applicationMessage;
|
ApplicationMessage = applicationMessage;
|
||||||
|
|
||||||
// Intercept.
|
// Intercept.
|
||||||
var eventArgs = new InterceptingMqttClientPublishEventArgs
|
var eventArgs = new InterceptingPublishEventArgs
|
||||||
{
|
{
|
||||||
ClientId = _clientId,
|
ClientId = _clientId,
|
||||||
ApplicationMessage = applicationMessage,
|
ApplicationMessage = applicationMessage,
|
||||||
@@ -53,7 +53,7 @@ namespace MQTTnet.Server
|
|||||||
eventArgs.ProcessPublish = false;
|
eventArgs.ProcessPublish = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _eventContainer.InterceptingClientPublishEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
await _eventContainer.InterceptingPublishEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
// Expose results.
|
// Expose results.
|
||||||
ProcessPublish = eventArgs.ProcessPublish && eventArgs.ApplicationMessage != null;
|
ProcessPublish = eventArgs.ProcessPublish && eventArgs.ApplicationMessage != null;
|
||||||
|
|||||||
+6
-6
@@ -14,7 +14,7 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttClientConnection : IDisposable
|
public sealed class MqttClient : IDisposable
|
||||||
{
|
{
|
||||||
readonly Dictionary<ushort, string> _topicAlias = new Dictionary<ushort, string>();
|
readonly Dictionary<ushort, string> _topicAlias = new Dictionary<ushort, string>();
|
||||||
readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
|
readonly MqttPacketDispatcher _packetDispatcher = new MqttPacketDispatcher();
|
||||||
@@ -32,10 +32,10 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
CancellationTokenSource _cancellationToken;
|
CancellationTokenSource _cancellationToken;
|
||||||
|
|
||||||
public MqttClientConnection(
|
public MqttClient(
|
||||||
MqttConnectPacket connectPacket,
|
MqttConnectPacket connectPacket,
|
||||||
IMqttChannelAdapter channelAdapter,
|
IMqttChannelAdapter channelAdapter,
|
||||||
MqttClientSession session,
|
MqttSession session,
|
||||||
MqttServerOptions serverOptions,
|
MqttServerOptions serverOptions,
|
||||||
MqttServerEventContainer eventContainer,
|
MqttServerEventContainer eventContainer,
|
||||||
MqttClientSessionsManager sessionsManager,
|
MqttClientSessionsManager sessionsManager,
|
||||||
@@ -54,7 +54,7 @@ namespace MQTTnet.Server
|
|||||||
_applicationMessageInterceptorInvoker = new MqttApplicationMessageInterceptorInvoker(eventContainer, Id, Session.Items);
|
_applicationMessageInterceptorInvoker = new MqttApplicationMessageInterceptorInvoker(eventContainer, Id, Session.Items);
|
||||||
|
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
_logger = logger.WithSource(nameof(MqttClientConnection));
|
_logger = logger.WithSource(nameof(MqttClient));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Id => _connectPacket.ClientId;
|
public string Id => _connectPacket.ClientId;
|
||||||
@@ -63,13 +63,13 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public IMqttChannelAdapter ChannelAdapter { get; }
|
public IMqttChannelAdapter ChannelAdapter { get; }
|
||||||
|
|
||||||
public MqttClientConnectionStatistics Statistics { get; } = new MqttClientConnectionStatistics();
|
public MqttClientStatistics Statistics { get; } = new MqttClientStatistics();
|
||||||
|
|
||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
public ushort KeepAlivePeriod => _connectPacket.KeepAlivePeriod;
|
public ushort KeepAlivePeriod => _connectPacket.KeepAlivePeriod;
|
||||||
|
|
||||||
public MqttClientSession Session { get; }
|
public MqttSession Session { get; }
|
||||||
|
|
||||||
public bool IsTakenOver { get; set; }
|
public bool IsTakenOver { get; set; }
|
||||||
|
|
||||||
@@ -20,14 +20,14 @@ namespace MQTTnet.Server
|
|||||||
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
|
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
|
||||||
|
|
||||||
readonly AsyncLock _createConnectionSyncRoot = new AsyncLock();
|
readonly AsyncLock _createConnectionSyncRoot = new AsyncLock();
|
||||||
readonly Dictionary<string, MqttClientConnection> _clientConnections = new Dictionary<string, MqttClientConnection>(4096);
|
readonly Dictionary<string, MqttClient> _clients = new Dictionary<string, MqttClient>(4096);
|
||||||
readonly Dictionary<string, MqttClientSession> _clientSessions = new Dictionary<string, MqttClientSession>(4096);
|
readonly Dictionary<string, MqttSession> _sessions = new Dictionary<string, MqttSession>(4096);
|
||||||
|
|
||||||
readonly IDictionary<object, object> _serverSessionItems = new ConcurrentDictionary<object, object>();
|
readonly IDictionary<object, object> _serverSessionItems = new ConcurrentDictionary<object, object>();
|
||||||
|
|
||||||
readonly MqttConnAckPacketFactory _connAckPacketFactory = new MqttConnAckPacketFactory();
|
readonly MqttConnAckPacketFactory _connAckPacketFactory = new MqttConnAckPacketFactory();
|
||||||
|
|
||||||
readonly IMqttRetainedMessagesManager _retainedMessagesManager;
|
readonly MqttRetainedMessagesManager _retainedMessagesManager;
|
||||||
readonly MqttServerEventContainer _eventContainer;
|
readonly MqttServerEventContainer _eventContainer;
|
||||||
readonly MqttServerOptions _options;
|
readonly MqttServerOptions _options;
|
||||||
readonly MqttNetSourceLogger _logger;
|
readonly MqttNetSourceLogger _logger;
|
||||||
@@ -35,7 +35,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public MqttClientSessionsManager(
|
public MqttClientSessionsManager(
|
||||||
MqttServerOptions options,
|
MqttServerOptions options,
|
||||||
IMqttRetainedMessagesManager retainedMessagesManager,
|
MqttRetainedMessagesManager retainedMessagesManager,
|
||||||
MqttServerEventContainer eventContainer,
|
MqttServerEventContainer eventContainer,
|
||||||
IMqttNetLogger logger)
|
IMqttNetLogger logger)
|
||||||
{
|
{
|
||||||
@@ -78,7 +78,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public async Task HandleClientConnectionAsync(IMqttChannelAdapter channelAdapter, CancellationToken cancellationToken)
|
public async Task HandleClientConnectionAsync(IMqttChannelAdapter channelAdapter, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
MqttClientConnection clientConnection = null;
|
MqttClient client = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -103,11 +103,11 @@ namespace MQTTnet.Server
|
|||||||
connAckPacket = _connAckPacketFactory.Create(connectionValidatorContext);
|
connAckPacket = _connAckPacketFactory.Create(connectionValidatorContext);
|
||||||
|
|
||||||
// Pass connAckPacket so that IsSessionPresent flag can be set if the client session already exists
|
// Pass connAckPacket so that IsSessionPresent flag can be set if the client session already exists
|
||||||
clientConnection = await CreateClientConnection(connectPacket, connAckPacket, channelAdapter, connectionValidatorContext.SessionItems).ConfigureAwait(false);
|
client = await CreateClientConnection(connectPacket, connAckPacket, channelAdapter, connectionValidatorContext.SessionItems).ConfigureAwait(false);
|
||||||
|
|
||||||
await clientConnection.SendPacketAsync(connAckPacket, cancellationToken).ConfigureAwait(false);
|
await client.SendPacketAsync(connAckPacket, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await _eventContainer.ClientConnectedEvent.InvokeAsync(() => new MqttServerClientConnectedEventArgs
|
await _eventContainer.ClientConnectedEvent.InvokeAsync(() => new ClientConnectedEventArgs
|
||||||
{
|
{
|
||||||
ClientId = connectPacket.ClientId,
|
ClientId = connectPacket.ClientId,
|
||||||
UserName = connectPacket.Username,
|
UserName = connectPacket.Username,
|
||||||
@@ -115,7 +115,7 @@ namespace MQTTnet.Server
|
|||||||
Endpoint = channelAdapter.Endpoint
|
Endpoint = channelAdapter.Endpoint
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
await clientConnection.RunAsync().ConfigureAwait(false);
|
await client.RunAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
@@ -126,33 +126,33 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (clientConnection != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
if (clientConnection.Id != null)
|
if (client.Id != null)
|
||||||
{
|
{
|
||||||
// in case it is a takeover _clientConnections already contains the new connection
|
// in case it is a takeover _clientConnections already contains the new connection
|
||||||
if (!clientConnection.IsTakenOver)
|
if (!client.IsTakenOver)
|
||||||
{
|
{
|
||||||
lock (_clientConnections)
|
lock (_clients)
|
||||||
{
|
{
|
||||||
_clientConnections.Remove(clientConnection.Id);
|
_clients.Remove(client.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_options.EnablePersistentSessions)
|
if (!_options.EnablePersistentSessions)
|
||||||
{
|
{
|
||||||
await DeleteSessionAsync(clientConnection.Id).ConfigureAwait(false);
|
await DeleteSessionAsync(client.Id).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoint = clientConnection.Endpoint;
|
var endpoint = client.Endpoint;
|
||||||
|
|
||||||
if (clientConnection.Id != null && !clientConnection.IsTakenOver)
|
if (client.Id != null && !client.IsTakenOver)
|
||||||
{
|
{
|
||||||
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new MqttServerClientDisconnectedEventArgs
|
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new ClientDisconnectedEventArgs
|
||||||
{
|
{
|
||||||
ClientId = clientConnection.Id,
|
ClientId = client.Id,
|
||||||
DisconnectType = clientConnection.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean,
|
DisconnectType = client.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean,
|
||||||
Endpoint = endpoint
|
Endpoint = endpoint
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -167,11 +167,11 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public async Task CloseAllConnectionsAsync()
|
public async Task CloseAllConnectionsAsync()
|
||||||
{
|
{
|
||||||
List<MqttClientConnection> connections;
|
List<MqttClient> connections;
|
||||||
lock (_clientConnections)
|
lock (_clients)
|
||||||
{
|
{
|
||||||
connections = _clientConnections.Values.ToList();
|
connections = _clients.Values.ToList();
|
||||||
_clientConnections.Clear();
|
_clients.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var connection in connections)
|
foreach (var connection in connections)
|
||||||
@@ -180,11 +180,11 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MqttClientConnection> GetConnections()
|
public List<MqttClient> GetConnections()
|
||||||
{
|
{
|
||||||
lock (_clientConnections)
|
lock (_clients)
|
||||||
{
|
{
|
||||||
return _clientConnections.Values.ToList();
|
return _clients.Values.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,9 +192,9 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
var result = new List<IMqttClientStatus>();
|
var result = new List<IMqttClientStatus>();
|
||||||
|
|
||||||
lock (_clientConnections)
|
lock (_clients)
|
||||||
{
|
{
|
||||||
foreach (var connection in _clientConnections.Values)
|
foreach (var connection in _clients.Values)
|
||||||
{
|
{
|
||||||
var clientStatus = new MqttClientStatus(connection)
|
var clientStatus = new MqttClientStatus(connection)
|
||||||
{
|
{
|
||||||
@@ -212,9 +212,9 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
var result = new List<IMqttSessionStatus>();
|
var result = new List<IMqttSessionStatus>();
|
||||||
|
|
||||||
lock (_clientSessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
foreach (var session in _clientSessions.Values)
|
foreach (var session in _sessions.Values)
|
||||||
{
|
{
|
||||||
var sessionStatus = new MqttSessionStatus(session);
|
var sessionStatus = new MqttSessionStatus(session);
|
||||||
result.Add(sessionStatus);
|
result.Add(sessionStatus);
|
||||||
@@ -263,18 +263,18 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public async Task DeleteSessionAsync(string clientId)
|
public async Task DeleteSessionAsync(string clientId)
|
||||||
{
|
{
|
||||||
MqttClientConnection connection;
|
MqttClient connection;
|
||||||
MqttClientSession session;
|
MqttSession session;
|
||||||
|
|
||||||
lock (_clientConnections)
|
lock (_clients)
|
||||||
{
|
{
|
||||||
_clientConnections.TryGetValue(clientId, out connection);
|
_clients.TryGetValue(clientId, out connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (_clientSessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
_clientSessions.TryGetValue(clientId, out session);
|
_sessions.TryGetValue(clientId, out session);
|
||||||
_clientSessions.Remove(clientId);
|
_sessions.Remove(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -331,67 +331,16 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// MqttPendingApplicationMessage pendingApplicationMessage;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// pendingApplicationMessage = _messageQueue.Take();
|
|
||||||
// }
|
|
||||||
// catch (ArgumentNullException)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // catch (ThreadAbortException)
|
|
||||||
// // {
|
|
||||||
// // return;
|
|
||||||
// // }
|
|
||||||
// catch (ObjectDisposedException)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//var clientConnection = pendingApplicationMessage.Sender;
|
|
||||||
//var senderClientId = clientConnection?.Id ?? _options.ClientId;
|
|
||||||
|
|
||||||
// // TODO: Only use PUBLISH packets internally!
|
|
||||||
// var applicationMessage = new MqttApplicationMessageFactory().Create(pendingApplicationMessage.PublishPacket);
|
|
||||||
//
|
|
||||||
// var interceptor = _options.ApplicationMessageInterceptor;
|
|
||||||
// if (interceptor != null)
|
|
||||||
// {
|
|
||||||
// var interceptorContext = await InterceptApplicationMessageAsync(interceptor, clientConnection, applicationMessage).ConfigureAwait(false);
|
|
||||||
// if (interceptorContext != null)
|
|
||||||
// {
|
|
||||||
// if (interceptorContext.CloseConnection)
|
|
||||||
// {
|
|
||||||
// if (clientConnection != null)
|
|
||||||
// {
|
|
||||||
// await clientConnection.StopAsync(MqttClientDisconnectReason.NormalDisconnection).ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (interceptorContext.ApplicationMessage == null || !interceptorContext.ProcessPublish)
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// applicationMessage = interceptorContext.ApplicationMessage;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// await _eventContainer.ApplicationMessageReceivedEvent.InvokeAsync(
|
|
||||||
// () => new MqttApplicationMessageReceivedEventArgs(senderClientId, applicationMessage, null, null))
|
|
||||||
// .ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (applicationMessage.Retain)
|
if (applicationMessage.Retain)
|
||||||
{
|
{
|
||||||
await _retainedMessagesManager.HandleMessageAsync(senderClientId, applicationMessage).ConfigureAwait(false);
|
await _retainedMessagesManager.UpdateMessage(senderClientId, applicationMessage).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var deliveryCount = 0;
|
var deliveryCount = 0;
|
||||||
List<MqttClientSession> sessions;
|
List<MqttSession> sessions;
|
||||||
lock (_clientSessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
sessions = _clientSessions.Values.ToList();
|
sessions = _sessions.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var clientSession in sessions)
|
foreach (var clientSession in sessions)
|
||||||
@@ -434,7 +383,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
if (deliveryCount == 0)
|
if (deliveryCount == 0)
|
||||||
{
|
{
|
||||||
await _eventContainer.ApplicationMessageNotConsumedEvent.InvokeAsync(() => new MqttApplicationMessageNotConsumedEventArgs
|
await _eventContainer.ApplicationMessageNotConsumedEvent.InvokeAsync(() => new ApplicationMessageNotConsumedEventArgs
|
||||||
{
|
{
|
||||||
ApplicationMessage = applicationMessage,
|
ApplicationMessage = applicationMessage,
|
||||||
SenderClientId = senderClientId
|
SenderClientId = senderClientId
|
||||||
@@ -447,14 +396,14 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<ValidatingMqttClientConnectionEventArgs> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
async Task<ValidatingConnectionEventArgs> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
||||||
{
|
{
|
||||||
var context = new ValidatingMqttClientConnectionEventArgs(connectPacket, channelAdapter)
|
var context = new ValidatingConnectionEventArgs(connectPacket, channelAdapter)
|
||||||
{
|
{
|
||||||
SessionItems = new ConcurrentDictionary<object, object>()
|
SessionItems = new ConcurrentDictionary<object, object>()
|
||||||
};
|
};
|
||||||
|
|
||||||
await _eventContainer.ValidatingClientConnectionEvent.InvokeAsync(context).ConfigureAwait(false);
|
await _eventContainer.ValidatingConnectionEvent.InvokeAsync(context).ConfigureAwait(false);
|
||||||
|
|
||||||
// Check the client ID and set a random one if supported.
|
// Check the client ID and set a random one if supported.
|
||||||
if (string.IsNullOrEmpty(connectPacket.ClientId) && channelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500)
|
if (string.IsNullOrEmpty(connectPacket.ClientId) && channelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500)
|
||||||
@@ -470,22 +419,21 @@ namespace MQTTnet.Server
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<MqttClientConnection> CreateClientConnection(
|
async Task<MqttClient> CreateClientConnection(
|
||||||
MqttConnectPacket connectPacket,
|
MqttConnectPacket connectPacket,
|
||||||
MqttConnAckPacket connAckPacket,
|
MqttConnAckPacket connAckPacket,
|
||||||
IMqttChannelAdapter channelAdapter,
|
IMqttChannelAdapter channelAdapter,
|
||||||
IDictionary<object, object> sessionItems)
|
IDictionary<object, object> sessionItems)
|
||||||
{
|
{
|
||||||
MqttClientConnection connection;
|
MqttClient connection;
|
||||||
|
|
||||||
using (await _createConnectionSyncRoot.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
using (await _createConnectionSyncRoot.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
MqttClientSession session;
|
MqttSession session;
|
||||||
lock (_clientSessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
if (!_clientSessions.TryGetValue(connectPacket.ClientId, out session))
|
if (!_sessions.TryGetValue(connectPacket.ClientId, out session))
|
||||||
{
|
{
|
||||||
_logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId);
|
|
||||||
session = CreateSession(connectPacket.ClientId, sessionItems);
|
session = CreateSession(connectPacket.ClientId, sessionItems);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -503,29 +451,38 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_clientSessions[connectPacket.ClientId] = session;
|
_sessions[connectPacket.ClientId] = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttClientConnection existingConnection;
|
if (!connAckPacket.IsSessionPresent)
|
||||||
|
|
||||||
lock (_clientConnections)
|
|
||||||
{
|
{
|
||||||
_clientConnections.TryGetValue(connectPacket.ClientId, out existingConnection);
|
var preparingSessionEventArgs = new PreparingSessionEventArgs();
|
||||||
|
await _eventContainer.PreparingSessionEvent.InvokeAsync(preparingSessionEventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// TODO: Import subscriptions etc.
|
||||||
|
//session.SubscriptionsManager.Subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
|
MqttClient existing;
|
||||||
|
|
||||||
|
lock (_clients)
|
||||||
|
{
|
||||||
|
_clients.TryGetValue(connectPacket.ClientId, out existing);
|
||||||
connection = CreateConnection(connectPacket, channelAdapter, session);
|
connection = CreateConnection(connectPacket, channelAdapter, session);
|
||||||
|
|
||||||
_clientConnections[connectPacket.ClientId] = connection;
|
_clients[connectPacket.ClientId] = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingConnection != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
existingConnection.IsTakenOver = true;
|
existing.IsTakenOver = true;
|
||||||
await existingConnection.StopAsync(MqttClientDisconnectReason.SessionTakenOver).ConfigureAwait(false);
|
await existing.StopAsync(MqttClientDisconnectReason.SessionTakenOver).ConfigureAwait(false);
|
||||||
|
|
||||||
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new MqttServerClientDisconnectedEventArgs
|
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new ClientDisconnectedEventArgs
|
||||||
{
|
{
|
||||||
ClientId = existingConnection.Id,
|
ClientId = existing.Id,
|
||||||
DisconnectType = MqttClientDisconnectType.Takeover,
|
DisconnectType = MqttClientDisconnectType.Takeover,
|
||||||
Endpoint = existingConnection.Endpoint
|
Endpoint = existing.Endpoint
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -566,11 +523,11 @@ namespace MQTTnet.Server
|
|||||||
// return interceptorContext;
|
// return interceptorContext;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
MqttClientSession GetClientSession(string clientId)
|
MqttSession GetClientSession(string clientId)
|
||||||
{
|
{
|
||||||
lock (_clientSessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
if (!_clientSessions.TryGetValue(clientId, out var session))
|
if (!_sessions.TryGetValue(clientId, out var session))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
||||||
}
|
}
|
||||||
@@ -579,9 +536,9 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttClientConnection CreateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttClientSession session)
|
MqttClient CreateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttSession session)
|
||||||
{
|
{
|
||||||
return new MqttClientConnection(
|
return new MqttClient(
|
||||||
connectPacket,
|
connectPacket,
|
||||||
channelAdapter,
|
channelAdapter,
|
||||||
session,
|
session,
|
||||||
@@ -591,9 +548,11 @@ namespace MQTTnet.Server
|
|||||||
_rootLogger);
|
_rootLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttClientSession CreateSession(string clientId, IDictionary<object, object> sessionItems)
|
MqttSession CreateSession(string clientId, IDictionary<object, object> sessionItems)
|
||||||
{
|
{
|
||||||
return new MqttClientSession(
|
_logger.Verbose("Created a new session for client '{0}'.", clientId);
|
||||||
|
|
||||||
|
return new MqttSession(
|
||||||
clientId,
|
clientId,
|
||||||
sessionItems,
|
sessionItems,
|
||||||
_options,
|
_options,
|
||||||
@@ -606,12 +565,12 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
_createConnectionSyncRoot?.Dispose();
|
_createConnectionSyncRoot?.Dispose();
|
||||||
|
|
||||||
foreach (var clientConnection in _clientConnections.Values)
|
foreach (var clientConnection in _clients.Values)
|
||||||
{
|
{
|
||||||
clientConnection.Dispose();
|
clientConnection.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var session in _clientSessions.Values)
|
foreach (var session in _sessions.Values)
|
||||||
{
|
{
|
||||||
session.Dispose();
|
session.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ using MQTTnet.Packets;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttClientConnectionStatistics
|
public sealed class MqttClientStatistics
|
||||||
{
|
{
|
||||||
// Start with 1 because the CONNACK packet is not counted here.
|
// Start with 1 because the CONNACK packet is not counted here.
|
||||||
long _receivedPacketsCount = 1;
|
long _receivedPacketsCount = 1;
|
||||||
@@ -15,7 +15,7 @@ namespace MQTTnet.Server
|
|||||||
long _receivedApplicationMessagesCount;
|
long _receivedApplicationMessagesCount;
|
||||||
long _sentApplicationMessagesCount;
|
long _sentApplicationMessagesCount;
|
||||||
|
|
||||||
public MqttClientConnectionStatistics()
|
public MqttClientStatistics()
|
||||||
{
|
{
|
||||||
ConnectedTimestamp = DateTime.UtcNow;
|
ConnectedTimestamp = DateTime.UtcNow;
|
||||||
|
|
||||||
@@ -16,29 +16,29 @@ namespace MQTTnet.Server
|
|||||||
readonly ReaderWriterLockSlim _subscriptionsLock = new ReaderWriterLockSlim();
|
readonly ReaderWriterLockSlim _subscriptionsLock = new ReaderWriterLockSlim();
|
||||||
readonly Dictionary<string, MqttSubscription> _subscriptions = new Dictionary<string, MqttSubscription>(4096);
|
readonly Dictionary<string, MqttSubscription> _subscriptions = new Dictionary<string, MqttSubscription>(4096);
|
||||||
|
|
||||||
readonly MqttClientSession _clientSession;
|
readonly MqttSession _session;
|
||||||
readonly MqttServerOptions _options;
|
readonly MqttServerOptions _options;
|
||||||
readonly MqttServerEventContainer _eventContainer;
|
readonly MqttServerEventContainer _eventContainer;
|
||||||
readonly IMqttRetainedMessagesManager _retainedMessagesManager;
|
readonly MqttRetainedMessagesManager _retainedMessagesManager;
|
||||||
|
|
||||||
public MqttClientSubscriptionsManager(
|
public MqttClientSubscriptionsManager(
|
||||||
MqttClientSession clientSession,
|
MqttSession session,
|
||||||
MqttServerOptions serverOptions,
|
MqttServerOptions serverOptions,
|
||||||
MqttServerEventContainer eventContainer,
|
MqttServerEventContainer eventContainer,
|
||||||
IMqttRetainedMessagesManager retainedMessagesManager)
|
MqttRetainedMessagesManager retainedMessagesManager)
|
||||||
{
|
{
|
||||||
_clientSession = clientSession ?? throw new ArgumentNullException(nameof(clientSession));
|
_session = session ?? throw new ArgumentNullException(nameof(session));
|
||||||
_options = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
_options = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
||||||
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||||
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MqttSubscribeResult> Subscribe(MqttSubscribePacket subscribePacket, CancellationToken cancellationToken)
|
public async Task<SubscribeResult> Subscribe(MqttSubscribePacket subscribePacket, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
if (subscribePacket == null) throw new ArgumentNullException(nameof(subscribePacket));
|
||||||
|
|
||||||
var retainedApplicationMessages = await _retainedMessagesManager.GetMessagesAsync().ConfigureAwait(false);
|
var retainedApplicationMessages = await _retainedMessagesManager.GetMessages().ConfigureAwait(false);
|
||||||
var result = new MqttSubscribeResult();
|
var result = new SubscribeResult();
|
||||||
|
|
||||||
// The topic filters are order by its QoS so that the higher QoS will win over a
|
// The topic filters are order by its QoS so that the higher QoS will win over a
|
||||||
// lower one.
|
// lower one.
|
||||||
@@ -79,9 +79,9 @@ namespace MQTTnet.Server
|
|||||||
subscribePacket.Properties?.SubscriptionIdentifier ?? 0,
|
subscribePacket.Properties?.SubscriptionIdentifier ?? 0,
|
||||||
interceptorContext.Response.ReasonCode);
|
interceptorContext.Response.ReasonCode);
|
||||||
|
|
||||||
await _eventContainer.ClientSubscribedTopicEvent.InvokeAsync(() => new MqttServerClientSubscribedTopicEventArgs
|
await _eventContainer.ClientSubscribedTopicEvent.InvokeAsync(() => new ClientSubscribedTopicEventArgs
|
||||||
{
|
{
|
||||||
ClientId = _clientSession.Id,
|
ClientId = _session.Id,
|
||||||
TopicFilter = finalTopicFilter
|
TopicFilter = finalTopicFilter
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -135,9 +135,9 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
foreach (var topicFilter in unsubscribePacket.TopicFilters)
|
foreach (var topicFilter in unsubscribePacket.TopicFilters)
|
||||||
{
|
{
|
||||||
await _eventContainer.ClientUnsubscribedTopicEvent.InvokeAsync(() => new MqttServerClientUnsubscribedTopicEventArgs
|
await _eventContainer.ClientUnsubscribedTopicEvent.InvokeAsync(() => new ClientUnsubscribedTopicEventArgs
|
||||||
{
|
{
|
||||||
ClientId = _clientSession.Id,
|
ClientId = _session.Id,
|
||||||
TopicFilter = topicFilter
|
TopicFilter = topicFilter
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ namespace MQTTnet.Server
|
|||||||
_subscriptionsLock.ExitReadLock();
|
_subscriptionsLock.ExitReadLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
var senderIsReceiver = string.Equals(senderClientId, _clientSession.Id);
|
var senderIsReceiver = string.Equals(senderClientId, _session.Id);
|
||||||
|
|
||||||
var qosLevels = new HashSet<MqttQualityOfServiceLevel>();
|
var qosLevels = new HashSet<MqttQualityOfServiceLevel>();
|
||||||
var subscriptionIdentifiers = new HashSet<uint>();
|
var subscriptionIdentifiers = new HashSet<uint>();
|
||||||
@@ -262,7 +262,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void FilterRetainedApplicationMessages(IList<MqttApplicationMessage> retainedApplicationMessages, CreateSubscriptionResult createSubscriptionResult,
|
static void FilterRetainedApplicationMessages(IList<MqttApplicationMessage> retainedApplicationMessages, CreateSubscriptionResult createSubscriptionResult,
|
||||||
MqttSubscribeResult subscribeResult)
|
SubscribeResult subscribeResult)
|
||||||
{
|
{
|
||||||
for (var i = retainedApplicationMessages.Count - 1; i >= 0; i--)
|
for (var i = retainedApplicationMessages.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -294,14 +294,13 @@ namespace MQTTnet.Server
|
|||||||
var queuedApplicationMessage = new MqttQueuedApplicationMessage
|
var queuedApplicationMessage = new MqttQueuedApplicationMessage
|
||||||
{
|
{
|
||||||
ApplicationMessage = retainedApplicationMessage,
|
ApplicationMessage = retainedApplicationMessage,
|
||||||
IsRetainedMessage = true,
|
|
||||||
SubscriptionQualityOfServiceLevel = createSubscriptionResult.Subscription.GrantedQualityOfServiceLevel
|
SubscriptionQualityOfServiceLevel = createSubscriptionResult.Subscription.GrantedQualityOfServiceLevel
|
||||||
};
|
};
|
||||||
|
|
||||||
if (createSubscriptionResult.Subscription.Identifier > 0)
|
// if (createSubscriptionResult.Subscription.Identifier > 0)
|
||||||
{
|
// {
|
||||||
queuedApplicationMessage.SubscriptionIdentifiers = new List<uint> {createSubscriptionResult.Subscription.Identifier};
|
// queuedApplicationMessage.SubscriptionIdentifiers = new List<uint> {createSubscriptionResult.Subscription.Identifier};
|
||||||
}
|
// }
|
||||||
|
|
||||||
subscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage);
|
subscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage);
|
||||||
|
|
||||||
@@ -309,14 +308,14 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<InterceptingMqttClientSubscriptionEventArgs> InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken)
|
async Task<InterceptingSubscriptionEventArgs> InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var subscriptionReceivedEventArgs = new InterceptingMqttClientSubscriptionEventArgs
|
var subscriptionReceivedEventArgs = new InterceptingSubscriptionEventArgs
|
||||||
{
|
{
|
||||||
ClientId = _clientSession.Id,
|
ClientId = _session.Id,
|
||||||
TopicFilter = topicFilter,
|
TopicFilter = topicFilter,
|
||||||
SessionItems = _clientSession.Items,
|
SessionItems = _session.Items,
|
||||||
Session = new MqttSessionStatus(_clientSession),
|
Session = new MqttSessionStatus(_session),
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -339,19 +338,19 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _eventContainer.InterceptingClientSubscriptionEvent.InvokeAsync(subscriptionReceivedEventArgs).ConfigureAwait(false);
|
await _eventContainer.InterceptingSubscriptionEvent.InvokeAsync(subscriptionReceivedEventArgs).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return subscriptionReceivedEventArgs;
|
return subscriptionReceivedEventArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<InterceptingMqttClientUnsubscriptionEventArgs> InterceptUnsubscribe(string topicFilter, MqttSubscription mqttSubscription, CancellationToken cancellationToken)
|
async Task<InterceptingUnsubscriptionEventArgs> InterceptUnsubscribe(string topicFilter, MqttSubscription mqttSubscription, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var clientUnsubscribingTopicEventArgs = new InterceptingMqttClientUnsubscriptionEventArgs
|
var clientUnsubscribingTopicEventArgs = new InterceptingUnsubscriptionEventArgs
|
||||||
{
|
{
|
||||||
ClientId = _clientSession.Id,
|
ClientId = _session.Id,
|
||||||
Topic = topicFilter,
|
Topic = topicFilter,
|
||||||
SessionItems = _clientSession.Items,
|
SessionItems = _session.Items,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -364,7 +363,7 @@ namespace MQTTnet.Server
|
|||||||
clientUnsubscribingTopicEventArgs.Response.ReasonCode = MqttUnsubscribeReasonCode.Success;
|
clientUnsubscribingTopicEventArgs.Response.ReasonCode = MqttUnsubscribeReasonCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _eventContainer.InterceptingClientUnsubscriptionEvent.InvokeAsync(clientUnsubscribingTopicEventArgs).ConfigureAwait(false);
|
await _eventContainer.InterceptingUnsubscriptionEvent.InvokeAsync(clientUnsubscribingTopicEventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
return clientUnsubscribingTopicEventArgs;
|
return clientUnsubscribingTopicEventArgs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,45 +9,36 @@ using MQTTnet.Internal;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttRetainedMessagesManager : IMqttRetainedMessagesManager
|
public sealed class MqttRetainedMessagesManager
|
||||||
{
|
{
|
||||||
readonly AsyncLock _storageAccessLock = new AsyncLock();
|
|
||||||
readonly Dictionary<string, MqttApplicationMessage> _messages = new Dictionary<string, MqttApplicationMessage>(4096);
|
readonly Dictionary<string, MqttApplicationMessage> _messages = new Dictionary<string, MqttApplicationMessage>(4096);
|
||||||
|
readonly AsyncLock _storageAccessLock = new AsyncLock();
|
||||||
|
|
||||||
MqttNetSourceLogger _logger;
|
readonly MqttServerEventContainer _eventContainer;
|
||||||
MqttServerOptions _options;
|
readonly MqttNetSourceLogger _logger;
|
||||||
|
|
||||||
// TODO: Get rid of the logger here!
|
public MqttRetainedMessagesManager(MqttServerEventContainer eventContainer, IMqttNetLogger logger)
|
||||||
public Task Start(MqttServerOptions options, IMqttNetLogger logger)
|
|
||||||
{
|
{
|
||||||
|
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||||
|
|
||||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||||
_logger = logger.WithSource(nameof(MqttRetainedMessagesManager));
|
_logger = logger.WithSource(nameof(MqttRetainedMessagesManager));
|
||||||
|
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
return PlatformAbstractionLayer.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadMessagesAsync()
|
public async Task LoadMessages()
|
||||||
{
|
{
|
||||||
if (_options.Storage == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var retainedMessages = await _options.Storage.LoadRetainedMessagesAsync().ConfigureAwait(false);
|
var eventArgs = new LoadingRetainedMessagesEventArgs();
|
||||||
|
await _eventContainer.LoadingRetainedMessagesEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||||
|
|
||||||
lock (_messages)
|
lock (_messages)
|
||||||
{
|
{
|
||||||
_messages.Clear();
|
_messages.Clear();
|
||||||
|
|
||||||
if (retainedMessages != null)
|
foreach (var retainedMessage in eventArgs.StoredRetainedMessages ?? new List<MqttApplicationMessage>())
|
||||||
{
|
{
|
||||||
foreach (var retainedMessage in retainedMessages)
|
_messages[retainedMessage.Topic] = retainedMessage;
|
||||||
{
|
|
||||||
_messages[retainedMessage.Topic] = retainedMessage;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +48,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task HandleMessageAsync(string clientId, MqttApplicationMessage applicationMessage)
|
public async Task UpdateMessage(string clientId, MqttApplicationMessage applicationMessage)
|
||||||
{
|
{
|
||||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||||
|
|
||||||
@@ -102,12 +93,16 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
if (saveIsRequired)
|
if (saveIsRequired)
|
||||||
{
|
{
|
||||||
if (_options.Storage != null)
|
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
var eventArgs = new RetainedMessageChangedEventArgs
|
||||||
{
|
{
|
||||||
await _options.Storage.SaveRetainedMessagesAsync(messagesForSave).ConfigureAwait(false);
|
ClientId = clientId,
|
||||||
}
|
ChangedRetainedMessage = applicationMessage,
|
||||||
|
StoredRetainedMessages = messagesForSave
|
||||||
|
};
|
||||||
|
|
||||||
|
await _eventContainer.RetainedMessageChangedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +112,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IList<MqttApplicationMessage>> GetMessagesAsync()
|
public Task<IList<MqttApplicationMessage>> GetMessages()
|
||||||
{
|
{
|
||||||
lock (_messages)
|
lock (_messages)
|
||||||
{
|
{
|
||||||
@@ -125,19 +120,16 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ClearMessagesAsync()
|
public async Task ClearMessages()
|
||||||
{
|
{
|
||||||
lock (_messages)
|
lock (_messages)
|
||||||
{
|
{
|
||||||
_messages.Clear();
|
_messages.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_options.Storage != null)
|
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
await _eventContainer.RetainedMessagesClearedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||||
{
|
|
||||||
await _options.Storage.SaveRetainedMessagesAsync(new List<MqttApplicationMessage>()).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,29 +5,31 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
public sealed class MqttServerEventContainer
|
public sealed class MqttServerEventContainer
|
||||||
{
|
{
|
||||||
public AsyncEvent<InterceptingMqttClientSubscriptionEventArgs> InterceptingClientSubscriptionEvent { get; } = new AsyncEvent<InterceptingMqttClientSubscriptionEventArgs>();
|
public AsyncEvent<InterceptingSubscriptionEventArgs> InterceptingSubscriptionEvent { get; } = new AsyncEvent<InterceptingSubscriptionEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<InterceptingMqttClientUnsubscriptionEventArgs> InterceptingClientUnsubscriptionEvent { get; } = new AsyncEvent<InterceptingMqttClientUnsubscriptionEventArgs>();
|
public AsyncEvent<InterceptingUnsubscriptionEventArgs> InterceptingUnsubscriptionEvent { get; } = new AsyncEvent<InterceptingUnsubscriptionEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<InterceptingMqttClientPublishEventArgs> InterceptingClientPublishEvent { get; } = new AsyncEvent<InterceptingMqttClientPublishEventArgs>();
|
public AsyncEvent<InterceptingPublishEventArgs> InterceptingPublishEvent { get; } = new AsyncEvent<InterceptingPublishEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<ValidatingMqttClientConnectionEventArgs> ValidatingClientConnectionEvent { get; } = new AsyncEvent<ValidatingMqttClientConnectionEventArgs>();
|
public AsyncEvent<ValidatingConnectionEventArgs> ValidatingConnectionEvent { get; } = new AsyncEvent<ValidatingConnectionEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<MqttServerClientConnectedEventArgs> ClientConnectedEvent { get; } = new AsyncEvent<MqttServerClientConnectedEventArgs>();
|
public AsyncEvent<ClientConnectedEventArgs> ClientConnectedEvent { get; } = new AsyncEvent<ClientConnectedEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<MqttServerClientDisconnectedEventArgs> ClientDisconnectedEvent { get; } = new AsyncEvent<MqttServerClientDisconnectedEventArgs>();
|
public AsyncEvent<ClientDisconnectedEventArgs> ClientDisconnectedEvent { get; } = new AsyncEvent<ClientDisconnectedEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<MqttServerClientSubscribedTopicEventArgs> ClientSubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientSubscribedTopicEventArgs>();
|
public AsyncEvent<ClientSubscribedTopicEventArgs> ClientSubscribedTopicEvent { get; } = new AsyncEvent<ClientSubscribedTopicEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs> ClientUnsubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs>();
|
public AsyncEvent<ClientUnsubscribedTopicEventArgs> ClientUnsubscribedTopicEvent { get; } = new AsyncEvent<ClientUnsubscribedTopicEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<PreparingMqttClientSessionEventArgs> PreparingClientSessionEvent { get; } = new AsyncEvent<PreparingMqttClientSessionEventArgs>();
|
public AsyncEvent<PreparingSessionEventArgs> PreparingSessionEvent { get; } = new AsyncEvent<PreparingSessionEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<MqttApplicationMessageNotConsumedEventArgs> ApplicationMessageNotConsumedEvent { get; } = new AsyncEvent<MqttApplicationMessageNotConsumedEventArgs>();
|
public AsyncEvent<ApplicationMessageNotConsumedEventArgs> ApplicationMessageNotConsumedEvent { get; } = new AsyncEvent<ApplicationMessageNotConsumedEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<EventArgs> RetainedApplicationMessageChangedEvent { get; } = new AsyncEvent<EventArgs>();
|
public AsyncEvent<RetainedMessageChangedEventArgs> RetainedMessageChangedEvent { get; } = new AsyncEvent<RetainedMessageChangedEventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<EventArgs> RetainedApplicationMessageClearedEvent { get; } = new AsyncEvent<EventArgs>();
|
public AsyncEvent<LoadingRetainedMessagesEventArgs> LoadingRetainedMessagesEvent { get; } = new AsyncEvent<LoadingRetainedMessagesEventArgs>();
|
||||||
|
|
||||||
|
public AsyncEvent<EventArgs> RetainedMessagesClearedEvent { get; } = new AsyncEvent<EventArgs>();
|
||||||
|
|
||||||
public AsyncEvent<InterceptingPacketEventArgs> InterceptingInboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
public AsyncEvent<InterceptingPacketEventArgs> InterceptingInboundPacketEvent { get; } = new AsyncEvent<InterceptingPacketEventArgs>();
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryMaintainConnection(MqttClientConnection connection, DateTime now)
|
void TryMaintainConnection(MqttClient connection, DateTime now)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-3
@@ -10,7 +10,7 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttClientSession : IDisposable
|
public sealed class MqttSession : IDisposable
|
||||||
{
|
{
|
||||||
readonly MqttPacketBus _packetBus = new MqttPacketBus();
|
readonly MqttPacketBus _packetBus = new MqttPacketBus();
|
||||||
|
|
||||||
@@ -19,11 +19,11 @@ namespace MQTTnet.Server
|
|||||||
readonly MqttServerOptions _serverOptions;
|
readonly MqttServerOptions _serverOptions;
|
||||||
readonly MqttClientSessionsManager _clientSessionsManager;
|
readonly MqttClientSessionsManager _clientSessionsManager;
|
||||||
|
|
||||||
public MqttClientSession(string clientId,
|
public MqttSession(string clientId,
|
||||||
IDictionary<object, object> items,
|
IDictionary<object, object> items,
|
||||||
MqttServerOptions serverOptions,
|
MqttServerOptions serverOptions,
|
||||||
MqttServerEventContainer eventContainer,
|
MqttServerEventContainer eventContainer,
|
||||||
IMqttRetainedMessagesManager retainedMessagesManager,
|
MqttRetainedMessagesManager retainedMessagesManager,
|
||||||
MqttClientSessionsManager clientSessionsManager)
|
MqttClientSessionsManager clientSessionsManager)
|
||||||
{
|
{
|
||||||
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
||||||
+1
-1
@@ -3,7 +3,7 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttSubscribeResult
|
public sealed class SubscribeResult
|
||||||
{
|
{
|
||||||
public List<MqttSubscribeReturnCode> ReturnCodes { get; } = new List<MqttSubscribeReturnCode>(128);
|
public List<MqttSubscribeReturnCode> ReturnCodes { get; } = new List<MqttSubscribeReturnCode>(128);
|
||||||
|
|
||||||
@@ -6,14 +6,6 @@ namespace MQTTnet.Server
|
|||||||
public sealed class MqttQueuedApplicationMessage
|
public sealed class MqttQueuedApplicationMessage
|
||||||
{
|
{
|
||||||
public MqttApplicationMessage ApplicationMessage { get; set; }
|
public MqttApplicationMessage ApplicationMessage { get; set; }
|
||||||
|
|
||||||
public string SenderClientId { get; set; }
|
|
||||||
|
|
||||||
public bool IsRetainedMessage { get; set; }
|
|
||||||
|
|
||||||
public List<uint> SubscriptionIdentifiers { get; set; }
|
|
||||||
|
|
||||||
public bool IsDuplicate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the subscription quality of service level.
|
/// Gets or sets the subscription quality of service level.
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
using MQTTnet.Exceptions;
|
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -24,7 +23,7 @@ namespace MQTTnet.Server
|
|||||||
readonly MqttNetSourceLogger _logger;
|
readonly MqttNetSourceLogger _logger;
|
||||||
|
|
||||||
MqttClientSessionsManager _clientSessionsManager;
|
MqttClientSessionsManager _clientSessionsManager;
|
||||||
IMqttRetainedMessagesManager _retainedMessagesManager;
|
MqttRetainedMessagesManager _retainedMessagesManager;
|
||||||
MqttServerKeepAliveMonitor _keepAliveMonitor;
|
MqttServerKeepAliveMonitor _keepAliveMonitor;
|
||||||
CancellationTokenSource _cancellationTokenSource;
|
CancellationTokenSource _cancellationTokenSource;
|
||||||
|
|
||||||
@@ -52,19 +51,19 @@ namespace MQTTnet.Server
|
|||||||
remove => _eventContainer.StoppedEvent.RemoveHandler(value);
|
remove => _eventContainer.StoppedEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<ValidatingMqttClientConnectionEventArgs, Task> ValidatingClientConnectionAsync
|
public event Func<ValidatingConnectionEventArgs, Task> ValidatingConnectionAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ValidatingClientConnectionEvent.AddHandler(value);
|
add => _eventContainer.ValidatingConnectionEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ValidatingClientConnectionEvent.RemoveHandler(value);
|
remove => _eventContainer.ValidatingConnectionEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<MqttServerClientConnectedEventArgs, Task> ClientConnectedAsync
|
public event Func<ClientConnectedEventArgs, Task> ClientConnectedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ClientConnectedEvent.AddHandler(value);
|
add => _eventContainer.ClientConnectedEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ClientConnectedEvent.RemoveHandler(value);
|
remove => _eventContainer.ClientConnectedEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<MqttServerClientDisconnectedEventArgs, Task> ClientDisconnectedAsync
|
public event Func<ClientDisconnectedEventArgs, Task> ClientDisconnectedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ClientDisconnectedEvent.AddHandler(value);
|
add => _eventContainer.ClientDisconnectedEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ClientDisconnectedEvent.RemoveHandler(value);
|
remove => _eventContainer.ClientDisconnectedEvent.RemoveHandler(value);
|
||||||
@@ -82,63 +81,69 @@ namespace MQTTnet.Server
|
|||||||
remove => _eventContainer.InterceptingOutboundPacketEvent.RemoveHandler(value);
|
remove => _eventContainer.InterceptingOutboundPacketEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<InterceptingMqttClientSubscriptionEventArgs, Task> InterceptingClientSubscriptionAsync
|
public event Func<InterceptingSubscriptionEventArgs, Task> InterceptingSubscriptionAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.InterceptingClientSubscriptionEvent.AddHandler(value);
|
add => _eventContainer.InterceptingSubscriptionEvent.AddHandler(value);
|
||||||
remove => _eventContainer.InterceptingClientSubscriptionEvent.RemoveHandler(value);
|
remove => _eventContainer.InterceptingSubscriptionEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<InterceptingMqttClientUnsubscriptionEventArgs, Task> InterceptingClientUnsubscriptionAsync
|
public event Func<InterceptingUnsubscriptionEventArgs, Task> InterceptingUnsubscriptionAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.InterceptingClientUnsubscriptionEvent.AddHandler(value);
|
add => _eventContainer.InterceptingUnsubscriptionEvent.AddHandler(value);
|
||||||
remove => _eventContainer.InterceptingClientUnsubscriptionEvent.RemoveHandler(value);
|
remove => _eventContainer.InterceptingUnsubscriptionEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<InterceptingMqttClientPublishEventArgs, Task> InterceptingClientPublishAsync
|
public event Func<InterceptingPublishEventArgs, Task> InterceptingPublishAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.InterceptingClientPublishEvent.AddHandler(value);
|
add => _eventContainer.InterceptingPublishEvent.AddHandler(value);
|
||||||
remove => _eventContainer.InterceptingClientPublishEvent.RemoveHandler(value);
|
remove => _eventContainer.InterceptingPublishEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<MqttServerClientSubscribedTopicEventArgs, Task> ClientSubscribedTopicAsync
|
public event Func<ClientSubscribedTopicEventArgs, Task> ClientSubscribedTopicAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ClientSubscribedTopicEvent.AddHandler(value);
|
add => _eventContainer.ClientSubscribedTopicEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ClientSubscribedTopicEvent.RemoveHandler(value);
|
remove => _eventContainer.ClientSubscribedTopicEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<MqttServerClientUnsubscribedTopicEventArgs, Task> ClientUnsubscribedTopicAsync
|
public event Func<ClientUnsubscribedTopicEventArgs, Task> ClientUnsubscribedTopicAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ClientUnsubscribedTopicEvent.AddHandler(value);
|
add => _eventContainer.ClientUnsubscribedTopicEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ClientUnsubscribedTopicEvent.RemoveHandler(value);
|
remove => _eventContainer.ClientUnsubscribedTopicEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<PreparingMqttClientSessionEventArgs, Task> PreparingClientSessionAsync
|
public event Func<PreparingSessionEventArgs, Task> PreparingSessionAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.PreparingClientSessionEvent.AddHandler(value);
|
add => _eventContainer.PreparingSessionEvent.AddHandler(value);
|
||||||
remove => _eventContainer.PreparingClientSessionEvent.RemoveHandler(value);
|
remove => _eventContainer.PreparingSessionEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<MqttApplicationMessageNotConsumedEventArgs, Task> ApplicationMessageNotConsumedAsync
|
public event Func<ApplicationMessageNotConsumedEventArgs, Task> ApplicationMessageNotConsumedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.ApplicationMessageNotConsumedEvent.AddHandler(value);
|
add => _eventContainer.ApplicationMessageNotConsumedEvent.AddHandler(value);
|
||||||
remove => _eventContainer.ApplicationMessageNotConsumedEvent.RemoveHandler(value);
|
remove => _eventContainer.ApplicationMessageNotConsumedEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<EventArgs, Task> RetainedApplicationMessageChangedAsync
|
public event Func<RetainedMessageChangedEventArgs, Task> RetainedMessageChangedAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.RetainedApplicationMessageChangedEvent.AddHandler(value);
|
add => _eventContainer.RetainedMessageChangedEvent.AddHandler(value);
|
||||||
remove => _eventContainer.RetainedApplicationMessageChangedEvent.RemoveHandler(value);
|
remove => _eventContainer.RetainedMessageChangedEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event Func<EventArgs, Task> RetainedApplicationMessagesClearedAsync
|
public event Func<LoadingRetainedMessagesEventArgs, Task> LoadingRetainedMessageAsync
|
||||||
{
|
{
|
||||||
add => _eventContainer.RetainedApplicationMessageClearedEvent.AddHandler(value);
|
add => _eventContainer.LoadingRetainedMessagesEvent.AddHandler(value);
|
||||||
remove => _eventContainer.RetainedApplicationMessageClearedEvent.RemoveHandler(value);
|
remove => _eventContainer.LoadingRetainedMessagesEvent.RemoveHandler(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<EventArgs, Task> RetainedMessagesClearedAsync
|
||||||
|
{
|
||||||
|
add => _eventContainer.RetainedMessagesClearedEvent.AddHandler(value);
|
||||||
|
remove => _eventContainer.RetainedMessagesClearedEvent.RemoveHandler(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsStarted => _cancellationTokenSource != null;
|
public bool IsStarted => _cancellationTokenSource != null;
|
||||||
|
|
||||||
public Task<IList<IMqttClientStatus>> GetClientStatusAsync()
|
public Task<IList<IMqttClientStatus>> GetClientsAsync()
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotStarted();
|
ThrowIfNotStarted();
|
||||||
@@ -146,7 +151,7 @@ namespace MQTTnet.Server
|
|||||||
return _clientSessionsManager.GetClientStatusAsync();
|
return _clientSessionsManager.GetClientStatusAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IList<IMqttSessionStatus>> GetSessionStatusAsync()
|
public Task<IList<IMqttSessionStatus>> GetSessionsAsync()
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotStarted();
|
ThrowIfNotStarted();
|
||||||
@@ -154,20 +159,44 @@ namespace MQTTnet.Server
|
|||||||
return _clientSessionsManager.GetSessionStatusAsync();
|
return _clientSessionsManager.GetSessionStatusAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IList<MqttApplicationMessage>> GetRetainedApplicationMessagesAsync()
|
/// <summary>
|
||||||
|
/// Gets all currently cached retained messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of retained messages.</returns>
|
||||||
|
public Task<IList<MqttApplicationMessage>> GetRetainedMessagesAsync()
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotStarted();
|
ThrowIfNotStarted();
|
||||||
|
|
||||||
return _retainedMessagesManager.GetMessagesAsync();
|
return _retainedMessagesManager.GetMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ClearRetainedApplicationMessagesAsync()
|
/// <summary>
|
||||||
|
/// Deletes all retained messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task.</returns>
|
||||||
|
public Task DeleteRetainedMessagesAsync()
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotStarted();
|
ThrowIfNotStarted();
|
||||||
|
|
||||||
return _retainedMessagesManager?.ClearMessagesAsync() ?? PlatformAbstractionLayer.CompletedTask;
|
return _retainedMessagesManager?.ClearMessages() ?? PlatformAbstractionLayer.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the specified retained message.
|
||||||
|
/// Setting the payload to null or empty will delete the retained message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="retainedMessage">The retained message.</param>
|
||||||
|
/// <returns>A task.</returns>
|
||||||
|
public Task UpdateRetainedMessageAsync(MqttApplicationMessage retainedMessage)
|
||||||
|
{
|
||||||
|
if (retainedMessage == null) throw new ArgumentNullException(nameof(retainedMessage));
|
||||||
|
|
||||||
|
ThrowIfDisposed();
|
||||||
|
ThrowIfNotStarted();
|
||||||
|
|
||||||
|
return _retainedMessagesManager?.UpdateMessage(null, retainedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SubscribeAsync(string clientId, ICollection<MqttTopicFilter> topicFilters)
|
public Task SubscribeAsync(string clientId, ICollection<MqttTopicFilter> topicFilters)
|
||||||
@@ -220,10 +249,8 @@ namespace MQTTnet.Server
|
|||||||
_cancellationTokenSource = new CancellationTokenSource();
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
var cancellationToken = _cancellationTokenSource.Token;
|
var cancellationToken = _cancellationTokenSource.Token;
|
||||||
|
|
||||||
_retainedMessagesManager = _options.RetainedMessagesManager ?? throw new MqttConfigurationException("options.RetainedMessagesManager should not be null.");
|
_retainedMessagesManager = new MqttRetainedMessagesManager(_eventContainer, _rootLogger);
|
||||||
|
await _retainedMessagesManager.LoadMessages().ConfigureAwait(false);
|
||||||
await _retainedMessagesManager.Start(_options, _rootLogger).ConfigureAwait(false);
|
|
||||||
await _retainedMessagesManager.LoadMessagesAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
_clientSessionsManager = new MqttClientSessionsManager(_options, _retainedMessagesManager, _eventContainer, _rootLogger);
|
_clientSessionsManager = new MqttClientSessionsManager(_options, _retainedMessagesManager, _eventContainer, _rootLogger);
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,7 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
return server.SubscribeAsync(clientId, topicFilters);
|
return server.SubscribeAsync(clientId, topicFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task SubscribeAsync(this MqttServer server, string clientId, string topic, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
|
||||||
{
|
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
|
||||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
|
|
||||||
return server.SubscribeAsync(clientId, new MqttTopicFilterBuilder().WithTopic(topic).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Task SubscribeAsync(this MqttServer server, string clientId, string topic)
|
public static Task SubscribeAsync(this MqttServer server, string clientId, string topic)
|
||||||
{
|
{
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
@@ -34,102 +25,5 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
return server.SubscribeAsync(clientId, new MqttTopicFilterBuilder().WithTopic(topic).Build());
|
return server.SubscribeAsync(clientId, new MqttTopicFilterBuilder().WithTopic(topic).Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task UnsubscribeAsync(this MqttServer server, string clientId, params string[] topicFilters)
|
|
||||||
{
|
|
||||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
|
||||||
|
|
||||||
return server.UnsubscribeAsync(clientId, topicFilters);
|
|
||||||
}
|
|
||||||
|
|
||||||
// public static async Task PublishAsync(this IMqttServer server, IEnumerable<MqttApplicationMessage> applicationMessages)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
|
||||||
//
|
|
||||||
// foreach (var applicationMessage in applicationMessages)
|
|
||||||
// {
|
|
||||||
// await server.PublishAsync(applicationMessage).ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, MqttApplicationMessage applicationMessage)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
|
||||||
//
|
|
||||||
// return server.PublishAsync(applicationMessage, CancellationToken.None);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static async Task PublishAsync(this IMqttServer server, params MqttApplicationMessage[] applicationMessages)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
|
||||||
//
|
|
||||||
// foreach (var applicationMessage in applicationMessages)
|
|
||||||
// {
|
|
||||||
// await server.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, string topic)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
//
|
|
||||||
// return server.PublishAsync(builder => builder
|
|
||||||
// .WithTopic(topic));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, string topic, string payload)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
//
|
|
||||||
// return server.PublishAsync(builder => builder
|
|
||||||
// .WithTopic(topic)
|
|
||||||
// .WithPayload(payload));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
//
|
|
||||||
// return server.PublishAsync(builder => builder
|
|
||||||
// .WithTopic(topic)
|
|
||||||
// .WithPayload(payload)
|
|
||||||
// .WithQualityOfServiceLevel(qualityOfServiceLevel));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
// if (topic == null) throw new ArgumentNullException(nameof(topic));
|
|
||||||
//
|
|
||||||
// return server.PublishAsync(builder => builder
|
|
||||||
// .WithTopic(topic)
|
|
||||||
// .WithPayload(payload)
|
|
||||||
// .WithQualityOfServiceLevel(qualityOfServiceLevel)
|
|
||||||
// .WithRetainFlag(retain));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
//
|
|
||||||
// var message = builder(new MqttApplicationMessageBuilder()).Build();
|
|
||||||
// return server.PublishAsync(message, cancellationToken);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public static Task<MqttClientPublishResult> PublishAsync(this IMqttServer server, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
|
||||||
// {
|
|
||||||
// if (server == null) throw new ArgumentNullException(nameof(server));
|
|
||||||
//
|
|
||||||
// var message = builder(new MqttApplicationMessageBuilder()).Build();
|
|
||||||
// return server.PublishAsync(message, CancellationToken.None);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,5 @@ namespace MQTTnet.Server
|
|||||||
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(15);
|
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(15);
|
||||||
|
|
||||||
public TimeSpan KeepAliveMonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500);
|
public TimeSpan KeepAliveMonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500);
|
||||||
|
|
||||||
public IMqttServerStorage Storage { get; set; }
|
|
||||||
|
|
||||||
public IMqttRetainedMessagesManager RetainedMessagesManager { get; set; } = new MqttRetainedMessagesManager();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,18 +140,6 @@ namespace MQTTnet.Server
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public MqttServerOptionsBuilder WithStorage(IMqttServerStorage value)
|
|
||||||
{
|
|
||||||
_options.Storage = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MqttServerOptionsBuilder WithRetainedMessagesManager(IMqttRetainedMessagesManager value)
|
|
||||||
{
|
|
||||||
_options.RetainedMessagesManager = value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value)
|
// public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value)
|
||||||
// {
|
// {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ using MQTTnet.Packets;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttApplicationMessageResponse
|
public sealed class PublishResponse
|
||||||
{
|
{
|
||||||
public MqttApplicationMessageResponseReasonCode ReasonCode { get; set; } = MqttApplicationMessageResponseReasonCode.Success;
|
public MqttApplicationMessageResponseReasonCode ReasonCode { get; set; } = MqttApplicationMessageResponseReasonCode.Success;
|
||||||
|
|
||||||
@@ -7,9 +7,9 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
public sealed class MqttClientStatus : IMqttClientStatus
|
public sealed class MqttClientStatus : IMqttClientStatus
|
||||||
{
|
{
|
||||||
readonly MqttClientConnection _connection;
|
readonly MqttClient _connection;
|
||||||
|
|
||||||
public MqttClientStatus(MqttClientConnection connection)
|
public MqttClientStatus(MqttClient connection)
|
||||||
{
|
{
|
||||||
_connection = connection ?? throw new ArgumentNullException(nameof(connection));
|
_connection = connection ?? throw new ArgumentNullException(nameof(connection));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
public sealed class MqttSessionStatus : IMqttSessionStatus
|
public sealed class MqttSessionStatus : IMqttSessionStatus
|
||||||
{
|
{
|
||||||
readonly MqttClientSession _session;
|
readonly MqttSession _session;
|
||||||
|
|
||||||
public MqttSessionStatus(MqttClientSession session)
|
public MqttSessionStatus(MqttSession session)
|
||||||
{
|
{
|
||||||
_session = session ?? throw new ArgumentNullException(nameof(session));
|
_session = session ?? throw new ArgumentNullException(nameof(session));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Diagnostics;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public interface IMqttRetainedMessagesManager
|
|
||||||
{
|
|
||||||
Task Start(MqttServerOptions options, IMqttNetLogger logger);
|
|
||||||
|
|
||||||
Task LoadMessagesAsync();
|
|
||||||
|
|
||||||
Task ClearMessagesAsync();
|
|
||||||
|
|
||||||
Task HandleMessageAsync(string clientId, MqttApplicationMessage applicationMessage);
|
|
||||||
|
|
||||||
Task<IList<MqttApplicationMessage>> GetMessagesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using MQTTnet.Packets;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public interface IMqttServerPersistedSession
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the client identifier.
|
|
||||||
/// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues.
|
|
||||||
/// </summary>
|
|
||||||
string ClientId { get; }
|
|
||||||
|
|
||||||
IDictionary<object, object> Items { get; }
|
|
||||||
|
|
||||||
IList<MqttTopicFilter> Subscriptions { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last will message.
|
|
||||||
/// In MQTT, you use the last will message feature to notify other clients about an ungracefully disconnected client.
|
|
||||||
/// </summary>
|
|
||||||
MqttApplicationMessage WillMessage { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the will delay interval.
|
|
||||||
/// This is the time between the client disconnect and the time the will message will be sent.
|
|
||||||
/// </summary>
|
|
||||||
uint? WillDelayInterval { get; }
|
|
||||||
|
|
||||||
DateTime? SessionExpiryTimestamp { get; }
|
|
||||||
|
|
||||||
IList<MqttQueuedApplicationMessage> PendingApplicationMessages { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public interface IMqttServerPersistedSessionsStorage
|
|
||||||
{
|
|
||||||
Task<IList<IMqttServerPersistedSession>> LoadPersistedSessionsAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MQTTnet.Server
|
|
||||||
{
|
|
||||||
public interface IMqttServerStorage
|
|
||||||
{
|
|
||||||
Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages);
|
|
||||||
|
|
||||||
Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -4,7 +4,7 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttSubscribeResponse
|
public sealed class SubscribeResponse
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the reason code which is sent to the client.
|
/// Gets or sets the reason code which is sent to the client.
|
||||||
+1
-1
@@ -4,7 +4,7 @@ using MQTTnet.Protocol;
|
|||||||
|
|
||||||
namespace MQTTnet.Server
|
namespace MQTTnet.Server
|
||||||
{
|
{
|
||||||
public sealed class MqttUnsubscribeResponse
|
public sealed class UnsubscribeResponse
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the reason code which is sent to the client.
|
/// Gets or sets the reason code which is sent to the client.
|
||||||
@@ -110,7 +110,7 @@ namespace MQTTnet.Tests.Client
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count);
|
Assert.AreEqual(0, (await server.GetClientsAsync()).Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace MQTTnet.Tests.Client
|
|||||||
var client = await testEnvironment.ConnectLowLevelClient();
|
var client = await testEnvironment.ConnectLowLevelClient();
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
server.InterceptingClientPublishAsync += c =>
|
server.InterceptingPublishAsync += c =>
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -766,8 +766,8 @@ namespace MQTTnet.Tests.Client
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
var clientStatus = await testEnvironment.Server.GetClientStatusAsync();
|
var clientStatus = await testEnvironment.Server.GetClientsAsync();
|
||||||
var sessionStatus = await testEnvironment.Server.GetSessionStatusAsync();
|
var sessionStatus = await testEnvironment.Server.GetSessionsAsync();
|
||||||
|
|
||||||
for (var i = 0; i < 98; i++)
|
for (var i = 0; i < 98; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
using MQTTnet.Formatter;
|
using MQTTnet.Formatter;
|
||||||
using MQTTnet.Tests.Mockups;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MQTTnet.Tests.MQTTv5
|
namespace MQTTnet.Tests.MQTTv5
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class Server_Tests : BaseTestClass
|
public sealed class Server_Tests : BaseTestClass
|
||||||
{
|
{
|
||||||
public TestContext TestContext { get; set; }
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task Will_Message_Send()
|
public async Task Will_Message_Send()
|
||||||
{
|
{
|
||||||
@@ -46,7 +43,7 @@ namespace MQTTnet.Tests.MQTTv5
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task Validate_IsSessionPresent()
|
public async Task Validate_IsSessionPresent()
|
||||||
{
|
{
|
||||||
using (var testEnvironment = new TestEnvironment(TestContext))
|
using (var testEnvironment = CreateTestEnvironment())
|
||||||
{
|
{
|
||||||
// Create server with persistent sessions enabled
|
// Create server with persistent sessions enabled
|
||||||
|
|
||||||
@@ -84,7 +81,6 @@ namespace MQTTnet.Tests.MQTTv5
|
|||||||
.WithClientId(ClientId)
|
.WithClientId(ClientId)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
var result = await client2.ConnectAsync(options).ConfigureAwait(false);
|
var result = await client2.ConnectAsync(options).ConfigureAwait(false);
|
||||||
|
|
||||||
await client2.DisconnectAsync();
|
await client2.DisconnectAsync();
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ namespace MQTTnet.Tests.Mockups
|
|||||||
|
|
||||||
Server = Factory.CreateMqttServer(options, ServerLogger);
|
Server = Factory.CreateMqttServer(options, ServerLogger);
|
||||||
|
|
||||||
Server.ValidatingClientConnectionAsync += e =>
|
Server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
if (TestContext != null)
|
if (TestContext != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MQTTnet.Server;
|
|
||||||
|
|
||||||
namespace MQTTnet.Tests.Mockups
|
|
||||||
{
|
|
||||||
public class TestServerStorage : IMqttServerStorage
|
|
||||||
{
|
|
||||||
public IList<MqttApplicationMessage> Messages = new List<MqttApplicationMessage>();
|
|
||||||
|
|
||||||
public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
|
|
||||||
{
|
|
||||||
Messages = messages;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
|
|
||||||
{
|
|
||||||
return Task.FromResult(Messages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
var disconnectedMre = new ManualResetEventSlim();
|
var disconnectedMre = new ManualResetEventSlim();
|
||||||
|
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(e.ClientId))
|
if (string.IsNullOrEmpty(e.ClientId))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
MqttServerClientConnectedEventArgs eventArgs = null;
|
ClientConnectedEventArgs eventArgs = null;
|
||||||
server.ClientConnectedAsync += e =>
|
server.ClientConnectedAsync += e =>
|
||||||
{
|
{
|
||||||
eventArgs = e;
|
eventArgs = e;
|
||||||
@@ -45,7 +45,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
MqttServerClientDisconnectedEventArgs eventArgs = null;
|
ClientDisconnectedEventArgs eventArgs = null;
|
||||||
server.ClientDisconnectedAsync += e =>
|
server.ClientDisconnectedAsync += e =>
|
||||||
{
|
{
|
||||||
eventArgs = e;
|
eventArgs = e;
|
||||||
@@ -72,7 +72,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
MqttServerClientSubscribedTopicEventArgs eventArgs = null;
|
ClientSubscribedTopicEventArgs eventArgs = null;
|
||||||
server.ClientSubscribedTopicAsync += e =>
|
server.ClientSubscribedTopicAsync += e =>
|
||||||
{
|
{
|
||||||
eventArgs = e;
|
eventArgs = e;
|
||||||
@@ -99,7 +99,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
MqttServerClientUnsubscribedTopicEventArgs eventArgs = null;
|
ClientUnsubscribedTopicEventArgs eventArgs = null;
|
||||||
server.ClientUnsubscribedTopicAsync += e =>
|
server.ClientUnsubscribedTopicAsync += e =>
|
||||||
{
|
{
|
||||||
eventArgs = e;
|
eventArgs = e;
|
||||||
@@ -125,8 +125,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
InterceptingMqttClientPublishEventArgs eventArgs = null;
|
InterceptingPublishEventArgs eventArgs = null;
|
||||||
server.InterceptingClientPublishAsync += e =>
|
server.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
eventArgs = e;
|
eventArgs = e;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
|
|
||||||
var retainedMessages = await server.GetRetainedApplicationMessagesAsync();
|
var retainedMessages = await server.GetRetainedMessagesAsync();
|
||||||
|
|
||||||
Assert.AreEqual(ClientCount, retainedMessages.Count);
|
Assert.AreEqual(ClientCount, retainedMessages.Count);
|
||||||
|
|
||||||
@@ -530,7 +530,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.InterceptingClientPublishAsync += e =>
|
server.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
e.ApplicationMessage = new MqttApplicationMessage {Topic = "new_topic"};
|
e.ApplicationMessage = new MqttApplicationMessage {Topic = "new_topic"};
|
||||||
|
|
||||||
@@ -557,19 +557,24 @@ namespace MQTTnet.Tests.Server
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task Persist_Retained_Message()
|
public async Task Persist_Retained_Message()
|
||||||
{
|
{
|
||||||
var serverStorage = new TestServerStorage();
|
|
||||||
|
|
||||||
using (var testEnvironment = CreateTestEnvironment())
|
using (var testEnvironment = CreateTestEnvironment())
|
||||||
{
|
{
|
||||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithStorage(serverStorage));
|
List<MqttApplicationMessage> savedRetainedMessages = null;
|
||||||
|
|
||||||
|
var s = await testEnvironment.StartServer();
|
||||||
|
s.RetainedMessageChangedAsync += e =>
|
||||||
|
{
|
||||||
|
savedRetainedMessages = e.StoredRetainedMessages;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
|
||||||
var c1 = await testEnvironment.ConnectClient();
|
var c1 = await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
|
||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
Assert.AreEqual(1, serverStorage.Messages.Count);
|
Assert.AreEqual(1, savedRetainedMessages?.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +622,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
using (var testEnvironment = CreateTestEnvironment())
|
using (var testEnvironment = CreateTestEnvironment())
|
||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
server.InterceptingClientPublishAsync += e =>
|
server.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
e.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
|
e.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -698,7 +703,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
e.ReasonCode = MqttConnectReasonCode.NotAuthorized;
|
e.ReasonCode = MqttConnectReasonCode.NotAuthorized;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -711,7 +716,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
Dictionary<string, bool> _connected;
|
Dictionary<string, bool> _connected;
|
||||||
|
|
||||||
void ConnectionValidationHandler(ValidatingMqttClientConnectionEventArgs eventArgs)
|
void ConnectionValidationHandler(ValidatingConnectionEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (_connected.ContainsKey(eventArgs.ClientId))
|
if (_connected.ContainsKey(eventArgs.ClientId))
|
||||||
{
|
{
|
||||||
@@ -734,7 +739,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
ConnectionValidationHandler(e);
|
ConnectionValidationHandler(e);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -923,12 +928,12 @@ namespace MQTTnet.Tests.Server
|
|||||||
var clientOptions = new MqttClientOptionsBuilder();
|
var clientOptions = new MqttClientOptionsBuilder();
|
||||||
var c1 = await testEnvironment.ConnectClient(clientOptions);
|
var c1 = await testEnvironment.ConnectClient(clientOptions);
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
Assert.AreEqual(1, (await server.GetClientStatusAsync()).Count);
|
Assert.AreEqual(1, (await server.GetClientsAsync()).Count);
|
||||||
|
|
||||||
await c1.DisconnectAsync();
|
await c1.DisconnectAsync();
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count);
|
Assert.AreEqual(0, (await server.GetClientsAsync()).Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -965,7 +970,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.InterceptingClientSubscriptionAsync += e =>
|
server.InterceptingSubscriptionAsync += e =>
|
||||||
{
|
{
|
||||||
// This should lead to no subscriptions for "n" at all. So also no sending of retained messages.
|
// This should lead to no subscriptions for "n" at all. So also no sending of retained messages.
|
||||||
if (e.TopicFilter.Topic == "n")
|
if (e.TopicFilter.Topic == "n")
|
||||||
@@ -1021,7 +1026,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
await client1.DisconnectAsync();
|
await client1.DisconnectAsync();
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
Assert.AreEqual(0, clientStatus.Count);
|
Assert.AreEqual(0, clientStatus.Count);
|
||||||
|
|
||||||
var client2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("b"));
|
var client2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("b"));
|
||||||
@@ -1032,8 +1037,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
clientStatus = await server.GetClientStatusAsync();
|
clientStatus = await server.GetClientsAsync();
|
||||||
var sessionStatus = await server.GetSessionStatusAsync();
|
var sessionStatus = await server.GetSessionsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(0, clientStatus.Count);
|
Assert.AreEqual(0, clientStatus.Count);
|
||||||
Assert.AreEqual(2, sessionStatus.Count);
|
Assert.AreEqual(2, sessionStatus.Count);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using MQTTnet.Diagnostics;
|
||||||
using MQTTnet.Packets;
|
using MQTTnet.Packets;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
@@ -12,19 +13,37 @@ namespace MQTTnet.Tests.Server
|
|||||||
[TestClass]
|
[TestClass]
|
||||||
public sealed class MqttSubscriptionsManager_Tests : BaseTestClass
|
public sealed class MqttSubscriptionsManager_Tests : BaseTestClass
|
||||||
{
|
{
|
||||||
|
MqttClientSubscriptionsManager _subscriptionsManager;
|
||||||
|
|
||||||
|
[TestInitialize]
|
||||||
|
public void TestInitialize()
|
||||||
|
{
|
||||||
|
var logger = new TestLogger();
|
||||||
|
var options = new MqttServerOptions();
|
||||||
|
var retainedMessagesManager = new MqttRetainedMessagesManager(new MqttServerEventContainer(), logger);
|
||||||
|
var eventContainer = new MqttServerEventContainer();
|
||||||
|
|
||||||
|
var session = new MqttSession(
|
||||||
|
"",
|
||||||
|
new ConcurrentDictionary<object, object>(),
|
||||||
|
options,
|
||||||
|
eventContainer,
|
||||||
|
retainedMessagesManager,
|
||||||
|
new MqttClientSessionsManager(options, retainedMessagesManager, eventContainer, logger));
|
||||||
|
|
||||||
|
_subscriptionsManager = new MqttClientSubscriptionsManager(session, new MqttServerOptions(), new MqttServerEventContainer(),
|
||||||
|
new MqttRetainedMessagesManager(new MqttServerEventContainer(), new MqttNetNullLogger()));
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MqttSubscriptionsManager_SubscribeSingleSuccess()
|
public async Task MqttSubscriptionsManager_SubscribeSingleSuccess()
|
||||||
{
|
{
|
||||||
var s = CreateSession();
|
|
||||||
|
|
||||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(), new MqttRetainedMessagesManager());
|
|
||||||
|
|
||||||
var sp = new MqttSubscribePacket();
|
var sp = new MqttSubscribePacket();
|
||||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||||
|
|
||||||
await sm.Subscribe(sp, CancellationToken.None);
|
await _subscriptionsManager.Subscribe(sp, CancellationToken.None);
|
||||||
|
|
||||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "");
|
var result = _subscriptionsManager.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "");
|
||||||
Assert.IsTrue(result.IsSubscribed);
|
Assert.IsTrue(result.IsSubscribed);
|
||||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
||||||
}
|
}
|
||||||
@@ -32,16 +51,12 @@ namespace MQTTnet.Tests.Server
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MqttSubscriptionsManager_SubscribeDifferentQoSSuccess()
|
public async Task MqttSubscriptionsManager_SubscribeDifferentQoSSuccess()
|
||||||
{
|
{
|
||||||
var s = CreateSession();
|
|
||||||
|
|
||||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(), new MqttRetainedMessagesManager());
|
|
||||||
|
|
||||||
var sp = new MqttSubscribePacket();
|
var sp = new MqttSubscribePacket();
|
||||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
sp.TopicFilters.Add(new MqttTopicFilter {Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce});
|
||||||
|
|
||||||
await sm.Subscribe(sp, CancellationToken.None);
|
await _subscriptionsManager.Subscribe(sp, CancellationToken.None);
|
||||||
|
|
||||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
var result = _subscriptionsManager.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
||||||
Assert.IsTrue(result.IsSubscribed);
|
Assert.IsTrue(result.IsSubscribed);
|
||||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtMostOnce);
|
||||||
}
|
}
|
||||||
@@ -49,17 +64,13 @@ namespace MQTTnet.Tests.Server
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MqttSubscriptionsManager_SubscribeTwoTimesSuccess()
|
public async Task MqttSubscriptionsManager_SubscribeTwoTimesSuccess()
|
||||||
{
|
{
|
||||||
var s = CreateSession();
|
|
||||||
|
|
||||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(), new MqttRetainedMessagesManager());
|
|
||||||
|
|
||||||
var sp = new MqttSubscribePacket();
|
var sp = new MqttSubscribePacket();
|
||||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "#", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
sp.TopicFilters.Add(new MqttTopicFilter {Topic = "#", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce});
|
||||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
|
sp.TopicFilters.Add(new MqttTopicFilter {Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce});
|
||||||
|
|
||||||
await sm.Subscribe(sp, CancellationToken.None);
|
await _subscriptionsManager.Subscribe(sp, CancellationToken.None);
|
||||||
|
|
||||||
var result = sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
var result = _subscriptionsManager.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce, "");
|
||||||
Assert.IsTrue(result.IsSubscribed);
|
Assert.IsTrue(result.IsSubscribed);
|
||||||
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtLeastOnce);
|
Assert.AreEqual(result.QualityOfServiceLevel, MqttQualityOfServiceLevel.AtLeastOnce);
|
||||||
}
|
}
|
||||||
@@ -67,53 +78,29 @@ namespace MQTTnet.Tests.Server
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MqttSubscriptionsManager_SubscribeSingleNoSuccess()
|
public async Task MqttSubscriptionsManager_SubscribeSingleNoSuccess()
|
||||||
{
|
{
|
||||||
var s = CreateSession();
|
|
||||||
|
|
||||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(), new MqttRetainedMessagesManager());
|
|
||||||
|
|
||||||
var sp = new MqttSubscribePacket();
|
var sp = new MqttSubscribePacket();
|
||||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||||
|
|
||||||
await sm.Subscribe(sp, CancellationToken.None);
|
await _subscriptionsManager.Subscribe(sp, CancellationToken.None);
|
||||||
|
|
||||||
Assert.IsFalse(sm.CheckSubscriptions("A/B/X", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
Assert.IsFalse(_subscriptionsManager.CheckSubscriptions("A/B/X", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MqttSubscriptionsManager_SubscribeAndUnsubscribeSingle()
|
public async Task MqttSubscriptionsManager_SubscribeAndUnsubscribeSingle()
|
||||||
{
|
{
|
||||||
var s = CreateSession();
|
|
||||||
|
|
||||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(), new MqttRetainedMessagesManager());
|
|
||||||
|
|
||||||
var sp = new MqttSubscribePacket();
|
var sp = new MqttSubscribePacket();
|
||||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||||
|
|
||||||
await sm.Subscribe(sp, CancellationToken.None);
|
await _subscriptionsManager.Subscribe(sp, CancellationToken.None);
|
||||||
|
|
||||||
Assert.IsTrue(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
Assert.IsTrue(_subscriptionsManager.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||||
|
|
||||||
var up = new MqttUnsubscribePacket();
|
var up = new MqttUnsubscribePacket();
|
||||||
up.TopicFilters.Add("A/B/C");
|
up.TopicFilters.Add("A/B/C");
|
||||||
await sm.Unsubscribe(up, CancellationToken.None);
|
await _subscriptionsManager.Unsubscribe(up, CancellationToken.None);
|
||||||
|
|
||||||
Assert.IsFalse(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
Assert.IsFalse(_subscriptionsManager.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce, "").IsSubscribed);
|
||||||
}
|
|
||||||
|
|
||||||
MqttClientSession CreateSession()
|
|
||||||
{
|
|
||||||
var logger = new TestLogger();
|
|
||||||
var options = new MqttServerOptions();
|
|
||||||
var retainedMessagesManager = new MqttRetainedMessagesManager();
|
|
||||||
var eventContainer = new MqttServerEventContainer();
|
|
||||||
|
|
||||||
return new MqttClientSession(
|
|
||||||
"",
|
|
||||||
new ConcurrentDictionary<object, object>(),
|
|
||||||
options,
|
|
||||||
eventContainer,
|
|
||||||
retainedMessagesManager,
|
|
||||||
new MqttClientSessionsManager(options, retainedMessagesManager, eventContainer, logger));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
if (e.Username != "UserName1")
|
if (e.Username != "UserName1")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
e.ReasonCode = MqttConnectReasonCode.ServerMoved;
|
e.ReasonCode = MqttConnectReasonCode.ServerMoved;
|
||||||
e.ServerReference = "new_server";
|
e.ServerReference = "new_server";
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
// Don't validate anything. Just set some session items.
|
// Don't validate anything. Just set some session items.
|
||||||
e.SessionItems["can_subscribe_x"] = true;
|
e.SessionItems["can_subscribe_x"] = true;
|
||||||
@@ -29,7 +29,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
server.InterceptingClientSubscriptionAsync += e =>
|
server.InterceptingSubscriptionAsync += e =>
|
||||||
{
|
{
|
||||||
if (e.TopicFilter.Topic == "x")
|
if (e.TopicFilter.Topic == "x")
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
server.InterceptingClientPublishAsync += e =>
|
server.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
e.ApplicationMessage.Payload =
|
e.ApplicationMessage.Payload =
|
||||||
Encoding.UTF8.GetBytes(
|
Encoding.UTF8.GetBytes(
|
||||||
@@ -80,7 +80,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.ValidatingClientConnectionAsync += e =>
|
server.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
// Don't validate anything. Just set some session items.
|
// Don't validate anything. Just set some session items.
|
||||||
e.SessionItems["can_subscribe_x"] = true;
|
e.SessionItems["can_subscribe_x"] = true;
|
||||||
@@ -91,7 +91,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await testEnvironment.ConnectClient();
|
await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
var sessionStatus = await testEnvironment.Server.GetSessionStatusAsync();
|
var sessionStatus = await testEnvironment.Server.GetSessionsAsync();
|
||||||
var session = sessionStatus.First();
|
var session = sessionStatus.First();
|
||||||
|
|
||||||
Assert.AreEqual(true, session.Items["can_subscribe_x"]);
|
Assert.AreEqual(true, session.Items["can_subscribe_x"]);
|
||||||
@@ -128,7 +128,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
var client = await testEnvironment.ConnectClient();
|
var client = await testEnvironment.ConnectClient();
|
||||||
|
|
||||||
// Arrange session status tracking.
|
// Arrange session status tracking.
|
||||||
var status = await server.GetSessionStatusAsync();
|
var status = await server.GetSessionsAsync();
|
||||||
var clientStatus = status[0];
|
var clientStatus = status[0];
|
||||||
|
|
||||||
var deletedEventFired = false;
|
var deletedEventFired = false;
|
||||||
@@ -158,7 +158,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
var messageReceivedHandler = testEnvironment.CreateApplicationMessageHandler(client);
|
var messageReceivedHandler = testEnvironment.CreateApplicationMessageHandler(client);
|
||||||
|
|
||||||
// Arrange session status tracking.
|
// Arrange session status tracking.
|
||||||
var status = await server.GetSessionStatusAsync();
|
var status = await server.GetSessionsAsync();
|
||||||
var clientStatus = status[0];
|
var clientStatus = status[0];
|
||||||
|
|
||||||
// Act: Inject the application message.
|
// Act: Inject the application message.
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
var sessionStatus = await server.GetSessionStatusAsync();
|
var sessionStatus = await server.GetSessionsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(2, clientStatus.Count);
|
Assert.AreEqual(2, clientStatus.Count);
|
||||||
Assert.AreEqual(2, sessionStatus.Count);
|
Assert.AreEqual(2, sessionStatus.Count);
|
||||||
@@ -37,8 +37,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
clientStatus = await server.GetClientStatusAsync();
|
clientStatus = await server.GetClientsAsync();
|
||||||
sessionStatus = await server.GetSessionStatusAsync();
|
sessionStatus = await server.GetSessionsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(0, clientStatus.Count);
|
Assert.AreEqual(0, clientStatus.Count);
|
||||||
Assert.AreEqual(0, sessionStatus.Count);
|
Assert.AreEqual(0, sessionStatus.Count);
|
||||||
@@ -56,7 +56,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(1, clientStatus.Count);
|
Assert.AreEqual(1, clientStatus.Count);
|
||||||
Assert.IsTrue(clientStatus.Any(s => s.ClientId == c1.Options.ClientId));
|
Assert.IsTrue(clientStatus.Any(s => s.ClientId == c1.Options.ClientId));
|
||||||
@@ -67,7 +67,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
Assert.IsFalse(c1.IsConnected);
|
Assert.IsFalse(c1.IsConnected);
|
||||||
|
|
||||||
clientStatus = await server.GetClientStatusAsync();
|
clientStatus = await server.GetClientsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(0, clientStatus.Count);
|
Assert.AreEqual(0, clientStatus.Count);
|
||||||
}
|
}
|
||||||
@@ -87,8 +87,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
var sessionStatus = await server.GetSessionStatusAsync();
|
var sessionStatus = await server.GetSessionsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(1, clientStatus.Count);
|
Assert.AreEqual(1, clientStatus.Count);
|
||||||
Assert.AreEqual(2, sessionStatus.Count);
|
Assert.AreEqual(2, sessionStatus.Count);
|
||||||
@@ -97,8 +97,8 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
clientStatus = await server.GetClientStatusAsync();
|
clientStatus = await server.GetClientsAsync();
|
||||||
sessionStatus = await server.GetSessionStatusAsync();
|
sessionStatus = await server.GetSessionsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(0, clientStatus.Count);
|
Assert.AreEqual(0, clientStatus.Count);
|
||||||
Assert.AreEqual(2, sessionStatus.Count);
|
Assert.AreEqual(2, sessionStatus.Count);
|
||||||
@@ -119,7 +119,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
await c1.PublishAsync("a");
|
await c1.PublishAsync("a");
|
||||||
await Task.Delay(50);
|
await Task.Delay(50);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount);
|
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount);
|
||||||
Assert.AreEqual(0, clientStatus.First().ReceivedApplicationMessagesCount);
|
Assert.AreEqual(0, clientStatus.First().ReceivedApplicationMessagesCount);
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
|
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
|
||||||
var clientStatus = await server.GetClientStatusAsync();
|
var clientStatus = await server.GetClientsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount, "SAMC invalid!");
|
Assert.AreEqual(i, clientStatus.First().SentApplicationMessagesCount, "SAMC invalid!");
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.InterceptingClientSubscriptionAsync += e =>
|
server.InterceptingSubscriptionAsync += e =>
|
||||||
{
|
{
|
||||||
// Set the topic to "a" regards what the client wants to subscribe.
|
// Set the topic to "a" regards what the client wants to subscribe.
|
||||||
e.TopicFilter.Topic = "a";
|
e.TopicFilter.Topic = "a";
|
||||||
@@ -290,7 +290,7 @@ namespace MQTTnet.Tests.Server
|
|||||||
{
|
{
|
||||||
var server = await testEnvironment.StartServer();
|
var server = await testEnvironment.StartServer();
|
||||||
|
|
||||||
server.InterceptingClientSubscriptionAsync += e =>
|
server.InterceptingSubscriptionAsync += e =>
|
||||||
{
|
{
|
||||||
if (e.TopicFilter.Topic == "not_allowed_topic")
|
if (e.TopicFilter.Topic == "not_allowed_topic")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,39 +134,6 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RetainedMessageHandler : IMqttServerStorage
|
|
||||||
{
|
|
||||||
const string Filename = "C:\\MQTT\\RetainedMessages.json";
|
|
||||||
|
|
||||||
public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
|
|
||||||
{
|
|
||||||
var directory = Path.GetDirectoryName(Filename);
|
|
||||||
if (!Directory.Exists(directory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(Filename, JsonConvert.SerializeObject(messages));
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
|
|
||||||
{
|
|
||||||
IList<MqttApplicationMessage> retainedMessages;
|
|
||||||
if (File.Exists(Filename))
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText(Filename);
|
|
||||||
retainedMessages = JsonConvert.DeserializeObject<List<MqttApplicationMessage>>(json);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retainedMessages = new List<MqttApplicationMessage>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult(retainedMessages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WikiCode
|
public class WikiCode
|
||||||
{
|
{
|
||||||
public void Code()
|
public void Code()
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Diagnostics;
|
using MQTTnet.Diagnostics;
|
||||||
|
using MQTTnet.Extensions.ManagedClient;
|
||||||
using MQTTnet.Implementations;
|
using MQTTnet.Implementations;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using MQTTnet.Server;
|
using MQTTnet.Server;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace MQTTnet.TestApp.NetCore
|
namespace MQTTnet.TestApp.NetCore
|
||||||
{
|
{
|
||||||
@@ -36,10 +40,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var options = new MqttServerOptions
|
var options = new MqttServerOptions();
|
||||||
{
|
|
||||||
Storage = new RetainedMessageHandler()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extend the timestamp for all messages from clients.
|
// Extend the timestamp for all messages from clients.
|
||||||
// Protect several topics from being subscribed from every client.
|
// Protect several topics from being subscribed from every client.
|
||||||
@@ -52,7 +53,45 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
|
|
||||||
var mqttServer = new MqttFactory().CreateMqttServer(options);
|
var mqttServer = new MqttFactory().CreateMqttServer(options);
|
||||||
|
|
||||||
mqttServer.InterceptingClientPublishAsync += e =>
|
const string Filename = "C:\\MQTT\\RetainedMessages.json";
|
||||||
|
|
||||||
|
mqttServer.RetainedMessageChangedAsync += e =>
|
||||||
|
{
|
||||||
|
var directory = Path.GetDirectoryName(Filename);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(Filename, JsonConvert.SerializeObject(e.StoredRetainedMessages));
|
||||||
|
return Task.FromResult(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
mqttServer.RetainedMessagesClearedAsync += e =>
|
||||||
|
{
|
||||||
|
File.Delete(Filename);
|
||||||
|
return Task.FromResult(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
mqttServer.LoadingRetainedMessageAsync += e =>
|
||||||
|
{
|
||||||
|
List<MqttApplicationMessage> retainedMessages;
|
||||||
|
if (File.Exists(Filename))
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(Filename);
|
||||||
|
retainedMessages = JsonConvert.DeserializeObject<List<MqttApplicationMessage>>(json);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retainedMessages = new List<MqttApplicationMessage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
e.StoredRetainedMessages = retainedMessages;
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
mqttServer.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
if (MqttTopicFilterComparer.Compare(e.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#") == MqttTopicFilterCompareResult.IsMatch)
|
if (MqttTopicFilterComparer.Compare(e.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#") == MqttTopicFilterCompareResult.IsMatch)
|
||||||
{
|
{
|
||||||
@@ -70,7 +109,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
return PlatformAbstractionLayer.CompletedTask;
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
mqttServer.ValidatingClientConnectionAsync += e =>
|
mqttServer.ValidatingConnectionAsync += e =>
|
||||||
{
|
{
|
||||||
if (e.ClientId == "SpecialClient")
|
if (e.ClientId == "SpecialClient")
|
||||||
{
|
{
|
||||||
@@ -83,7 +122,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
return PlatformAbstractionLayer.CompletedTask;
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
mqttServer.InterceptingClientSubscriptionAsync += e =>
|
mqttServer.InterceptingSubscriptionAsync += e =>
|
||||||
{
|
{
|
||||||
if (e.TopicFilter.Topic.StartsWith("admin/foo/bar") && e.ClientId != "theAdmin")
|
if (e.TopicFilter.Topic.StartsWith("admin/foo/bar") && e.ClientId != "theAdmin")
|
||||||
{
|
{
|
||||||
@@ -99,7 +138,7 @@ namespace MQTTnet.TestApp.NetCore
|
|||||||
return PlatformAbstractionLayer.CompletedTask;
|
return PlatformAbstractionLayer.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
mqttServer.InterceptingClientPublishAsync += e =>
|
mqttServer.InterceptingPublishAsync += e =>
|
||||||
{
|
{
|
||||||
MqttNetConsoleLogger.PrintToConsole(
|
MqttNetConsoleLogger.PrintToConsole(
|
||||||
$"'{e.ClientId}' reported '{e.ApplicationMessage.Topic}' > '{Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0])}'",
|
$"'{e.ClientId}' reported '{e.ApplicationMessage.Topic}' > '{Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0])}'",
|
||||||
|
|||||||
Reference in New Issue
Block a user