mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-16 09:13:02 +08:00
Move events to server level instead of options.
This commit is contained in:
@@ -36,9 +36,9 @@ namespace MQTTnet.AspNetCore.Extensions
|
||||
return app;
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<IMqttServer> configure)
|
||||
public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action<MqttServer> configure)
|
||||
{
|
||||
var server = app.ApplicationServices.GetRequiredService<IMqttServer>();
|
||||
var server = app.ApplicationServices.GetRequiredService<MqttServer>();
|
||||
|
||||
configure(server);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace MQTTnet.AspNetCore.Extensions
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, IMqttServerOptions options)
|
||||
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, MqttServerOptions options)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MQTTnet.AspNetCore.Extensions
|
||||
|
||||
public static IServiceCollection AddHostedMqttServer(this IServiceCollection services, Action<MqttServerOptionsBuilder> configure)
|
||||
{
|
||||
services.AddSingleton<IMqttServerOptions>(s =>
|
||||
services.AddSingleton<MqttServerOptions>(s =>
|
||||
{
|
||||
var builder = new MqttServerOptionsBuilder();
|
||||
configure(builder);
|
||||
@@ -38,7 +38,7 @@ namespace MQTTnet.AspNetCore.Extensions
|
||||
|
||||
public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action<AspNetMqttServerOptionsBuilder> configure)
|
||||
{
|
||||
services.AddSingleton<IMqttServerOptions>(s =>
|
||||
services.AddSingleton<MqttServerOptions>(s =>
|
||||
{
|
||||
var builder = new AspNetMqttServerOptionsBuilder(s);
|
||||
configure(builder);
|
||||
@@ -50,17 +50,17 @@ namespace MQTTnet.AspNetCore.Extensions
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddHostedMqttServer<TOptions>(this IServiceCollection services)
|
||||
where TOptions : class, IMqttServerOptions
|
||||
{
|
||||
services.AddSingleton<IMqttServerOptions, TOptions>();
|
||||
// public static IServiceCollection AddHostedMqttServer<TOptions>(this IServiceCollection services)
|
||||
// where TOptions : MqttServerOptions
|
||||
// {
|
||||
// services.AddSingleton<MqttServerOptions, TOptions>();
|
||||
//
|
||||
// services.AddHostedMqttServer();
|
||||
//
|
||||
// return services;
|
||||
// }
|
||||
|
||||
services.AddHostedMqttServer();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
|
||||
static IServiceCollection AddHostedMqttServer(this IServiceCollection services)
|
||||
{
|
||||
var logger = new MqttNetEventLogger();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace MQTTnet.AspNetCore
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
public Task StartAsync(MqttServerOptions options)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Server.Status;
|
||||
|
||||
namespace MQTTnet.AspNetCore
|
||||
{
|
||||
public sealed class MqttHostedServer : IMqttServer, IHostedService
|
||||
{
|
||||
readonly MqttServer _mqttServer;
|
||||
readonly IMqttServerOptions _options;
|
||||
|
||||
public MqttHostedServer(IMqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||
public MqttHostedServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
|
||||
_mqttServer = new MqttServer(adapters, logger);
|
||||
_mqttServer = new MqttServer(options, adapters, logger);
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_ = _mqttServer.StartAsync(_options);
|
||||
_ = _mqttServer.StartAsync();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -34,22 +28,10 @@ namespace MQTTnet.AspNetCore
|
||||
{
|
||||
return _mqttServer.StopAsync();
|
||||
}
|
||||
|
||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
|
||||
{
|
||||
get => _mqttServer.ApplicationMessageReceivedHandler;
|
||||
set => _mqttServer.ApplicationMessageReceivedHandler = value;
|
||||
}
|
||||
|
||||
public event Func<MqttApplicationMessageReceivedEventArgs, Task> ApplicationMessageReceivedAsync
|
||||
{
|
||||
add => _mqttServer.ApplicationMessageReceivedAsync += value;
|
||||
remove => _mqttServer.ApplicationMessageReceivedAsync -= value;
|
||||
}
|
||||
|
||||
public Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||
public Task<MqttClientPublishResult> PublishAsync(string senderClientId, MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||
{
|
||||
return _mqttServer.PublishAsync(applicationMessage, cancellationToken);
|
||||
return _mqttServer.PublishAsync(senderClientId, applicationMessage, cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -58,45 +40,7 @@ namespace MQTTnet.AspNetCore
|
||||
}
|
||||
|
||||
public bool IsStarted => _mqttServer.IsStarted;
|
||||
|
||||
public IMqttServerStartedHandler StartedHandler
|
||||
{
|
||||
get => _mqttServer.StartedHandler;
|
||||
set => _mqttServer.StartedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerStoppedHandler StoppedHandler
|
||||
{
|
||||
get => _mqttServer.StoppedHandler;
|
||||
set => _mqttServer.StoppedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientConnectedHandler ClientConnectedHandler
|
||||
{
|
||||
get => _mqttServer.ClientConnectedHandler;
|
||||
set => _mqttServer.ClientConnectedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientDisconnectedHandler ClientDisconnectedHandler
|
||||
{
|
||||
get => _mqttServer.ClientDisconnectedHandler;
|
||||
set => _mqttServer.ClientDisconnectedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientSubscribedTopicHandler ClientSubscribedTopicHandler
|
||||
{
|
||||
get => _mqttServer.ClientSubscribedTopicHandler;
|
||||
set => _mqttServer.ClientSubscribedTopicHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientUnsubscribedTopicHandler ClientUnsubscribedTopicHandler
|
||||
{
|
||||
get => _mqttServer.ClientUnsubscribedTopicHandler;
|
||||
set => _mqttServer.ClientUnsubscribedTopicHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerOptions Options => _mqttServer.Options;
|
||||
|
||||
|
||||
public Task<IList<IMqttClientStatus>> GetClientStatusAsync()
|
||||
{
|
||||
return _mqttServer.GetClientStatusAsync();
|
||||
@@ -127,9 +71,9 @@ namespace MQTTnet.AspNetCore
|
||||
return _mqttServer.UnsubscribeAsync(clientId, topicFilters);
|
||||
}
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
public Task StartAsync()
|
||||
{
|
||||
return _mqttServer.StartAsync(options);
|
||||
return _mqttServer.StartAsync();
|
||||
}
|
||||
|
||||
public Task StopAsync()
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace MQTTnet.AspNetCore
|
||||
|
||||
public Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
public Task StartAsync(MqttServerOptions options)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using MQTTnet.Client;
|
||||
|
||||
namespace MQTTnet.Extensions.ManagedClient
|
||||
{
|
||||
public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||
public interface IManagedMqttClient : IMqttApplicationMessageReceiver, IMqttApplicationMessagePublisher, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the internally used MQTT client.
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
|
||||
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
||||
where TReceiver : IApplicationMessageReceiver
|
||||
where TReceiver : IMqttApplicationMessageReceiver
|
||||
{
|
||||
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
|
||||
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
||||
where TReceiver : IApplicationMessageReceiver
|
||||
where TReceiver : IMqttApplicationMessageReceiver
|
||||
{
|
||||
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
|
||||
public static TReceiver UseApplicationMessageReceivedHandler<TReceiver>(this TReceiver receiver, IMqttApplicationMessageReceivedHandler handler)
|
||||
where TReceiver : IApplicationMessageReceiver
|
||||
where TReceiver : IMqttApplicationMessageReceiver
|
||||
{
|
||||
if (receiver == null) throw new ArgumentNullException(nameof(receiver));
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
return client.UnsubscribeAsync(topicFilters);
|
||||
}
|
||||
|
||||
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, IEnumerable<MqttApplicationMessage> applicationMessages)
|
||||
public static async Task PublishAsync(this IMqttApplicationMessagePublisher publisher, IEnumerable<MqttApplicationMessage> applicationMessages)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||
@@ -152,7 +152,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
@@ -160,7 +160,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
return publisher.PublishAsync(applicationMessage, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static async Task PublishAsync(this IApplicationMessagePublisher publisher, params MqttApplicationMessage[] applicationMessages)
|
||||
public static async Task PublishAsync(this IMqttApplicationMessagePublisher publisher, params MqttApplicationMessage[] applicationMessages)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
|
||||
@@ -171,7 +171,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, string topic)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -180,7 +180,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
.WithTopic(topic));
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, string topic, string payload)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -190,7 +190,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
.WithPayload(payload));
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -201,7 +201,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
.WithQualityOfServiceLevel(qualityOfServiceLevel));
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
if (topic == null) throw new ArgumentNullException(nameof(topic));
|
||||
@@ -213,7 +213,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
.WithRetainFlag(retain));
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder, CancellationToken cancellationToken)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
return publisher.PublishAsync(message, cancellationToken);
|
||||
}
|
||||
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||
public static Task<MqttClientPublishResult> PublishAsync(this IMqttApplicationMessagePublisher publisher, Func<MqttApplicationMessageBuilder, MqttApplicationMessageBuilder> builder)
|
||||
{
|
||||
if (publisher == null) throw new ArgumentNullException(nameof(publisher));
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@ namespace MQTTnet.Extensions.ManagedClient
|
||||
{
|
||||
public static class MqttFactoryExtensions
|
||||
{
|
||||
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory)
|
||||
public static IManagedMqttClient CreateManagedMqttClient(this MqttFactory factory)
|
||||
{
|
||||
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
||||
|
||||
return new ManagedMqttClient(factory.CreateMqttClient(), factory.DefaultLogger);
|
||||
}
|
||||
|
||||
public static IManagedMqttClient CreateManagedMqttClient(this IMqttFactory factory, IMqttNetLogger logger)
|
||||
public static IManagedMqttClient CreateManagedMqttClient(this MqttFactory factory, IMqttNetLogger logger)
|
||||
{
|
||||
if (factory == null) throw new ArgumentNullException(nameof(factory));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace MQTTnet.Extensions.WebSocket4Net
|
||||
{
|
||||
public static class MqttFactoryExtensions
|
||||
{
|
||||
public static IMqttFactory UseWebSocket4Net(this IMqttFactory mqttFactory)
|
||||
public static MqttFactory UseWebSocket4Net(this MqttFactory mqttFactory)
|
||||
{
|
||||
if (mqttFactory == null) throw new ArgumentNullException(nameof(mqttFactory));
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace MQTTnet.Adapter
|
||||
{
|
||||
Func<IMqttChannelAdapter, Task> ClientHandler { get; set; }
|
||||
|
||||
Task StartAsync(IMqttServerOptions options);
|
||||
Task StartAsync(MqttServerOptions options);
|
||||
Task StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/// Gets or sets the reason code.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public MqttClientDisconnectReason ReasonCode { get; set; } = MqttClientDisconnectReason.NormalDisconnection;
|
||||
public MqttClientDisconnectReason Reason { get; set; } = MqttClientDisconnectReason.NormalDisconnection;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the reason string.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace MQTTnet.Client.Disconnecting
|
||||
{
|
||||
public sealed class MqttClientDisconnectOptionsBuilder
|
||||
{
|
||||
MqttClientDisconnectReason _reason = MqttClientDisconnectReason.NormalDisconnection;
|
||||
string _reasonString;
|
||||
|
||||
public MqttClientDisconnectOptionsBuilder WithReasonString(string value)
|
||||
{
|
||||
_reasonString = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientDisconnectOptionsBuilder WithReason(MqttClientDisconnectReason value)
|
||||
{
|
||||
_reason = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientDisconnectOptions Build()
|
||||
{
|
||||
return new MqttClientDisconnectOptions
|
||||
{
|
||||
Reason = _reason,
|
||||
ReasonString = _reasonString
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public interface IMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||
public interface IMqttClient : IMqttApplicationMessageReceiver, IMqttApplicationMessagePublisher, IDisposable
|
||||
{
|
||||
bool IsConnected { get; }
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.LowLevelClient;
|
||||
|
||||
namespace MQTTnet.Client
|
||||
{
|
||||
public interface IMqttClientFactory
|
||||
{
|
||||
IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory);
|
||||
|
||||
ILowLevelMqttClient CreateLowLevelMqttClient();
|
||||
|
||||
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger);
|
||||
|
||||
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttClientAdapterFactory clientAdapterFactory);
|
||||
|
||||
ILowLevelMqttClient CreateLowLevelMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory clientAdapterFactory);
|
||||
|
||||
IMqttClient CreateMqttClient();
|
||||
|
||||
IMqttClient CreateMqttClient(IMqttNetLogger logger);
|
||||
|
||||
IMqttClient CreateMqttClient(IMqttClientAdapterFactory adapterFactory);
|
||||
|
||||
IMqttClient CreateMqttClient(IMqttNetLogger logger, IMqttClientAdapterFactory adapterFactory);
|
||||
}
|
||||
}
|
||||
@@ -150,13 +150,13 @@ namespace MQTTnet.Client
|
||||
return client.DisconnectAsync(options, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static Task DisconnectAsync(this IMqttClient client, MqttClientDisconnectReason reasonCode, string reasonString = null)
|
||||
public static Task DisconnectAsync(this IMqttClient client, MqttClientDisconnectReason reason, string reasonString = null)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
return client.DisconnectAsync(new MqttClientDisconnectOptions
|
||||
{
|
||||
ReasonCode = reasonCode,
|
||||
Reason = reason,
|
||||
ReasonString = reasonString
|
||||
}, CancellationToken.None);
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace MQTTnet.Formatter
|
||||
{
|
||||
public sealed class MqttConnAckPacketFactory
|
||||
{
|
||||
public MqttConnAckPacket Create(MqttConnectionValidatorContext connectionValidatorContext)
|
||||
public MqttConnAckPacket Create(ValidatingMqttClientConnectionEventArgs clientConnectionValidationEventArgs)
|
||||
{
|
||||
if (connectionValidatorContext == null) throw new ArgumentNullException(nameof(connectionValidatorContext));
|
||||
if (clientConnectionValidationEventArgs == null) throw new ArgumentNullException(nameof(clientConnectionValidationEventArgs));
|
||||
|
||||
var connAckPacket = new MqttConnAckPacket
|
||||
{
|
||||
ReturnCode = MqttConnectReasonCodeConverter.ToConnectReturnCode(connectionValidatorContext.ReasonCode),
|
||||
ReasonCode = connectionValidatorContext.ReasonCode,
|
||||
ReturnCode = MqttConnectReasonCodeConverter.ToConnectReturnCode(clientConnectionValidationEventArgs.ReasonCode),
|
||||
ReasonCode = clientConnectionValidationEventArgs.ReasonCode,
|
||||
Properties =
|
||||
{
|
||||
RetainAvailable = true,
|
||||
@@ -22,17 +22,17 @@ namespace MQTTnet.Formatter
|
||||
TopicAliasMaximum = ushort.MaxValue,
|
||||
WildcardSubscriptionAvailable = true,
|
||||
|
||||
AuthenticationMethod = connectionValidatorContext.AuthenticationMethod,
|
||||
AuthenticationData = connectionValidatorContext.ResponseAuthenticationData,
|
||||
AssignedClientIdentifier = connectionValidatorContext.AssignedClientIdentifier,
|
||||
ReasonString = connectionValidatorContext.ReasonString,
|
||||
ServerReference = connectionValidatorContext.ServerReference
|
||||
AuthenticationMethod = clientConnectionValidationEventArgs.AuthenticationMethod,
|
||||
AuthenticationData = clientConnectionValidationEventArgs.ResponseAuthenticationData,
|
||||
AssignedClientIdentifier = clientConnectionValidationEventArgs.AssignedClientIdentifier,
|
||||
ReasonString = clientConnectionValidationEventArgs.ReasonString,
|
||||
ServerReference = clientConnectionValidationEventArgs.ServerReference
|
||||
}
|
||||
};
|
||||
|
||||
if (connectionValidatorContext.ResponseUserProperties != null)
|
||||
if (clientConnectionValidationEventArgs.ResponseUserProperties != null)
|
||||
{
|
||||
connAckPacket.Properties.UserProperties.AddRange(connectionValidatorContext.ResponseUserProperties);
|
||||
connAckPacket.Properties.UserProperties.AddRange(clientConnectionValidationEventArgs.ResponseUserProperties);
|
||||
}
|
||||
|
||||
return connAckPacket;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace MQTTnet.Formatter
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.ReasonCode = (MqttDisconnectReasonCode) clientDisconnectOptions.ReasonCode;
|
||||
packet.ReasonCode = (MqttDisconnectReasonCode) clientDisconnectOptions.Reason;
|
||||
}
|
||||
|
||||
return packet;
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ using MQTTnet.Client.Publishing;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public interface IApplicationMessagePublisher
|
||||
public interface IMqttApplicationMessagePublisher
|
||||
{
|
||||
Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default);
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ using MQTTnet.Client.Receiving;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public interface IApplicationMessageReceiver
|
||||
public interface IMqttApplicationMessageReceiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the application message received handler that is fired every time a new message is received on the client's subscriptions.
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public interface IMqttFactory : IMqttClientFactory, IMqttServerFactory
|
||||
{
|
||||
IMqttNetLogger DefaultLogger { get; }
|
||||
|
||||
IDictionary<object, object> Properties { get; }
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace MQTTnet.Implementations
|
||||
|
||||
public bool TreatSocketOpeningErrorAsWarning { get; set; }
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
public Task StartAsync(MqttServerOptions options)
|
||||
{
|
||||
if (_cancellationTokenSource != null) throw new InvalidOperationException("Server is already started.");
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Internal
|
||||
{
|
||||
public sealed class AsyncEvent<TEventArgs>
|
||||
public sealed class AsyncEvent<TEventArgs> where TEventArgs : EventArgs
|
||||
{
|
||||
readonly List<Func<TEventArgs, Task>> _handlers = new List<Func<TEventArgs, Task>>();
|
||||
|
||||
@@ -29,5 +30,19 @@ namespace MQTTnet.Internal
|
||||
await handler.Invoke(eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TEventArgs> InvokeAsync(Func<TEventArgs> eventArgsProvider)
|
||||
{
|
||||
if (eventArgsProvider == null) throw new ArgumentNullException(nameof(eventArgsProvider));
|
||||
|
||||
if (!_handlers.Any())
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var eventArgs = eventArgsProvider.Invoke();
|
||||
await InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
return eventArgs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=server_005Coptions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=server_005Cstatus/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -6,6 +6,7 @@ using MQTTnet.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client.Subscribing;
|
||||
using MQTTnet.Client.Unsubscribing;
|
||||
@@ -13,7 +14,7 @@ using MQTTnet.Diagnostics.Logger;
|
||||
|
||||
namespace MQTTnet
|
||||
{
|
||||
public sealed class MqttFactory : IMqttFactory
|
||||
public sealed class MqttFactory
|
||||
{
|
||||
IMqttClientAdapterFactory _clientAdapterFactory;
|
||||
|
||||
@@ -29,14 +30,14 @@ namespace MQTTnet
|
||||
|
||||
public IMqttNetLogger DefaultLogger { get; }
|
||||
|
||||
public IList<Func<IMqttFactory, IMqttServerAdapter>> DefaultServerAdapters { get; } = new List<Func<IMqttFactory, IMqttServerAdapter>>
|
||||
public IList<Func<MqttFactory, IMqttServerAdapter>> DefaultServerAdapters { get; } = new List<Func<MqttFactory, IMqttServerAdapter>>
|
||||
{
|
||||
factory => new MqttTcpServerAdapter(factory.DefaultLogger)
|
||||
};
|
||||
|
||||
public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
|
||||
|
||||
public IMqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory)
|
||||
public MqttFactory UseClientAdapterFactory(IMqttClientAdapterFactory clientAdapterFactory)
|
||||
{
|
||||
_clientAdapterFactory = clientAdapterFactory ?? throw new ArgumentNullException(nameof(clientAdapterFactory));
|
||||
return this;
|
||||
@@ -96,42 +97,47 @@ namespace MQTTnet
|
||||
return new MqttClient(clientAdapterFactory, logger);
|
||||
}
|
||||
|
||||
public IMqttServer CreateMqttServer()
|
||||
public MqttServer CreateMqttServer(MqttServerOptions options)
|
||||
{
|
||||
return CreateMqttServer(DefaultLogger);
|
||||
return CreateMqttServer(options, DefaultLogger);
|
||||
}
|
||||
|
||||
public IMqttServer CreateMqttServer(IMqttNetLogger logger)
|
||||
public MqttServer CreateMqttServer(MqttServerOptions options, IMqttNetLogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
var serverAdapters = DefaultServerAdapters.Select(a => a.Invoke(this));
|
||||
return CreateMqttServer(serverAdapters, logger);
|
||||
return CreateMqttServer(options, serverAdapters, logger);
|
||||
}
|
||||
|
||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters, IMqttNetLogger logger)
|
||||
public MqttServer CreateMqttServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> serverAdapters, IMqttNetLogger logger)
|
||||
{
|
||||
if (serverAdapters == null) throw new ArgumentNullException(nameof(serverAdapters));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
return new MqttServer(serverAdapters, logger);
|
||||
return new MqttServer(options, serverAdapters, logger);
|
||||
}
|
||||
|
||||
public IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> serverAdapters)
|
||||
public MqttServer CreateMqttServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> serverAdapters)
|
||||
{
|
||||
if (serverAdapters == null) throw new ArgumentNullException(nameof(serverAdapters));
|
||||
|
||||
return new MqttServer(serverAdapters, DefaultLogger);
|
||||
return new MqttServer(options, serverAdapters, DefaultLogger);
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder CreateServerOptionsBuilder()
|
||||
{
|
||||
return new MqttServerOptionsBuilder();
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder CreateClientOptionsBuilder()
|
||||
{
|
||||
return new MqttClientOptionsBuilder();
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder CreateServerOptionsBuilder()
|
||||
|
||||
public MqttClientDisconnectOptionsBuilder CreateClientDisconnectOptionsBuilder()
|
||||
{
|
||||
return new MqttServerOptionsBuilder();
|
||||
return new MqttClientDisconnectOptionsBuilder();
|
||||
}
|
||||
|
||||
public MqttClientSubscribeOptionsBuilder CreateSubscribeOptionsBuilder()
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class GetSubscribedMessagesFilter
|
||||
{
|
||||
public bool IsNewSubscription { get; set; }
|
||||
|
||||
public MqttTopicFilter TopicFilter { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttClientSession
|
||||
{
|
||||
/// <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; }
|
||||
|
||||
Task StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttRetainedMessagesManager
|
||||
{
|
||||
Task Start(IMqttServerOptions options, IMqttNetLogger logger);
|
||||
Task Start(MqttServerOptions options, IMqttNetLogger logger);
|
||||
|
||||
Task LoadMessagesAsync();
|
||||
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
using System;
|
||||
using MQTTnet.Server.Status;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServer : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable
|
||||
public interface IMqttServer : IDisposable
|
||||
{
|
||||
bool IsStarted { get; }
|
||||
IMqttServerStartedHandler StartedHandler { get; set; }
|
||||
IMqttServerStoppedHandler StoppedHandler { get; set; }
|
||||
|
||||
IMqttServerClientConnectedHandler ClientConnectedHandler { get; set; }
|
||||
IMqttServerClientDisconnectedHandler ClientDisconnectedHandler { get; set; }
|
||||
IMqttServerClientSubscribedTopicHandler ClientSubscribedTopicHandler { get; set; }
|
||||
IMqttServerClientUnsubscribedTopicHandler ClientUnsubscribedTopicHandler { get; set; }
|
||||
|
||||
IMqttServerOptions Options { get; }
|
||||
|
||||
|
||||
Task<IList<IMqttClientStatus>> GetClientStatusAsync();
|
||||
Task<IList<IMqttSessionStatus>> GetSessionStatusAsync();
|
||||
|
||||
@@ -27,7 +17,7 @@ namespace MQTTnet.Server
|
||||
Task SubscribeAsync(string clientId, ICollection<MqttTopicFilter> topicFilters);
|
||||
Task UnsubscribeAsync(string clientId, ICollection<string> topicFilters);
|
||||
|
||||
Task StartAsync(IMqttServerOptions options);
|
||||
Task StartAsync();
|
||||
Task StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerApplicationMessageInterceptor
|
||||
{
|
||||
Task InterceptApplicationMessagePublishAsync(MqttApplicationMessageInterceptorContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerClientConnectedHandler
|
||||
{
|
||||
Task HandleClientConnectedAsync(MqttServerClientConnectedEventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerClientDisconnectedHandler
|
||||
{
|
||||
Task HandleClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerClientMessageQueueInterceptor
|
||||
{
|
||||
Task InterceptClientMessageQueueEnqueueAsync(MqttClientMessageQueueInterceptorContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerClientSubscribedTopicHandler
|
||||
{
|
||||
Task HandleClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerClientUnsubscribedTopicHandler
|
||||
{
|
||||
Task HandleClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerConnectionValidator
|
||||
{
|
||||
Task ValidateConnectionAsync(MqttConnectionValidatorContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerFactory
|
||||
{
|
||||
IList<Func<IMqttFactory, IMqttServerAdapter>> DefaultServerAdapters { get; }
|
||||
|
||||
IMqttServer CreateMqttServer();
|
||||
|
||||
IMqttServer CreateMqttServer(IMqttNetLogger logger);
|
||||
|
||||
IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> adapters);
|
||||
|
||||
IMqttServer CreateMqttServer(IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerOptions
|
||||
{
|
||||
/// <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; }
|
||||
|
||||
bool EnablePersistentSessions { get; }
|
||||
|
||||
int MaxPendingMessagesPerClient { get; }
|
||||
MqttPendingMessagesOverflowStrategy PendingMessagesOverflowStrategy { get; }
|
||||
|
||||
TimeSpan DefaultCommunicationTimeout { get; }
|
||||
TimeSpan KeepAliveMonitorInterval { get; }
|
||||
|
||||
IMqttServerConnectionValidator ConnectionValidator { get; }
|
||||
IMqttServerSubscriptionInterceptor SubscriptionInterceptor { get; }
|
||||
IMqttServerUnsubscriptionInterceptor UnsubscriptionInterceptor { get; }
|
||||
IMqttServerApplicationMessageInterceptor ApplicationMessageInterceptor { get; }
|
||||
IMqttServerClientMessageQueueInterceptor ClientMessageQueueInterceptor { get; }
|
||||
IMqttServerApplicationMessageInterceptor UndeliveredMessageInterceptor { get; }
|
||||
|
||||
MqttServerTcpEndpointOptions DefaultEndpointOptions { get; }
|
||||
MqttServerTlsTcpEndpointOptions TlsEndpointOptions { get; }
|
||||
|
||||
IMqttServerStorage Storage { get; }
|
||||
|
||||
IMqttRetainedMessagesManager RetainedMessagesManager { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerStartedHandler
|
||||
{
|
||||
Task HandleServerStartedAsync(EventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerStoppedHandler
|
||||
{
|
||||
Task HandleServerStoppedAsync(EventArgs eventArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerSubscriptionInterceptor
|
||||
{
|
||||
Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttServerUnsubscriptionInterceptor
|
||||
{
|
||||
Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context);
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttApplicationMessageInterceptorContext
|
||||
public sealed class InterceptingMqttClientPublishEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client identifier.
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using MQTTnet.Server.Status;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttSubscriptionInterceptorContext
|
||||
public sealed class InterceptingMqttClientSubscriptionEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client identifier.
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttUnsubscriptionInterceptorContext
|
||||
public sealed class InterceptingMqttClientUnsubscriptionEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client identifier.
|
||||
@@ -7,13 +7,13 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttApplicationMessageInterceptorInvoker
|
||||
{
|
||||
readonly IMqttServerOptions _serverOptions;
|
||||
readonly MqttServerEventContainer _eventContainer;
|
||||
readonly string _clientId;
|
||||
readonly IDictionary<object, object> _sessionItems;
|
||||
|
||||
public MqttApplicationMessageInterceptorInvoker(IMqttServerOptions serverOptions, string clientId, IDictionary<object, object> sessionItems)
|
||||
public MqttApplicationMessageInterceptorInvoker(MqttServerEventContainer eventContainer, string clientId, IDictionary<object, object> sessionItems)
|
||||
{
|
||||
_serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
||||
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||
_clientId = clientId ?? throw new ArgumentNullException(nameof(clientId));
|
||||
_sessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems));
|
||||
}
|
||||
@@ -35,13 +35,7 @@ namespace MQTTnet.Server.Internal
|
||||
ApplicationMessage = applicationMessage;
|
||||
|
||||
// Intercept.
|
||||
var interceptor = _serverOptions.ApplicationMessageInterceptor;
|
||||
if (interceptor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var interceptorContext = new MqttApplicationMessageInterceptorContext
|
||||
var eventArgs = new InterceptingMqttClientPublishEventArgs
|
||||
{
|
||||
ClientId = _clientId,
|
||||
ApplicationMessage = applicationMessage,
|
||||
@@ -51,13 +45,13 @@ namespace MQTTnet.Server.Internal
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
await interceptor.InterceptApplicationMessagePublishAsync(interceptorContext).ConfigureAwait(false);
|
||||
await _eventContainer.InterceptingClientPublishEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
|
||||
// Expose results.
|
||||
ProcessPublish = interceptorContext.ProcessPublish && interceptorContext.ApplicationMessage != null;
|
||||
CloseConnection = interceptorContext.CloseConnection;
|
||||
Response = interceptorContext.Response;
|
||||
ApplicationMessage = interceptorContext.ApplicationMessage;
|
||||
ProcessPublish = eventArgs.ProcessPublish && eventArgs.ApplicationMessage != null;
|
||||
CloseConnection = eventArgs.CloseConnection;
|
||||
Response = eventArgs.Response;
|
||||
ApplicationMessage = eventArgs.ApplicationMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
readonly MqttApplicationMessageInterceptorInvoker _applicationMessageInterceptorInvoker;
|
||||
|
||||
readonly IMqttServerOptions _serverOptions;
|
||||
readonly MqttServerOptions _serverOptions;
|
||||
readonly MqttConnectPacket _connectPacket;
|
||||
|
||||
CancellationTokenSource _cancellationToken;
|
||||
@@ -35,7 +35,8 @@ namespace MQTTnet.Server.Internal
|
||||
MqttConnectPacket connectPacket,
|
||||
IMqttChannelAdapter channelAdapter,
|
||||
MqttClientSession session,
|
||||
IMqttServerOptions serverOptions,
|
||||
MqttServerOptions serverOptions,
|
||||
MqttServerEventContainer eventContainer,
|
||||
MqttClientSessionsManager sessionsManager,
|
||||
IMqttNetLogger logger)
|
||||
{
|
||||
@@ -48,7 +49,7 @@ namespace MQTTnet.Server.Internal
|
||||
Session = session ?? throw new ArgumentNullException(nameof(session));
|
||||
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
||||
|
||||
_applicationMessageInterceptorInvoker = new MqttApplicationMessageInterceptorInvoker(_serverOptions, Id, Session.Items);
|
||||
_applicationMessageInterceptorInvoker = new MqttApplicationMessageInterceptorInvoker(eventContainer, Id, Session.Items);
|
||||
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.WithSource(nameof(MqttClientConnection));
|
||||
@@ -132,7 +133,7 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
var willPublishPacket = _packetFactories.Publish.Create(Session.LatestConnectPacket);
|
||||
var willApplicationMessage = _applicationMessageFactory.Create(willPublishPacket);
|
||||
_ = _sessionsManager.DispatchPublishPacket(willApplicationMessage, this);
|
||||
_ = _sessionsManager.DispatchPublishPacket(Id, willApplicationMessage);
|
||||
Session.WillMessageSent = true;
|
||||
}
|
||||
|
||||
@@ -433,7 +434,7 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (_applicationMessageInterceptorInvoker.ProcessPublish)
|
||||
{
|
||||
await _sessionsManager.DispatchPublishPacket(applicationMessage, this).ConfigureAwait(false);
|
||||
await _sessionsManager.DispatchPublishPacket(Id, applicationMessage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
switch (publishPacket.QualityOfServiceLevel)
|
||||
@@ -496,7 +497,7 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
var disconnectOptions = new MqttClientDisconnectOptions
|
||||
{
|
||||
ReasonCode = reason,
|
||||
Reason = reason,
|
||||
ReasonString = reason.ToString()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Server.Status;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
readonly Dictionary<ushort, MqttPublishPacket> _unacknowledgedPublishPackets = new Dictionary<ushort, MqttPublishPacket>();
|
||||
|
||||
readonly IMqttServerOptions _serverOptions;
|
||||
readonly MqttServerOptions _serverOptions;
|
||||
readonly MqttClientSessionsManager _clientSessionsManager;
|
||||
|
||||
public MqttClientSession(string clientId,
|
||||
IDictionary<object, object> items,
|
||||
MqttServerEventDispatcher eventDispatcher,
|
||||
IMqttServerOptions serverOptions,
|
||||
MqttServerOptions serverOptions,
|
||||
MqttServerEventContainer eventContainer,
|
||||
IMqttRetainedMessagesManager retainedMessagesManager,
|
||||
MqttClientSessionsManager clientSessionsManager)
|
||||
{
|
||||
@@ -31,25 +31,25 @@ namespace MQTTnet.Server.Internal
|
||||
Id = clientId ?? throw new ArgumentNullException(nameof(clientId));
|
||||
Items = items ?? throw new ArgumentNullException(nameof(items));
|
||||
|
||||
SubscriptionsManager = new MqttClientSubscriptionsManager(this, serverOptions, eventDispatcher, retainedMessagesManager);
|
||||
SubscriptionsManager = new MqttClientSubscriptionsManager(this, serverOptions, eventContainer, retainedMessagesManager);
|
||||
}
|
||||
|
||||
public event EventHandler Deleted;
|
||||
|
||||
|
||||
public string Id { get; }
|
||||
|
||||
public MqttPacketIdentifierProvider PacketIdentifierProvider { get; } = new MqttPacketIdentifierProvider();
|
||||
|
||||
public DateTime CreatedTimestamp { get; } = DateTime.UtcNow;
|
||||
|
||||
|
||||
//public bool IsCleanSession { get; set; } = true;
|
||||
|
||||
public MqttConnectPacket LatestConnectPacket { get; set; }
|
||||
|
||||
public MqttClientSubscriptionsManager SubscriptionsManager { get; }
|
||||
|
||||
|
||||
public IDictionary<object, object> Items { get; }
|
||||
|
||||
|
||||
public bool WillMessageSent { get; set; }
|
||||
|
||||
public long PendingDataPacketsCount => _packetBus.DataPacketsCount;
|
||||
@@ -58,7 +58,7 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
_unacknowledgedPublishPackets.Remove(packetIdentifier);
|
||||
}
|
||||
|
||||
|
||||
public void EnqueuePacket(MqttPacketBusItem packetBusItem)
|
||||
{
|
||||
if (packetBusItem == null) throw new ArgumentNullException(nameof(packetBusItem));
|
||||
@@ -75,19 +75,19 @@ namespace MQTTnet.Server.Internal
|
||||
// TODO: Implement.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (packetBusItem.Packet is MqttPublishPacket publishPacket)
|
||||
{
|
||||
if (publishPacket.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
_unacknowledgedPublishPackets[publishPacket.PacketIdentifier] = publishPacket;
|
||||
}
|
||||
|
||||
|
||||
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Data);
|
||||
}
|
||||
else if (packetBusItem.Packet is MqttPingReqPacket || packetBusItem.Packet is MqttPingRespPacket)
|
||||
{
|
||||
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Health);
|
||||
_packetBus.Enqueue(packetBusItem, MqttPacketBusPartition.Health);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,17 +99,17 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
return _packetBus.DequeueAsync(cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
public Task DeleteAsync()
|
||||
{
|
||||
return _clientSessionsManager.DeleteSessionAsync(Id);
|
||||
}
|
||||
|
||||
|
||||
public void OnDeleted()
|
||||
{
|
||||
Deleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
||||
public void Recover()
|
||||
{
|
||||
// TODO: Keep the bus and only insert pending items again.
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttClientSessionApplicationMessagesQueue : IDisposable
|
||||
{
|
||||
readonly AsyncQueue<MqttQueuedApplicationMessage> _messageQueue = new AsyncQueue<MqttQueuedApplicationMessage>();
|
||||
|
||||
readonly IMqttServerOptions _options;
|
||||
|
||||
public MqttClientSessionApplicationMessagesQueue(IMqttServerOptions options)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
public int Count => _messageQueue.Count;
|
||||
|
||||
public void Enqueue(MqttQueuedApplicationMessage queuedApplicationMessage)
|
||||
{
|
||||
if (queuedApplicationMessage == null) throw new ArgumentNullException(nameof(queuedApplicationMessage));
|
||||
|
||||
lock (_messageQueue)
|
||||
{
|
||||
if (_messageQueue.Count >= _options.MaxPendingMessagesPerClient)
|
||||
{
|
||||
if (_options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropNewMessage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_options.PendingMessagesOverflowStrategy == MqttPendingMessagesOverflowStrategy.DropOldestQueuedMessage)
|
||||
{
|
||||
_messageQueue.TryDequeue();
|
||||
}
|
||||
}
|
||||
|
||||
_messageQueue.Enqueue(queuedApplicationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MqttQueuedApplicationMessage> Dequeue(CancellationToken cancellationToken)
|
||||
{
|
||||
var dequeueResult = await _messageQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (!dequeueResult.IsSuccess)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return dequeueResult.Item;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_messageQueue.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_messageQueue?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,11 @@ using MQTTnet.Formatter;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server.Status;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttClientSessionsManager
|
||||
public sealed class MqttClientSessionsManager : IDisposable
|
||||
{
|
||||
//readonly BlockingCollection<MqttPendingApplicationMessage> _messageQueue = new BlockingCollection<MqttPendingApplicationMessage>();
|
||||
readonly MqttPacketFactories _packetFactories = new MqttPacketFactories();
|
||||
|
||||
readonly AsyncLock _createConnectionSyncRoot = new AsyncLock();
|
||||
@@ -29,33 +27,27 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
readonly MqttConnAckPacketFactory _connAckPacketFactory = new MqttConnAckPacketFactory();
|
||||
|
||||
readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
|
||||
readonly IMqttRetainedMessagesManager _retainedMessagesManager;
|
||||
readonly IMqttServerOptions _options;
|
||||
readonly MqttServerEventContainer _eventContainer;
|
||||
readonly MqttServerOptions _options;
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
readonly IMqttNetLogger _rootLogger;
|
||||
|
||||
public MqttClientSessionsManager(
|
||||
IMqttServerOptions options,
|
||||
MqttServerOptions options,
|
||||
IMqttRetainedMessagesManager retainedMessagesManager,
|
||||
MqttServerEventDispatcher eventDispatcher,
|
||||
MqttServerEventContainer eventContainer,
|
||||
IMqttNetLogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.WithSource(nameof(MqttClientSessionsManager));
|
||||
_rootLogger = logger;
|
||||
|
||||
_eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher));
|
||||
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
||||
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||
}
|
||||
|
||||
// public void Start(CancellationToken cancellationToken)
|
||||
// {
|
||||
// Task.Run(() => TryProcessQueuedApplicationMessagesAsync(cancellationToken), cancellationToken).RunInBackground(_logger);
|
||||
// }
|
||||
|
||||
|
||||
async Task<MqttConnectPacket> ReceiveConnectPacket(IMqttChannelAdapter channelAdapter, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -115,8 +107,14 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
await channelAdapter.SendPacketAsync(connAckPacket, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await _eventDispatcher.SafeNotifyClientConnectedAsync(connectPacket, channelAdapter).ConfigureAwait(false);
|
||||
|
||||
await _eventContainer.ClientConnectedEvent.InvokeAsync(() => new MqttServerClientConnectedEventArgs
|
||||
{
|
||||
ClientId = connectPacket.ClientId,
|
||||
UserName = connectPacket.Username,
|
||||
ProtocolVersion = channelAdapter.PacketFormatterAdapter.ProtocolVersion,
|
||||
Endpoint = channelAdapter.Endpoint
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
await clientConnection.RunAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -151,11 +149,12 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (clientConnection.Id != null && !clientConnection.IsTakenOver)
|
||||
{
|
||||
// The event is fired at a separate place in case of a handover!
|
||||
await _eventDispatcher.SafeNotifyClientDisconnectedAsync(
|
||||
clientConnection.Id,
|
||||
clientConnection.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean,
|
||||
endpoint).ConfigureAwait(false);
|
||||
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new MqttServerClientDisconnectedEventArgs
|
||||
{
|
||||
ClientId = clientConnection.Id,
|
||||
DisconnectType = clientConnection.IsCleanDisconnect ? MqttClientDisconnectType.Clean : MqttClientDisconnectType.NotClean,
|
||||
Endpoint = endpoint
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,12 +327,10 @@ namespace MQTTnet.Server.Internal
|
||||
// }
|
||||
// }
|
||||
|
||||
public async Task DispatchPublishPacket(MqttApplicationMessage applicationMessage, MqttClientConnection sender)
|
||||
public async Task DispatchPublishPacket(string senderClientId, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
var senderClientId = sender?.Id ?? _options.ClientId;
|
||||
|
||||
// MqttPendingApplicationMessage pendingApplicationMessage;
|
||||
// try
|
||||
// {
|
||||
@@ -381,8 +378,10 @@ namespace MQTTnet.Server.Internal
|
||||
// }
|
||||
// }
|
||||
|
||||
await _eventDispatcher.SafeNotifyApplicationMessageReceivedAsync(senderClientId, applicationMessage).ConfigureAwait(false);
|
||||
|
||||
// await _eventContainer.ApplicationMessageReceivedEvent.InvokeAsync(
|
||||
// () => new MqttApplicationMessageReceivedEventArgs(senderClientId, applicationMessage, null, null))
|
||||
// .ConfigureAwait(false);
|
||||
|
||||
if (applicationMessage.Retain)
|
||||
{
|
||||
await _retainedMessagesManager.HandleMessageAsync(senderClientId, applicationMessage).ConfigureAwait(false);
|
||||
@@ -442,14 +441,15 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (deliveryCount == 0)
|
||||
{
|
||||
var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor;
|
||||
if (undeliveredMessageInterceptor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The delegate signature is the same as for regular message interceptor. So the call is fine and just uses a different interceptor.
|
||||
await InterceptApplicationMessageAsync(undeliveredMessageInterceptor, sender, applicationMessage).ConfigureAwait(false);
|
||||
// TODO: Addd event for not delivered publish packets.
|
||||
// var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor;
|
||||
// if (undeliveredMessageInterceptor == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // The delegate signature is the same as for regular message interceptor. So the call is fine and just uses a different interceptor.
|
||||
// await InterceptApplicationMessageAsync(undeliveredMessageInterceptor, sender, applicationMessage).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
@@ -458,22 +458,14 @@ namespace MQTTnet.Server.Internal
|
||||
}
|
||||
}
|
||||
|
||||
async Task<MqttConnectionValidatorContext> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
||||
async Task<ValidatingMqttClientConnectionEventArgs> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
||||
{
|
||||
var context = new MqttConnectionValidatorContext(connectPacket, channelAdapter)
|
||||
var context = new ValidatingMqttClientConnectionEventArgs(connectPacket, channelAdapter)
|
||||
{
|
||||
SessionItems = new ConcurrentDictionary<object, object>()
|
||||
};
|
||||
|
||||
var connectionValidator = _options.ConnectionValidator;
|
||||
|
||||
if (connectionValidator == null)
|
||||
{
|
||||
context.ReasonCode = MqttConnectReasonCode.Success;
|
||||
return context;
|
||||
}
|
||||
|
||||
await connectionValidator.ValidateConnectionAsync(context).ConfigureAwait(false);
|
||||
|
||||
await _eventContainer.ValidatingClientConnectionEvent.InvokeAsync(context).ConfigureAwait(false);
|
||||
|
||||
// Check the client ID and set a random one if supported.
|
||||
if (string.IsNullOrEmpty(connectPacket.ClientId) && channelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500)
|
||||
@@ -537,7 +529,12 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (existingConnection != null)
|
||||
{
|
||||
await _eventDispatcher.SafeNotifyClientDisconnectedAsync(existingConnection.Id, MqttClientDisconnectType.Takeover, existingConnection.Endpoint);
|
||||
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(() => new MqttServerClientDisconnectedEventArgs
|
||||
{
|
||||
ClientId = existingConnection.Id,
|
||||
DisconnectType = MqttClientDisconnectType.Takeover,
|
||||
Endpoint = existingConnection.Endpoint
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
existingConnection.IsTakenOver = true;
|
||||
await existingConnection.StopAsync(MqttClientDisconnectReason.SessionTakenOver).ConfigureAwait(false);
|
||||
@@ -547,38 +544,38 @@ namespace MQTTnet.Server.Internal
|
||||
return connection;
|
||||
}
|
||||
|
||||
async Task<MqttApplicationMessageInterceptorContext> InterceptApplicationMessageAsync(
|
||||
IMqttServerApplicationMessageInterceptor interceptor,
|
||||
MqttClientConnection clientConnection,
|
||||
MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
string senderClientId;
|
||||
IDictionary<object, object> sessionItems;
|
||||
|
||||
var messageIsFromServer = clientConnection == null;
|
||||
if (messageIsFromServer)
|
||||
{
|
||||
senderClientId = _options.ClientId;
|
||||
sessionItems = _serverSessionItems;
|
||||
}
|
||||
else
|
||||
{
|
||||
senderClientId = clientConnection.Id;
|
||||
sessionItems = clientConnection.Session.Items;
|
||||
}
|
||||
|
||||
var interceptorContext = new MqttApplicationMessageInterceptorContext
|
||||
{
|
||||
ClientId = senderClientId,
|
||||
SessionItems = sessionItems,
|
||||
ProcessPublish = true,
|
||||
ApplicationMessage = applicationMessage,
|
||||
CloseConnection = false
|
||||
};
|
||||
|
||||
await interceptor.InterceptApplicationMessagePublishAsync(interceptorContext).ConfigureAwait(false);
|
||||
return interceptorContext;
|
||||
}
|
||||
// async Task<InterceptingMqttClientPublishEventArgs> InterceptApplicationMessageAsync(
|
||||
// IMqttServerApplicationMessageInterceptor interceptor,
|
||||
// MqttClientConnection clientConnection,
|
||||
// MqttApplicationMessage applicationMessage)
|
||||
// {
|
||||
// string senderClientId;
|
||||
// IDictionary<object, object> sessionItems;
|
||||
//
|
||||
// var messageIsFromServer = clientConnection == null;
|
||||
// if (messageIsFromServer)
|
||||
// {
|
||||
// senderClientId = _options.ClientId;
|
||||
// sessionItems = _serverSessionItems;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// senderClientId = clientConnection.Id;
|
||||
// sessionItems = clientConnection.Session.Items;
|
||||
// }
|
||||
//
|
||||
// var interceptorContext = new InterceptingMqttClientPublishEventArgs
|
||||
// {
|
||||
// ClientId = senderClientId,
|
||||
// SessionItems = sessionItems,
|
||||
// ProcessPublish = true,
|
||||
// ApplicationMessage = applicationMessage,
|
||||
// CloseConnection = false
|
||||
// };
|
||||
//
|
||||
// await interceptor.InterceptApplicationMessagePublishAsync(interceptorContext).ConfigureAwait(false);
|
||||
// return interceptorContext;
|
||||
// }
|
||||
|
||||
MqttClientSession GetClientSession(string clientId)
|
||||
{
|
||||
@@ -600,6 +597,7 @@ namespace MQTTnet.Server.Internal
|
||||
channelAdapter,
|
||||
session,
|
||||
_options,
|
||||
_eventContainer,
|
||||
this,
|
||||
_rootLogger);
|
||||
}
|
||||
@@ -609,10 +607,25 @@ namespace MQTTnet.Server.Internal
|
||||
return new MqttClientSession(
|
||||
clientId,
|
||||
sessionItems,
|
||||
_eventDispatcher,
|
||||
_options,
|
||||
_eventContainer,
|
||||
_retainedMessagesManager,
|
||||
this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_createConnectionSyncRoot?.Dispose();
|
||||
|
||||
foreach (var clientConnection in _clientConnections.Values)
|
||||
{
|
||||
clientConnection.Dispose();
|
||||
}
|
||||
|
||||
foreach (var session in _clientSessions.Values)
|
||||
{
|
||||
session.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server.Status;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
@@ -18,19 +17,19 @@ namespace MQTTnet.Server.Internal
|
||||
readonly Dictionary<string, MqttSubscription> _subscriptions = new Dictionary<string, MqttSubscription>(4096);
|
||||
|
||||
readonly MqttClientSession _clientSession;
|
||||
readonly IMqttServerOptions _options;
|
||||
readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
readonly MqttServerOptions _options;
|
||||
readonly MqttServerEventContainer _eventContainer;
|
||||
readonly IMqttRetainedMessagesManager _retainedMessagesManager;
|
||||
|
||||
public MqttClientSubscriptionsManager(
|
||||
MqttClientSession clientSession,
|
||||
IMqttServerOptions serverOptions,
|
||||
MqttServerEventDispatcher eventDispatcher,
|
||||
MqttServerOptions serverOptions,
|
||||
MqttServerEventContainer eventContainer,
|
||||
IMqttRetainedMessagesManager retainedMessagesManager)
|
||||
{
|
||||
_clientSession = clientSession ?? throw new ArgumentNullException(nameof(clientSession));
|
||||
_options = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions));
|
||||
_eventDispatcher = eventDispatcher ?? throw new ArgumentNullException(nameof(eventDispatcher));
|
||||
_eventContainer = eventContainer ?? throw new ArgumentNullException(nameof(eventContainer));
|
||||
_retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager));
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ namespace MQTTnet.Server.Internal
|
||||
}
|
||||
else
|
||||
{
|
||||
result.ReturnCodes.Add((MqttSubscribeReturnCode)interceptorContext.Response.ReasonCode);
|
||||
result.ReturnCodes.Add((MqttSubscribeReturnCode) interceptorContext.Response.ReasonCode);
|
||||
result.ReasonCodes.Add(interceptorContext.Response.ReasonCode);
|
||||
}
|
||||
|
||||
@@ -75,16 +74,18 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (interceptorContext.ProcessSubscription)
|
||||
{
|
||||
var subscription = CreateSubscription(
|
||||
var createSubscriptionResult = CreateSubscription(
|
||||
finalTopicFilter,
|
||||
subscribePacket.Properties?.SubscriptionIdentifier ?? 0,
|
||||
interceptorContext.Response.ReasonCode);
|
||||
|
||||
await _eventDispatcher
|
||||
.SafeNotifyClientSubscribedTopicAsync(_clientSession.Id, finalTopicFilter)
|
||||
.ConfigureAwait(false);
|
||||
await _eventContainer.ClientSubscribedTopicEvent.InvokeAsync(() => new MqttServerClientSubscribedTopicEventArgs
|
||||
{
|
||||
ClientId = _clientSession.Id,
|
||||
TopicFilter = finalTopicFilter
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
FilterRetainedApplicationMessages(retainedApplicationMessages, subscription, result);
|
||||
FilterRetainedApplicationMessages(retainedApplicationMessages, createSubscriptionResult, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +135,11 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
foreach (var topicFilter in unsubscribePacket.TopicFilters)
|
||||
{
|
||||
await _eventDispatcher.SafeNotifyClientUnsubscribedTopicAsync(_clientSession.Id, topicFilter).ConfigureAwait(false);
|
||||
await _eventContainer.ClientUnsubscribedTopicEvent.InvokeAsync(() => new MqttServerClientUnsubscribedTopicEventArgs
|
||||
{
|
||||
ClientId = _clientSession.Id,
|
||||
TopicFilter = topicFilter
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -201,7 +206,14 @@ namespace MQTTnet.Server.Internal
|
||||
};
|
||||
}
|
||||
|
||||
MqttSubscription CreateSubscription(MqttTopicFilter topicFilter, uint subscriptionIdentifier, MqttSubscribeReasonCode reasonCode)
|
||||
public sealed class CreateSubscriptionResult
|
||||
{
|
||||
public MqttSubscription Subscription { get; set; }
|
||||
|
||||
public bool IsNewSubscription { get; set; }
|
||||
}
|
||||
|
||||
CreateSubscriptionResult CreateSubscription(MqttTopicFilter topicFilter, uint subscriptionIdentifier, MqttSubscribeReasonCode reasonCode)
|
||||
{
|
||||
var subscription = new MqttSubscription
|
||||
{
|
||||
@@ -229,10 +241,12 @@ namespace MQTTnet.Server.Internal
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
bool isNewSubscription;
|
||||
|
||||
_subscriptionsLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
subscription.IsNewSubscription = !_subscriptions.ContainsKey(topicFilter.Topic);
|
||||
isNewSubscription = !_subscriptions.ContainsKey(topicFilter.Topic);
|
||||
_subscriptions[topicFilter.Topic] = subscription;
|
||||
}
|
||||
finally
|
||||
@@ -240,11 +254,15 @@ namespace MQTTnet.Server.Internal
|
||||
_subscriptionsLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
return subscription;
|
||||
return new CreateSubscriptionResult
|
||||
{
|
||||
IsNewSubscription = isNewSubscription,
|
||||
Subscription = subscription
|
||||
};
|
||||
}
|
||||
|
||||
static void FilterRetainedApplicationMessages(IList<MqttApplicationMessage> retainedApplicationMessages,
|
||||
MqttSubscription mqttSubscription, MqttSubscribeResult mqttSubscribeResult)
|
||||
static void FilterRetainedApplicationMessages(IList<MqttApplicationMessage> retainedApplicationMessages, CreateSubscriptionResult createSubscriptionResult,
|
||||
MqttSubscribeResult subscribeResult)
|
||||
{
|
||||
for (var i = retainedApplicationMessages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -254,20 +272,20 @@ namespace MQTTnet.Server.Internal
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mqttSubscription.RetainHandling == MqttRetainHandling.DoNotSendOnSubscribe)
|
||||
if (createSubscriptionResult.Subscription.RetainHandling == MqttRetainHandling.DoNotSendOnSubscribe)
|
||||
{
|
||||
// This is a MQTT V5+ feature.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mqttSubscription.RetainHandling == MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly &&
|
||||
!mqttSubscription.IsNewSubscription)
|
||||
if (createSubscriptionResult.Subscription.RetainHandling == MqttRetainHandling.SendAtSubscribeIfNewSubscriptionOnly &&
|
||||
!createSubscriptionResult.IsNewSubscription)
|
||||
{
|
||||
// This is a MQTT V5+ feature.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MqttTopicFilterComparer.Compare(retainedApplicationMessage.Topic, mqttSubscription.Topic) !=
|
||||
if (MqttTopicFilterComparer.Compare(retainedApplicationMessage.Topic, createSubscriptionResult.Subscription.Topic) !=
|
||||
MqttTopicFilterCompareResult.IsMatch)
|
||||
{
|
||||
continue;
|
||||
@@ -277,23 +295,23 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
ApplicationMessage = retainedApplicationMessage,
|
||||
IsRetainedMessage = true,
|
||||
SubscriptionQualityOfServiceLevel = mqttSubscription.GrantedQualityOfServiceLevel
|
||||
SubscriptionQualityOfServiceLevel = createSubscriptionResult.Subscription.GrantedQualityOfServiceLevel
|
||||
};
|
||||
|
||||
if (mqttSubscription.Identifier > 0)
|
||||
if (createSubscriptionResult.Subscription.Identifier > 0)
|
||||
{
|
||||
queuedApplicationMessage.SubscriptionIdentifiers = new List<uint> {mqttSubscription.Identifier};
|
||||
queuedApplicationMessage.SubscriptionIdentifiers = new List<uint> {createSubscriptionResult.Subscription.Identifier};
|
||||
}
|
||||
|
||||
mqttSubscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage);
|
||||
subscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage);
|
||||
|
||||
retainedApplicationMessages[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<MqttSubscriptionInterceptorContext> InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken)
|
||||
async Task<InterceptingMqttClientSubscriptionEventArgs> InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken)
|
||||
{
|
||||
var context = new MqttSubscriptionInterceptorContext
|
||||
var subscriptionReceivedEventArgs = new InterceptingMqttClientSubscriptionEventArgs
|
||||
{
|
||||
ClientId = _clientSession.Id,
|
||||
TopicFilter = topicFilter,
|
||||
@@ -304,36 +322,32 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
|
||||
{
|
||||
context.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS0;
|
||||
subscriptionReceivedEventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS0;
|
||||
}
|
||||
else if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
|
||||
{
|
||||
context.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS1;
|
||||
subscriptionReceivedEventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS1;
|
||||
}
|
||||
else if (topicFilter.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
|
||||
{
|
||||
context.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS2;
|
||||
subscriptionReceivedEventArgs.Response.ReasonCode = MqttSubscribeReasonCode.GrantedQoS2;
|
||||
}
|
||||
|
||||
|
||||
if (topicFilter.Topic.StartsWith("$share/"))
|
||||
{
|
||||
context.Response.ReasonCode = MqttSubscribeReasonCode.SharedSubscriptionsNotSupported;
|
||||
subscriptionReceivedEventArgs.Response.ReasonCode = MqttSubscribeReasonCode.SharedSubscriptionsNotSupported;
|
||||
}
|
||||
else
|
||||
{
|
||||
var interceptor = _options.SubscriptionInterceptor;
|
||||
if (interceptor != null)
|
||||
{
|
||||
await interceptor.InterceptSubscriptionAsync(context).ConfigureAwait(false);
|
||||
}
|
||||
await _eventContainer.InterceptingClientSubscriptionEvent.InvokeAsync(subscriptionReceivedEventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return context;
|
||||
return subscriptionReceivedEventArgs;
|
||||
}
|
||||
|
||||
async Task<MqttUnsubscriptionInterceptorContext> InterceptUnsubscribe(string topicFilter, MqttSubscription mqttSubscription, CancellationToken cancellationToken)
|
||||
async Task<InterceptingMqttClientUnsubscriptionEventArgs> InterceptUnsubscribe(string topicFilter, MqttSubscription mqttSubscription, CancellationToken cancellationToken)
|
||||
{
|
||||
var context = new MqttUnsubscriptionInterceptorContext
|
||||
var clientUnsubscribingTopicEventArgs = new InterceptingMqttClientUnsubscriptionEventArgs
|
||||
{
|
||||
ClientId = _clientSession.Id,
|
||||
Topic = topicFilter,
|
||||
@@ -343,22 +357,16 @@ namespace MQTTnet.Server.Internal
|
||||
|
||||
if (mqttSubscription == null)
|
||||
{
|
||||
context.Response.ReasonCode = MqttUnsubscribeReasonCode.NoSubscriptionExisted;
|
||||
clientUnsubscribingTopicEventArgs.Response.ReasonCode = MqttUnsubscribeReasonCode.NoSubscriptionExisted;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.ReasonCode = MqttUnsubscribeReasonCode.Success;
|
||||
clientUnsubscribingTopicEventArgs.Response.ReasonCode = MqttUnsubscribeReasonCode.Success;
|
||||
}
|
||||
|
||||
var interceptor = _options.UnsubscriptionInterceptor;
|
||||
if (interceptor == null)
|
||||
{
|
||||
return context;
|
||||
}
|
||||
await _eventContainer.InterceptingClientUnsubscriptionEvent.InvokeAsync(clientUnsubscribingTopicEventArgs).ConfigureAwait(false);
|
||||
|
||||
await interceptor.InterceptUnsubscriptionAsync(context).ConfigureAwait(false);
|
||||
|
||||
return context;
|
||||
return clientUnsubscribingTopicEventArgs;
|
||||
}
|
||||
|
||||
static MqttQualityOfServiceLevel GetEffectiveQoS(MqttQualityOfServiceLevel qosLevel, ICollection<MqttQualityOfServiceLevel> subscribedQoSLevels)
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
@@ -16,10 +15,10 @@ namespace MQTTnet.Server.Internal
|
||||
readonly Dictionary<string, MqttApplicationMessage> _messages = new Dictionary<string, MqttApplicationMessage>(4096);
|
||||
|
||||
MqttNetSourceLogger _logger;
|
||||
IMqttServerOptions _options;
|
||||
MqttServerOptions _options;
|
||||
|
||||
// TODO: Get rid of the logger here!
|
||||
public Task Start(IMqttServerOptions options, IMqttNetLogger logger)
|
||||
public Task Start(MqttServerOptions options, IMqttNetLogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.WithSource(nameof(MqttRetainedMessagesManager));
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttServerEventContainer
|
||||
{
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
|
||||
public MqttServerEventContainer(IMqttNetLogger logger)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
_logger = logger.WithSource(nameof(MqttServerEventContainer));
|
||||
}
|
||||
|
||||
public AsyncEvent<InterceptingMqttClientSubscriptionEventArgs> InterceptingClientSubscriptionEvent { get; } = new AsyncEvent<InterceptingMqttClientSubscriptionEventArgs>();
|
||||
|
||||
public AsyncEvent<InterceptingMqttClientUnsubscriptionEventArgs> InterceptingClientUnsubscriptionEvent { get; } = new AsyncEvent<InterceptingMqttClientUnsubscriptionEventArgs>();
|
||||
|
||||
public AsyncEvent<InterceptingMqttClientPublishEventArgs> InterceptingClientPublishEvent { get; } = new AsyncEvent<InterceptingMqttClientPublishEventArgs>();
|
||||
|
||||
public AsyncEvent<ValidatingMqttClientConnectionEventArgs> ValidatingClientConnectionEvent { get; } = new AsyncEvent<ValidatingMqttClientConnectionEventArgs>();
|
||||
public AsyncEvent<MqttServerClientConnectedEventArgs> ClientConnectedEvent { get; } = new AsyncEvent<MqttServerClientConnectedEventArgs>();
|
||||
public AsyncEvent<MqttServerClientDisconnectedEventArgs> ClientDisconnectedEvent { get; } = new AsyncEvent<MqttServerClientDisconnectedEventArgs>();
|
||||
public AsyncEvent<MqttServerClientSubscribedTopicEventArgs> ClientSubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientSubscribedTopicEventArgs>();
|
||||
public AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs> ClientUnsubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs>();
|
||||
|
||||
public AsyncEvent<PreparingMqttClientSessionEventArgs> PreparingClientSessionEvent { get; } = new AsyncEvent<PreparingMqttClientSessionEventArgs>();
|
||||
public AsyncEvent<EventArgs> StartedEvent { get; } = new AsyncEvent<EventArgs>();
|
||||
|
||||
public AsyncEvent<EventArgs> StoppedEvent { get; } = new AsyncEvent<EventArgs>();
|
||||
|
||||
// public async Task SafeNotifyClientConnectedAsync(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var eventArgs = new MqttServerClientConnectedEventArgs
|
||||
// {
|
||||
// ClientId = connectPacket.ClientId,
|
||||
// UserName = connectPacket.Username,
|
||||
// ProtocolVersion = channelAdapter.PacketFormatterAdapter.ProtocolVersion,
|
||||
// Endpoint = channelAdapter.Endpoint
|
||||
// };
|
||||
//
|
||||
// var handler = ClientConnectedHandler;
|
||||
// if (handler != null)
|
||||
// {
|
||||
// await handler.HandleClientConnectedAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
//
|
||||
// await ClientConnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
// catch (Exception exception)
|
||||
// {
|
||||
// _logger.Error(exception, "Error while handling custom 'ClientConnected' event.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public async Task SafeNotifyClientDisconnectedAsync(string clientId, MqttClientDisconnectType disconnectType, string endpoint)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var eventArgs = new MqttServerClientDisconnectedEventArgs
|
||||
// {
|
||||
// ClientId = clientId,
|
||||
// DisconnectType = disconnectType,
|
||||
// Endpoint = endpoint
|
||||
// };
|
||||
//
|
||||
// var handler = ClientDisconnectedHandler;
|
||||
// if (handler != null)
|
||||
// {
|
||||
// await handler.HandleClientDisconnectedAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
//
|
||||
// await ClientDisconnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
// catch (Exception exception)
|
||||
// {
|
||||
// _logger.Error(exception, "Error while handling custom 'ClientDisconnected' event.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public async Task SafeNotifyClientSubscribedTopicAsync(string clientId, MqttTopicFilter topicFilter)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var eventArgs = new MqttServerClientSubscribedTopicEventArgs
|
||||
// {
|
||||
// ClientId = clientId,
|
||||
// TopicFilter = topicFilter
|
||||
// };
|
||||
//
|
||||
// var handler = ClientSubscribedTopicHandler;
|
||||
// if (handler != null)
|
||||
// {
|
||||
// await handler.HandleClientSubscribedTopicAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
//
|
||||
// await ClientSubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
// catch (Exception exception)
|
||||
// {
|
||||
// _logger.Error(exception, "Error while handling custom 'ClientSubscribedTopic' event.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public async Task SafeNotifyClientUnsubscribedTopicAsync(string clientId, string topicFilter)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var eventArgs = new MqttServerClientUnsubscribedTopicEventArgs
|
||||
// {
|
||||
// ClientId = clientId,
|
||||
// TopicFilter = topicFilter
|
||||
// };
|
||||
//
|
||||
// var handler = ClientUnsubscribedTopicHandler;
|
||||
// if (handler != null)
|
||||
// {
|
||||
// await handler.HandleClientUnsubscribedTopicAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
//
|
||||
// await ClientUnsubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
// catch (Exception exception)
|
||||
// {
|
||||
// _logger.Error(exception, "Error while handling custom 'ClientUnsubscribedTopic' event.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public async Task SafeNotifyApplicationMessageReceivedAsync(string senderClientId, MqttApplicationMessage applicationMessage)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientId, applicationMessage, null, null);
|
||||
//
|
||||
// var handler = ApplicationMessageReceivedHandler;
|
||||
// if (handler != null)
|
||||
// {
|
||||
// await handler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
//
|
||||
// await ApplicationMessageReceivedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
// }
|
||||
// catch (Exception exception)
|
||||
// {
|
||||
// _logger.Error(exception, "Error while handling custom 'ApplicationMessageReceived' event.");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttServerEventDispatcher
|
||||
{
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
|
||||
public MqttServerEventDispatcher(IMqttNetLogger logger)
|
||||
{
|
||||
if (logger is null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
_logger = logger.WithSource(nameof(MqttServerEventDispatcher));
|
||||
}
|
||||
|
||||
public AsyncEvent<MqttServerClientConnectedEventArgs> ClientConnectedEvent { get; } = new AsyncEvent<MqttServerClientConnectedEventArgs>();
|
||||
|
||||
public AsyncEvent<MqttServerClientDisconnectedEventArgs> ClientDisconnectedEvent { get; } = new AsyncEvent<MqttServerClientDisconnectedEventArgs>();
|
||||
|
||||
public AsyncEvent<MqttServerClientSubscribedTopicEventArgs> ClientSubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientSubscribedTopicEventArgs>();
|
||||
|
||||
public AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs> ClientUnsubscribedTopicEvent { get; } = new AsyncEvent<MqttServerClientUnsubscribedTopicEventArgs>();
|
||||
|
||||
public AsyncEvent<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceivedEvent { get; } = new AsyncEvent<MqttApplicationMessageReceivedEventArgs>();
|
||||
|
||||
public IMqttServerClientConnectedHandler ClientConnectedHandler { get; set; }
|
||||
|
||||
public IMqttServerClientDisconnectedHandler ClientDisconnectedHandler { get; set; }
|
||||
|
||||
public IMqttServerClientSubscribedTopicHandler ClientSubscribedTopicHandler { get; set; }
|
||||
|
||||
public IMqttServerClientUnsubscribedTopicHandler ClientUnsubscribedTopicHandler { get; set; }
|
||||
|
||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler { get; set; }
|
||||
|
||||
public async Task SafeNotifyClientConnectedAsync(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArgs = new MqttServerClientConnectedEventArgs
|
||||
{
|
||||
ClientId = connectPacket.ClientId,
|
||||
UserName = connectPacket.Username,
|
||||
ProtocolVersion = channelAdapter.PacketFormatterAdapter.ProtocolVersion,
|
||||
Endpoint = channelAdapter.Endpoint
|
||||
};
|
||||
|
||||
var handler = ClientConnectedHandler;
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleClientConnectedAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ClientConnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling custom 'ClientConnected' event.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SafeNotifyClientDisconnectedAsync(string clientId, MqttClientDisconnectType disconnectType, string endpoint)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArgs = new MqttServerClientDisconnectedEventArgs
|
||||
{
|
||||
ClientId = clientId,
|
||||
DisconnectType = disconnectType,
|
||||
Endpoint = endpoint
|
||||
};
|
||||
|
||||
var handler = ClientDisconnectedHandler;
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleClientDisconnectedAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ClientDisconnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling custom 'ClientDisconnected' event.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SafeNotifyClientSubscribedTopicAsync(string clientId, MqttTopicFilter topicFilter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArgs = new MqttServerClientSubscribedTopicEventArgs
|
||||
{
|
||||
ClientId = clientId,
|
||||
TopicFilter = topicFilter
|
||||
};
|
||||
|
||||
var handler = ClientSubscribedTopicHandler;
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleClientSubscribedTopicAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ClientSubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling custom 'ClientSubscribedTopic' event.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SafeNotifyClientUnsubscribedTopicAsync(string clientId, string topicFilter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArgs = new MqttServerClientUnsubscribedTopicEventArgs
|
||||
{
|
||||
ClientId = clientId,
|
||||
TopicFilter = topicFilter
|
||||
};
|
||||
|
||||
var handler = ClientUnsubscribedTopicHandler;
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleClientUnsubscribedTopicAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ClientUnsubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling custom 'ClientUnsubscribedTopic' event.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SafeNotifyApplicationMessageReceivedAsync(string senderClientId, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientId, applicationMessage, null, null);
|
||||
|
||||
var handler = ApplicationMessageReceivedHandler;
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleApplicationMessageReceivedAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ApplicationMessageReceivedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Error(exception, "Error while handling custom 'ApplicationMessageReceived' event.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,11 @@ namespace MQTTnet.Server.Internal
|
||||
{
|
||||
public sealed class MqttServerKeepAliveMonitor
|
||||
{
|
||||
readonly IMqttServerOptions _options;
|
||||
readonly MqttServerOptions _options;
|
||||
readonly MqttClientSessionsManager _sessionsManager;
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
|
||||
public MqttServerKeepAliveMonitor(IMqttServerOptions options, MqttClientSessionsManager sessionsManager, IMqttNetLogger logger)
|
||||
public MqttServerKeepAliveMonitor(MqttServerOptions options, MqttClientSessionsManager sessionsManager, IMqttNetLogger logger)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
|
||||
|
||||
@@ -15,7 +15,5 @@ namespace MQTTnet.Server.Internal
|
||||
public MqttQualityOfServiceLevel GrantedQualityOfServiceLevel { get; set; }
|
||||
|
||||
public uint Identifier { get; set; }
|
||||
|
||||
public bool IsNewSubscription { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttClientMessageQueueInterceptorDelegate : IMqttServerClientMessageQueueInterceptor
|
||||
{
|
||||
readonly Func<MqttClientMessageQueueInterceptorContext, Task> _callback;
|
||||
|
||||
public MqttClientMessageQueueInterceptorDelegate(Action<MqttClientMessageQueueInterceptorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttClientMessageQueueInterceptorDelegate(Func<MqttClientMessageQueueInterceptorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task InterceptClientMessageQueueEnqueueAsync(MqttClientMessageQueueInterceptorContext context)
|
||||
{
|
||||
return _callback(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttPendingApplicationMessage
|
||||
{
|
||||
public MqttPendingApplicationMessage(MqttPublishPacket publishPacket, MqttClientConnection sender)
|
||||
{
|
||||
Sender = sender;
|
||||
PublishPacket = publishPacket;
|
||||
}
|
||||
|
||||
public MqttClientConnection Sender { get; }
|
||||
|
||||
public MqttPublishPacket PublishPacket { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server.Status;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -16,13 +14,12 @@ using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServer : Disposable, IMqttServer
|
||||
public class MqttServer : Disposable, IMqttServer
|
||||
{
|
||||
readonly AsyncEvent<EventArgs> _startedEvent = new AsyncEvent<EventArgs>();
|
||||
readonly AsyncEvent<EventArgs> _stoppedEvent = new AsyncEvent<EventArgs>();
|
||||
readonly MqttServerEventContainer _eventContainer;
|
||||
|
||||
readonly MqttServerEventDispatcher _eventDispatcher;
|
||||
readonly ICollection<IMqttServerAdapter> _adapters;
|
||||
readonly MqttServerOptions _options;
|
||||
readonly IMqttNetLogger _rootLogger;
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
|
||||
@@ -31,98 +28,87 @@ namespace MQTTnet.Server
|
||||
MqttServerKeepAliveMonitor _keepAliveMonitor;
|
||||
CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
public MqttServer(IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||
public MqttServer(MqttServerOptions options, IEnumerable<IMqttServerAdapter> adapters, IMqttNetLogger logger)
|
||||
{
|
||||
if (adapters == null) throw new ArgumentNullException(nameof(adapters));
|
||||
_adapters = adapters.ToList();
|
||||
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
_logger = logger.WithSource(nameof(MqttServer));
|
||||
_options = options;
|
||||
_rootLogger = logger;
|
||||
|
||||
_eventDispatcher = new MqttServerEventDispatcher(logger);
|
||||
_eventContainer = new MqttServerEventContainer(logger);
|
||||
}
|
||||
|
||||
public bool IsStarted => _cancellationTokenSource != null;
|
||||
|
||||
public IMqttServerStartedHandler StartedHandler { get; set; }
|
||||
|
||||
public event Func<EventArgs, Task> StartedAsync
|
||||
{
|
||||
add => _startedEvent.AddHandler(value);
|
||||
remove => _startedEvent.RemoveHandler(value);
|
||||
add => _eventContainer.StartedEvent.AddHandler(value);
|
||||
remove => _eventContainer.StartedEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerStoppedHandler StoppedHandler { get; set; }
|
||||
|
||||
|
||||
public event Func<EventArgs, Task> StoppedAsync
|
||||
{
|
||||
add => _stoppedEvent.AddHandler(value);
|
||||
remove => _stoppedEvent.RemoveHandler(value);
|
||||
add => _eventContainer.StoppedEvent.AddHandler(value);
|
||||
remove => _eventContainer.StoppedEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerClientConnectedHandler ClientConnectedHandler
|
||||
public event Func<ValidatingMqttClientConnectionEventArgs, Task> ValidatingClientConnectionAsync
|
||||
{
|
||||
get => _eventDispatcher.ClientConnectedHandler;
|
||||
set => _eventDispatcher.ClientConnectedHandler = value;
|
||||
add => _eventContainer.ValidatingClientConnectionEvent.AddHandler(value);
|
||||
remove => _eventContainer.ValidatingClientConnectionEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
|
||||
public event Func<MqttServerClientConnectedEventArgs, Task> ClientConnectedAsync
|
||||
{
|
||||
add => _eventDispatcher.ClientConnectedEvent.AddHandler(value);
|
||||
remove => _eventDispatcher.ClientConnectedEvent.RemoveHandler(value);
|
||||
add => _eventContainer.ClientConnectedEvent.AddHandler(value);
|
||||
remove => _eventContainer.ClientConnectedEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerClientDisconnectedHandler ClientDisconnectedHandler
|
||||
{
|
||||
get => _eventDispatcher.ClientDisconnectedHandler;
|
||||
set => _eventDispatcher.ClientDisconnectedHandler = value;
|
||||
}
|
||||
|
||||
|
||||
public event Func<MqttServerClientDisconnectedEventArgs, Task> ClientDisconnectedAsync
|
||||
{
|
||||
add => _eventDispatcher.ClientDisconnectedEvent.AddHandler(value);
|
||||
remove => _eventDispatcher.ClientDisconnectedEvent.RemoveHandler(value);
|
||||
add => _eventContainer.ClientDisconnectedEvent.AddHandler(value);
|
||||
remove => _eventContainer.ClientDisconnectedEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerClientSubscribedTopicHandler ClientSubscribedTopicHandler
|
||||
public event Func<InterceptingMqttClientSubscriptionEventArgs, Task> InterceptingClientSubscriptionAsync
|
||||
{
|
||||
get => _eventDispatcher.ClientSubscribedTopicHandler;
|
||||
set => _eventDispatcher.ClientSubscribedTopicHandler = value;
|
||||
add => _eventContainer.InterceptingClientSubscriptionEvent.AddHandler(value);
|
||||
remove => _eventContainer.InterceptingClientSubscriptionEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
|
||||
public event Func<InterceptingMqttClientUnsubscriptionEventArgs, Task> InterceptingClientUnsubscriptionAsync
|
||||
{
|
||||
add => _eventContainer.InterceptingClientUnsubscriptionEvent.AddHandler(value);
|
||||
remove => _eventContainer.InterceptingClientUnsubscriptionEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public event Func<InterceptingMqttClientPublishEventArgs, Task> InterceptingClientPublishAsync
|
||||
{
|
||||
add => _eventContainer.InterceptingClientPublishEvent.AddHandler(value);
|
||||
remove => _eventContainer.InterceptingClientPublishEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public event Func<MqttServerClientSubscribedTopicEventArgs, Task> ClientSubscribedTopicAsync
|
||||
{
|
||||
add => _eventDispatcher.ClientSubscribedTopicEvent.AddHandler(value);
|
||||
remove => _eventDispatcher.ClientSubscribedTopicEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerClientUnsubscribedTopicHandler ClientUnsubscribedTopicHandler
|
||||
{
|
||||
get => _eventDispatcher.ClientUnsubscribedTopicHandler;
|
||||
set => _eventDispatcher.ClientUnsubscribedTopicHandler = value;
|
||||
add => _eventContainer.ClientSubscribedTopicEvent.AddHandler(value);
|
||||
remove => _eventContainer.ClientSubscribedTopicEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public event Func<MqttServerClientUnsubscribedTopicEventArgs, Task> ClientUnsubscribedTopicAsync
|
||||
{
|
||||
add => _eventDispatcher.ClientUnsubscribedTopicEvent.AddHandler(value);
|
||||
remove => _eventDispatcher.ClientUnsubscribedTopicEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
|
||||
{
|
||||
get => _eventDispatcher.ApplicationMessageReceivedHandler;
|
||||
set => _eventDispatcher.ApplicationMessageReceivedHandler = value;
|
||||
add => _eventContainer.ClientUnsubscribedTopicEvent.AddHandler(value);
|
||||
remove => _eventContainer.ClientUnsubscribedTopicEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public event Func<MqttApplicationMessageReceivedEventArgs, Task> ApplicationMessageReceivedAsync
|
||||
public event Func<PreparingMqttClientSessionEventArgs, Task> PreparingClientSessionAsync
|
||||
{
|
||||
add => _eventDispatcher.ApplicationMessageReceivedEvent.AddHandler(value);
|
||||
remove => _eventDispatcher.ApplicationMessageReceivedEvent.RemoveHandler(value);
|
||||
add => _eventContainer.PreparingClientSessionEvent.AddHandler(value);
|
||||
remove => _eventContainer.PreparingClientSessionEvent.RemoveHandler(value);
|
||||
}
|
||||
|
||||
public IMqttServerOptions Options { get; private set; }
|
||||
|
||||
public bool IsStarted => _cancellationTokenSource != null;
|
||||
|
||||
public Task<IList<IMqttClientStatus>> GetClientStatusAsync()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -182,7 +168,7 @@ namespace MQTTnet.Server
|
||||
return _clientSessionsManager.UnsubscribeAsync(clientId, topicFilters);
|
||||
}
|
||||
|
||||
public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||
public async Task<MqttClientPublishResult> PublishAsync(string senderClientId, MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
|
||||
@@ -192,47 +178,38 @@ namespace MQTTnet.Server
|
||||
|
||||
ThrowIfNotStarted();
|
||||
|
||||
await _clientSessionsManager.DispatchPublishPacket(applicationMessage, null);
|
||||
await _clientSessionsManager.DispatchPublishPacket(senderClientId, applicationMessage);
|
||||
|
||||
return new MqttClientPublishResult();
|
||||
}
|
||||
|
||||
public async Task StartAsync(IMqttServerOptions options)
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfStarted();
|
||||
|
||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
var cancellationToken = _cancellationTokenSource.Token;
|
||||
|
||||
_retainedMessagesManager = Options.RetainedMessagesManager ?? throw new MqttConfigurationException("options.RetainedMessagesManager should not be null.");
|
||||
_retainedMessagesManager = _options.RetainedMessagesManager ?? throw new MqttConfigurationException("options.RetainedMessagesManager should not be null.");
|
||||
|
||||
await _retainedMessagesManager.Start(Options, _rootLogger).ConfigureAwait(false);
|
||||
await _retainedMessagesManager.Start(_options, _rootLogger).ConfigureAwait(false);
|
||||
await _retainedMessagesManager.LoadMessagesAsync().ConfigureAwait(false);
|
||||
|
||||
_clientSessionsManager = new MqttClientSessionsManager(Options, _retainedMessagesManager, _eventDispatcher, _rootLogger);
|
||||
//_clientSessionsManager.Start(cancellationToken);
|
||||
|
||||
_keepAliveMonitor = new MqttServerKeepAliveMonitor(Options, _clientSessionsManager, _rootLogger);
|
||||
_clientSessionsManager = new MqttClientSessionsManager(_options, _retainedMessagesManager, _eventContainer, _rootLogger);
|
||||
|
||||
_keepAliveMonitor = new MqttServerKeepAliveMonitor(_options, _clientSessionsManager, _rootLogger);
|
||||
_keepAliveMonitor.Start(cancellationToken);
|
||||
|
||||
foreach (var adapter in _adapters)
|
||||
{
|
||||
adapter.ClientHandler = c => OnHandleClient(c, cancellationToken);
|
||||
await adapter.StartAsync(Options).ConfigureAwait(false);
|
||||
await adapter.StartAsync(_options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_logger.Info("Started.");
|
||||
|
||||
var startedHandler = StartedHandler;
|
||||
if (startedHandler != null)
|
||||
{
|
||||
await startedHandler.HandleServerStartedAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await _startedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
await _eventContainer.StartedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
@@ -267,13 +244,7 @@ namespace MQTTnet.Server
|
||||
_retainedMessagesManager = null;
|
||||
}
|
||||
|
||||
var stoppedHandler = StoppedHandler;
|
||||
if (stoppedHandler != null)
|
||||
{
|
||||
await stoppedHandler.HandleServerStoppedAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await _stoppedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
await _eventContainer.StoppedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerApplicationMessageInterceptorDelegate : IMqttServerApplicationMessageInterceptor
|
||||
{
|
||||
readonly Func<MqttApplicationMessageInterceptorContext, Task> _callback;
|
||||
|
||||
public MqttServerApplicationMessageInterceptorDelegate(Action<MqttApplicationMessageInterceptorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerApplicationMessageInterceptorDelegate(Func<MqttApplicationMessageInterceptorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task InterceptApplicationMessagePublishAsync(MqttApplicationMessageInterceptorContext context)
|
||||
{
|
||||
return _callback(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerClientConnectedHandlerDelegate : IMqttServerClientConnectedHandler
|
||||
{
|
||||
readonly Func<MqttServerClientConnectedEventArgs, Task> _handler;
|
||||
|
||||
public MqttServerClientConnectedHandlerDelegate(Action<MqttServerClientConnectedEventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerClientConnectedHandlerDelegate(Func<MqttServerClientConnectedEventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleClientConnectedAsync(MqttServerClientConnectedEventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerClientDisconnectedHandlerDelegate : IMqttServerClientDisconnectedHandler
|
||||
{
|
||||
readonly Func<MqttServerClientDisconnectedEventArgs, Task> _handler;
|
||||
|
||||
public MqttServerClientDisconnectedHandlerDelegate(Action<MqttServerClientDisconnectedEventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerClientDisconnectedHandlerDelegate(Func<MqttServerClientDisconnectedEventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
[Obsolete("Use MqttServerClientSubscribedTopicHandlerDelegate instead. This will be removed in a future version.")]
|
||||
public sealed class MqttServerClientSubscribedHandlerDelegate : MqttServerClientSubscribedTopicHandlerDelegate
|
||||
{
|
||||
public MqttServerClientSubscribedHandlerDelegate(Action<MqttServerClientSubscribedTopicEventArgs> handler) : base(handler)
|
||||
{
|
||||
}
|
||||
|
||||
public MqttServerClientSubscribedHandlerDelegate(Func<MqttServerClientSubscribedTopicEventArgs, Task> handler) : base(handler)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MqttServerClientSubscribedTopicHandlerDelegate : IMqttServerClientSubscribedTopicHandler
|
||||
{
|
||||
readonly Func<MqttServerClientSubscribedTopicEventArgs, Task> _handler;
|
||||
|
||||
public MqttServerClientSubscribedTopicHandlerDelegate(Action<MqttServerClientSubscribedTopicEventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerClientSubscribedTopicHandlerDelegate(Func<MqttServerClientSubscribedTopicEventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerClientUnsubscribedTopicHandlerDelegate : IMqttServerClientUnsubscribedTopicHandler
|
||||
{
|
||||
readonly Func<MqttServerClientUnsubscribedTopicEventArgs, Task> _handler;
|
||||
|
||||
public MqttServerClientUnsubscribedTopicHandlerDelegate(Action<MqttServerClientUnsubscribedTopicEventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerClientUnsubscribedTopicHandlerDelegate(Func<MqttServerClientUnsubscribedTopicEventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerConnectionValidatorDelegate : IMqttServerConnectionValidator
|
||||
{
|
||||
readonly Func<MqttConnectionValidatorContext, Task> _callback;
|
||||
|
||||
public MqttServerConnectionValidatorDelegate(Action<MqttConnectionValidatorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerConnectionValidatorDelegate(Func<MqttConnectionValidatorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task ValidateConnectionAsync(MqttConnectionValidatorContext context)
|
||||
{
|
||||
return _callback(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Protocol;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -10,102 +8,6 @@ namespace MQTTnet.Server
|
||||
{
|
||||
public static class MqttServerExtensions
|
||||
{
|
||||
public static IMqttServer UseClientConnectedHandler(this IMqttServer server, Func<MqttServerClientConnectedEventArgs, Task> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseClientConnectedHandler((IMqttServerClientConnectedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseClientConnectedHandler(new MqttServerClientConnectedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseClientConnectedHandler(this IMqttServer server, Action<MqttServerClientConnectedEventArgs> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseClientConnectedHandler((IMqttServerClientConnectedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseClientConnectedHandler(new MqttServerClientConnectedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseClientConnectedHandler(this IMqttServer server, IMqttServerClientConnectedHandler handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
server.ClientConnectedHandler = handler;
|
||||
return server;
|
||||
}
|
||||
|
||||
public static IMqttServer UseClientDisconnectedHandler(this IMqttServer server, Func<MqttServerClientDisconnectedEventArgs, Task> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseClientDisconnectedHandler((IMqttServerClientDisconnectedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseClientDisconnectedHandler(new MqttServerClientDisconnectedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseClientDisconnectedHandler(this IMqttServer server, Action<MqttServerClientDisconnectedEventArgs> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseClientDisconnectedHandler((IMqttServerClientDisconnectedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseClientDisconnectedHandler(new MqttServerClientDisconnectedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseClientDisconnectedHandler(this IMqttServer server, IMqttServerClientDisconnectedHandler handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
server.ClientDisconnectedHandler = handler;
|
||||
return server;
|
||||
}
|
||||
|
||||
public static IMqttServer UseApplicationMessageReceivedHandler(this IMqttServer server, Func<MqttApplicationMessageReceivedEventArgs, Task> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseApplicationMessageReceivedHandler(this IMqttServer server, Action<MqttApplicationMessageReceivedEventArgs> handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return server.UseApplicationMessageReceivedHandler((IMqttApplicationMessageReceivedHandler)null);
|
||||
}
|
||||
|
||||
return server.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(handler));
|
||||
}
|
||||
|
||||
public static IMqttServer UseApplicationMessageReceivedHandler(this IMqttServer server, IMqttApplicationMessageReceivedHandler handler)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
|
||||
server.ApplicationMessageReceivedHandler = handler;
|
||||
return server;
|
||||
}
|
||||
|
||||
public static Task SubscribeAsync(this IMqttServer server, string clientId, params MqttTopicFilter[] topicFilters)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
@@ -142,92 +44,92 @@ namespace MQTTnet.Server
|
||||
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));
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
|
||||
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, MqttApplicationMessage applicationMessage)
|
||||
{
|
||||
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
|
||||
// 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));
|
||||
// }
|
||||
|
||||
return server.PublishAsync(applicationMessage, CancellationToken.None);
|
||||
}
|
||||
// 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 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));
|
||||
// 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));
|
||||
// }
|
||||
|
||||
foreach (var applicationMessage in applicationMessages)
|
||||
{
|
||||
await server.PublishAsync(applicationMessage, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
// 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, 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);
|
||||
}
|
||||
// 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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerMultiThreadedApplicationMessageInterceptorDelegate : IMqttServerApplicationMessageInterceptor
|
||||
{
|
||||
readonly Func<MqttApplicationMessageInterceptorContext, Task> _callback;
|
||||
|
||||
public MqttServerMultiThreadedApplicationMessageInterceptorDelegate(Action<MqttApplicationMessageInterceptorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public Func<MqttApplicationMessageInterceptorContext, Exception, Task> ExceptionHandler { get; set; }
|
||||
|
||||
public MqttServerMultiThreadedApplicationMessageInterceptorDelegate(Func<MqttApplicationMessageInterceptorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task InterceptApplicationMessagePublishAsync(MqttApplicationMessageInterceptorContext context)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await _callback.Invoke(context).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var exceptionHandler = ExceptionHandler;
|
||||
if (exceptionHandler != null)
|
||||
{
|
||||
await exceptionHandler.Invoke(context, exception).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}).RunInBackground();
|
||||
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerStartedHandlerDelegate : IMqttServerStartedHandler
|
||||
{
|
||||
readonly Func<EventArgs, Task> _handler;
|
||||
|
||||
public MqttServerStartedHandlerDelegate(Action<EventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerStartedHandlerDelegate(Func<EventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleServerStartedAsync(EventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerStoppedHandlerDelegate : IMqttServerStoppedHandler
|
||||
{
|
||||
readonly Func<EventArgs, Task> _handler;
|
||||
|
||||
public MqttServerStoppedHandlerDelegate(Action<EventArgs> handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
_handler = eventArgs =>
|
||||
{
|
||||
handler(eventArgs);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerStoppedHandlerDelegate(Func<EventArgs, Task> handler)
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
public Task HandleServerStoppedAsync(EventArgs eventArgs)
|
||||
{
|
||||
return _handler(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerSubscriptionInterceptorDelegate : IMqttServerSubscriptionInterceptor
|
||||
{
|
||||
readonly Func<MqttSubscriptionInterceptorContext, Task> _callback;
|
||||
|
||||
public MqttServerSubscriptionInterceptorDelegate(Action<MqttSubscriptionInterceptorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerSubscriptionInterceptorDelegate(Func<MqttSubscriptionInterceptorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context)
|
||||
{
|
||||
return _callback(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Implementations;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerUnsubscriptionInterceptorDelegate : IMqttServerUnsubscriptionInterceptor
|
||||
{
|
||||
readonly Func<MqttUnsubscriptionInterceptorContext, Task> _callback;
|
||||
|
||||
public MqttServerUnsubscriptionInterceptorDelegate(Action<MqttUnsubscriptionInterceptorContext> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException(nameof(callback));
|
||||
|
||||
_callback = context =>
|
||||
{
|
||||
callback(context);
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public MqttServerUnsubscriptionInterceptorDelegate(Func<MqttUnsubscriptionInterceptorContext, Task> callback)
|
||||
{
|
||||
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
|
||||
}
|
||||
|
||||
public Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context)
|
||||
{
|
||||
return _callback(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-21
@@ -3,18 +3,12 @@ using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerOptions : IMqttServerOptions
|
||||
public class MqttServerOptions
|
||||
{
|
||||
public MqttServerTcpEndpointOptions DefaultEndpointOptions { get; } = new MqttServerTcpEndpointOptions();
|
||||
|
||||
public MqttServerTlsTcpEndpointOptions TlsEndpointOptions { get; } = new MqttServerTlsTcpEndpointOptions();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the client identifier.
|
||||
/// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues.
|
||||
/// </summary>
|
||||
public string ClientId { get; set; }
|
||||
|
||||
|
||||
public bool EnablePersistentSessions { get; set; }
|
||||
|
||||
public int MaxPendingMessagesPerClient { get; set; } = 250;
|
||||
@@ -24,19 +18,7 @@ namespace MQTTnet.Server
|
||||
public TimeSpan DefaultCommunicationTimeout { get; set; } = TimeSpan.FromSeconds(15);
|
||||
|
||||
public TimeSpan KeepAliveMonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500);
|
||||
|
||||
public IMqttServerConnectionValidator ConnectionValidator { get; set; }
|
||||
|
||||
public IMqttServerApplicationMessageInterceptor ApplicationMessageInterceptor { get; set; }
|
||||
|
||||
public IMqttServerClientMessageQueueInterceptor ClientMessageQueueInterceptor { get; set; }
|
||||
|
||||
public IMqttServerSubscriptionInterceptor SubscriptionInterceptor { get; set; }
|
||||
|
||||
public IMqttServerUnsubscriptionInterceptor UnsubscriptionInterceptor { get; set; }
|
||||
|
||||
public IMqttServerApplicationMessageInterceptor UndeliveredMessageInterceptor { get; set; }
|
||||
|
||||
|
||||
public IMqttServerStorage Storage { get; set; }
|
||||
|
||||
public IMqttRetainedMessagesManager RetainedMessagesManager { get; set; } = new MqttRetainedMessagesManager();
|
||||
+38
-98
@@ -152,97 +152,37 @@ namespace MQTTnet.Server
|
||||
_options.RetainedMessagesManager = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithConnectionValidator(IMqttServerConnectionValidator value)
|
||||
{
|
||||
_options.ConnectionValidator = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithConnectionValidator(Action<MqttConnectionValidatorContext> value)
|
||||
{
|
||||
_options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithConnectionValidator(Func<MqttConnectionValidatorContext, Task> value)
|
||||
{
|
||||
_options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
// public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value)
|
||||
// {
|
||||
// _options.ApplicationMessageInterceptor = value;
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Action<InterceptingMqttClientPublishEventArgs> value)
|
||||
// {
|
||||
// _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Func<InterceptingMqttClientPublishEventArgs, Task> value)
|
||||
// {
|
||||
// _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Action<InterceptingMqttClientPublishEventArgs> value)
|
||||
// {
|
||||
// _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Func<InterceptingMqttClientPublishEventArgs, Task> value)
|
||||
// {
|
||||
// _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value);
|
||||
// return this;
|
||||
// }
|
||||
|
||||
public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value)
|
||||
{
|
||||
_options.ApplicationMessageInterceptor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Action<MqttApplicationMessageInterceptorContext> value)
|
||||
{
|
||||
_options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Func<MqttApplicationMessageInterceptorContext, Task> value)
|
||||
{
|
||||
_options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Action<MqttApplicationMessageInterceptorContext> value)
|
||||
{
|
||||
_options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Func<MqttApplicationMessageInterceptorContext, Task> value)
|
||||
{
|
||||
_options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithClientMessageQueueInterceptor(IMqttServerClientMessageQueueInterceptor value)
|
||||
{
|
||||
_options.ClientMessageQueueInterceptor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithClientMessageQueueInterceptor(Action<MqttClientMessageQueueInterceptorContext> value)
|
||||
{
|
||||
_options.ClientMessageQueueInterceptor = new MqttClientMessageQueueInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithSubscriptionInterceptor(IMqttServerSubscriptionInterceptor value)
|
||||
{
|
||||
_options.SubscriptionInterceptor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithSubscriptionInterceptor(Action<MqttSubscriptionInterceptorContext> value)
|
||||
{
|
||||
_options.SubscriptionInterceptor = new MqttServerSubscriptionInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithUnsubscriptionInterceptor(IMqttServerUnsubscriptionInterceptor value)
|
||||
{
|
||||
_options.UnsubscriptionInterceptor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithUnsubscriptionInterceptor(Action<MqttUnsubscriptionInterceptorContext> value)
|
||||
{
|
||||
_options.UnsubscriptionInterceptor = new MqttServerUnsubscriptionInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithUndeliveredMessageInterceptor(Action<MqttApplicationMessageInterceptorContext> value)
|
||||
{
|
||||
_options.UndeliveredMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttServerOptionsBuilder WithDefaultEndpointReuseAddress()
|
||||
{
|
||||
_options.DefaultEndpointOptions.ReuseAddress = true;
|
||||
@@ -261,16 +201,16 @@ namespace MQTTnet.Server
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the client ID which is used when publishing messages from the server directly.
|
||||
/// </summary>
|
||||
public MqttServerOptionsBuilder WithClientId(string value)
|
||||
{
|
||||
_options.ClientId = value;
|
||||
return this;
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Gets or sets the client ID which is used when publishing messages from the server directly.
|
||||
// /// </summary>
|
||||
// public MqttServerOptionsBuilder WithClientId(string value)
|
||||
// {
|
||||
// _options.ClientId = value;
|
||||
// return this;
|
||||
// }
|
||||
|
||||
public IMqttServerOptions Build()
|
||||
public MqttServerOptions Build()
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class PreparingMqttClientSessionEventArgs : EventArgs
|
||||
{
|
||||
public string ClientId { get; internal set; }
|
||||
|
||||
// TODO: Allow adding of packets to the queue etc.
|
||||
|
||||
/*
|
||||
* The Session State in the Server consists of:
|
||||
· The existence of a Session, even if the rest of the Session State is empty.
|
||||
· The Clients subscriptions, including any Subscription Identifiers.
|
||||
· QoS 1 and QoS 2 messages which have been sent to the Client, but have not been completely acknowledged.
|
||||
· QoS 1 and QoS 2 messages pending transmission to the Client and OPTIONALLY QoS 0 messages pending transmission to the Client.
|
||||
· QoS 2 messages which have been received from the Client, but have not been completely acknowledged.The Will Message and the Will Delay Interval
|
||||
· If the Session is currently not connected, the time at which the Session will end and Session State will be discarded.
|
||||
*/
|
||||
|
||||
public bool IsExistingSession { get; set; }
|
||||
|
||||
public List<MqttSubscription> Subscriptions { get; } = new List<MqttSubscription>();
|
||||
|
||||
public List<MqttPublishPacket> PublishPackets { get; } = new List<MqttPublishPacket>();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using MQTTnet.Formatter;
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Formatter;
|
||||
|
||||
namespace MQTTnet.Server.Status
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttClientStatus
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Server.Status
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public interface IMqttSessionStatus
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using MQTTnet.Formatter;
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server.Status
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttClientStatus : IMqttClientStatus
|
||||
{
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Formatter.V5;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Server.Internal;
|
||||
|
||||
namespace MQTTnet.Server.Status
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttSessionStatus : IMqttSessionStatus
|
||||
{
|
||||
|
||||
+2
-2
@@ -10,12 +10,12 @@ using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttConnectionValidatorContext
|
||||
public sealed class ValidatingMqttClientConnectionEventArgs : EventArgs
|
||||
{
|
||||
readonly MqttConnectPacket _connectPacket;
|
||||
readonly IMqttChannelAdapter _clientAdapter;
|
||||
|
||||
public MqttConnectionValidatorContext(MqttConnectPacket connectPacket, IMqttChannelAdapter clientAdapter)
|
||||
public ValidatingMqttClientConnectionEventArgs(MqttConnectPacket connectPacket, IMqttChannelAdapter clientAdapter)
|
||||
{
|
||||
_connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket));
|
||||
_clientAdapter = clientAdapter ?? throw new ArgumentNullException(nameof(clientAdapter));
|
||||
@@ -33,7 +33,7 @@ namespace MQTTnet.AspNetCore.Tests.Mockups
|
||||
}
|
||||
}
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
public Task StartAsync(MqttServerOptions options)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -11,19 +11,20 @@ namespace MQTTnet.Benchmarks
|
||||
[MemoryDiagnoser]
|
||||
public class MessageProcessingBenchmark
|
||||
{
|
||||
IMqttServer _mqttServer;
|
||||
MqttServer _mqttServer;
|
||||
IMqttClient _mqttClient;
|
||||
MqttApplicationMessage _message;
|
||||
|
||||
[GlobalSetup]
|
||||
public void Setup()
|
||||
{
|
||||
var serverOptions = new MqttServerOptionsBuilder().Build();
|
||||
|
||||
var factory = new MqttFactory();
|
||||
_mqttServer = factory.CreateMqttServer();
|
||||
_mqttServer = factory.CreateMqttServer(serverOptions);
|
||||
_mqttClient = factory.CreateMqttClient();
|
||||
|
||||
var serverOptions = new MqttServerOptionsBuilder().Build();
|
||||
_mqttServer.StartAsync(serverOptions).GetAwaiter().GetResult();
|
||||
_mqttServer.StartAsync().GetAwaiter().GetResult();
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost").Build();
|
||||
|
||||
@@ -31,10 +31,11 @@ namespace MQTTnet.Benchmarks
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_mqttServer = factory.CreateMqttServer(new[] { tcpServer }, new MqttNetEventLogger());
|
||||
|
||||
var serverOptions = new MqttServerOptionsBuilder().Build();
|
||||
_mqttServer.StartAsync(serverOptions).GetAwaiter().GetResult();
|
||||
_mqttServer = factory.CreateMqttServer(serverOptions, new[] { tcpServer }, new MqttNetEventLogger());
|
||||
|
||||
|
||||
_mqttServer.StartAsync().GetAwaiter().GetResult();
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithTcpServer("localhost").Build();
|
||||
|
||||
@@ -149,8 +149,7 @@ namespace MQTTnet.Tests.Client
|
||||
|
||||
connected = GetConnectedTask(managedClient);
|
||||
|
||||
await testEnvironment.Server.StartAsync(new MqttServerOptionsBuilder()
|
||||
.WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
|
||||
await testEnvironment.Server.StartAsync();
|
||||
|
||||
await connected;
|
||||
|
||||
|
||||
@@ -34,10 +34,11 @@ namespace MQTTnet.Tests.Client
|
||||
var client = await testEnvironment.ConnectLowLevelClient();
|
||||
|
||||
var i = 0;
|
||||
server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c =>
|
||||
server.InterceptingClientPublishAsync += c =>
|
||||
{
|
||||
i++;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await client.SendAsync(new MqttConnectPacket
|
||||
{
|
||||
@@ -223,7 +224,7 @@ namespace MQTTnet.Tests.Client
|
||||
await Task.Delay(500);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
|
||||
await server.StartAsync();
|
||||
await Task.Delay(500);
|
||||
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
@@ -260,7 +261,7 @@ namespace MQTTnet.Tests.Client
|
||||
}
|
||||
}
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
|
||||
await server.StartAsync();
|
||||
await Task.Delay(500);
|
||||
|
||||
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Diagnostics.Logger;
|
||||
using MQTTnet.Extensions.ManagedClient;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Factory
|
||||
{
|
||||
@@ -66,88 +67,88 @@ namespace MQTTnet.Tests.Factory
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateApplicationMessageBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_ClientOptionsBuilder()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateClientOptionsBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_ServerOptionsBuilder()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateServerOptionsBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_SubscribeOptionsBuilder()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateSubscribeOptionsBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_UnsubscribeOptionsBuilder()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateUnsubscribeOptionsBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_TopicFilterBuilder()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var builder = factory.CreateTopicFilterBuilder();
|
||||
|
||||
|
||||
Assert.IsNotNull(builder);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_MqttServer()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var server = factory.CreateMqttServer();
|
||||
|
||||
var server = factory.CreateMqttServer(new MqttServerOptionsBuilder().Build());
|
||||
|
||||
Assert.IsNotNull(server);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_MqttClient()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var client = factory.CreateMqttClient();
|
||||
|
||||
|
||||
Assert.IsNotNull(client);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_LowLevelMqttClient()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var client = factory.CreateLowLevelMqttClient();
|
||||
|
||||
|
||||
Assert.IsNotNull(client);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Create_ManagedMqttClient()
|
||||
{
|
||||
var factory = new MqttFactory();
|
||||
var client = factory.CreateManagedMqttClient();
|
||||
|
||||
|
||||
Assert.IsNotNull(client);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace MQTTnet.Tests.Mockups
|
||||
|
||||
public MqttFactory Factory { get; } = new MqttFactory();
|
||||
|
||||
public IMqttServer Server { get; private set; }
|
||||
public MqttServer Server { get; private set; }
|
||||
|
||||
public bool IgnoreClientLogErrors { get; set; }
|
||||
|
||||
@@ -173,46 +173,60 @@ namespace MQTTnet.Tests.Mockups
|
||||
return new MqttRpcClient(await ConnectClient(), options);
|
||||
}
|
||||
|
||||
public IMqttServer CreateServer()
|
||||
public MqttServer CreateServer(MqttServerOptions options)
|
||||
{
|
||||
if (Server != null)
|
||||
{
|
||||
throw new InvalidOperationException("Server already started.");
|
||||
}
|
||||
|
||||
Server = new TestServerWrapper(Factory.CreateMqttServer(ServerLogger), TestContext, this);
|
||||
Server = Factory.CreateMqttServer(options, ServerLogger);
|
||||
|
||||
Server.ValidatingClientConnectionAsync += e =>
|
||||
{
|
||||
if (TestContext != null)
|
||||
{
|
||||
// Null is used when the client id is assigned from the server!
|
||||
if (!string.IsNullOrEmpty(e.ClientId) && !e.ClientId.StartsWith(TestContext.TestName))
|
||||
{
|
||||
TrackException(new InvalidOperationException($"Invalid client ID used ({e.ClientId}). It must start with UnitTest name."));
|
||||
e.ReasonCode = Protocol.MqttConnectReasonCode.ClientIdentifierNotValid;
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
return Server;
|
||||
}
|
||||
|
||||
public Task<IMqttServer> StartServer()
|
||||
public Task<MqttServer> StartServer()
|
||||
{
|
||||
return StartServer(Factory.CreateServerOptionsBuilder());
|
||||
}
|
||||
|
||||
public async Task<IMqttServer> StartServer(MqttServerOptionsBuilder options)
|
||||
public async Task<MqttServer> StartServer(MqttServerOptionsBuilder options)
|
||||
{
|
||||
var server = CreateServer();
|
||||
var server = CreateServer(options.Build());
|
||||
|
||||
options.WithDefaultEndpointPort(ServerPort);
|
||||
options.WithMaxPendingMessagesPerClient(int.MaxValue);
|
||||
|
||||
await server.StartAsync(options.Build());
|
||||
await server.StartAsync();
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
public async Task<IMqttServer> StartServer(Action<MqttServerOptionsBuilder> options)
|
||||
public async Task<MqttServer> StartServer(Action<MqttServerOptionsBuilder> options)
|
||||
{
|
||||
var server = CreateServer();
|
||||
|
||||
var optionsBuilder = Factory.CreateServerOptionsBuilder();
|
||||
optionsBuilder.WithDefaultEndpointPort(ServerPort);
|
||||
optionsBuilder.WithMaxPendingMessagesPerClient(int.MaxValue);
|
||||
|
||||
options?.Invoke(optionsBuilder);
|
||||
options.Invoke(optionsBuilder);
|
||||
|
||||
await server.StartAsync(optionsBuilder.Build());
|
||||
|
||||
var server = CreateServer(optionsBuilder.Build());
|
||||
await server.StartAsync();
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Client.Publishing;
|
||||
using MQTTnet.Client.Receiving;
|
||||
using MQTTnet.Server;
|
||||
using MQTTnet.Server.Status;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Tests.Mockups
|
||||
{
|
||||
public sealed class TestServerWrapper : IMqttServer
|
||||
{
|
||||
public TestServerWrapper(IMqttServer implementation, TestContext testContext, TestEnvironment testEnvironment)
|
||||
{
|
||||
Implementation = implementation;
|
||||
TestContext = testContext;
|
||||
TestEnvironment = testEnvironment;
|
||||
}
|
||||
|
||||
public IMqttServer Implementation { get; }
|
||||
public TestContext TestContext { get; }
|
||||
public TestEnvironment TestEnvironment { get; }
|
||||
|
||||
public bool IsStarted { get; }
|
||||
|
||||
public IMqttServerStartedHandler StartedHandler
|
||||
{
|
||||
get => Implementation.StartedHandler;
|
||||
set => Implementation.StartedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerStoppedHandler StoppedHandler
|
||||
{
|
||||
get => Implementation.StoppedHandler;
|
||||
set => Implementation.StoppedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientConnectedHandler ClientConnectedHandler
|
||||
{
|
||||
get => Implementation.ClientConnectedHandler;
|
||||
set => Implementation.ClientConnectedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientDisconnectedHandler ClientDisconnectedHandler
|
||||
{
|
||||
get => Implementation.ClientDisconnectedHandler;
|
||||
set => Implementation.ClientDisconnectedHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientSubscribedTopicHandler ClientSubscribedTopicHandler
|
||||
{
|
||||
get => Implementation.ClientSubscribedTopicHandler;
|
||||
set => Implementation.ClientSubscribedTopicHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerClientUnsubscribedTopicHandler ClientUnsubscribedTopicHandler
|
||||
{
|
||||
get => Implementation.ClientUnsubscribedTopicHandler;
|
||||
set => Implementation.ClientUnsubscribedTopicHandler = value;
|
||||
}
|
||||
|
||||
public IMqttServerOptions Options => Implementation.Options;
|
||||
|
||||
public IMqttApplicationMessageReceivedHandler ApplicationMessageReceivedHandler
|
||||
{
|
||||
get => Implementation.ApplicationMessageReceivedHandler;
|
||||
set => Implementation.ApplicationMessageReceivedHandler = value;
|
||||
}
|
||||
|
||||
public event Func<MqttApplicationMessageReceivedEventArgs, Task> ApplicationMessageReceivedAsync
|
||||
{
|
||||
add => Implementation.ApplicationMessageReceivedAsync += value;
|
||||
remove => Implementation.ApplicationMessageReceivedAsync -= value;
|
||||
}
|
||||
|
||||
public Task ClearRetainedApplicationMessagesAsync()
|
||||
{
|
||||
return Implementation.ClearRetainedApplicationMessagesAsync();
|
||||
}
|
||||
|
||||
public Task<IList<IMqttClientStatus>> GetClientStatusAsync()
|
||||
{
|
||||
return Implementation.GetClientStatusAsync();
|
||||
}
|
||||
|
||||
public Task<IList<MqttApplicationMessage>> GetRetainedApplicationMessagesAsync()
|
||||
{
|
||||
return Implementation.GetRetainedApplicationMessagesAsync();
|
||||
}
|
||||
|
||||
public Task<IList<IMqttSessionStatus>> GetSessionStatusAsync()
|
||||
{
|
||||
return Implementation.GetSessionStatusAsync();
|
||||
}
|
||||
|
||||
public Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken)
|
||||
{
|
||||
return Implementation.PublishAsync(applicationMessage, cancellationToken);
|
||||
}
|
||||
|
||||
public Task StartAsync(IMqttServerOptions options)
|
||||
{
|
||||
if (TestContext != null)
|
||||
{
|
||||
var serverOptions = (MqttServerOptions)options;
|
||||
|
||||
if (serverOptions.ConnectionValidator == null)
|
||||
{
|
||||
serverOptions.ConnectionValidator = new MqttServerConnectionValidatorDelegate(ConnectionValidator);
|
||||
}
|
||||
}
|
||||
|
||||
return Implementation.StartAsync(options);
|
||||
}
|
||||
|
||||
public Task StopAsync()
|
||||
{
|
||||
return Implementation.StopAsync();
|
||||
}
|
||||
|
||||
public Task SubscribeAsync(string clientId, ICollection<MqttTopicFilter> topicFilters)
|
||||
{
|
||||
return Implementation.SubscribeAsync(clientId, topicFilters);
|
||||
}
|
||||
|
||||
public Task UnsubscribeAsync(string clientId, ICollection<string> topicFilters)
|
||||
{
|
||||
return Implementation.UnsubscribeAsync(clientId, topicFilters);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Implementation.Dispose();
|
||||
}
|
||||
|
||||
void ConnectionValidator(MqttConnectionValidatorContext ctx)
|
||||
{
|
||||
if (!ctx.ClientId.StartsWith(TestContext.TestName))
|
||||
{
|
||||
TestEnvironment.TrackException(new InvalidOperationException($"Invalid client ID used ({ctx.ClientId}). It must start with UnitTest name."));
|
||||
ctx.ReasonCode = Protocol.MqttConnectReasonCode.ClientIdentifierNotValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using MQTTnet.Client;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Protocol;
|
||||
using MQTTnet.Server;
|
||||
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
@@ -34,27 +33,31 @@ namespace MQTTnet.Tests.Server
|
||||
|
||||
// Arrange server
|
||||
var disconnectedMre = new ManualResetEventSlim();
|
||||
var serverOptions = new MqttServerOptionsBuilder()
|
||||
.WithConnectionValidator(context =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(context.ClientId))
|
||||
{
|
||||
context.AssignedClientIdentifier = assignedClientId;
|
||||
context.ReasonCode = MqttConnectReasonCode.Success;
|
||||
}
|
||||
});
|
||||
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
testEnvironment.Server.UseClientConnectedHandler(args =>
|
||||
var server = await testEnvironment.StartServer();
|
||||
server.ValidatingClientConnectionAsync += e =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.ClientId))
|
||||
{
|
||||
e.AssignedClientIdentifier = assignedClientId;
|
||||
e.ReasonCode = MqttConnectReasonCode.Success;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
testEnvironment.Server.ClientConnectedAsync += args =>
|
||||
{
|
||||
serverConnectedClientId = args.ClientId;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
testEnvironment.Server.UseClientDisconnectedHandler(args =>
|
||||
testEnvironment.Server.ClientDisconnectedAsync += args =>
|
||||
{
|
||||
serverDisconnectedClientId = args.ClientId;
|
||||
disconnectedMre.Set();
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
// Arrange client
|
||||
var client = testEnvironment.CreateClient();
|
||||
|
||||
@@ -20,10 +20,11 @@ namespace MQTTnet.Tests.Server
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientConnectedEventArgs eventArgs = null;
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e =>
|
||||
server.ClientConnectedAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
|
||||
|
||||
@@ -46,10 +47,11 @@ namespace MQTTnet.Tests.Server
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientDisconnectedEventArgs eventArgs = null;
|
||||
server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(e =>
|
||||
server.ClientDisconnectedAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var client = await testEnvironment.ConnectClient(o => o.WithCredentials("TheUser"));
|
||||
await client.DisconnectAsync();
|
||||
@@ -72,10 +74,11 @@ namespace MQTTnet.Tests.Server
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientSubscribedTopicEventArgs eventArgs = null;
|
||||
server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(e =>
|
||||
server.ClientSubscribedTopicAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.SubscribeAsync("The/Topic", MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
@@ -98,10 +101,11 @@ namespace MQTTnet.Tests.Server
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttServerClientUnsubscribedTopicEventArgs eventArgs = null;
|
||||
server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e =>
|
||||
server.ClientUnsubscribedTopicAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.UnsubscribeAsync("The/Topic");
|
||||
@@ -122,11 +126,12 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
MqttApplicationMessageReceivedEventArgs eventArgs = null;
|
||||
server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e =>
|
||||
InterceptingMqttClientPublishEventArgs eventArgs = null;
|
||||
server.InterceptingClientPublishAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
await client.PublishAsync("The_Topic", "The_Payload");
|
||||
@@ -146,15 +151,16 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = testEnvironment.CreateServer();
|
||||
|
||||
var server = testEnvironment.CreateServer(new MqttServerOptions());
|
||||
|
||||
EventArgs eventArgs = null;
|
||||
server.StartedHandler = new MqttServerStartedHandlerDelegate(e =>
|
||||
server.StartedAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().Build());
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await server.StartAsync();
|
||||
|
||||
await LongTestDelay();
|
||||
|
||||
@@ -170,10 +176,11 @@ namespace MQTTnet.Tests.Server
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
EventArgs eventArgs = null;
|
||||
server.StoppedHandler = new MqttServerStoppedHandlerDelegate(e =>
|
||||
server.StoppedAsync += e =>
|
||||
{
|
||||
eventArgs = e;
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await server.StopAsync();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace MQTTnet.Tests.Server
|
||||
[DataRow(null, null)]
|
||||
public async Task Use_Admissible_Credentials(string username, string password)
|
||||
{
|
||||
using (var testEnvironment = new TestEnvironment())
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer();
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace MQTTnet.Tests.Server
|
||||
Assert.AreEqual(1, receivedMessagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task Publish_From_Server()
|
||||
{
|
||||
@@ -210,9 +210,9 @@ namespace MQTTnet.Tests.Server
|
||||
client.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
|
||||
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
|
||||
await client.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
|
||||
await client.SubscribeAsync(new MqttTopicFilter {Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce});
|
||||
|
||||
await server.PublishAsync(message);
|
||||
await server.PublishAsync("server", message);
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
@@ -237,8 +237,8 @@ namespace MQTTnet.Tests.Server
|
||||
|
||||
c3.UseApplicationMessageReceivedHandler(c => { Interlocked.Increment(ref receivedMessagesCount); });
|
||||
|
||||
await c2.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }).ConfigureAwait(false);
|
||||
await c3.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }).ConfigureAwait(false);
|
||||
await c2.SubscribeAsync(new MqttTopicFilter {Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce}).ConfigureAwait(false);
|
||||
await c3.SubscribeAsync(new MqttTopicFilter {Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce}).ConfigureAwait(false);
|
||||
|
||||
var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
|
||||
|
||||
@@ -318,11 +318,11 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(async e =>
|
||||
server.ClientConnectedAsync += async e =>
|
||||
{
|
||||
// Every client will automatically subscribe to this topic.
|
||||
await server.SubscribeAsync(e.ClientId, "topic1");
|
||||
});
|
||||
};
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
var receivedMessages = new List<MqttApplicationMessage>();
|
||||
@@ -379,13 +379,22 @@ namespace MQTTnet.Tests.Server
|
||||
var clientConnectedCalled = 0;
|
||||
var clientDisconnectedCalled = 0;
|
||||
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ => Interlocked.Increment(ref clientConnectedCalled));
|
||||
server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ => Interlocked.Increment(ref clientDisconnectedCalled));
|
||||
server.ClientConnectedAsync += e =>
|
||||
{
|
||||
Interlocked.Increment(ref clientConnectedCalled);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
server.ClientDisconnectedAsync += e =>
|
||||
{
|
||||
Interlocked.Increment(ref clientDisconnectedCalled);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder());
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
|
||||
Assert.AreEqual(1, clientConnectedCalled);
|
||||
Assert.AreEqual(0, clientDisconnectedCalled);
|
||||
|
||||
@@ -490,9 +499,14 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(
|
||||
new MqttServerOptionsBuilder().WithApplicationMessageInterceptor(
|
||||
c => { c.ApplicationMessage = new MqttApplicationMessage { Topic = "new_topic" }; }));
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
server.InterceptingClientPublishAsync += e =>
|
||||
{
|
||||
e.ApplicationMessage = new MqttApplicationMessage {Topic = "new_topic"};
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
string receivedTopic = null;
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
@@ -531,7 +545,15 @@ namespace MQTTnet.Tests.Server
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer();
|
||||
server.UseClientConnectedHandler(async e => { await server.PublishAsync("/test/1", "true", MqttQualityOfServiceLevel.ExactlyOnce, false); });
|
||||
server.ClientConnectedAsync += async e =>
|
||||
{
|
||||
await server.PublishAsync("server", new MqttApplicationMessage
|
||||
{
|
||||
Topic = "/test/1",
|
||||
Payload = Encoding.UTF8.GetBytes("true"),
|
||||
QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce
|
||||
});
|
||||
};
|
||||
|
||||
string receivedTopic = null;
|
||||
|
||||
@@ -553,21 +575,24 @@ namespace MQTTnet.Tests.Server
|
||||
[TestMethod]
|
||||
public async Task Intercept_Message()
|
||||
{
|
||||
void Interceptor(MqttApplicationMessageInterceptorContext context)
|
||||
{
|
||||
context.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
|
||||
}
|
||||
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithApplicationMessageInterceptor(Interceptor));
|
||||
var server = await testEnvironment.StartServer();
|
||||
server.InterceptingClientPublishAsync += e =>
|
||||
{
|
||||
e.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var c1 = await testEnvironment.ConnectClient();
|
||||
var c2 = await testEnvironment.ConnectClient();
|
||||
await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("test").Build());
|
||||
|
||||
var isIntercepted = false;
|
||||
c2.UseApplicationMessageReceivedHandler(c => { isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(c.ApplicationMessage.Payload), StringComparison.Ordinal) == 0; });
|
||||
c2.UseApplicationMessageReceivedHandler(c =>
|
||||
{
|
||||
isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(c.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
|
||||
});
|
||||
|
||||
await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("test").Build());
|
||||
await c1.DisconnectAsync();
|
||||
@@ -622,13 +647,17 @@ namespace MQTTnet.Tests.Server
|
||||
[TestMethod]
|
||||
public async Task Deny_Connection()
|
||||
{
|
||||
var serverOptions = new MqttServerOptionsBuilder().WithConnectionValidator(context => { context.ReasonCode = MqttConnectReasonCode.NotAuthorized; });
|
||||
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
|
||||
await testEnvironment.StartServer(serverOptions);
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
server.ValidatingClientConnectionAsync += e =>
|
||||
{
|
||||
e.ReasonCode = MqttConnectReasonCode.NotAuthorized;
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var connectingFailedException = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(() => testEnvironment.ConnectClient());
|
||||
Assert.AreEqual(MqttClientConnectResultCode.NotAuthorized, connectingFailedException.ResultCode);
|
||||
@@ -637,7 +666,7 @@ namespace MQTTnet.Tests.Server
|
||||
|
||||
Dictionary<string, bool> _connected;
|
||||
|
||||
private void ConnectionValidationHandler(MqttConnectionValidatorContext eventArgs)
|
||||
void ConnectionValidationHandler(ValidatingMqttClientConnectionEventArgs eventArgs)
|
||||
{
|
||||
if (_connected.ContainsKey(eventArgs.ClientId))
|
||||
{
|
||||
@@ -647,7 +676,6 @@ namespace MQTTnet.Tests.Server
|
||||
|
||||
_connected[eventArgs.ClientId] = true;
|
||||
eventArgs.ReasonCode = MqttConnectReasonCode.Success;
|
||||
return;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -658,27 +686,36 @@ namespace MQTTnet.Tests.Server
|
||||
testEnvironment.IgnoreClientLogErrors = true;
|
||||
|
||||
_connected = new Dictionary<string, bool>();
|
||||
var options = new MqttServerOptionsBuilder();
|
||||
options.WithConnectionValidator(e => ConnectionValidationHandler(e));
|
||||
var server = await testEnvironment.StartServer(options);
|
||||
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
server.ValidatingClientConnectionAsync += e =>
|
||||
{
|
||||
ConnectionValidationHandler(e);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var events = new List<string>();
|
||||
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ =>
|
||||
server.ClientConnectedAsync += e =>
|
||||
{
|
||||
lock (events)
|
||||
{
|
||||
events.Add("c");
|
||||
}
|
||||
});
|
||||
|
||||
server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ =>
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
server.ClientDisconnectedAsync += e =>
|
||||
{
|
||||
lock (events)
|
||||
{
|
||||
events.Add("d");
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var clientOptions = new MqttClientOptionsBuilder()
|
||||
.WithClientId("same_id");
|
||||
@@ -743,25 +780,29 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
var server = await testEnvironment.StartServer(new MqttServerOptionsBuilder());
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
var events = new List<string>();
|
||||
|
||||
server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ =>
|
||||
server.ClientConnectedAsync += e =>
|
||||
{
|
||||
lock (events)
|
||||
{
|
||||
events.Add("c");
|
||||
}
|
||||
});
|
||||
|
||||
server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ =>
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
server.ClientDisconnectedAsync += e =>
|
||||
{
|
||||
lock (events)
|
||||
{
|
||||
events.Add("d");
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var clientOptionsBuilder = new MqttClientOptionsBuilder()
|
||||
.WithClientId(Guid.NewGuid().ToString());
|
||||
@@ -863,7 +904,7 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
}
|
||||
|
||||
await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
|
||||
await server.StartAsync();
|
||||
await testEnvironment.ConnectClient();
|
||||
}
|
||||
}
|
||||
@@ -873,14 +914,18 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(c =>
|
||||
var server = await testEnvironment.StartServer();
|
||||
|
||||
server.InterceptingClientSubscriptionAsync += e =>
|
||||
{
|
||||
// This should lead to no subscriptions for "n" at all. So also no sending of retained messages.
|
||||
if (c.TopicFilter.Topic == "n")
|
||||
if (e.TopicFilter.Topic == "n")
|
||||
{
|
||||
c.Response.ReasonCode = MqttSubscribeReasonCode.UnspecifiedError;
|
||||
e.Response.ReasonCode = MqttSubscribeReasonCode.UnspecifiedError;
|
||||
}
|
||||
}));
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
// Prepare some retained messages.
|
||||
var client1 = await testEnvironment.ConnectClient();
|
||||
@@ -904,7 +949,7 @@ namespace MQTTnet.Tests.Server
|
||||
}
|
||||
});
|
||||
|
||||
await client2.SubscribeAsync(new MqttTopicFilter { Topic = "y" }, new MqttTopicFilter { Topic = "n" });
|
||||
await client2.SubscribeAsync(new MqttTopicFilter {Topic = "y"}, new MqttTopicFilter {Topic = "n"});
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
@@ -964,7 +1009,7 @@ namespace MQTTnet.Tests.Server
|
||||
var c2 = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithClientId("sender"));
|
||||
await c2.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
|
||||
await Task.Delay(500);
|
||||
|
||||
|
||||
await c2.DisconnectAsync().ConfigureAwait(false);
|
||||
|
||||
await Task.Delay(500);
|
||||
@@ -982,81 +1027,87 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var undeliverd = string.Empty;
|
||||
|
||||
var options = new MqttServerOptionsBuilder().WithUndeliveredMessageInterceptor(
|
||||
context => { undeliverd = context.ApplicationMessage.Topic; });
|
||||
|
||||
await testEnvironment.StartServer(options);
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
|
||||
await client.SubscribeAsync("b");
|
||||
|
||||
await client.PublishAsync("a", null, MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual("a", undeliverd);
|
||||
throw new NotImplementedException();
|
||||
|
||||
// var options = new MqttServerOptionsBuilder().WithUndeliveredMessageInterceptor(
|
||||
// context => { undeliverd = context.ApplicationMessage.Topic; });
|
||||
//
|
||||
// await testEnvironment.StartServer(options);
|
||||
//
|
||||
// var client = await testEnvironment.ConnectClient();
|
||||
//
|
||||
// await client.SubscribeAsync("b");
|
||||
//
|
||||
// await client.PublishAsync("a", null, MqttQualityOfServiceLevel.ExactlyOnce);
|
||||
//
|
||||
// await Task.Delay(500);
|
||||
//
|
||||
// Assert.AreEqual("a", undeliverd);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Intercept_ClientMessageQueue()
|
||||
{
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder()
|
||||
.WithClientMessageQueueInterceptor(c => c.ApplicationMessage.Topic = "a"));
|
||||
|
||||
var topicAReceived = false;
|
||||
var topicBReceived = false;
|
||||
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
client.UseApplicationMessageReceivedHandler(c =>
|
||||
{
|
||||
if (c.ApplicationMessage.Topic == "a")
|
||||
{
|
||||
topicAReceived = true;
|
||||
}
|
||||
else if (c.ApplicationMessage.Topic == "b")
|
||||
{
|
||||
topicBReceived = true;
|
||||
}
|
||||
});
|
||||
|
||||
await client.SubscribeAsync("a");
|
||||
await client.SubscribeAsync("b");
|
||||
|
||||
await client.PublishAsync("b");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsTrue(topicAReceived);
|
||||
Assert.IsFalse(topicBReceived);
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
|
||||
// using (var testEnvironment = CreateTestEnvironment())
|
||||
// {
|
||||
// await testEnvironment.StartServer(new MqttServerOptionsBuilder()
|
||||
// .WithClientMessageQueueInterceptor(c => c.ApplicationMessage.Topic = "a"));
|
||||
//
|
||||
// var topicAReceived = false;
|
||||
// var topicBReceived = false;
|
||||
//
|
||||
// var client = await testEnvironment.ConnectClient();
|
||||
// client.UseApplicationMessageReceivedHandler(c =>
|
||||
// {
|
||||
// if (c.ApplicationMessage.Topic == "a")
|
||||
// {
|
||||
// topicAReceived = true;
|
||||
// }
|
||||
// else if (c.ApplicationMessage.Topic == "b")
|
||||
// {
|
||||
// topicBReceived = true;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// await client.SubscribeAsync("a");
|
||||
// await client.SubscribeAsync("b");
|
||||
//
|
||||
// await client.PublishAsync("b");
|
||||
//
|
||||
// await Task.Delay(500);
|
||||
//
|
||||
// Assert.IsTrue(topicAReceived);
|
||||
// Assert.IsFalse(topicBReceived);
|
||||
// }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Intercept_ClientMessageQueue_Different_QoS_Of_Subscription_And_Message()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
const string topic = "a";
|
||||
|
||||
using (var testEnvironment = CreateTestEnvironment())
|
||||
{
|
||||
await testEnvironment.StartServer(new MqttServerOptionsBuilder()
|
||||
.WithClientMessageQueueInterceptor(c => { })); // Interceptor does nothing but has to be present.
|
||||
|
||||
bool receivedMessage = false;
|
||||
var client = await testEnvironment.ConnectClient();
|
||||
client.UseApplicationMessageReceivedHandler(c => { receivedMessage = true; });
|
||||
|
||||
await client.SubscribeAsync(topic, MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
|
||||
await client.PublishAsync(new MqttApplicationMessage { Topic = topic, QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.IsTrue(receivedMessage);
|
||||
}
|
||||
// using (var testEnvironment = CreateTestEnvironment())
|
||||
// {
|
||||
// await testEnvironment.StartServer(new MqttServerOptionsBuilder()
|
||||
// .WithClientMessageQueueInterceptor(c => { })); // Interceptor does nothing but has to be present.
|
||||
//
|
||||
// bool receivedMessage = false;
|
||||
// var client = await testEnvironment.ConnectClient();
|
||||
// client.UseApplicationMessageReceivedHandler(c => { receivedMessage = true; });
|
||||
//
|
||||
// await client.SubscribeAsync(topic, MqttQualityOfServiceLevel.AtLeastOnce);
|
||||
//
|
||||
// await client.PublishAsync(new MqttApplicationMessage {Topic = topic, QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce});
|
||||
//
|
||||
// await Task.Delay(500);
|
||||
//
|
||||
// Assert.IsTrue(receivedMessage);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,14 @@ using MQTTnet.Tests.Mockups;
|
||||
namespace MQTTnet.Tests.Server
|
||||
{
|
||||
[TestClass]
|
||||
public class MqttSubscriptionsManager_Tests : BaseTestClass
|
||||
public sealed class MqttSubscriptionsManager_Tests : BaseTestClass
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task MqttSubscriptionsManager_SubscribeSingleSuccess()
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
@@ -35,7 +35,7 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
@@ -52,7 +52,7 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilter { Topic = "#", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
|
||||
@@ -70,7 +70,7 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
@@ -85,7 +85,7 @@ namespace MQTTnet.Tests.Server
|
||||
{
|
||||
var s = CreateSession();
|
||||
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventDispatcher(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
var sm = new MqttClientSubscriptionsManager(s, new MqttServerOptions(), new MqttServerEventContainer(new TestLogger()), new MqttRetainedMessagesManager());
|
||||
|
||||
var sp = new MqttSubscribePacket();
|
||||
sp.TopicFilters.Add(new MqttTopicFilterBuilder().WithTopic("A/B/C").Build());
|
||||
@@ -106,15 +106,15 @@ namespace MQTTnet.Tests.Server
|
||||
var logger = new TestLogger();
|
||||
var options = new MqttServerOptions();
|
||||
var retainedMessagesManager = new MqttRetainedMessagesManager();
|
||||
var eventDispatcher = new MqttServerEventDispatcher(logger);
|
||||
|
||||
var eventContainer = new MqttServerEventContainer(logger);
|
||||
|
||||
return new MqttClientSession(
|
||||
"",
|
||||
new ConcurrentDictionary<object, object>(),
|
||||
eventDispatcher,
|
||||
options,
|
||||
eventContainer,
|
||||
retainedMessagesManager,
|
||||
new MqttClientSessionsManager(options, retainedMessagesManager, eventDispatcher, logger));
|
||||
new MqttClientSessionsManager(options, retainedMessagesManager, eventContainer, logger));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user