diff --git a/Source/MQTTnet.AspnetCore/Extensions/ApplicationBuilderExtensions.cs b/Source/MQTTnet.AspnetCore/Extensions/ApplicationBuilderExtensions.cs index d9e7ed81..feb63fef 100644 --- a/Source/MQTTnet.AspnetCore/Extensions/ApplicationBuilderExtensions.cs +++ b/Source/MQTTnet.AspnetCore/Extensions/ApplicationBuilderExtensions.cs @@ -36,9 +36,9 @@ namespace MQTTnet.AspNetCore.Extensions return app; } - public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action configure) + public static IApplicationBuilder UseMqttServer(this IApplicationBuilder app, Action configure) { - var server = app.ApplicationServices.GetRequiredService(); + var server = app.ApplicationServices.GetRequiredService(); configure(server); diff --git a/Source/MQTTnet.AspnetCore/Extensions/ServiceCollectionExtensions.cs b/Source/MQTTnet.AspnetCore/Extensions/ServiceCollectionExtensions.cs index 683fe1cc..66295f5d 100644 --- a/Source/MQTTnet.AspnetCore/Extensions/ServiceCollectionExtensions.cs +++ b/Source/MQTTnet.AspnetCore/Extensions/ServiceCollectionExtensions.cs @@ -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 configure) { - services.AddSingleton(s => + services.AddSingleton(s => { var builder = new MqttServerOptionsBuilder(); configure(builder); @@ -38,7 +38,7 @@ namespace MQTTnet.AspNetCore.Extensions public static IServiceCollection AddHostedMqttServerWithServices(this IServiceCollection services, Action configure) { - services.AddSingleton(s => + services.AddSingleton(s => { var builder = new AspNetMqttServerOptionsBuilder(s); configure(builder); @@ -50,17 +50,17 @@ namespace MQTTnet.AspNetCore.Extensions return services; } - public static IServiceCollection AddHostedMqttServer(this IServiceCollection services) - where TOptions : class, IMqttServerOptions - { - services.AddSingleton(); + // public static IServiceCollection AddHostedMqttServer(this IServiceCollection services) + // where TOptions : MqttServerOptions + // { + // services.AddSingleton(); + // + // 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(); diff --git a/Source/MQTTnet.AspnetCore/MqttConnectionHandler.cs b/Source/MQTTnet.AspnetCore/MqttConnectionHandler.cs index 8cc1022d..49fdb945 100644 --- a/Source/MQTTnet.AspnetCore/MqttConnectionHandler.cs +++ b/Source/MQTTnet.AspnetCore/MqttConnectionHandler.cs @@ -33,7 +33,7 @@ namespace MQTTnet.AspNetCore } } - public Task StartAsync(IMqttServerOptions options) + public Task StartAsync(MqttServerOptions options) { return Task.CompletedTask; } diff --git a/Source/MQTTnet.AspnetCore/MqttHostedServer.cs b/Source/MQTTnet.AspnetCore/MqttHostedServer.cs index 9c08246a..10cb1078 100644 --- a/Source/MQTTnet.AspnetCore/MqttHostedServer.cs +++ b/Source/MQTTnet.AspnetCore/MqttHostedServer.cs @@ -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 adapters, IMqttNetLogger logger) + public MqttHostedServer(MqttServerOptions options, IEnumerable 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 ApplicationMessageReceivedAsync - { - add => _mqttServer.ApplicationMessageReceivedAsync += value; - remove => _mqttServer.ApplicationMessageReceivedAsync -= value; - } - public Task PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken) + public Task 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> 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() diff --git a/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs b/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs index 270305d1..f1d1fd89 100644 --- a/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs +++ b/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs @@ -21,7 +21,7 @@ namespace MQTTnet.AspNetCore public Func ClientHandler { get; set; } - public Task StartAsync(IMqttServerOptions options) + public Task StartAsync(MqttServerOptions options) { return Task.CompletedTask; } diff --git a/Source/MQTTnet.Extensions.ManagedClient/IManagedMqttClient.cs b/Source/MQTTnet.Extensions.ManagedClient/IManagedMqttClient.cs index cc2490cb..40940f52 100644 --- a/Source/MQTTnet.Extensions.ManagedClient/IManagedMqttClient.cs +++ b/Source/MQTTnet.Extensions.ManagedClient/IManagedMqttClient.cs @@ -8,7 +8,7 @@ using MQTTnet.Client; namespace MQTTnet.Extensions.ManagedClient { - public interface IManagedMqttClient : IApplicationMessageReceiver, IApplicationMessagePublisher, IDisposable + public interface IManagedMqttClient : IMqttApplicationMessageReceiver, IMqttApplicationMessagePublisher, IDisposable { /// /// Gets the internally used MQTT client. diff --git a/Source/MQTTnet.Extensions.ManagedClient/ManagedMqttClientExtensions.cs b/Source/MQTTnet.Extensions.ManagedClient/ManagedMqttClientExtensions.cs index d92e5c25..518f78dc 100644 --- a/Source/MQTTnet.Extensions.ManagedClient/ManagedMqttClientExtensions.cs +++ b/Source/MQTTnet.Extensions.ManagedClient/ManagedMqttClientExtensions.cs @@ -77,7 +77,7 @@ namespace MQTTnet.Extensions.ManagedClient } public static TReceiver UseApplicationMessageReceivedHandler(this TReceiver receiver, Func 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(this TReceiver receiver, Action 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(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 applicationMessages) + public static async Task PublishAsync(this IMqttApplicationMessagePublisher publisher, IEnumerable 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 PublishAsync(this IApplicationMessagePublisher publisher, MqttApplicationMessage applicationMessage) + public static Task 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 PublishAsync(this IApplicationMessagePublisher publisher, string topic) + public static Task 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 PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload) + public static Task 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 PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel) + public static Task 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 PublishAsync(this IApplicationMessagePublisher publisher, string topic, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, bool retain) + public static Task 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 PublishAsync(this IApplicationMessagePublisher publisher, Func builder, CancellationToken cancellationToken) + public static Task PublishAsync(this IMqttApplicationMessagePublisher publisher, Func 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 PublishAsync(this IApplicationMessagePublisher publisher, Func builder) + public static Task PublishAsync(this IMqttApplicationMessagePublisher publisher, Func builder) { if (publisher == null) throw new ArgumentNullException(nameof(publisher)); diff --git a/Source/MQTTnet.Extensions.ManagedClient/MqttFactoryExtensions.cs b/Source/MQTTnet.Extensions.ManagedClient/MqttFactoryExtensions.cs index 10256c58..e8fda4a9 100644 --- a/Source/MQTTnet.Extensions.ManagedClient/MqttFactoryExtensions.cs +++ b/Source/MQTTnet.Extensions.ManagedClient/MqttFactoryExtensions.cs @@ -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)); diff --git a/Source/MQTTnet.Extensions.WebSocket4Net/MqttFactoryExtensions.cs b/Source/MQTTnet.Extensions.WebSocket4Net/MqttFactoryExtensions.cs index 327074d1..011ca945 100644 --- a/Source/MQTTnet.Extensions.WebSocket4Net/MqttFactoryExtensions.cs +++ b/Source/MQTTnet.Extensions.WebSocket4Net/MqttFactoryExtensions.cs @@ -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)); diff --git a/Source/MQTTnet/Adapter/IMqttServerAdapter.cs b/Source/MQTTnet/Adapter/IMqttServerAdapter.cs index 52cda51d..78198f11 100644 --- a/Source/MQTTnet/Adapter/IMqttServerAdapter.cs +++ b/Source/MQTTnet/Adapter/IMqttServerAdapter.cs @@ -8,7 +8,7 @@ namespace MQTTnet.Adapter { Func ClientHandler { get; set; } - Task StartAsync(IMqttServerOptions options); + Task StartAsync(MqttServerOptions options); Task StopAsync(); } } diff --git a/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptions.cs b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptions.cs index 7f8c6441..ebf41292 100644 --- a/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptions.cs +++ b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptions.cs @@ -6,7 +6,7 @@ /// Gets or sets the reason code. /// Hint: MQTT 5 feature only. /// - public MqttClientDisconnectReason ReasonCode { get; set; } = MqttClientDisconnectReason.NormalDisconnection; + public MqttClientDisconnectReason Reason { get; set; } = MqttClientDisconnectReason.NormalDisconnection; /// /// Gets or sets the reason string. diff --git a/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptionsBuilder.cs b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptionsBuilder.cs new file mode 100644 index 00000000..c158e918 --- /dev/null +++ b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectOptionsBuilder.cs @@ -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 + }; + } + } +} \ No newline at end of file diff --git a/Source/MQTTnet/Client/IMqttClient.cs b/Source/MQTTnet/Client/IMqttClient.cs index 79feb1a3..11b515b9 100644 --- a/Source/MQTTnet/Client/IMqttClient.cs +++ b/Source/MQTTnet/Client/IMqttClient.cs @@ -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; } diff --git a/Source/MQTTnet/Client/IMqttClientFactory.cs b/Source/MQTTnet/Client/IMqttClientFactory.cs deleted file mode 100644 index 48314565..00000000 --- a/Source/MQTTnet/Client/IMqttClientFactory.cs +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Client/MqttClientExtensions.cs b/Source/MQTTnet/Client/MqttClientExtensions.cs index 97c500b6..89e92565 100644 --- a/Source/MQTTnet/Client/MqttClientExtensions.cs +++ b/Source/MQTTnet/Client/MqttClientExtensions.cs @@ -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); } diff --git a/Source/MQTTnet/Formatter/MqttConnAckPacketFactory.cs b/Source/MQTTnet/Formatter/MqttConnAckPacketFactory.cs index fd05b369..83d63977 100644 --- a/Source/MQTTnet/Formatter/MqttConnAckPacketFactory.cs +++ b/Source/MQTTnet/Formatter/MqttConnAckPacketFactory.cs @@ -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; diff --git a/Source/MQTTnet/Formatter/MqttDisconnectPacketFactory.cs b/Source/MQTTnet/Formatter/MqttDisconnectPacketFactory.cs index b0b3ebcf..f7d00d6c 100644 --- a/Source/MQTTnet/Formatter/MqttDisconnectPacketFactory.cs +++ b/Source/MQTTnet/Formatter/MqttDisconnectPacketFactory.cs @@ -16,7 +16,7 @@ namespace MQTTnet.Formatter } else { - packet.ReasonCode = (MqttDisconnectReasonCode) clientDisconnectOptions.ReasonCode; + packet.ReasonCode = (MqttDisconnectReasonCode) clientDisconnectOptions.Reason; } return packet; diff --git a/Source/MQTTnet/IApplicationMessagePublisher.cs b/Source/MQTTnet/IMqttApplicationMessagePublisher.cs similarity index 83% rename from Source/MQTTnet/IApplicationMessagePublisher.cs rename to Source/MQTTnet/IMqttApplicationMessagePublisher.cs index 7a93069c..ed43fbbe 100644 --- a/Source/MQTTnet/IApplicationMessagePublisher.cs +++ b/Source/MQTTnet/IMqttApplicationMessagePublisher.cs @@ -4,7 +4,7 @@ using MQTTnet.Client.Publishing; namespace MQTTnet { - public interface IApplicationMessagePublisher + public interface IMqttApplicationMessagePublisher { Task PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default); } diff --git a/Source/MQTTnet/IApplicationMessageReceiver.cs b/Source/MQTTnet/IMqttApplicationMessageReceiver.cs similarity index 92% rename from Source/MQTTnet/IApplicationMessageReceiver.cs rename to Source/MQTTnet/IMqttApplicationMessageReceiver.cs index fbd20ccc..0a674b5a 100644 --- a/Source/MQTTnet/IApplicationMessageReceiver.cs +++ b/Source/MQTTnet/IMqttApplicationMessageReceiver.cs @@ -4,7 +4,7 @@ using MQTTnet.Client.Receiving; namespace MQTTnet { - public interface IApplicationMessageReceiver + public interface IMqttApplicationMessageReceiver { /// /// Gets or sets the application message received handler that is fired every time a new message is received on the client's subscriptions. diff --git a/Source/MQTTnet/IMqttFactory.cs b/Source/MQTTnet/IMqttFactory.cs deleted file mode 100644 index 1c65f5c5..00000000 --- a/Source/MQTTnet/IMqttFactory.cs +++ /dev/null @@ -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 Properties { get; } - } -} diff --git a/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs b/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs index e3d495f9..02fa19c1 100644 --- a/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs +++ b/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs @@ -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."); diff --git a/Source/MQTTnet/Internal/AsyncEvent.cs b/Source/MQTTnet/Internal/AsyncEvent.cs index ba868f0e..9fbaa19c 100644 --- a/Source/MQTTnet/Internal/AsyncEvent.cs +++ b/Source/MQTTnet/Internal/AsyncEvent.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace MQTTnet.Internal { - public sealed class AsyncEvent + public sealed class AsyncEvent where TEventArgs : EventArgs { readonly List> _handlers = new List>(); @@ -29,5 +30,19 @@ namespace MQTTnet.Internal await handler.Invoke(eventArgs); } } + + public async Task InvokeAsync(Func 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; + } } } \ No newline at end of file diff --git a/Source/MQTTnet/MQTTnet.csproj.DotSettings b/Source/MQTTnet/MQTTnet.csproj.DotSettings new file mode 100644 index 00000000..c72d42a0 --- /dev/null +++ b/Source/MQTTnet/MQTTnet.csproj.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/Source/MQTTnet/MqttFactory.cs b/Source/MQTTnet/MqttFactory.cs index 6a036598..fbdec74e 100644 --- a/Source/MQTTnet/MqttFactory.cs +++ b/Source/MQTTnet/MqttFactory.cs @@ -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> DefaultServerAdapters { get; } = new List> + public IList> DefaultServerAdapters { get; } = new List> { factory => new MqttTcpServerAdapter(factory.DefaultLogger) }; public IDictionary Properties { get; } = new Dictionary(); - 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 serverAdapters, IMqttNetLogger logger) + public MqttServer CreateMqttServer(MqttServerOptions options, IEnumerable 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 serverAdapters) + public MqttServer CreateMqttServer(MqttServerOptions options, IEnumerable 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() diff --git a/Source/MQTTnet/Server/GetSubscribedMessagesFilter.cs b/Source/MQTTnet/Server/GetSubscribedMessagesFilter.cs deleted file mode 100644 index 004efeaf..00000000 --- a/Source/MQTTnet/Server/GetSubscribedMessagesFilter.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace MQTTnet.Server -{ - public sealed class GetSubscribedMessagesFilter - { - public bool IsNewSubscription { get; set; } - - public MqttTopicFilter TopicFilter { get; set; } - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/IMqttClientSession.cs b/Source/MQTTnet/Server/IMqttClientSession.cs deleted file mode 100644 index f522df68..00000000 --- a/Source/MQTTnet/Server/IMqttClientSession.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttClientSession - { - /// - /// Gets the client identifier. - /// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues. - /// - string ClientId { get; } - - Task StopAsync(); - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/IMqttRetainedMessagesManager.cs b/Source/MQTTnet/Server/IMqttRetainedMessagesManager.cs index 4b85a7e1..bc4022e4 100644 --- a/Source/MQTTnet/Server/IMqttRetainedMessagesManager.cs +++ b/Source/MQTTnet/Server/IMqttRetainedMessagesManager.cs @@ -7,7 +7,7 @@ namespace MQTTnet.Server { public interface IMqttRetainedMessagesManager { - Task Start(IMqttServerOptions options, IMqttNetLogger logger); + Task Start(MqttServerOptions options, IMqttNetLogger logger); Task LoadMessagesAsync(); diff --git a/Source/MQTTnet/Server/IMqttServer.cs b/Source/MQTTnet/Server/IMqttServer.cs index 4b920cf8..389a9f20 100644 --- a/Source/MQTTnet/Server/IMqttServer.cs +++ b/Source/MQTTnet/Server/IMqttServer.cs @@ -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> GetClientStatusAsync(); Task> GetSessionStatusAsync(); @@ -27,7 +17,7 @@ namespace MQTTnet.Server Task SubscribeAsync(string clientId, ICollection topicFilters); Task UnsubscribeAsync(string clientId, ICollection topicFilters); - Task StartAsync(IMqttServerOptions options); + Task StartAsync(); Task StopAsync(); } } \ No newline at end of file diff --git a/Source/MQTTnet/Server/IMqttServerApplicationMessageInterceptor.cs b/Source/MQTTnet/Server/IMqttServerApplicationMessageInterceptor.cs deleted file mode 100644 index 64fe0471..00000000 --- a/Source/MQTTnet/Server/IMqttServerApplicationMessageInterceptor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerApplicationMessageInterceptor - { - Task InterceptApplicationMessagePublishAsync(MqttApplicationMessageInterceptorContext context); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerClientConnectedHandler.cs b/Source/MQTTnet/Server/IMqttServerClientConnectedHandler.cs deleted file mode 100644 index b507e41b..00000000 --- a/Source/MQTTnet/Server/IMqttServerClientConnectedHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerClientConnectedHandler - { - Task HandleClientConnectedAsync(MqttServerClientConnectedEventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerClientDisconnectedHandler.cs b/Source/MQTTnet/Server/IMqttServerClientDisconnectedHandler.cs deleted file mode 100644 index 3614d2d2..00000000 --- a/Source/MQTTnet/Server/IMqttServerClientDisconnectedHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerClientDisconnectedHandler - { - Task HandleClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerClientMessageQueueInterceptor.cs b/Source/MQTTnet/Server/IMqttServerClientMessageQueueInterceptor.cs deleted file mode 100644 index c6f97a73..00000000 --- a/Source/MQTTnet/Server/IMqttServerClientMessageQueueInterceptor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerClientMessageQueueInterceptor - { - Task InterceptClientMessageQueueEnqueueAsync(MqttClientMessageQueueInterceptorContext context); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerClientSubscribedTopicHandler.cs b/Source/MQTTnet/Server/IMqttServerClientSubscribedTopicHandler.cs deleted file mode 100644 index 6f82bb36..00000000 --- a/Source/MQTTnet/Server/IMqttServerClientSubscribedTopicHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerClientSubscribedTopicHandler - { - Task HandleClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerClientUnsubscribedTopicHandler.cs b/Source/MQTTnet/Server/IMqttServerClientUnsubscribedTopicHandler.cs deleted file mode 100644 index 077a80f9..00000000 --- a/Source/MQTTnet/Server/IMqttServerClientUnsubscribedTopicHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerClientUnsubscribedTopicHandler - { - Task HandleClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerConnectionValidator.cs b/Source/MQTTnet/Server/IMqttServerConnectionValidator.cs deleted file mode 100644 index 68b5be6f..00000000 --- a/Source/MQTTnet/Server/IMqttServerConnectionValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerConnectionValidator - { - Task ValidateConnectionAsync(MqttConnectionValidatorContext context); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerFactory.cs b/Source/MQTTnet/Server/IMqttServerFactory.cs deleted file mode 100644 index a612c861..00000000 --- a/Source/MQTTnet/Server/IMqttServerFactory.cs +++ /dev/null @@ -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> DefaultServerAdapters { get; } - - IMqttServer CreateMqttServer(); - - IMqttServer CreateMqttServer(IMqttNetLogger logger); - - IMqttServer CreateMqttServer(IEnumerable adapters); - - IMqttServer CreateMqttServer(IEnumerable adapters, IMqttNetLogger logger); - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/IMqttServerOptions.cs b/Source/MQTTnet/Server/IMqttServerOptions.cs deleted file mode 100644 index f5cad0dc..00000000 --- a/Source/MQTTnet/Server/IMqttServerOptions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace MQTTnet.Server -{ - public interface IMqttServerOptions - { - /// - /// Gets the client identifier. - /// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues. - /// - 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; } - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/IMqttServerStartedHandler.cs b/Source/MQTTnet/Server/IMqttServerStartedHandler.cs deleted file mode 100644 index e6155f14..00000000 --- a/Source/MQTTnet/Server/IMqttServerStartedHandler.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerStartedHandler - { - Task HandleServerStartedAsync(EventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerStoppedHandler.cs b/Source/MQTTnet/Server/IMqttServerStoppedHandler.cs deleted file mode 100644 index 34df3236..00000000 --- a/Source/MQTTnet/Server/IMqttServerStoppedHandler.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerStoppedHandler - { - Task HandleServerStoppedAsync(EventArgs eventArgs); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerSubscriptionInterceptor.cs b/Source/MQTTnet/Server/IMqttServerSubscriptionInterceptor.cs deleted file mode 100644 index a7ce95ef..00000000 --- a/Source/MQTTnet/Server/IMqttServerSubscriptionInterceptor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerSubscriptionInterceptor - { - Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context); - } -} diff --git a/Source/MQTTnet/Server/IMqttServerUnsubscriptionInterceptor.cs b/Source/MQTTnet/Server/IMqttServerUnsubscriptionInterceptor.cs deleted file mode 100644 index 96693832..00000000 --- a/Source/MQTTnet/Server/IMqttServerUnsubscriptionInterceptor.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace MQTTnet.Server -{ - public interface IMqttServerUnsubscriptionInterceptor - { - Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context); - } -} diff --git a/Source/MQTTnet/Server/MqttApplicationMessageInterceptorContext.cs b/Source/MQTTnet/Server/InterceptingMqttClientPublishEventArgs.cs similarity index 91% rename from Source/MQTTnet/Server/MqttApplicationMessageInterceptorContext.cs rename to Source/MQTTnet/Server/InterceptingMqttClientPublishEventArgs.cs index bad2bc33..ca67b04c 100644 --- a/Source/MQTTnet/Server/MqttApplicationMessageInterceptorContext.cs +++ b/Source/MQTTnet/Server/InterceptingMqttClientPublishEventArgs.cs @@ -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 { /// /// Gets the client identifier. diff --git a/Source/MQTTnet/Server/MqttSubscriptionInterceptorContext.cs b/Source/MQTTnet/Server/InterceptingMqttClientSubscriptionEventArgs.cs similarity index 93% rename from Source/MQTTnet/Server/MqttSubscriptionInterceptorContext.cs rename to Source/MQTTnet/Server/InterceptingMqttClientSubscriptionEventArgs.cs index 3ec75a10..02bb2405 100644 --- a/Source/MQTTnet/Server/MqttSubscriptionInterceptorContext.cs +++ b/Source/MQTTnet/Server/InterceptingMqttClientSubscriptionEventArgs.cs @@ -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 { /// /// Gets the client identifier. diff --git a/Source/MQTTnet/Server/MqttUnsubscriptionInterceptorContext.cs b/Source/MQTTnet/Server/InterceptingMqttClientUnsubscriptionEventArgs.cs similarity index 93% rename from Source/MQTTnet/Server/MqttUnsubscriptionInterceptorContext.cs rename to Source/MQTTnet/Server/InterceptingMqttClientUnsubscriptionEventArgs.cs index 4371f38b..0092abb7 100644 --- a/Source/MQTTnet/Server/MqttUnsubscriptionInterceptorContext.cs +++ b/Source/MQTTnet/Server/InterceptingMqttClientUnsubscriptionEventArgs.cs @@ -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 { /// /// Gets the client identifier. diff --git a/Source/MQTTnet/Server/Internal/MqttApplicationMessageInterceptorInvoker.cs b/Source/MQTTnet/Server/Internal/MqttApplicationMessageInterceptorInvoker.cs index 418d281f..ad30a733 100644 --- a/Source/MQTTnet/Server/Internal/MqttApplicationMessageInterceptorInvoker.cs +++ b/Source/MQTTnet/Server/Internal/MqttApplicationMessageInterceptorInvoker.cs @@ -7,13 +7,13 @@ namespace MQTTnet.Server.Internal { public sealed class MqttApplicationMessageInterceptorInvoker { - readonly IMqttServerOptions _serverOptions; + readonly MqttServerEventContainer _eventContainer; readonly string _clientId; readonly IDictionary _sessionItems; - public MqttApplicationMessageInterceptorInvoker(IMqttServerOptions serverOptions, string clientId, IDictionary sessionItems) + public MqttApplicationMessageInterceptorInvoker(MqttServerEventContainer eventContainer, string clientId, IDictionary 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; } } } \ No newline at end of file diff --git a/Source/MQTTnet/Server/Internal/MqttClientConnection.cs b/Source/MQTTnet/Server/Internal/MqttClientConnection.cs index ff5dcc40..90eda9d6 100644 --- a/Source/MQTTnet/Server/Internal/MqttClientConnection.cs +++ b/Source/MQTTnet/Server/Internal/MqttClientConnection.cs @@ -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() }; diff --git a/Source/MQTTnet/Server/Internal/MqttClientConnectionStatistics.cs b/Source/MQTTnet/Server/Internal/MqttClientConnectionStatistics.cs index c23c6f06..5c55d65b 100644 --- a/Source/MQTTnet/Server/Internal/MqttClientConnectionStatistics.cs +++ b/Source/MQTTnet/Server/Internal/MqttClientConnectionStatistics.cs @@ -1,7 +1,6 @@ using System; using System.Threading; using MQTTnet.Packets; -using MQTTnet.Server.Status; namespace MQTTnet.Server.Internal { diff --git a/Source/MQTTnet/Server/Internal/MqttClientSession.cs b/Source/MQTTnet/Server/Internal/MqttClientSession.cs index 3aa8db5a..1b3f6dbb 100644 --- a/Source/MQTTnet/Server/Internal/MqttClientSession.cs +++ b/Source/MQTTnet/Server/Internal/MqttClientSession.cs @@ -16,13 +16,13 @@ namespace MQTTnet.Server.Internal readonly Dictionary _unacknowledgedPublishPackets = new Dictionary(); - readonly IMqttServerOptions _serverOptions; + readonly MqttServerOptions _serverOptions; readonly MqttClientSessionsManager _clientSessionsManager; public MqttClientSession(string clientId, IDictionary 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 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. diff --git a/Source/MQTTnet/Server/Internal/MqttClientSessionApplicationMessagesQueue.cs b/Source/MQTTnet/Server/Internal/MqttClientSessionApplicationMessagesQueue.cs deleted file mode 100644 index da49c5b4..00000000 --- a/Source/MQTTnet/Server/Internal/MqttClientSessionApplicationMessagesQueue.cs +++ /dev/null @@ -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 _messageQueue = new AsyncQueue(); - - 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 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(); - } - } -} diff --git a/Source/MQTTnet/Server/Internal/MqttClientSessionsManager.cs b/Source/MQTTnet/Server/Internal/MqttClientSessionsManager.cs index 9a1de8b4..0c6333f8 100644 --- a/Source/MQTTnet/Server/Internal/MqttClientSessionsManager.cs +++ b/Source/MQTTnet/Server/Internal/MqttClientSessionsManager.cs @@ -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 _messageQueue = new BlockingCollection(); 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 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 ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter) + async Task ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter) { - var context = new MqttConnectionValidatorContext(connectPacket, channelAdapter) + var context = new ValidatingMqttClientConnectionEventArgs(connectPacket, channelAdapter) { SessionItems = new ConcurrentDictionary() }; - - 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 InterceptApplicationMessageAsync( - IMqttServerApplicationMessageInterceptor interceptor, - MqttClientConnection clientConnection, - MqttApplicationMessage applicationMessage) - { - string senderClientId; - IDictionary 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 InterceptApplicationMessageAsync( + // IMqttServerApplicationMessageInterceptor interceptor, + // MqttClientConnection clientConnection, + // MqttApplicationMessage applicationMessage) + // { + // string senderClientId; + // IDictionary 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(); + } + } } } \ No newline at end of file diff --git a/Source/MQTTnet/Server/Internal/MqttClientSubscriptionsManager.cs b/Source/MQTTnet/Server/Internal/MqttClientSubscriptionsManager.cs index b65f7a9a..a01aa8e2 100644 --- a/Source/MQTTnet/Server/Internal/MqttClientSubscriptionsManager.cs +++ b/Source/MQTTnet/Server/Internal/MqttClientSubscriptionsManager.cs @@ -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 _subscriptions = new Dictionary(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 retainedApplicationMessages, - MqttSubscription mqttSubscription, MqttSubscribeResult mqttSubscribeResult) + static void FilterRetainedApplicationMessages(IList 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 {mqttSubscription.Identifier}; + queuedApplicationMessage.SubscriptionIdentifiers = new List {createSubscriptionResult.Subscription.Identifier}; } - mqttSubscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage); + subscribeResult.RetainedApplicationMessages.Add(queuedApplicationMessage); retainedApplicationMessages[i] = null; } } - async Task InterceptSubscribe(MqttTopicFilter topicFilter, CancellationToken cancellationToken) + async Task 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 InterceptUnsubscribe(string topicFilter, MqttSubscription mqttSubscription, CancellationToken cancellationToken) + async Task 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 subscribedQoSLevels) diff --git a/Source/MQTTnet/Server/Internal/MqttRetainedMessagesManager.cs b/Source/MQTTnet/Server/Internal/MqttRetainedMessagesManager.cs index ebe8ee2d..4555150b 100644 --- a/Source/MQTTnet/Server/Internal/MqttRetainedMessagesManager.cs +++ b/Source/MQTTnet/Server/Internal/MqttRetainedMessagesManager.cs @@ -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 _messages = new Dictionary(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)); diff --git a/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs b/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs new file mode 100644 index 00000000..5d050d0f --- /dev/null +++ b/Source/MQTTnet/Server/Internal/MqttServerEventContainer.cs @@ -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 InterceptingClientSubscriptionEvent { get; } = new AsyncEvent(); + + public AsyncEvent InterceptingClientUnsubscriptionEvent { get; } = new AsyncEvent(); + + public AsyncEvent InterceptingClientPublishEvent { get; } = new AsyncEvent(); + + public AsyncEvent ValidatingClientConnectionEvent { get; } = new AsyncEvent(); + public AsyncEvent ClientConnectedEvent { get; } = new AsyncEvent(); + public AsyncEvent ClientDisconnectedEvent { get; } = new AsyncEvent(); + public AsyncEvent ClientSubscribedTopicEvent { get; } = new AsyncEvent(); + public AsyncEvent ClientUnsubscribedTopicEvent { get; } = new AsyncEvent(); + + public AsyncEvent PreparingClientSessionEvent { get; } = new AsyncEvent(); + public AsyncEvent StartedEvent { get; } = new AsyncEvent(); + + public AsyncEvent StoppedEvent { get; } = new AsyncEvent(); + + // 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."); + // } + // } + } +} diff --git a/Source/MQTTnet/Server/Internal/MqttServerEventDispatcher.cs b/Source/MQTTnet/Server/Internal/MqttServerEventDispatcher.cs deleted file mode 100644 index 3410bd42..00000000 --- a/Source/MQTTnet/Server/Internal/MqttServerEventDispatcher.cs +++ /dev/null @@ -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 ClientConnectedEvent { get; } = new AsyncEvent(); - - public AsyncEvent ClientDisconnectedEvent { get; } = new AsyncEvent(); - - public AsyncEvent ClientSubscribedTopicEvent { get; } = new AsyncEvent(); - - public AsyncEvent ClientUnsubscribedTopicEvent { get; } = new AsyncEvent(); - - public AsyncEvent ApplicationMessageReceivedEvent { get; } = new AsyncEvent(); - - 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."); - } - } - } -} diff --git a/Source/MQTTnet/Server/Internal/MqttServerKeepAliveMonitor.cs b/Source/MQTTnet/Server/Internal/MqttServerKeepAliveMonitor.cs index b7a848b1..f73af5ac 100644 --- a/Source/MQTTnet/Server/Internal/MqttServerKeepAliveMonitor.cs +++ b/Source/MQTTnet/Server/Internal/MqttServerKeepAliveMonitor.cs @@ -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)); diff --git a/Source/MQTTnet/Server/Internal/MqttSubscription.cs b/Source/MQTTnet/Server/Internal/MqttSubscription.cs index 9234ea2b..a78663bc 100644 --- a/Source/MQTTnet/Server/Internal/MqttSubscription.cs +++ b/Source/MQTTnet/Server/Internal/MqttSubscription.cs @@ -15,7 +15,5 @@ namespace MQTTnet.Server.Internal public MqttQualityOfServiceLevel GrantedQualityOfServiceLevel { get; set; } public uint Identifier { get; set; } - - public bool IsNewSubscription { get; set; } } } \ No newline at end of file diff --git a/Source/MQTTnet/Server/MqttServerClientConnectedEventArgs.cs b/Source/MQTTnet/Server/MqttClientConnectedEventArgs.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerClientConnectedEventArgs.cs rename to Source/MQTTnet/Server/MqttClientConnectedEventArgs.cs diff --git a/Source/MQTTnet/Server/MqttServerClientDisconnectedEventArgs.cs b/Source/MQTTnet/Server/MqttClientDisconnectedEventArgs.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerClientDisconnectedEventArgs.cs rename to Source/MQTTnet/Server/MqttClientDisconnectedEventArgs.cs diff --git a/Source/MQTTnet/Server/MqttClientMessageQueueInterceptorDelegate.cs b/Source/MQTTnet/Server/MqttClientMessageQueueInterceptorDelegate.cs deleted file mode 100644 index 9d1118dd..00000000 --- a/Source/MQTTnet/Server/MqttClientMessageQueueInterceptorDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttClientMessageQueueInterceptorDelegate : IMqttServerClientMessageQueueInterceptor - { - readonly Func _callback; - - public MqttClientMessageQueueInterceptorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttClientMessageQueueInterceptorDelegate(Func callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - public Task InterceptClientMessageQueueEnqueueAsync(MqttClientMessageQueueInterceptorContext context) - { - return _callback(context); - } - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/MqttServerClientSubscribedTopicEventArgs.cs b/Source/MQTTnet/Server/MqttClientSubscribedTopicEventArgs.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerClientSubscribedTopicEventArgs.cs rename to Source/MQTTnet/Server/MqttClientSubscribedTopicEventArgs.cs diff --git a/Source/MQTTnet/Server/MqttServerClientUnsubscribedTopicEventArgs.cs b/Source/MQTTnet/Server/MqttClientUnsubscribedTopicEventArgs.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerClientUnsubscribedTopicEventArgs.cs rename to Source/MQTTnet/Server/MqttClientUnsubscribedTopicEventArgs.cs diff --git a/Source/MQTTnet/Server/MqttPendingApplicationMessage.cs b/Source/MQTTnet/Server/MqttPendingApplicationMessage.cs deleted file mode 100644 index 2c12e4b0..00000000 --- a/Source/MQTTnet/Server/MqttPendingApplicationMessage.cs +++ /dev/null @@ -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; } - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/MqttServer.cs b/Source/MQTTnet/Server/MqttServer.cs index 0ae875e4..227d9e04 100644 --- a/Source/MQTTnet/Server/MqttServer.cs +++ b/Source/MQTTnet/Server/MqttServer.cs @@ -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 _startedEvent = new AsyncEvent(); - readonly AsyncEvent _stoppedEvent = new AsyncEvent(); + readonly MqttServerEventContainer _eventContainer; - readonly MqttServerEventDispatcher _eventDispatcher; readonly ICollection _adapters; + readonly MqttServerOptions _options; readonly IMqttNetLogger _rootLogger; readonly MqttNetSourceLogger _logger; @@ -31,98 +28,87 @@ namespace MQTTnet.Server MqttServerKeepAliveMonitor _keepAliveMonitor; CancellationTokenSource _cancellationTokenSource; - public MqttServer(IEnumerable adapters, IMqttNetLogger logger) + public MqttServer(MqttServerOptions options, IEnumerable 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 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 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 ValidatingClientConnectionAsync { - get => _eventDispatcher.ClientConnectedHandler; - set => _eventDispatcher.ClientConnectedHandler = value; + add => _eventContainer.ValidatingClientConnectionEvent.AddHandler(value); + remove => _eventContainer.ValidatingClientConnectionEvent.RemoveHandler(value); } - + public event Func 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 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 InterceptingClientSubscriptionAsync { - get => _eventDispatcher.ClientSubscribedTopicHandler; - set => _eventDispatcher.ClientSubscribedTopicHandler = value; + add => _eventContainer.InterceptingClientSubscriptionEvent.AddHandler(value); + remove => _eventContainer.InterceptingClientSubscriptionEvent.RemoveHandler(value); } - + + public event Func InterceptingClientUnsubscriptionAsync + { + add => _eventContainer.InterceptingClientUnsubscriptionEvent.AddHandler(value); + remove => _eventContainer.InterceptingClientUnsubscriptionEvent.RemoveHandler(value); + } + + public event Func InterceptingClientPublishAsync + { + add => _eventContainer.InterceptingClientPublishEvent.AddHandler(value); + remove => _eventContainer.InterceptingClientPublishEvent.RemoveHandler(value); + } + public event Func 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 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 ApplicationMessageReceivedAsync + public event Func 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> GetClientStatusAsync() { ThrowIfDisposed(); @@ -182,7 +168,7 @@ namespace MQTTnet.Server return _clientSessionsManager.UnsubscribeAsync(clientId, topicFilters); } - public async Task PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken) + public async Task 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) diff --git a/Source/MQTTnet/Server/MqttServerApplicationMessageInterceptorDelegate.cs b/Source/MQTTnet/Server/MqttServerApplicationMessageInterceptorDelegate.cs deleted file mode 100644 index e946399d..00000000 --- a/Source/MQTTnet/Server/MqttServerApplicationMessageInterceptorDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerApplicationMessageInterceptorDelegate : IMqttServerApplicationMessageInterceptor - { - readonly Func _callback; - - public MqttServerApplicationMessageInterceptorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerApplicationMessageInterceptorDelegate(Func callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - public Task InterceptApplicationMessagePublishAsync(MqttApplicationMessageInterceptorContext context) - { - return _callback(context); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerClientConnectedHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerClientConnectedHandlerDelegate.cs deleted file mode 100644 index a416ea9c..00000000 --- a/Source/MQTTnet/Server/MqttServerClientConnectedHandlerDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerClientConnectedHandlerDelegate : IMqttServerClientConnectedHandler - { - readonly Func _handler; - - public MqttServerClientConnectedHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerClientConnectedHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleClientConnectedAsync(MqttServerClientConnectedEventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerClientDisconnectedHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerClientDisconnectedHandlerDelegate.cs deleted file mode 100644 index 2a03df90..00000000 --- a/Source/MQTTnet/Server/MqttServerClientDisconnectedHandlerDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerClientDisconnectedHandlerDelegate : IMqttServerClientDisconnectedHandler - { - readonly Func _handler; - - public MqttServerClientDisconnectedHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerClientDisconnectedHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerClientSubscribedTopicHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerClientSubscribedTopicHandlerDelegate.cs deleted file mode 100644 index 6dbf4a31..00000000 --- a/Source/MQTTnet/Server/MqttServerClientSubscribedTopicHandlerDelegate.cs +++ /dev/null @@ -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 handler) : base(handler) - { - } - - public MqttServerClientSubscribedHandlerDelegate(Func handler) : base(handler) - { - } - } - - public class MqttServerClientSubscribedTopicHandlerDelegate : IMqttServerClientSubscribedTopicHandler - { - readonly Func _handler; - - public MqttServerClientSubscribedTopicHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerClientSubscribedTopicHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerClientUnsubscribedTopicHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerClientUnsubscribedTopicHandlerDelegate.cs deleted file mode 100644 index c93636c8..00000000 --- a/Source/MQTTnet/Server/MqttServerClientUnsubscribedTopicHandlerDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerClientUnsubscribedTopicHandlerDelegate : IMqttServerClientUnsubscribedTopicHandler - { - readonly Func _handler; - - public MqttServerClientUnsubscribedTopicHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerClientUnsubscribedTopicHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerConnectionValidatorDelegate.cs b/Source/MQTTnet/Server/MqttServerConnectionValidatorDelegate.cs deleted file mode 100644 index b6a51a17..00000000 --- a/Source/MQTTnet/Server/MqttServerConnectionValidatorDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerConnectionValidatorDelegate : IMqttServerConnectionValidator - { - readonly Func _callback; - - public MqttServerConnectionValidatorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerConnectionValidatorDelegate(Func callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - public Task ValidateConnectionAsync(MqttConnectionValidatorContext context) - { - return _callback(context); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerExtensions.cs b/Source/MQTTnet/Server/MqttServerExtensions.cs index b0282b37..60d9bc58 100644 --- a/Source/MQTTnet/Server/MqttServerExtensions.cs +++ b/Source/MQTTnet/Server/MqttServerExtensions.cs @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 PublishAsync(this IMqttServer server, Func 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 PublishAsync(this IMqttServer server, Func builder) - { - if (server == null) throw new ArgumentNullException(nameof(server)); - - var message = builder(new MqttApplicationMessageBuilder()).Build(); - return server.PublishAsync(message, CancellationToken.None); - } + // public static Task PublishAsync(this IMqttServer server, Func 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 PublishAsync(this IMqttServer server, Func builder) + // { + // if (server == null) throw new ArgumentNullException(nameof(server)); + // + // var message = builder(new MqttApplicationMessageBuilder()).Build(); + // return server.PublishAsync(message, CancellationToken.None); + // } } } diff --git a/Source/MQTTnet/Server/MqttServerMultiThreadedApplicationMessageInterceptorDelegate.cs b/Source/MQTTnet/Server/MqttServerMultiThreadedApplicationMessageInterceptorDelegate.cs deleted file mode 100644 index bd7b6ec9..00000000 --- a/Source/MQTTnet/Server/MqttServerMultiThreadedApplicationMessageInterceptorDelegate.cs +++ /dev/null @@ -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 _callback; - - public MqttServerMultiThreadedApplicationMessageInterceptorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public Func ExceptionHandler { get; set; } - - public MqttServerMultiThreadedApplicationMessageInterceptorDelegate(Func 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; - } - } -} \ No newline at end of file diff --git a/Source/MQTTnet/Server/MqttServerStartedHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerStartedHandlerDelegate.cs deleted file mode 100644 index ad331844..00000000 --- a/Source/MQTTnet/Server/MqttServerStartedHandlerDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerStartedHandlerDelegate : IMqttServerStartedHandler - { - readonly Func _handler; - - public MqttServerStartedHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerStartedHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleServerStartedAsync(EventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerStoppedHandlerDelegate.cs b/Source/MQTTnet/Server/MqttServerStoppedHandlerDelegate.cs deleted file mode 100644 index 8a9a37e2..00000000 --- a/Source/MQTTnet/Server/MqttServerStoppedHandlerDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerStoppedHandlerDelegate : IMqttServerStoppedHandler - { - readonly Func _handler; - - public MqttServerStoppedHandlerDelegate(Action handler) - { - if (handler == null) throw new ArgumentNullException(nameof(handler)); - - _handler = eventArgs => - { - handler(eventArgs); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerStoppedHandlerDelegate(Func handler) - { - _handler = handler ?? throw new ArgumentNullException(nameof(handler)); - } - - public Task HandleServerStoppedAsync(EventArgs eventArgs) - { - return _handler(eventArgs); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerSubscriptionInterceptorDelegate.cs b/Source/MQTTnet/Server/MqttServerSubscriptionInterceptorDelegate.cs deleted file mode 100644 index 88d68234..00000000 --- a/Source/MQTTnet/Server/MqttServerSubscriptionInterceptorDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerSubscriptionInterceptorDelegate : IMqttServerSubscriptionInterceptor - { - readonly Func _callback; - - public MqttServerSubscriptionInterceptorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerSubscriptionInterceptorDelegate(Func callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - public Task InterceptSubscriptionAsync(MqttSubscriptionInterceptorContext context) - { - return _callback(context); - } - } -} diff --git a/Source/MQTTnet/Server/MqttServerUnsubscriptionInterceptorDelegate.cs b/Source/MQTTnet/Server/MqttServerUnsubscriptionInterceptorDelegate.cs deleted file mode 100644 index d70f1e14..00000000 --- a/Source/MQTTnet/Server/MqttServerUnsubscriptionInterceptorDelegate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using MQTTnet.Implementations; - -namespace MQTTnet.Server -{ - public sealed class MqttServerUnsubscriptionInterceptorDelegate : IMqttServerUnsubscriptionInterceptor - { - readonly Func _callback; - - public MqttServerUnsubscriptionInterceptorDelegate(Action callback) - { - if (callback == null) throw new ArgumentNullException(nameof(callback)); - - _callback = context => - { - callback(context); - return PlatformAbstractionLayer.CompletedTask; - }; - } - - public MqttServerUnsubscriptionInterceptorDelegate(Func callback) - { - _callback = callback ?? throw new ArgumentNullException(nameof(callback)); - } - - public Task InterceptUnsubscriptionAsync(MqttUnsubscriptionInterceptorContext context) - { - return _callback(context); - } - } -} diff --git a/Source/MQTTnet/Server/IMqttServerCertificateCredentials.cs b/Source/MQTTnet/Server/Options/IMqttServerCertificateCredentials.cs similarity index 100% rename from Source/MQTTnet/Server/IMqttServerCertificateCredentials.cs rename to Source/MQTTnet/Server/Options/IMqttServerCertificateCredentials.cs diff --git a/Source/MQTTnet/Server/MqttServerCertificateCredentials.cs b/Source/MQTTnet/Server/Options/MqttServerCertificateCredentials.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerCertificateCredentials.cs rename to Source/MQTTnet/Server/Options/MqttServerCertificateCredentials.cs diff --git a/Source/MQTTnet/Server/MqttServerOptions.cs b/Source/MQTTnet/Server/Options/MqttServerOptions.cs similarity index 52% rename from Source/MQTTnet/Server/MqttServerOptions.cs rename to Source/MQTTnet/Server/Options/MqttServerOptions.cs index 28233657..cb5a584a 100644 --- a/Source/MQTTnet/Server/MqttServerOptions.cs +++ b/Source/MQTTnet/Server/Options/MqttServerOptions.cs @@ -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(); - - /// - /// 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. - /// - 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(); diff --git a/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs b/Source/MQTTnet/Server/Options/MqttServerOptionsBuilder.cs similarity index 57% rename from Source/MQTTnet/Server/MqttServerOptionsBuilder.cs rename to Source/MQTTnet/Server/Options/MqttServerOptionsBuilder.cs index 0f2d6aea..9aec4f89 100644 --- a/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs +++ b/Source/MQTTnet/Server/Options/MqttServerOptionsBuilder.cs @@ -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 value) - { - _options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(value); - return this; - } - public MqttServerOptionsBuilder WithConnectionValidator(Func value) - { - _options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(value); - return this; - } + // public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value) + // { + // _options.ApplicationMessageInterceptor = value; + // return this; + // } + // + // public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Action value) + // { + // _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value); + // return this; + // } + // + // public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Func value) + // { + // _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value); + // return this; + // } + + // public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Action value) + // { + // _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value); + // return this; + // } + // + // public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Func value) + // { + // _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value); + // return this; + // } - public MqttServerOptionsBuilder WithApplicationMessageInterceptor(IMqttServerApplicationMessageInterceptor value) - { - _options.ApplicationMessageInterceptor = value; - return this; - } - - public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Action value) - { - _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithApplicationMessageInterceptor(Func value) - { - _options.ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Action value) - { - _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithMultiThreadedApplicationMessageInterceptor(Func value) - { - _options.ApplicationMessageInterceptor = new MqttServerMultiThreadedApplicationMessageInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithClientMessageQueueInterceptor(IMqttServerClientMessageQueueInterceptor value) - { - _options.ClientMessageQueueInterceptor = value; - return this; - } - - public MqttServerOptionsBuilder WithClientMessageQueueInterceptor(Action value) - { - _options.ClientMessageQueueInterceptor = new MqttClientMessageQueueInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithSubscriptionInterceptor(IMqttServerSubscriptionInterceptor value) - { - _options.SubscriptionInterceptor = value; - return this; - } - - public MqttServerOptionsBuilder WithSubscriptionInterceptor(Action value) - { - _options.SubscriptionInterceptor = new MqttServerSubscriptionInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithUnsubscriptionInterceptor(IMqttServerUnsubscriptionInterceptor value) - { - _options.UnsubscriptionInterceptor = value; - return this; - } - - public MqttServerOptionsBuilder WithUnsubscriptionInterceptor(Action value) - { - _options.UnsubscriptionInterceptor = new MqttServerUnsubscriptionInterceptorDelegate(value); - return this; - } - - public MqttServerOptionsBuilder WithUndeliveredMessageInterceptor(Action value) - { - _options.UndeliveredMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(value); - return this; - } - public MqttServerOptionsBuilder WithDefaultEndpointReuseAddress() { _options.DefaultEndpointOptions.ReuseAddress = true; @@ -261,16 +201,16 @@ namespace MQTTnet.Server return this; } - /// - /// Gets or sets the client ID which is used when publishing messages from the server directly. - /// - public MqttServerOptionsBuilder WithClientId(string value) - { - _options.ClientId = value; - return this; - } + // /// + // /// Gets or sets the client ID which is used when publishing messages from the server directly. + // /// + // public MqttServerOptionsBuilder WithClientId(string value) + // { + // _options.ClientId = value; + // return this; + // } - public IMqttServerOptions Build() + public MqttServerOptions Build() { return _options; } diff --git a/Source/MQTTnet/Server/MqttServerTcpEndpointBaseOptions.cs b/Source/MQTTnet/Server/Options/MqttServerTcpEndpointBaseOptions.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerTcpEndpointBaseOptions.cs rename to Source/MQTTnet/Server/Options/MqttServerTcpEndpointBaseOptions.cs diff --git a/Source/MQTTnet/Server/MqttServerTcpEndpointOptions.cs b/Source/MQTTnet/Server/Options/MqttServerTcpEndpointOptions.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerTcpEndpointOptions.cs rename to Source/MQTTnet/Server/Options/MqttServerTcpEndpointOptions.cs diff --git a/Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs b/Source/MQTTnet/Server/Options/MqttServerTlsTcpEndpointOptions.cs similarity index 100% rename from Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs rename to Source/MQTTnet/Server/Options/MqttServerTlsTcpEndpointOptions.cs diff --git a/Source/MQTTnet/Server/PreparingMqttClientSessionEventArgs.cs b/Source/MQTTnet/Server/PreparingMqttClientSessionEventArgs.cs new file mode 100644 index 00000000..6794bfe7 --- /dev/null +++ b/Source/MQTTnet/Server/PreparingMqttClientSessionEventArgs.cs @@ -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 Subscriptions { get; } = new List(); + + public List PublishPackets { get; } = new List(); + } +} \ No newline at end of file diff --git a/Source/MQTTnet/Server/Status/IMqttClientStatus.cs b/Source/MQTTnet/Server/Status/IMqttClientStatus.cs index 268d675d..c48ca1ad 100644 --- a/Source/MQTTnet/Server/Status/IMqttClientStatus.cs +++ b/Source/MQTTnet/Server/Status/IMqttClientStatus.cs @@ -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 { diff --git a/Source/MQTTnet/Server/Status/IMqttSessionStatus.cs b/Source/MQTTnet/Server/Status/IMqttSessionStatus.cs index f7a5b4a6..ad39de1b 100644 --- a/Source/MQTTnet/Server/Status/IMqttSessionStatus.cs +++ b/Source/MQTTnet/Server/Status/IMqttSessionStatus.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace MQTTnet.Server.Status +namespace MQTTnet.Server { public interface IMqttSessionStatus { diff --git a/Source/MQTTnet/Server/Status/MqttClientStatus.cs b/Source/MQTTnet/Server/Status/MqttClientStatus.cs index 3d9b9eef..26d08358 100644 --- a/Source/MQTTnet/Server/Status/MqttClientStatus.cs +++ b/Source/MQTTnet/Server/Status/MqttClientStatus.cs @@ -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 { diff --git a/Source/MQTTnet/Server/Status/MqttSessionStatus.cs b/Source/MQTTnet/Server/Status/MqttSessionStatus.cs index abb62047..01237006 100644 --- a/Source/MQTTnet/Server/Status/MqttSessionStatus.cs +++ b/Source/MQTTnet/Server/Status/MqttSessionStatus.cs @@ -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 { diff --git a/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs b/Source/MQTTnet/Server/ValidatingMqttClientConnectionEventArgs.cs similarity index 97% rename from Source/MQTTnet/Server/MqttConnectionValidatorContext.cs rename to Source/MQTTnet/Server/ValidatingMqttClientConnectionEventArgs.cs index c0f0135d..f412db7a 100644 --- a/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs +++ b/Source/MQTTnet/Server/ValidatingMqttClientConnectionEventArgs.cs @@ -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)); diff --git a/Tests/MQTTnet.AspNetCore.Tests/Mockups/ConnectionHandlerMockup.cs b/Tests/MQTTnet.AspNetCore.Tests/Mockups/ConnectionHandlerMockup.cs index 9adcebd2..931a0b33 100644 --- a/Tests/MQTTnet.AspNetCore.Tests/Mockups/ConnectionHandlerMockup.cs +++ b/Tests/MQTTnet.AspNetCore.Tests/Mockups/ConnectionHandlerMockup.cs @@ -33,7 +33,7 @@ namespace MQTTnet.AspNetCore.Tests.Mockups } } - public Task StartAsync(IMqttServerOptions options) + public Task StartAsync(MqttServerOptions options) { return Task.CompletedTask; } diff --git a/Tests/MQTTnet.Benchmarks/MessageProcessingBenchmark.cs b/Tests/MQTTnet.Benchmarks/MessageProcessingBenchmark.cs index 91718f15..3c897cac 100644 --- a/Tests/MQTTnet.Benchmarks/MessageProcessingBenchmark.cs +++ b/Tests/MQTTnet.Benchmarks/MessageProcessingBenchmark.cs @@ -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(); diff --git a/Tests/MQTTnet.Benchmarks/MqttTcpChannelBenchmark.cs b/Tests/MQTTnet.Benchmarks/MqttTcpChannelBenchmark.cs index 32ca9e79..d000a239 100644 --- a/Tests/MQTTnet.Benchmarks/MqttTcpChannelBenchmark.cs +++ b/Tests/MQTTnet.Benchmarks/MqttTcpChannelBenchmark.cs @@ -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(); diff --git a/Tests/MQTTnet.Core.Tests/Client/ManagedMqttClient_Tests.cs b/Tests/MQTTnet.Core.Tests/Client/ManagedMqttClient_Tests.cs index 7f29468b..7d382990 100644 --- a/Tests/MQTTnet.Core.Tests/Client/ManagedMqttClient_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Client/ManagedMqttClient_Tests.cs @@ -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; diff --git a/Tests/MQTTnet.Core.Tests/Client/MqttClient_Tests.cs b/Tests/MQTTnet.Core.Tests/Client/MqttClient_Tests.cs index 3e9d8923..cf459b9b 100644 --- a/Tests/MQTTnet.Core.Tests/Client/MqttClient_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Client/MqttClient_Tests.cs @@ -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()); diff --git a/Tests/MQTTnet.Core.Tests/Factory/MqttFactory_Tests.cs b/Tests/MQTTnet.Core.Tests/Factory/MqttFactory_Tests.cs index d7b5b274..45a4d458 100644 --- a/Tests/MQTTnet.Core.Tests/Factory/MqttFactory_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Factory/MqttFactory_Tests.cs @@ -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); } } diff --git a/Tests/MQTTnet.Core.Tests/Mockups/TestEnvironment.cs b/Tests/MQTTnet.Core.Tests/Mockups/TestEnvironment.cs index 3d00abc0..f2061204 100644 --- a/Tests/MQTTnet.Core.Tests/Mockups/TestEnvironment.cs +++ b/Tests/MQTTnet.Core.Tests/Mockups/TestEnvironment.cs @@ -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 StartServer() + public Task StartServer() { return StartServer(Factory.CreateServerOptionsBuilder()); } - public async Task StartServer(MqttServerOptionsBuilder options) + public async Task 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 StartServer(Action options) + public async Task StartServer(Action 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; } diff --git a/Tests/MQTTnet.Core.Tests/Mockups/TestServerWrapper.cs b/Tests/MQTTnet.Core.Tests/Mockups/TestServerWrapper.cs deleted file mode 100644 index 54c76bcb..00000000 --- a/Tests/MQTTnet.Core.Tests/Mockups/TestServerWrapper.cs +++ /dev/null @@ -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 ApplicationMessageReceivedAsync - { - add => Implementation.ApplicationMessageReceivedAsync += value; - remove => Implementation.ApplicationMessageReceivedAsync -= value; - } - - public Task ClearRetainedApplicationMessagesAsync() - { - return Implementation.ClearRetainedApplicationMessagesAsync(); - } - - public Task> GetClientStatusAsync() - { - return Implementation.GetClientStatusAsync(); - } - - public Task> GetRetainedApplicationMessagesAsync() - { - return Implementation.GetRetainedApplicationMessagesAsync(); - } - - public Task> GetSessionStatusAsync() - { - return Implementation.GetSessionStatusAsync(); - } - - public Task 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 topicFilters) - { - return Implementation.SubscribeAsync(clientId, topicFilters); - } - - public Task UnsubscribeAsync(string clientId, ICollection 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; - } - } - } -} \ No newline at end of file diff --git a/Tests/MQTTnet.Core.Tests/Server/Assigned_Client_ID_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Assigned_Client_ID_Tests.cs index 4cbb8585..6d0f7422 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Assigned_Client_ID_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Assigned_Client_ID_Tests.cs @@ -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(); diff --git a/Tests/MQTTnet.Core.Tests/Server/Events_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Events_Tests.cs index f74d713e..c5032d43 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Events_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Events_Tests.cs @@ -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(); diff --git a/Tests/MQTTnet.Core.Tests/Server/General.cs b/Tests/MQTTnet.Core.Tests/Server/General.cs index 0e452af6..8a37aa95 100644 --- a/Tests/MQTTnet.Core.Tests/Server/General.cs +++ b/Tests/MQTTnet.Core.Tests/Server/General.cs @@ -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(); @@ -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(() => testEnvironment.ConnectClient()); Assert.AreEqual(MqttClientConnectResultCode.NotAuthorized, connectingFailedException.ResultCode); @@ -637,7 +666,7 @@ namespace MQTTnet.Tests.Server Dictionary _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(); - 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(); - 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(); - 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); + // } } } } \ No newline at end of file diff --git a/Tests/MQTTnet.Core.Tests/Server/MqttSubscriptionsManager_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/MqttSubscriptionsManager_Tests.cs index 4d930dc4..72b085f5 100644 --- a/Tests/MQTTnet.Core.Tests/Server/MqttSubscriptionsManager_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/MqttSubscriptionsManager_Tests.cs @@ -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(), - eventDispatcher, options, + eventContainer, retainedMessagesManager, - new MqttClientSessionsManager(options, retainedMessagesManager, eventDispatcher, logger)); + new MqttClientSessionsManager(options, retainedMessagesManager, eventContainer, logger)); } } } diff --git a/Tests/MQTTnet.Core.Tests/Server/Security_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Security_Tests.cs index 3cddcf12..958fc24f 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Security_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Security_Tests.cs @@ -36,19 +36,19 @@ namespace MQTTnet.Tests.Server Assert.AreEqual("Error while authenticating. If the User Name Flag is set to 0, the Password Flag MUST be set to 0 [MQTT-3.1.2-22].", ex.Message, false); } } - + [TestMethod] public Task Handle_Wrong_UserName() { return TestCredentials("x", "Password1"); } - + [TestMethod] public Task Handle_Wrong_Password() { return TestCredentials("UserName", "x"); } - + [TestMethod] public Task Handle_Wrong_UserName_And_Password() { @@ -61,19 +61,22 @@ namespace MQTTnet.Tests.Server { testEnvironment.IgnoreClientLogErrors = true; - await testEnvironment.StartServer(testEnvironment.Factory.CreateServerOptionsBuilder() - .WithConnectionValidator(c => + var server = await testEnvironment.StartServer(); + + server.ValidatingClientConnectionAsync += e => + { + if (e.Username != "UserName1") { - if (c.Username != "UserName1") - { - c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; - } - - if (c.Password != "Password1") - { - c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; - } - })); + e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; + } + + if (e.Password != "Password1") + { + e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; + } + + return Task.CompletedTask; + }; var client = testEnvironment.CreateClient(); diff --git a/Tests/MQTTnet.Core.Tests/Server/Server_Reference_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Server_Reference_Tests.cs index 73b2f113..2e2aaf1b 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Server_Reference_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Server_Reference_Tests.cs @@ -19,14 +19,15 @@ namespace MQTTnet.Tests.Server { testEnvironment.IgnoreClientLogErrors = true; - await testEnvironment.StartServer(o => + var server = await testEnvironment.StartServer(); + + server.ValidatingClientConnectionAsync += e => { - o.WithConnectionValidator(v => - { - v.ReasonCode = MqttConnectReasonCode.ServerMoved; - v.ServerReference = "new_server"; - }); - }); + e.ReasonCode = MqttConnectReasonCode.ServerMoved; + e.ServerReference = "new_server"; + + return Task.CompletedTask; + }; try { diff --git a/Tests/MQTTnet.Core.Tests/Server/Session_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Session_Tests.cs index 88601e8e..ad24c4be 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Session_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Session_Tests.cs @@ -21,31 +21,38 @@ namespace MQTTnet.Tests.Server { using (var testEnvironment = CreateTestEnvironment()) { - var serverOptions = new MqttServerOptionsBuilder() - .WithConnectionValidator(delegate(MqttConnectionValidatorContext context) - { - // Don't validate anything. Just set some session items. - context.SessionItems["can_subscribe_x"] = true; - context.SessionItems["default_payload"] = "Hello World"; - }) - .WithSubscriptionInterceptor(delegate(MqttSubscriptionInterceptorContext context) - { - if (context.TopicFilter.Topic == "x") - { - if (context.SessionItems["can_subscribe_x"] as bool? == false) - { - context.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; - } - } - }) - .WithApplicationMessageInterceptor(delegate(MqttApplicationMessageInterceptorContext context) - { - context.ApplicationMessage.Payload = - Encoding.UTF8.GetBytes( - context.SessionItems["default_payload"] as string ?? String.Empty); - }); + var server = await testEnvironment.StartServer(); - await testEnvironment.StartServer(serverOptions); + server.ValidatingClientConnectionAsync += e => + { + // Don't validate anything. Just set some session items. + e.SessionItems["can_subscribe_x"] = true; + e.SessionItems["default_payload"] = "Hello World"; + + return Task.CompletedTask; + }; + + server.InterceptingClientSubscriptionAsync += e => + { + if (e.TopicFilter.Topic == "x") + { + if (e.SessionItems["can_subscribe_x"] as bool? == false) + { + e.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; + } + } + + return Task.CompletedTask; + }; + + server.InterceptingClientPublishAsync += e => + { + e.ApplicationMessage.Payload = + Encoding.UTF8.GetBytes( + e.SessionItems["default_payload"] as string ?? String.Empty); + + return Task.CompletedTask; + }; string receivedPayload = null; @@ -73,15 +80,16 @@ namespace MQTTnet.Tests.Server { using (var testEnvironment = CreateTestEnvironment()) { - var serverOptions = new MqttServerOptionsBuilder() - .WithConnectionValidator(delegate(MqttConnectionValidatorContext context) - { - // Don't validate anything. Just set some session items. - context.SessionItems["can_subscribe_x"] = true; - context.SessionItems["default_payload"] = "Hello World"; - }); + var server = await testEnvironment.StartServer(); - await testEnvironment.StartServer(serverOptions); + server.ValidatingClientConnectionAsync += e => + { + // Don't validate anything. Just set some session items. + e.SessionItems["can_subscribe_x"] = true; + e.SessionItems["default_payload"] = "Hello World"; + + return Task.CompletedTask; + }; await testEnvironment.ConnectClient(); diff --git a/Tests/MQTTnet.Core.Tests/Server/Subscribe_Tests.cs b/Tests/MQTTnet.Core.Tests/Server/Subscribe_Tests.cs index 16c39446..cb1385ee 100644 --- a/Tests/MQTTnet.Core.Tests/Server/Subscribe_Tests.cs +++ b/Tests/MQTTnet.Core.Tests/Server/Subscribe_Tests.cs @@ -19,13 +19,16 @@ namespace MQTTnet.Tests.Server { using (var testEnvironment = CreateTestEnvironment()) { - await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor( - c => - { - // Set the topic to "a" regards what the client wants to subscribe. - c.TopicFilter.Topic = "a"; - })); + var server = await testEnvironment.StartServer(); + server.InterceptingClientSubscriptionAsync += e => + { + // Set the topic to "a" regards what the client wants to subscribe. + e.TopicFilter.Topic = "a"; + + return Task.CompletedTask; + }; + var topicAReceived = false; var topicBReceived = false; @@ -74,10 +77,11 @@ namespace MQTTnet.Tests.Server Assert.AreEqual(0, receivedMessagesCount); var subscribeEventCalled = false; - server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(e => + server.ClientSubscribedTopicAsync += e => { subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == c1.Options.ClientId; - }); + return Task.CompletedTask; + }; await c1.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }); await Task.Delay(250); @@ -88,10 +92,11 @@ namespace MQTTnet.Tests.Server Assert.AreEqual(1, receivedMessagesCount); var unsubscribeEventCalled = false; - server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e => + server.ClientUnsubscribedTopicAsync += e => { unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == c1.Options.ClientId; - }); + return Task.CompletedTask; + }; await c1.UnsubscribeAsync("a"); await Task.Delay(250); @@ -260,14 +265,17 @@ namespace MQTTnet.Tests.Server { using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500)) { - await testEnvironment.StartServer(new MqttServerOptionsBuilder().WithSubscriptionInterceptor( - c => + var server = await testEnvironment.StartServer(); + + server.InterceptingClientSubscriptionAsync += e => + { + if (e.TopicFilter.Topic == "not_allowed_topic") { - if (c.TopicFilter.Topic == "not_allowed_topic") - { - c.Response.ReasonCode = MqttSubscribeReasonCode.TopicFilterInvalid; - } - })); + e.Response.ReasonCode = MqttSubscribeReasonCode.TopicFilterInvalid; + } + + return Task.CompletedTask; + }; var client = await testEnvironment.ConnectClient(); diff --git a/Tests/MQTTnet.TestApp.AspNetCore2/Startup.cs b/Tests/MQTTnet.TestApp.AspNetCore2/Startup.cs index 6eb8bfb8..07a5d69c 100644 --- a/Tests/MQTTnet.TestApp.AspNetCore2/Startup.cs +++ b/Tests/MQTTnet.TestApp.AspNetCore2/Startup.cs @@ -7,10 +7,8 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Logging; using MQTTnet.AspNetCore; using MQTTnet.AspNetCore.Extensions; -using MQTTnet.Server; namespace MQTTnet.TestApp.AspNetCore2 { @@ -44,7 +42,7 @@ namespace MQTTnet.TestApp.AspNetCore2 app.UseMqttServer(server => { - server.StartedHandler = new MqttServerStartedHandlerDelegate(async args => + server.StartedAsync += async args => { var frameworkName = GetType().Assembly.GetCustomAttribute()? .FrameworkName; @@ -57,7 +55,7 @@ namespace MQTTnet.TestApp.AspNetCore2 { try { - await server.PublishAsync(msg.Build()); + await server.PublishAsync("server", msg.Build()); msg.WithPayload($"Mqtt hosted on {frameworkName} is still awesome at {DateTime.Now}"); } catch (Exception e) @@ -69,7 +67,7 @@ namespace MQTTnet.TestApp.AspNetCore2 await Task.Delay(TimeSpan.FromSeconds(2)); } } - }); + }; }); app.Use((context, next) => diff --git a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs index b41d1995..3c20bff2 100644 --- a/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/PerformanceTest.cs @@ -58,8 +58,8 @@ namespace MQTTnet.TestApp.NetCore { try { - var mqttServer = new MqttFactory().CreateMqttServer(); - await mqttServer.StartAsync(new MqttServerOptions()).ConfigureAwait(false); + var mqttServer = new MqttFactory().CreateMqttServer(new MqttServerOptions()); + await mqttServer.StartAsync().ConfigureAwait(false); var options = new MqttClientOptions { @@ -202,8 +202,8 @@ namespace MQTTnet.TestApp.NetCore { try { - var mqttServer = new MqttFactory().CreateMqttServer(); - await mqttServer.StartAsync(new MqttServerOptions()); + var mqttServer = new MqttFactory().CreateMqttServer(new MqttServerOptions()); + await mqttServer.StartAsync(); var options = new MqttClientOptions { @@ -253,8 +253,8 @@ namespace MQTTnet.TestApp.NetCore { try { - var mqttServer = new MqttFactory().CreateMqttServer(); - await mqttServer.StartAsync(new MqttServerOptions()); + var mqttServer = new MqttFactory().CreateMqttServer(new MqttServerOptions()); + await mqttServer.StartAsync(); var options = new MqttClientOptions { diff --git a/Tests/MQTTnet.TestApp.NetCore/PublicBrokerTest.cs b/Tests/MQTTnet.TestApp.NetCore/PublicBrokerTest.cs index d8b8024f..b039c35b 100644 --- a/Tests/MQTTnet.TestApp.NetCore/PublicBrokerTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/PublicBrokerTest.cs @@ -27,7 +27,7 @@ namespace MQTTnet.TestApp.NetCore UseTls = true, SslProtocol = SslProtocols.Tls13, // Don't use this in production code. This handler simply allows any invalid certificate to work. - CertificateValidationHandler = (w) => true + CertificateValidationHandler = w => true }; #endif @@ -37,7 +37,7 @@ namespace MQTTnet.TestApp.NetCore UseTls = true, SslProtocol = SslProtocols.Tls12, // Don't use this in production code. This handler simply allows any invalid certificate to work. - CertificateValidationHandler = (w) => true + CertificateValidationHandler = w => true }; // mqtt.eclipseprojects.io diff --git a/Tests/MQTTnet.TestApp.NetCore/ServerAndClientTest.cs b/Tests/MQTTnet.TestApp.NetCore/ServerAndClientTest.cs index 28986397..47adca67 100644 --- a/Tests/MQTTnet.TestApp.NetCore/ServerAndClientTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/ServerAndClientTest.cs @@ -15,11 +15,10 @@ namespace MQTTnet.TestApp.NetCore MqttNetConsoleLogger.ForwardToConsole(logger); var factory = new MqttFactory(logger); - var server = factory.CreateMqttServer(); + var server = factory.CreateMqttServer( new MqttServerOptionsBuilder().Build()); var client = factory.CreateMqttClient(); - var serverOptions = new MqttServerOptionsBuilder().Build(); - await server.StartAsync(serverOptions); + await server.StartAsync(); var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("localhost").Build(); await client.ConnectAsync(clientOptions); diff --git a/Tests/MQTTnet.TestApp.NetCore/ServerTest.cs b/Tests/MQTTnet.TestApp.NetCore/ServerTest.cs index 64b43b04..b2d78d19 100644 --- a/Tests/MQTTnet.TestApp.NetCore/ServerTest.cs +++ b/Tests/MQTTnet.TestApp.NetCore/ServerTest.cs @@ -1,9 +1,8 @@ using System; using System.Text; using System.Threading.Tasks; -using MQTTnet.Client.Receiving; -using MQTTnet.Diagnostics; using MQTTnet.Diagnostics.Logger; +using MQTTnet.Implementations; using MQTTnet.Protocol; using MQTTnet.Server; using MQTTnet.Server.Internal; @@ -14,8 +13,8 @@ namespace MQTTnet.TestApp.NetCore { public static void RunEmptyServer() { - var mqttServer = new MqttFactory().CreateMqttServer(); - mqttServer.StartAsync(new MqttServerOptions()).GetAwaiter().GetResult(); + var mqttServer = new MqttFactory().CreateMqttServer(new MqttServerOptions()); + mqttServer.StartAsync().GetAwaiter().GetResult(); Console.WriteLine("Press any key to exit."); Console.ReadLine(); @@ -27,8 +26,8 @@ namespace MQTTnet.TestApp.NetCore MqttNetConsoleLogger.ForwardToConsole(logger); var mqttFactory = new MqttFactory(logger); - var mqttServer = mqttFactory.CreateMqttServer(); - mqttServer.StartAsync(new MqttServerOptions()).GetAwaiter().GetResult(); + var mqttServer = mqttFactory.CreateMqttServer(new MqttServerOptions()); + mqttServer.StartAsync().GetAwaiter().GetResult(); Console.WriteLine("Press any key to exit."); Console.ReadLine(); @@ -40,48 +39,7 @@ namespace MQTTnet.TestApp.NetCore { var options = new MqttServerOptions { - ConnectionValidator = new MqttServerConnectionValidatorDelegate(p => - { - if (p.ClientId == "SpecialClient") - { - if (p.Username != "USER" || p.Password != "PASS") - { - p.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; - } - } - }), - - Storage = new RetainedMessageHandler(), - - ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(context => - { - if (MqttTopicFilterComparer.Compare(context.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#") == MqttTopicFilterCompareResult.IsMatch) - { - // Replace the payload with the timestamp. But also extending a JSON - // based payload with the timestamp is a suitable use case. - context.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(DateTime.Now.ToString("O")); - } - - if (context.ApplicationMessage.Topic == "not_allowed_topic") - { - context.ProcessPublish = false; - context.CloseConnection = true; - } - }), - - SubscriptionInterceptor = new MqttServerSubscriptionInterceptorDelegate(context => - { - if (context.TopicFilter.Topic.StartsWith("admin/foo/bar") && context.ClientId != "theAdmin") - { - context.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; - } - - if (context.TopicFilter.Topic.StartsWith("the/secret/stuff") && context.ClientId != "Imperator") - { - context.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; - context.CloseConnection = true; - } - }) + Storage = new RetainedMessageHandler() }; // Extend the timestamp for all messages from clients. @@ -93,14 +51,63 @@ namespace MQTTnet.TestApp.NetCore //options.DefaultEndpointOptions.IsEnabled = true; //options.TlsEndpointOptions.IsEnabled = false; - var mqttServer = new MqttFactory().CreateMqttServer(); + var mqttServer = new MqttFactory().CreateMqttServer(options); - mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => + mqttServer.InterceptingClientPublishAsync += e => + { + if (MqttTopicFilterComparer.Compare(e.ApplicationMessage.Topic, "/myTopic/WithTimestamp/#") == MqttTopicFilterCompareResult.IsMatch) + { + // Replace the payload with the timestamp. But also extending a JSON + // based payload with the timestamp is a suitable use case. + e.ApplicationMessage.Payload = Encoding.UTF8.GetBytes(DateTime.Now.ToString("O")); + } + + if (e.ApplicationMessage.Topic == "not_allowed_topic") + { + e.ProcessPublish = false; + e.CloseConnection = true; + } + + return PlatformAbstractionLayer.CompletedTask; + }; + + mqttServer.ValidatingClientConnectionAsync += e => + { + if (e.ClientId == "SpecialClient") + { + if (e.Username != "USER" || e.Password != "PASS") + { + e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; + } + } + + return PlatformAbstractionLayer.CompletedTask; + }; + + mqttServer.InterceptingClientSubscriptionAsync += e => + { + if (e.TopicFilter.Topic.StartsWith("admin/foo/bar") && e.ClientId != "theAdmin") + { + e.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; + } + + if (e.TopicFilter.Topic.StartsWith("the/secret/stuff") && e.ClientId != "Imperator") + { + e.Response.ReasonCode = MqttSubscribeReasonCode.ImplementationSpecificError; + e.CloseConnection = true; + } + + return PlatformAbstractionLayer.CompletedTask; + }; + + mqttServer.InterceptingClientPublishAsync += e => { MqttNetConsoleLogger.PrintToConsole( $"'{e.ClientId}' reported '{e.ApplicationMessage.Topic}' > '{Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0])}'", ConsoleColor.Magenta); - }); + + return PlatformAbstractionLayer.CompletedTask; + }; //options.ApplicationMessageInterceptor = c => //{ @@ -124,12 +131,13 @@ namespace MQTTnet.TestApp.NetCore // } //}; - mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e => + mqttServer.ClientConnectedAsync += e => { Console.Write("Client disconnected event fired."); - }); + return PlatformAbstractionLayer.CompletedTask; + }; - await mqttServer.StartAsync(options); + await mqttServer.StartAsync(); Console.WriteLine("Press any key to exit."); Console.ReadLine();