├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ └── ci.yml ├── .gitignore ├── CODE-OF-CONDUCT.md ├── Directory.Build.props ├── Images ├── Logo_128x128.png ├── MQTT.svg ├── icon_256.png ├── icon_512.png ├── icon_64.png ├── icon_det_256.png ├── icon_det_512.png ├── icon_det_64.png └── nuget.png ├── LICENSE ├── MQTTnet.sln ├── MQTTnet.sln.DotSettings ├── README.md ├── Samples ├── Client │ ├── Client_Connection_Samples.cs │ ├── Client_Publish_Samples.cs │ └── Client_Subscribe_Samples.cs ├── Diagnostics │ ├── Logger_Samples.cs │ └── PackageInspection_Samples.cs ├── Helpers │ └── ObjectExtensions.cs ├── MQTTnet.Samples.csproj ├── Program.cs ├── RpcClient │ └── RpcClient_Samples.cs └── Server │ ├── Server_ASP_NET_Samples.cs │ ├── Server_Diagnostics_Samples.cs │ ├── Server_Intercepting_Samples.cs │ ├── Server_Retained_Messages_Samples.cs │ ├── Server_Simple_Samples.cs │ └── Server_TLS_Samples.cs └── Source ├── MQTTnet.AspTestApp ├── MQTTnet.AspTestApp.csproj ├── Pages │ ├── Index.cshtml │ ├── Index.cshtml.cs │ ├── Shared │ │ └── _Layout.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── Program.cs ├── appsettings.Development.json ├── appsettings.json └── libman.json ├── MQTTnet.AspnetCore ├── ApplicationBuilderExtensions.cs ├── AspNetMqttServerOptionsBuilder.cs ├── BufferExtensions.cs ├── ConnectionBuilderExtensions.cs ├── DuplexPipe.cs ├── EndpointRouterExtensions.cs ├── MQTTnet.AspNetCore.csproj ├── MqttClientConnectionContextFactory.cs ├── MqttConnectionContext.cs ├── MqttConnectionHandler.cs ├── MqttHostedServer.cs ├── MqttSubProtocolSelector.cs ├── MqttWebSocketServerAdapter.cs ├── ReaderExtensions.cs ├── ServiceCollectionExtensions.cs ├── SocketAwaitable.cs ├── SocketConnection.cs ├── SocketReceiver.cs └── SocketSender.cs ├── MQTTnet.Benchmarks ├── AsyncLockBenchmark.cs ├── BaseBenchmark.cs ├── ChannelAdapterBenchmark.cs ├── LoggerBenchmark.cs ├── MQTTnet.Benchmarks.csproj ├── MemoryCopyBenchmark.cs ├── MessageDeliveryBenchmark.cs ├── MessageProcessingBenchmark.cs ├── MessageProcessingMqttConnectionContextBenchmark.cs ├── MqttBufferReaderBenchmark.cs ├── MqttPacketReaderWriterBenchmark.cs ├── MqttTcpChannelBenchmark.cs ├── Program.cs ├── ReaderExtensionsBenchmark.cs ├── RoundtripProcessingBenchmark.cs ├── SendPacketAsyncBenchmark.cs ├── SerializerBenchmark.cs ├── ServerProcessingBenchmark.cs ├── SubscribeBenchmark.cs ├── TcpPipesBenchmark.cs ├── TopicFilterComparerBenchmark.cs ├── TopicGenerator.cs └── UnsubscribeBenchmark.cs ├── MQTTnet.Extensions.Rpc ├── DefaultMqttRpcClientTopicGenerationStrategy.cs ├── IMqttRpcClient.cs ├── IMqttRpcClientTopicGenerationStrategy.cs ├── MQTTnet.Extensions.Rpc.csproj ├── MQTTnet.Extensions.Rpc.csproj.DotSettings ├── MqttFactoryExtensions.cs ├── MqttRpcClient.cs ├── MqttRpcClientExtensions.cs ├── MqttRpcClientOptions.cs ├── MqttRpcClientOptionsBuilder.cs ├── MqttRpcTopicPair.cs ├── SampleCCode.c └── TopicGenerationContext.cs ├── MQTTnet.Extensions.TopicTemplate ├── MQTTnet.Extensions.TopicTemplate.csproj ├── MqttTopicTemplate.cs ├── README.md └── TopicTemplateExtensions.cs ├── MQTTnet.Server ├── Disconnecting │ ├── MqttServerClientDisconnectOptions.cs │ └── MqttServerClientDisconnectOptionsBuilder.cs ├── EnhancedAuthentication │ ├── ExchangeEnhancedAuthenticationOptions.cs │ ├── ExchangeEnhancedAuthenticationOptionsFactory.cs │ ├── ExchangeEnhancedAuthenticationResult.cs │ └── ExchangeEnhancedAuthenticationResultFactory.cs ├── Events │ ├── ApplicationMessageEnqueuedEventArgs.cs │ ├── ApplicationMessageNotConsumedEventArgs.cs │ ├── ClientAcknowledgedPublishPacketEventArgs.cs │ ├── ClientConnectedEventArgs.cs │ ├── ClientDisconnectedEventArgs.cs │ ├── ClientSubscribedTopicEventArgs.cs │ ├── ClientUnsubscribedTopicEventArgs.cs │ ├── InterceptingClientApplicationMessageEnqueueEventArgs.cs │ ├── InterceptingPacketEventArgs.cs │ ├── InterceptingPublishEventArgs.cs │ ├── InterceptingSubscriptionEventArgs.cs │ ├── InterceptingUnsubscriptionEventArgs.cs │ ├── LoadingRetainedMessagesEventArgs.cs │ ├── PreparingSessionEventArgs.cs │ ├── QueueMessageOverwrittenEventArgs.cs │ ├── RetainedMessageChangedEventArgs.cs │ ├── SessionDeletedEventArgs.cs │ └── ValidatingConnectionEventArgs.cs ├── Exceptions │ └── MqttPendingMessagesOverflowException.cs ├── IMqttServerAdapter.cs ├── InjectedMqttApplicationMessage.cs ├── Internal │ ├── Adapter │ │ ├── MqttTcpServerAdapter.cs │ │ └── MqttTcpServerListener.cs │ ├── CheckSubscriptionsResult.cs │ ├── DispatchApplicationMessageResult.cs │ ├── EnqueueDataPacketResult.cs │ ├── Formatter │ │ ├── MqttConnAckPacketFactory.cs │ │ ├── MqttDisconnectPacketFactory.cs │ │ ├── MqttPubAckPacketFactory.cs │ │ ├── MqttPubCompPacketFactory.cs │ │ ├── MqttPubRecPacketFactory.cs │ │ ├── MqttPubRelPacketFactory.cs │ │ ├── MqttPublishPacketFactory.cs │ │ ├── MqttSubAckPacketFactory.cs │ │ └── MqttUnsubAckPacketFactory.cs │ ├── ISubscriptionChangedNotification.cs │ ├── MqttClientSessionsManager.cs │ ├── MqttClientStatistics.cs │ ├── MqttClientSubscriptionsManager.cs │ ├── MqttConnectedClient.cs │ ├── MqttRetainedMessagesManager.cs │ ├── MqttServerEventContainer.cs │ ├── MqttServerKeepAliveMonitor.cs │ ├── MqttSession.cs │ ├── MqttSessionsStorage.cs │ ├── MqttSubscription.cs │ ├── MqttTopicHash.cs │ ├── SubscribeResult.cs │ ├── TopicHashMaskSubscriptions.cs │ └── UnsubscribeResult.cs ├── MQTTnet.Server.csproj ├── MQTTnet.Server.csproj.DotSettings ├── MqttClientDisconnectType.cs ├── MqttRetainedMessageMatch.cs ├── MqttServer.cs ├── MqttServerExtensions.cs ├── MqttServerFactory.cs ├── Options │ ├── IMqttServerCertificateCredentials.cs │ ├── MqttPendingMessagesOverflowStrategy.cs │ ├── MqttServerCertificateCredentials.cs │ ├── MqttServerKeepAliveOptions.cs │ ├── MqttServerOptions.cs │ ├── MqttServerOptionsBuilder.cs │ ├── MqttServerTcpEndpointBaseOptions.cs │ ├── MqttServerTcpEndpointOptions.cs │ └── MqttServerTlsTcpEndpointOptions.cs ├── PublishResponse.cs ├── Status │ ├── MqttClientStatus.cs │ ├── MqttClientStatusExtensions.cs │ └── MqttSessionStatus.cs ├── Stopping │ ├── MqttServerStopOptions.cs │ └── MqttServerStopOptionsBuilder.cs ├── SubscribeResponse.cs └── UnsubscribeResponse.cs ├── MQTTnet.TestApp ├── AsyncLockTest.cs ├── ClientFlowTest.cs ├── ClientTest.cs ├── MQTTnet.TestApp.csproj ├── MessageThroughputTest.cs ├── MqttNetConsoleLogger.cs ├── PerformanceTest.cs ├── Program.cs ├── PublicBrokerTest.cs ├── ServerAndClientTest.cs ├── ServerTest.cs └── TopicGenerator.cs ├── MQTTnet.Tests ├── ASP │ ├── Mockups │ │ ├── ConnectionHandlerMockup.cs │ │ ├── DuplexPipeMockup.cs │ │ ├── LimitedMemoryPool.cs │ │ └── MemoryOwner.cs │ ├── MqttConnectionContextTest.cs │ └── ReaderExtensionsTest.cs ├── BaseTestClass.cs ├── Clients │ ├── LowLevelMqttClient │ │ └── LowLevelMqttClient_Tests.cs │ ├── MqttClient │ │ ├── MqttClient_Connection_Tests.cs │ │ └── MqttClient_Tests.cs │ └── MqttClientOptionsBuilder_Tests.cs ├── Diagnostics │ ├── Logger_Tests.cs │ ├── PacketInspection_Tests.cs │ └── SourceLogger_Tests.cs ├── Extensions │ ├── MqttTopicTemplate_Tests.cs │ └── Rpc_Tests.cs ├── Factory │ └── MqttFactory_Tests.cs ├── Formatter │ ├── MqttBufferReader_Tests.cs │ ├── MqttPacketSerialization_V3_Binary_Tests.cs │ ├── MqttPacketSerialization_V3_Tests.cs │ ├── MqttPacketSerialization_V5_Tests.cs │ └── MqttPacketWriter_Tests.cs ├── Helpers │ ├── MqttClientExtensions.cs │ ├── MqttPacketWriterExtensions.cs │ └── ReflectionExtensions.cs ├── Internal │ ├── AsyncEvent_Tests.cs │ ├── AsyncLock_Tests.cs │ ├── AsyncQueue_Tests.cs │ ├── AsyncSignal_Tests.cs │ ├── BlockingQueue_Tests.cs │ ├── CrossPlatformSocket_Tests.cs │ ├── MqttPacketBusItem_Tests.cs │ └── MqttPacketBus_Tests.cs ├── MQTTnet.Tests.csproj ├── MQTTv5 │ ├── Client_Tests.cs │ └── Server_Tests.cs ├── Mockups │ ├── MemoryMqttChannel.cs │ ├── TestApplicationMessageReceivedHandler.cs │ ├── TestEnvironment.cs │ └── TestLogger.cs ├── MqttApplicationMessageBuilder_Tests.cs ├── MqttApplicationMessageValidator_Tests.cs ├── MqttClientOptionsValidator_Tests.cs ├── MqttPacketIdentifierProvider_Tests.cs ├── MqttPacketSerializationHelper.cs ├── MqttPacketWriter_Tests.cs ├── MqttTcpChannel_Tests.cs ├── MqttTopicValidatorSubscribe_Tests.cs ├── MqttTopicValidator_Tests.cs ├── Protocol_Tests.cs ├── RoundtripTime_Tests.cs ├── Server │ ├── Assigned_Client_ID_Tests.cs │ ├── Connection_Tests.cs │ ├── Cross_Version_Tests.cs │ ├── Events_Tests.cs │ ├── General.cs │ ├── HotSwapCerts_Tests.cs │ ├── Injection_Tests.cs │ ├── Keep_Alive_Tests.cs │ ├── Load_Tests.cs │ ├── MqttRetainedMessageManager_Tests.cs │ ├── MqttSubscriptionsManager_Tests.cs │ ├── No_Local_Tests.cs │ ├── Publishing_Tests.cs │ ├── QoS_Tests.cs │ ├── Retain_As_Published_Tests.cs │ ├── Retain_Handling_Tests.cs │ ├── Retained_Messages_Tests.cs │ ├── Security_Tests.cs │ ├── Server_Reference_Tests.cs │ ├── Session_Tests.cs │ ├── Shared_Subscriptions_Tests.cs │ ├── Status_Tests.cs │ ├── Subscribe_Tests.cs │ ├── Subscription_Identifier_Tests.cs │ ├── Subscription_TopicHash_Tests.cs │ ├── Tls_Tests.cs │ ├── Topic_Alias_Tests.cs │ ├── Unsubscribe_Tests.cs │ ├── User_Properties_Tests.cs │ ├── Wildcard_Subscription_Available_Tests.cs │ └── Will_Tests.cs ├── TopicFilterComparer_Tests.cs └── TopicGenerator.cs ├── MQTTnet ├── Adapter │ ├── IMqttChannelAdapter.cs │ ├── IMqttClientAdapterFactory.cs │ ├── MqttChannelAdapter.cs │ ├── MqttConnectingFailedException.cs │ ├── MqttPacketInspector.cs │ └── ReceivedMqttPacket.cs ├── Certificates │ ├── BlobCertificateProvider.cs │ ├── ICertificateProvider.cs │ └── X509CertificateProvider.cs ├── Channel │ └── IMqttChannel.cs ├── Connecting │ ├── MqttClientConnectResult.cs │ ├── MqttClientConnectResultCode.cs │ ├── MqttClientConnectResultFactory.cs │ ├── MqttClientConnectedEventArgs.cs │ └── MqttClientConnectingEventArgs.cs ├── Diagnostics │ ├── Logger │ │ ├── IMqttNetLogger.cs │ │ ├── MqttNetEventLogger.cs │ │ ├── MqttNetLogLevel.cs │ │ ├── MqttNetLogMessage.cs │ │ ├── MqttNetLogMessagePublishedEventArgs.cs │ │ ├── MqttNetNullLogger.cs │ │ ├── MqttNetSourceLogger.cs │ │ └── MqttNetSourceLoggerExtensions.cs │ └── PacketInspection │ │ ├── InspectMqttPacketEventArgs.cs │ │ └── MqttPacketFlowDirection.cs ├── Disconnecting │ ├── MqttClientDisconnectOptions.cs │ ├── MqttClientDisconnectOptionsBuilder.cs │ ├── MqttClientDisconnectOptionsReason.cs │ ├── MqttClientDisconnectOptionsValidator.cs │ ├── MqttClientDisconnectReason.cs │ └── MqttClientDisconnectedEventArgs.cs ├── Exceptions │ ├── MqttClientDisconnectedException.cs │ ├── MqttClientNotConnectedException.cs │ ├── MqttClientUnexpectedDisconnectReceivedException.cs │ ├── MqttCommunicationException.cs │ ├── MqttCommunicationTimedOutException.cs │ ├── MqttConfigurationException.cs │ └── MqttProtocolViolationException.cs ├── Formatter │ ├── IMqttPacketFormatter.cs │ ├── MqttApplicationMessageFactory.cs │ ├── MqttBufferReader.cs │ ├── MqttBufferWriter.cs │ ├── MqttConnectPacketFactory.cs │ ├── MqttConnectReasonCodeConverter.cs │ ├── MqttDisconnectPacketFactory.cs │ ├── MqttFixedHeader.cs │ ├── MqttPacketBuffer.cs │ ├── MqttPacketFormatterAdapter.cs │ ├── MqttProtocolVersion.cs │ ├── MqttPubAckPacketFactory.cs │ ├── MqttPubCompPacketFactory.cs │ ├── MqttPubRecPacketFactory.cs │ ├── MqttPubRelPacketFactory.cs │ ├── MqttPublishPacketFactory.cs │ ├── MqttSubscribePacketFactory.cs │ ├── MqttUnsubscribePacketFactory.cs │ ├── ReadFixedHeaderResult.cs │ ├── V3 │ │ └── MqttV3PacketFormatter.cs │ └── V5 │ │ ├── MqttV5PacketDecoder.cs │ │ ├── MqttV5PacketEncoder.cs │ │ ├── MqttV5PacketFormatter.cs │ │ ├── MqttV5PropertiesReader.cs │ │ └── MqttV5PropertiesWriter.cs ├── IMqttClient.cs ├── Implementations │ ├── CrossPlatformSocket.cs │ ├── MqttClientAdapterFactory.cs │ ├── MqttTcpChannel.cs │ └── MqttWebSocketChannel.cs ├── InjectMqttApplicationMessageResult.cs ├── Internal │ ├── AsyncEvent.cs │ ├── AsyncEventInvocator.cs │ ├── AsyncLock.cs │ ├── AsyncQueue.cs │ ├── AsyncQueueDequeueResult.cs │ ├── AsyncSignal.cs │ ├── AsyncTaskCompletionSource.cs │ ├── BlockingQueue.cs │ ├── CancellationTokenSourceExtensions.cs │ ├── CompletedTask.cs │ ├── Disposable.cs │ ├── EmptyBuffer.cs │ ├── MqttClientEvents.cs │ ├── MqttMemoryHelper.cs │ ├── MqttPacketBus.cs │ ├── MqttPacketBusItem.cs │ ├── MqttPacketBusPartition.cs │ └── TaskExtensions.cs ├── LowLevelClient │ ├── ILowLevelMqttClient.cs │ └── LowLevelMqttClient.cs ├── MQTTnet.csproj ├── MQTTnet.csproj.DotSettings ├── MqttApplicationMessage.cs ├── MqttApplicationMessageBuilder.cs ├── MqttApplicationMessageExtensions.cs ├── MqttApplicationMessageValidator.cs ├── MqttClient.cs ├── MqttClientConnectionStatus.cs ├── MqttClientExtensions.cs ├── MqttClientFactory.cs ├── MqttPacketIdentifierProvider.cs ├── MqttTopicFilterBuilder.cs ├── MqttTopicFilterCompareResult.cs ├── MqttTopicFilterComparer.cs ├── Options │ ├── DefaultMqttCertificatesProvider.cs │ ├── IMqttClientCertificatesProvider.cs │ ├── IMqttClientChannelOptions.cs │ ├── IMqttClientCredentialsProvider.cs │ ├── IMqttEnhancedAuthenticationHandler.cs │ ├── MqttClientCertificateSelectionEventArgs.cs │ ├── MqttClientCertificateValidationEventArgs.cs │ ├── MqttClientCredentials.cs │ ├── MqttClientDefaultCertificateValidationHandler.cs │ ├── MqttClientOptions.cs │ ├── MqttClientOptionsBuilder.cs │ ├── MqttClientOptionsValidator.cs │ ├── MqttClientTcpOptions.cs │ ├── MqttClientTlsOptions.cs │ ├── MqttClientTlsOptionsBuilder.cs │ ├── MqttClientWebSocketOptions.cs │ ├── MqttClientWebSocketOptionsBuilder.cs │ ├── MqttClientWebSocketProxyOptions.cs │ ├── MqttClientWebSocketProxyOptionsBuilder.cs │ ├── MqttEnhancedAuthenticationEventArgs.cs │ ├── MqttEnhancedAuthenticationExchangeData.cs │ ├── ReceiveMqttEnhancedAuthenticationDataResult.cs │ └── SendMqttEnhancedAuthenticationDataOptions.cs ├── PacketDispatcher │ ├── IMqttPacketAwaitable.cs │ ├── MqttPacketAwaitable.cs │ ├── MqttPacketAwaitableFilter.cs │ └── MqttPacketDispatcher.cs ├── Packets │ ├── MqttAuthPacket.cs │ ├── MqttConnAckPacket.cs │ ├── MqttConnectPacket.cs │ ├── MqttDisconnectPacket.cs │ ├── MqttPacket.cs │ ├── MqttPacketExtensions.cs │ ├── MqttPacketWithIdentifier.cs │ ├── MqttPingReqPacket.cs │ ├── MqttPingRespPacket.cs │ ├── MqttPubAckPacket.cs │ ├── MqttPubCompPacket.cs │ ├── MqttPubRecPacket.cs │ ├── MqttPubRelPacket.cs │ ├── MqttPublishPacket.cs │ ├── MqttSubAckPacket.cs │ ├── MqttSubscribePacket.cs │ ├── MqttTopicFilter.cs │ ├── MqttUnsubAckPacket.cs │ ├── MqttUnsubscribePacket.cs │ └── MqttUserProperty.cs ├── Properties │ └── AssemblyInfo.cs ├── Protocol │ ├── MqttAuthenticateReasonCode.cs │ ├── MqttConnectReasonCode.cs │ ├── MqttConnectReturnCode.cs │ ├── MqttControlPacketType.cs │ ├── MqttDisconnectReasonCode.cs │ ├── MqttPayloadFormatIndicator.cs │ ├── MqttPorts.cs │ ├── MqttPropertyId.cs │ ├── MqttPubAckReasonCode.cs │ ├── MqttPubCompReasonCode.cs │ ├── MqttPubRecReasonCode.cs │ ├── MqttPubRelReasonCode.cs │ ├── MqttQualityOfServiceLevel.cs │ ├── MqttRetainHandling.cs │ ├── MqttSubscribeReasonCode.cs │ ├── MqttSubscribeReturnCode.cs │ ├── MqttTopicValidator.cs │ └── MqttUnsubscribeReasonCode.cs ├── Publishing │ ├── MqttClientPublishReasonCode.cs │ ├── MqttClientPublishResult.cs │ └── MqttClientPublishResultFactory.cs ├── Receiving │ ├── MqttApplicationMessageReceivedEventArgs.cs │ └── MqttApplicationMessageReceivedReasonCode.cs ├── Subscribing │ ├── MqttClientSubscribeOptions.cs │ ├── MqttClientSubscribeOptionsBuilder.cs │ ├── MqttClientSubscribeOptionsValidator.cs │ ├── MqttClientSubscribeResult.cs │ ├── MqttClientSubscribeResultCode.cs │ ├── MqttClientSubscribeResultFactory.cs │ └── MqttClientSubscribeResultItem.cs └── Unsubscribing │ ├── MqttClientUnsubscribeOptions.cs │ ├── MqttClientUnsubscribeOptionsBuilder.cs │ ├── MqttClientUnsubscribeOptionsValidator.cs │ ├── MqttClientUnsubscribeResult.cs │ ├── MqttClientUnsubscribeResultCode.cs │ ├── MqttClientUnsubscribeResultFactory.cs │ └── MqttClientUnsubscribeResultItem.cs └── ReleaseNotes.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Do you have a question related to the project? Use this template. 4 | title: '' 5 | labels: 'question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe your question 11 | A clear and concise description of what you want to know. 12 | 13 | ### Which project is your question related to? 14 | 15 | - Client 16 | - ManagedClient 17 | - Server 18 | - Generic 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project. 4 | title: '' 5 | labels: 'feature-request' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Describe the feature request 11 | Is your feature request related to a problem? Please describe. 12 | A clear and concise description of what the problem is. Example. I'm am trying to do [...] but [...] 13 | 14 | ### Which project is your feature request related to? 15 | 16 | - Client 17 | - ManagedClient 18 | - Server 19 | - Generic 20 | 21 | ### Describe the solution you'd like 22 | A clear and concise description of what you want to happen. 23 | 24 | ### Describe alternatives you've considered 25 | A clear and concise description of any alternative solutions or features you've considered. 26 | 27 | ### Additional context 28 | Add any other context or screenshots about the feature request here. 29 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | true 6 | true 7 | 8 | 9 | -------------------------------------------------------------------------------- /Images/Logo_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/Logo_128x128.png -------------------------------------------------------------------------------- /Images/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_256.png -------------------------------------------------------------------------------- /Images/icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_512.png -------------------------------------------------------------------------------- /Images/icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_64.png -------------------------------------------------------------------------------- /Images/icon_det_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_det_256.png -------------------------------------------------------------------------------- /Images/icon_det_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_det_512.png -------------------------------------------------------------------------------- /Images/icon_det_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/icon_det_64.png -------------------------------------------------------------------------------- /Images/nuget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet/MQTTnet/75ebf116cf43e3ab86bbf1f2ac1631e1417da9dd/Images/nuget.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | All Rights Reserved 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Samples/Helpers/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json; 6 | 7 | namespace MQTTnet.Samples.Helpers; 8 | 9 | internal static class ObjectExtensions 10 | { 11 | public static TObject DumpToConsole(this TObject @object) 12 | { 13 | var output = "NULL"; 14 | if (@object != null) 15 | { 16 | output = JsonSerializer.Serialize(@object, new JsonSerializerOptions 17 | { 18 | WriteIndented = true 19 | }); 20 | } 21 | 22 | Console.WriteLine($"[{@object?.GetType().Name}]:\r\n{output}"); 23 | return @object; 24 | } 25 | } -------------------------------------------------------------------------------- /Samples/MQTTnet.Samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | false 9 | true 10 | false 11 | false 12 | 1591;NETSDK1138;NU1803;NU1901;NU1902 13 | true 14 | all 15 | true 16 | low 17 | latest-Recommended 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/MQTTnet.AspTestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | false 8 | true 9 | false 10 | false 11 | 1591;NETSDK1138;NU1803;NU1901;NU1902 12 | true 13 | all 14 | true 15 | low 16 | latest-Recommended 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |
8 |

MQTTnet ASP.NET Core Test App

9 |
10 | 11 | 12 | 13 | 35 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace MQTTnet.AspTestApp.Pages; 8 | 9 | public class IndexModel : PageModel 10 | { 11 | readonly ILogger _logger; 12 | 13 | public IndexModel(ILogger logger) 14 | { 15 | _logger = logger; 16 | } 17 | 18 | public void OnGet() 19 | { 20 | _logger.LogDebug("OnGet"); 21 | } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - MQTTnet 7 | 8 | 9 | 10 | @RenderBody() 11 | 12 | @await RenderSectionAsync("Scripts", required: false) 13 | 14 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @namespace MQTTnet.AspTestApp.Pages 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /Source/MQTTnet.AspTestApp/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [] 5 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/AspNetMqttServerOptionsBuilder.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Server; 7 | 8 | namespace MQTTnet.AspNetCore; 9 | 10 | public sealed class AspNetMqttServerOptionsBuilder : MqttServerOptionsBuilder 11 | { 12 | public AspNetMqttServerOptionsBuilder(IServiceProvider serviceProvider) 13 | { 14 | ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); 15 | } 16 | 17 | public IServiceProvider ServiceProvider { get; } 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/BufferExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace MQTTnet.AspNetCore; 9 | 10 | public static class BufferExtensions 11 | { 12 | public static ArraySegment GetArray(this ReadOnlyMemory memory) 13 | { 14 | if (!MemoryMarshal.TryGetArray(memory, out var result)) 15 | { 16 | throw new InvalidOperationException("Buffer backed by array was expected"); 17 | } 18 | 19 | return result; 20 | } 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/ConnectionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.AspNetCore.Connections; 6 | 7 | namespace MQTTnet.AspNetCore; 8 | 9 | public static class ConnectionBuilderExtensions 10 | { 11 | public static IConnectionBuilder UseMqtt(this IConnectionBuilder builder) 12 | { 13 | return builder.UseConnectionHandler(); 14 | } 15 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/DuplexPipe.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO.Pipelines; 6 | 7 | namespace MQTTnet.AspNetCore; 8 | 9 | public class DuplexPipe : IDuplexPipe 10 | { 11 | public DuplexPipe(PipeReader reader, PipeWriter writer) 12 | { 13 | Input = reader; 14 | Output = writer; 15 | } 16 | 17 | public PipeReader Input { get; } 18 | 19 | public PipeWriter Output { get; } 20 | 21 | public static DuplexPipePair CreateConnectionPair(PipeOptions inputOptions, PipeOptions outputOptions) 22 | { 23 | var input = new Pipe(inputOptions); 24 | var output = new Pipe(outputOptions); 25 | 26 | var transportToApplication = new DuplexPipe(output.Reader, input.Writer); 27 | var applicationToTransport = new DuplexPipe(input.Reader, output.Writer); 28 | 29 | return new DuplexPipePair(applicationToTransport, transportToApplication); 30 | } 31 | 32 | // This class exists to work around issues with value tuple on .NET Framework 33 | public readonly struct DuplexPipePair 34 | { 35 | public IDuplexPipe Transport { get; } 36 | public IDuplexPipe Application { get; } 37 | 38 | public DuplexPipePair(IDuplexPipe transport, IDuplexPipe application) 39 | { 40 | Transport = transport; 41 | Application = application; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/EndpointRouterExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Routing; 8 | 9 | namespace MQTTnet.AspNetCore; 10 | 11 | public static class EndpointRouterExtensions 12 | { 13 | public static void MapMqtt(this IEndpointRouteBuilder endpoints, string pattern) 14 | { 15 | ArgumentNullException.ThrowIfNull(endpoints); 16 | 17 | endpoints.MapConnectionHandler(pattern, options => 18 | { 19 | options.WebSockets.SubProtocolSelector = MqttSubProtocolSelector.SelectSubProtocol; 20 | }); 21 | } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/MqttClientConnectionContextFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Adapter; 7 | using MQTTnet.Diagnostics.Logger; 8 | using MQTTnet.Formatter; 9 | 10 | namespace MQTTnet.AspNetCore; 11 | 12 | public sealed class MqttClientConnectionContextFactory : IMqttClientAdapterFactory 13 | { 14 | public IMqttChannelAdapter CreateClientAdapter(MqttClientOptions options, MqttPacketInspector packetInspector, IMqttNetLogger logger) 15 | { 16 | if (options == null) throw new ArgumentNullException(nameof(options)); 17 | 18 | switch (options.ChannelOptions) 19 | { 20 | case MqttClientTcpOptions tcpOptions: 21 | { 22 | var tcpConnection = new SocketConnection(tcpOptions.RemoteEndpoint); 23 | 24 | var formatter = new MqttPacketFormatterAdapter(options.ProtocolVersion, new MqttBufferWriter(4096, 65535)); 25 | return new MqttConnectionContext(formatter, tcpConnection); 26 | } 27 | default: 28 | { 29 | throw new NotSupportedException(); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/MqttSubProtocolSelector.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using Microsoft.AspNetCore.Http; 9 | 10 | namespace MQTTnet.AspNetCore; 11 | 12 | public static class MqttSubProtocolSelector 13 | { 14 | public static string SelectSubProtocol(HttpRequest request) 15 | { 16 | ArgumentNullException.ThrowIfNull(request); 17 | 18 | string subProtocol = null; 19 | if (request.Headers.TryGetValue("Sec-WebSocket-Protocol", out var requestedSubProtocolValues)) 20 | { 21 | subProtocol = SelectSubProtocol(requestedSubProtocolValues); 22 | } 23 | 24 | return subProtocol; 25 | } 26 | 27 | public static string SelectSubProtocol(IList requestedSubProtocolValues) 28 | { 29 | ArgumentNullException.ThrowIfNull(requestedSubProtocolValues); 30 | 31 | // Order the protocols to also match "mqtt", "mqttv-3.1", "mqttv-3.11" etc. 32 | return requestedSubProtocolValues.OrderByDescending(p => p.Length).FirstOrDefault(p => p.ToLower().StartsWith("mqtt")); 33 | } 34 | } -------------------------------------------------------------------------------- /Source/MQTTnet.AspnetCore/SocketReceiver.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO.Pipelines; 7 | using System.Net.Sockets; 8 | 9 | namespace MQTTnet.AspNetCore; 10 | 11 | public sealed class SocketReceiver 12 | { 13 | readonly SocketAwaitable _awaitable; 14 | readonly SocketAsyncEventArgs _eventArgs = new(); 15 | readonly Socket _socket; 16 | 17 | public SocketReceiver(Socket socket, PipeScheduler scheduler) 18 | { 19 | _socket = socket; 20 | _awaitable = new SocketAwaitable(scheduler); 21 | _eventArgs.UserToken = _awaitable; 22 | _eventArgs.Completed += (_, e) => ((SocketAwaitable)e.UserToken).Complete(e.BytesTransferred, e.SocketError); 23 | } 24 | 25 | public SocketAwaitable ReceiveAsync(Memory buffer) 26 | { 27 | _eventArgs.SetBuffer(buffer); 28 | 29 | if (!_socket.ReceiveAsync(_eventArgs)) 30 | { 31 | _awaitable.Complete(_eventArgs.BytesTransferred, _eventArgs.SocketError); 32 | } 33 | 34 | return _awaitable; 35 | } 36 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/BaseBenchmark.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Benchmarks; 6 | 7 | public abstract class BaseBenchmark 8 | { 9 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/MQTTnet.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | Exe 6 | Full 7 | net8.0 8 | false 9 | false 10 | false 11 | true 12 | 1591;NETSDK1138;NU1803;NU1901;NU1902;CS8892 13 | false 14 | all 15 | true 16 | low 17 | latest-Recommended 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/MemoryCopyBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Jobs; 3 | using System; 4 | 5 | 6 | namespace MQTTnet.Benchmarks; 7 | 8 | [SimpleJob(RuntimeMoniker.Net60)] 9 | [RPlotExporter, RankColumn] 10 | [MemoryDiagnoser] 11 | public class MemoryCopyBenchmark 12 | { 13 | const int MaxLength = 1024 * 8; 14 | 15 | byte[] _source; 16 | byte[] _target; 17 | 18 | [Params(64 - 1, 128 - 1, 256 - 1, 512 - 1, 1024 - 1, 2048 - 1, 5096 - 1)] 19 | public int Length { get; set; } 20 | 21 | [GlobalSetup] 22 | public void Setup() 23 | { 24 | _source = new byte[MaxLength]; 25 | _target = new byte[MaxLength]; 26 | } 27 | 28 | [Benchmark(Baseline = true)] 29 | public void Array_Copy() 30 | { 31 | Array.Copy(_source, 0, _target, 0, Length); 32 | } 33 | 34 | [Benchmark] 35 | public void Memory_Copy() 36 | { 37 | Internal.MqttMemoryHelper.Copy(_source, 0, _target, 0, Length); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/MessageProcessingBenchmark.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using BenchmarkDotNet.Jobs; 7 | using MQTTnet.Server; 8 | 9 | namespace MQTTnet.Benchmarks; 10 | 11 | [SimpleJob(RuntimeMoniker.Net60)] 12 | [RPlotExporter] 13 | [RankColumn] 14 | [MemoryDiagnoser] 15 | public class MessageProcessingBenchmark : BaseBenchmark 16 | { 17 | MqttApplicationMessage _message; 18 | IMqttClient _mqttClient; 19 | MqttServer _mqttServer; 20 | 21 | [Benchmark] 22 | public void Send_10000_Messages() 23 | { 24 | for (var i = 0; i < 10000; i++) 25 | { 26 | _mqttClient.PublishAsync(_message).GetAwaiter().GetResult(); 27 | } 28 | } 29 | 30 | [GlobalSetup] 31 | public void Setup() 32 | { 33 | var serverOptions = new MqttServerOptionsBuilder().Build(); 34 | 35 | var serverFactory = new MqttServerFactory(); 36 | _mqttServer = serverFactory.CreateMqttServer(serverOptions); 37 | var clientFactory = new MqttClientFactory(); 38 | _mqttClient = clientFactory.CreateMqttClient(); 39 | 40 | _mqttServer.StartAsync().GetAwaiter().GetResult(); 41 | 42 | var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("localhost").Build(); 43 | 44 | _mqttClient.ConnectAsync(clientOptions).GetAwaiter().GetResult(); 45 | 46 | _message = new MqttApplicationMessageBuilder().WithTopic("A").Build(); 47 | } 48 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/RoundtripProcessingBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Jobs; 3 | using MQTTnet.Tests.Mockups; 4 | using MQTTnet.Tests.Server; 5 | 6 | namespace MQTTnet.Benchmarks; 7 | 8 | [SimpleJob(RuntimeMoniker.Net60)] 9 | [RPlotExporter, RankColumn] 10 | [MemoryDiagnoser] 11 | public class RoundtripProcessingBenchmark : BaseBenchmark 12 | { 13 | [GlobalSetup] 14 | public void GlobalSetup() 15 | { 16 | TestEnvironment.EnableLogger = false; 17 | } 18 | 19 | [GlobalCleanup] 20 | public void GlobalCleanup() 21 | { 22 | } 23 | 24 | [Benchmark] 25 | public void Handle_100_000_Messages_In_Receiving_Client() 26 | { 27 | new Load_Tests().Handle_100_000_Messages_In_Receiving_Client().GetAwaiter().GetResult(); 28 | } 29 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Benchmarks/ServerProcessingBenchmark.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using BenchmarkDotNet.Attributes; 6 | using BenchmarkDotNet.Jobs; 7 | using MQTTnet.Tests.Mockups; 8 | using MQTTnet.Tests.Server; 9 | 10 | namespace MQTTnet.Benchmarks; 11 | 12 | [SimpleJob(RuntimeMoniker.Net60)] 13 | [RPlotExporter, RankColumn] 14 | [MemoryDiagnoser] 15 | public class ServerProcessingBenchmark : BaseBenchmark 16 | { 17 | [GlobalSetup] 18 | public void GlobalSetup() 19 | { 20 | TestEnvironment.EnableLogger = false; 21 | } 22 | 23 | [GlobalCleanup] 24 | public void GlobalCleanup() 25 | { 26 | } 27 | 28 | [Benchmark] 29 | public void Handle_100_000_Messages_In_Server_MqttClient() 30 | { 31 | new Load_Tests().Handle_100_000_Messages_In_Server().GetAwaiter().GetResult(); 32 | } 33 | 34 | //[Benchmark] 35 | public void Handle_100_000_Messages_In_Server_LowLevelMqttClient() 36 | { 37 | new Load_Tests().Handle_100_000_Messages_In_Low_Level_Client().GetAwaiter().GetResult(); 38 | } 39 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/DefaultMqttRpcClientTopicGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Extensions.Rpc; 8 | 9 | public sealed class DefaultMqttRpcClientTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy 10 | { 11 | public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) 12 | { 13 | ArgumentNullException.ThrowIfNull(context); 14 | 15 | if (context.MethodName.Contains("/") || context.MethodName.Contains("+") || context.MethodName.Contains("#")) 16 | { 17 | throw new ArgumentException("The method name cannot contain /, + or #."); 18 | } 19 | 20 | var requestTopic = $"MQTTnet.RPC/{Guid.NewGuid():N}/{context.MethodName}"; 21 | var responseTopic = requestTopic + "/response"; 22 | 23 | return new MqttRpcTopicPair 24 | { 25 | RequestTopic = requestTopic, 26 | ResponseTopic = responseTopic 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/IMqttRpcClient.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using MQTTnet.Protocol; 10 | 11 | namespace MQTTnet.Extensions.Rpc; 12 | 13 | public interface IMqttRpcClient : IDisposable 14 | { 15 | Task ExecuteAsync(TimeSpan timeout, string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, IDictionary parameters = null); 16 | 17 | Task ExecuteAsync(string methodName, byte[] payload, MqttQualityOfServiceLevel qualityOfServiceLevel, IDictionary parameters = null, CancellationToken cancellationToken = default); 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/IMqttRpcClientTopicGenerationStrategy.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Extensions.Rpc; 6 | 7 | public interface IMqttRpcClientTopicGenerationStrategy 8 | { 9 | MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context); 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MQTTnet.Extensions.Rpc.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  4 | True 6 | True -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MqttFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Extensions.Rpc; 8 | 9 | public static class MqttFactoryExtensions 10 | { 11 | public static IMqttRpcClient CreateMqttRpcClient(this MqttClientFactory clientFactory, IMqttClient mqttClient) 12 | { 13 | return clientFactory.CreateMqttRpcClient( 14 | mqttClient, 15 | new MqttRpcClientOptions 16 | { 17 | TopicGenerationStrategy = new DefaultMqttRpcClientTopicGenerationStrategy() 18 | }); 19 | } 20 | 21 | public static IMqttRpcClient CreateMqttRpcClient(this MqttClientFactory _, IMqttClient mqttClient, MqttRpcClientOptions rpcClientOptions) 22 | { 23 | ArgumentNullException.ThrowIfNull(mqttClient); 24 | ArgumentNullException.ThrowIfNull(rpcClientOptions); 25 | 26 | return new MqttRpcClient(mqttClient, rpcClientOptions); 27 | } 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MqttRpcClientExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using MQTTnet.Protocol; 10 | 11 | namespace MQTTnet.Extensions.Rpc; 12 | 13 | public static class MqttRpcClientExtensions 14 | { 15 | public static Task ExecuteAsync(this IMqttRpcClient client, TimeSpan timeout, string methodName, string payload, MqttQualityOfServiceLevel qualityOfServiceLevel, IDictionary parameters = null) 16 | { 17 | if (client == null) throw new ArgumentNullException(nameof(client)); 18 | 19 | var buffer = Encoding.UTF8.GetBytes(payload ?? string.Empty); 20 | 21 | return client.ExecuteAsync(timeout, methodName, buffer, qualityOfServiceLevel, parameters); 22 | } 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MqttRpcClientOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Extensions.Rpc; 6 | 7 | public sealed class MqttRpcClientOptions 8 | { 9 | public IMqttRpcClientTopicGenerationStrategy TopicGenerationStrategy { get; set; } = new DefaultMqttRpcClientTopicGenerationStrategy(); 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MqttRpcClientOptionsBuilder.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Extensions.Rpc; 8 | 9 | public sealed class MqttRpcClientOptionsBuilder 10 | { 11 | IMqttRpcClientTopicGenerationStrategy _topicGenerationStrategy = new DefaultMqttRpcClientTopicGenerationStrategy(); 12 | 13 | public MqttRpcClientOptions Build() 14 | { 15 | return new MqttRpcClientOptions 16 | { 17 | TopicGenerationStrategy = _topicGenerationStrategy 18 | }; 19 | } 20 | 21 | public MqttRpcClientOptionsBuilder WithTopicGenerationStrategy(IMqttRpcClientTopicGenerationStrategy value) 22 | { 23 | _topicGenerationStrategy = value ?? throw new ArgumentNullException(nameof(value)); 24 | 25 | return this; 26 | } 27 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/MqttRpcTopicPair.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Extensions.Rpc; 6 | 7 | public sealed class MqttRpcTopicPair 8 | { 9 | public string RequestTopic { get; set; } 10 | 11 | public string ResponseTopic { get; set; } 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Extensions.Rpc/SampleCCode.c: -------------------------------------------------------------------------------- 1 | // If using the MQTT client PubSubClient it must be ensured that the request topic for each method is subscribed like the following. 2 | _mqttClient.subscribe("MQTTnet.RPC/+/ping"); 3 | _mqttClient.subscribe("MQTTnet.RPC/+/do_something"); 4 | 5 | // It is not allowed to change the structure of the topic. Otherwise RPC will not work. So method names can be separated using 6 | // an _ or . but no +, # or /. If it is required to distinguish between devices own rules can be defined like the following. 7 | _mqttClient.subscribe("MQTTnet.RPC/+/deviceA.ping"); 8 | _mqttClient.subscribe("MQTTnet.RPC/+/deviceB.ping"); 9 | _mqttClient.subscribe("MQTTnet.RPC/+/deviceC.getTemperature"); 10 | 11 | // Within the callback of the MQTT client the topic must be checked if it belongs to MQTTnet RPC. The following code shows one 12 | // possible way of doing this. 13 | void mqtt_Callback(char *topic, byte *payload, unsigned int payloadLength) 14 | { 15 | String topicString = String(topic); 16 | 17 | if (topicString.startsWith("MQTTnet.RPC/")) { 18 | String responseTopic = topicString + String("/response"); 19 | 20 | if (topicString.endsWith("/deviceA.ping")) { 21 | mqtt_publish(responseTopic, "pong", false); 22 | return; 23 | } 24 | } 25 | } 26 | 27 | // Important notes: 28 | // ! Do not send response message with the _retain_ flag set to true. 29 | // ! All required data for a RPC call and the result must be placed into the payload. -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Disconnecting/MqttServerClientDisconnectOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public sealed class MqttServerClientDisconnectOptions 11 | { 12 | public MqttDisconnectReasonCode ReasonCode { get; set; } = MqttDisconnectReasonCode.NormalDisconnection; 13 | 14 | /// 15 | /// The reason string is sent to every client via a DISCONNECT packet. 16 | /// MQTT 5.0.0+ feature. 17 | /// 18 | public string ReasonString { get; set; } 19 | 20 | /// 21 | /// The server reference is sent to every client via a DISCONNECT packet. 22 | /// MQTT 5.0.0+ feature. 23 | /// 24 | public string ServerReference { get; set; } 25 | 26 | /// 27 | /// These user properties are sent to every client via a DISCONNECT packet. 28 | /// MQTT 5.0.0+ feature. 29 | /// 30 | public List UserProperties { get; set; } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/EnhancedAuthentication/ExchangeEnhancedAuthenticationOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.Server.EnhancedAuthentication; 8 | 9 | public sealed class ExchangeEnhancedAuthenticationOptions 10 | { 11 | public byte[] AuthenticationData { get; set; } 12 | 13 | public string ReasonString { get; set; } 14 | 15 | public List UserProperties { get; set; } 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/EnhancedAuthentication/ExchangeEnhancedAuthenticationResult.cs: -------------------------------------------------------------------------------- 1 | using MQTTnet.Packets; 2 | 3 | namespace MQTTnet.Server.EnhancedAuthentication; 4 | 5 | public sealed class ExchangeEnhancedAuthenticationResult 6 | { 7 | public string ReasonString { get; set; } 8 | 9 | public List UserProperties { get; set; } 10 | 11 | public byte[] AuthenticationData { get; set; } 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/EnhancedAuthentication/ExchangeEnhancedAuthenticationResultFactory.cs: -------------------------------------------------------------------------------- 1 | using MQTTnet.Packets; 2 | 3 | namespace MQTTnet.Server.EnhancedAuthentication; 4 | 5 | public static class ExchangeEnhancedAuthenticationResultFactory 6 | { 7 | public static ExchangeEnhancedAuthenticationResult Create(MqttAuthPacket authPacket) 8 | { 9 | ArgumentNullException.ThrowIfNull(authPacket); 10 | 11 | return new ExchangeEnhancedAuthenticationResult 12 | { 13 | AuthenticationData = authPacket.AuthenticationData, 14 | 15 | ReasonString = authPacket.ReasonString, 16 | UserProperties = authPacket.UserProperties 17 | }; 18 | } 19 | 20 | public static ExchangeEnhancedAuthenticationResult Create(MqttDisconnectPacket disconnectPacket) 21 | { 22 | ArgumentNullException.ThrowIfNull(disconnectPacket); 23 | 24 | return new ExchangeEnhancedAuthenticationResult 25 | { 26 | AuthenticationData = null, 27 | ReasonString = disconnectPacket.ReasonString, 28 | UserProperties = disconnectPacket.UserProperties 29 | 30 | // SessionExpiryInterval makes no sense because the connection is not yet made! 31 | // ServerReferences makes no sense when the client initiated a DISCONNECT! 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/ApplicationMessageEnqueuedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class ApplicationMessageEnqueuedEventArgs : EventArgs 8 | { 9 | public ApplicationMessageEnqueuedEventArgs(string senderClientId, string receiverClientId, MqttApplicationMessage applicationMessage, bool isDropped) 10 | { 11 | SenderClientId = senderClientId ?? throw new ArgumentNullException( nameof(senderClientId)); 12 | ReceiverClientId = receiverClientId ?? throw new ArgumentNullException(nameof(receiverClientId)); 13 | ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); 14 | IsDropped = isDropped; 15 | } 16 | 17 | public string SenderClientId { get; } 18 | 19 | public string ReceiverClientId { get; } 20 | 21 | public bool IsDropped { get; } 22 | 23 | public MqttApplicationMessage ApplicationMessage { get; } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/ApplicationMessageNotConsumedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class ApplicationMessageNotConsumedEventArgs : EventArgs 8 | { 9 | public ApplicationMessageNotConsumedEventArgs(MqttApplicationMessage applicationMessage, string senderId) 10 | { 11 | ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); 12 | SenderId = senderId; 13 | } 14 | 15 | /// 16 | /// Gets the application message which was not consumed by any client. 17 | /// 18 | public MqttApplicationMessage ApplicationMessage { get; } 19 | 20 | /// 21 | /// Gets the ID of the client which has sent the affected application message. 22 | /// 23 | public string SenderId { get; } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/ClientUnsubscribedTopicEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class ClientUnsubscribedTopicEventArgs : EventArgs 10 | { 11 | public ClientUnsubscribedTopicEventArgs(string clientId, string userName, string topicFilter, IDictionary sessionItems) 12 | { 13 | ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId)); 14 | UserName = userName; 15 | TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter)); 16 | SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems)); 17 | } 18 | 19 | /// 20 | /// Gets the client identifier. 21 | /// Hint: This identifier needs to be unique over all used clients / devices on the broker to avoid connection issues. 22 | /// 23 | public string ClientId { get; } 24 | 25 | /// 26 | /// Gets the user name of the client. 27 | /// 28 | public string UserName { get; } 29 | 30 | /// 31 | /// Gets or sets a key/value collection that can be used to share data within the scope of this session. 32 | /// 33 | public IDictionary SessionItems { get; } 34 | 35 | /// 36 | /// Gets or sets the topic filter. 37 | /// The topic filter can contain topics and wildcards. 38 | /// 39 | public string TopicFilter { get; } 40 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/InterceptingClientApplicationMessageEnqueueEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class InterceptingClientApplicationMessageEnqueueEventArgs : EventArgs 8 | { 9 | public InterceptingClientApplicationMessageEnqueueEventArgs(string senderClientId, string receiverClientId, MqttApplicationMessage applicationMessage) 10 | { 11 | SenderClientId = senderClientId ?? throw new ArgumentNullException(nameof(senderClientId)); 12 | ReceiverClientId = receiverClientId ?? throw new ArgumentNullException(nameof(receiverClientId)); 13 | ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); 14 | } 15 | 16 | /// 17 | /// Gets or sets whether the enqueue of the application message should be performed or not. 18 | /// If set to _False_ the client will not receive the application message. 19 | /// 20 | public bool AcceptEnqueue { get; set; } = true; 21 | 22 | public MqttApplicationMessage ApplicationMessage { get; } 23 | 24 | /// 25 | /// Indicates if the connection with the sender should be closed. 26 | /// 27 | public bool CloseSenderConnection { get; set; } 28 | 29 | public string ReceiverClientId { get; } 30 | 31 | public string SenderClientId { get; } 32 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/LoadingRetainedMessagesEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class LoadingRetainedMessagesEventArgs : EventArgs 8 | { 9 | public List LoadedRetainedMessages { get; set; } = new List(); 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/QueueMessageOverwrittenEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class QueueMessageOverwrittenEventArgs : EventArgs 10 | { 11 | public QueueMessageOverwrittenEventArgs(string receiverClientId, MqttPacket packet) 12 | { 13 | ReceiverClientId = receiverClientId ?? throw new ArgumentNullException(nameof(receiverClientId)); 14 | Packet = packet ?? throw new ArgumentNullException(nameof(packet)); 15 | } 16 | 17 | public MqttPacket Packet { get; } 18 | 19 | public string ReceiverClientId { get; } 20 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/RetainedMessageChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class RetainedMessageChangedEventArgs : EventArgs 8 | { 9 | public RetainedMessageChangedEventArgs(string clientId, MqttApplicationMessage changedRetainedMessage, List storedRetainedMessages) 10 | { 11 | ClientId = clientId ?? throw new ArgumentNullException(nameof(clientId)); 12 | ChangedRetainedMessage = changedRetainedMessage ?? throw new ArgumentNullException(nameof(changedRetainedMessage)); 13 | StoredRetainedMessages = storedRetainedMessages ?? throw new ArgumentNullException(nameof(storedRetainedMessages)); 14 | } 15 | 16 | public MqttApplicationMessage ChangedRetainedMessage { get; } 17 | 18 | public string ClientId { get; } 19 | 20 | public List StoredRetainedMessages { get; } 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Events/SessionDeletedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class SessionDeletedEventArgs : EventArgs 10 | { 11 | public SessionDeletedEventArgs(string id, string userName, IDictionary sessionItems) 12 | { 13 | Id = id ?? throw new ArgumentNullException(nameof(id)); 14 | UserName = userName; 15 | SessionItems = sessionItems ?? throw new ArgumentNullException(nameof(sessionItems)); 16 | } 17 | 18 | /// 19 | /// Gets the ID of the session. 20 | /// 21 | public string Id { get; } 22 | 23 | /// 24 | /// Gets the user name of the session. 25 | /// 26 | public string UserName { get; } 27 | 28 | /// 29 | /// Gets or sets a key/value collection that can be used to share data within the scope of this session. 30 | /// 31 | public IDictionary SessionItems { get; } 32 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Exceptions/MqttPendingMessagesOverflowException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server.Exceptions; 6 | 7 | public class MqttPendingMessagesOverflowException : Exception 8 | { 9 | public MqttPendingMessagesOverflowException(string sessionId, MqttPendingMessagesOverflowStrategy overflowStrategy) : base( 10 | $"Send buffer max pending messages overflow occurred for session '{sessionId}'. Strategy: {overflowStrategy}.") 11 | { 12 | SessionId = sessionId; 13 | OverflowStrategy = overflowStrategy; 14 | } 15 | 16 | public MqttPendingMessagesOverflowStrategy OverflowStrategy { get; } 17 | 18 | public string SessionId { get; } 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/IMqttServerAdapter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Adapter; 6 | using MQTTnet.Diagnostics.Logger; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public interface IMqttServerAdapter : IDisposable 11 | { 12 | Func ClientHandler { get; set; } 13 | 14 | Task StartAsync(MqttServerOptions options, IMqttNetLogger logger); 15 | 16 | Task StopAsync(); 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/InjectedMqttApplicationMessage.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class InjectedMqttApplicationMessage 10 | { 11 | public InjectedMqttApplicationMessage(MqttApplicationMessage applicationMessage) 12 | { 13 | ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); 14 | } 15 | 16 | public MqttApplicationMessage ApplicationMessage { get; } 17 | 18 | /// 19 | /// Gets or sets the session items which should be used for all event handlers which are involved in message 20 | /// processing. 21 | /// If _null_ is specified the singleton session items from the server are used instead. 22 | /// 23 | public IDictionary CustomSessionItems { get; set; } 24 | 25 | public string SenderClientId { get; set; } = string.Empty; 26 | 27 | public string SenderUserName { get; set; } 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/CheckSubscriptionsResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Protocol; 6 | 7 | namespace MQTTnet.Server.Internal; 8 | 9 | public sealed class CheckSubscriptionsResult 10 | { 11 | public static CheckSubscriptionsResult NotSubscribed { get; } = new CheckSubscriptionsResult(); 12 | 13 | public bool IsSubscribed { get; set; } 14 | 15 | public bool RetainAsPublished { get; set; } 16 | 17 | public List SubscriptionIdentifiers { get; set; } 18 | 19 | public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; } 20 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/DispatchApplicationMessageResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.Server.Internal; 8 | 9 | public sealed class DispatchApplicationMessageResult 10 | { 11 | public DispatchApplicationMessageResult(int reasonCode, bool closeConnection, string reasonString, List userProperties) 12 | { 13 | ReasonCode = reasonCode; 14 | CloseConnection = closeConnection; 15 | ReasonString = reasonString; 16 | UserProperties = userProperties; 17 | } 18 | 19 | public bool CloseConnection { get; } 20 | 21 | public int ReasonCode { get; } 22 | 23 | public string ReasonString { get; } 24 | 25 | public List UserProperties { get; } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/EnqueueDataPacketResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server.Internal; 6 | 7 | public enum EnqueueDataPacketResult 8 | { 9 | Enqueued, 10 | Dropped 11 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttDisconnectPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal.Formatter; 9 | 10 | public static class MqttDisconnectPacketFactory 11 | { 12 | static readonly MqttDisconnectPacket DefaultNormalDisconnection = new() 13 | { 14 | ReasonCode = MqttDisconnectReasonCode.NormalDisconnection, 15 | UserProperties = null, 16 | ReasonString = null, 17 | ServerReference = null, 18 | SessionExpiryInterval = 0 19 | }; 20 | 21 | public static MqttDisconnectPacket Create(MqttServerClientDisconnectOptions clientDisconnectOptions) 22 | { 23 | if (clientDisconnectOptions == null) 24 | { 25 | return DefaultNormalDisconnection; 26 | } 27 | 28 | return new MqttDisconnectPacket 29 | { 30 | ReasonCode = clientDisconnectOptions.ReasonCode, 31 | UserProperties = clientDisconnectOptions.UserProperties, 32 | ReasonString = clientDisconnectOptions.ReasonString, 33 | ServerReference = clientDisconnectOptions.ServerReference, 34 | SessionExpiryInterval = 0 // TODO: Not yet supported! 35 | }; 36 | } 37 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttPubAckPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal.Formatter; 9 | 10 | public static class MqttPubAckPacketFactory 11 | { 12 | public static MqttPubAckPacket Create(MqttPublishPacket publishPacket, DispatchApplicationMessageResult dispatchApplicationMessageResult) 13 | { 14 | ArgumentNullException.ThrowIfNull(publishPacket); 15 | ArgumentNullException.ThrowIfNull(dispatchApplicationMessageResult); 16 | 17 | var pubAckPacket = new MqttPubAckPacket 18 | { 19 | PacketIdentifier = publishPacket.PacketIdentifier, 20 | ReasonCode = (MqttPubAckReasonCode)dispatchApplicationMessageResult.ReasonCode, 21 | ReasonString = dispatchApplicationMessageResult.ReasonString, 22 | UserProperties = dispatchApplicationMessageResult.UserProperties 23 | }; 24 | 25 | return pubAckPacket; 26 | } 27 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttPubCompPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal.Formatter; 9 | 10 | public static class MqttPubCompPacketFactory 11 | { 12 | public static MqttPubCompPacket Create(MqttPubRelPacket pubRelPacket, MqttApplicationMessageReceivedReasonCode reasonCode) 13 | { 14 | ArgumentNullException.ThrowIfNull(pubRelPacket); 15 | 16 | return new MqttPubCompPacket 17 | { 18 | PacketIdentifier = pubRelPacket.PacketIdentifier, 19 | ReasonCode = (MqttPubCompReasonCode)(int)reasonCode 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttPubRecPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal.Formatter; 9 | 10 | public static class MqttPubRecPacketFactory 11 | { 12 | public static MqttPacket Create(MqttPublishPacket publishPacket, DispatchApplicationMessageResult dispatchApplicationMessageResult) 13 | { 14 | ArgumentNullException.ThrowIfNull(publishPacket); 15 | 16 | var pubRecPacket = new MqttPubRecPacket 17 | { 18 | PacketIdentifier = publishPacket.PacketIdentifier, 19 | ReasonCode = (MqttPubRecReasonCode)dispatchApplicationMessageResult.ReasonCode, 20 | ReasonString = dispatchApplicationMessageResult.ReasonString, 21 | UserProperties = dispatchApplicationMessageResult.UserProperties 22 | }; 23 | 24 | return pubRecPacket; 25 | } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttPubRelPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal.Formatter; 9 | 10 | public static class MqttPubRelPacketFactory 11 | { 12 | public static MqttPubRelPacket Create(MqttPubRecPacket pubRecPacket, MqttApplicationMessageReceivedReasonCode reasonCode) 13 | { 14 | ArgumentNullException.ThrowIfNull(pubRecPacket); 15 | 16 | return new MqttPubRelPacket 17 | { 18 | PacketIdentifier = pubRecPacket.PacketIdentifier, 19 | ReasonCode = (MqttPubRelReasonCode)(int)reasonCode 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttSubAckPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.Server.Internal.Formatter; 8 | 9 | public static class MqttSubAckPacketFactory 10 | { 11 | public static MqttSubAckPacket Create(MqttSubscribePacket subscribePacket, SubscribeResult subscribeResult) 12 | { 13 | ArgumentNullException.ThrowIfNull(subscribePacket); 14 | ArgumentNullException.ThrowIfNull(subscribeResult); 15 | 16 | var subAckPacket = new MqttSubAckPacket 17 | { 18 | PacketIdentifier = subscribePacket.PacketIdentifier, 19 | ReasonCodes = subscribeResult.ReasonCodes, 20 | ReasonString = subscribeResult.ReasonString, 21 | UserProperties = subscribeResult.UserProperties 22 | }; 23 | 24 | return subAckPacket; 25 | } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/Formatter/MqttUnsubAckPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.Server.Internal.Formatter; 8 | 9 | public static class MqttUnsubAckPacketFactory 10 | { 11 | public static MqttUnsubAckPacket Create(MqttUnsubscribePacket unsubscribePacket, UnsubscribeResult unsubscribeResult) 12 | { 13 | ArgumentNullException.ThrowIfNull(unsubscribePacket); 14 | ArgumentNullException.ThrowIfNull(unsubscribeResult); 15 | 16 | var unsubAckPacket = new MqttUnsubAckPacket 17 | { 18 | PacketIdentifier = unsubscribePacket.PacketIdentifier 19 | }; 20 | 21 | // MQTTv5.0.0 only. 22 | unsubAckPacket.ReasonCodes = unsubscribeResult.ReasonCodes; 23 | 24 | return unsubAckPacket; 25 | } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/ISubscriptionChangedNotification.cs: -------------------------------------------------------------------------------- 1 | namespace MQTTnet.Server.Internal; 2 | 3 | public interface ISubscriptionChangedNotification 4 | { 5 | void OnSubscriptionsAdded(MqttSession clientSession, List subscriptionsTopics); 6 | 7 | void OnSubscriptionsRemoved(MqttSession clientSession, List subscriptionTopics); 8 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/MqttSubscription.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Protocol; 6 | 7 | namespace MQTTnet.Server.Internal; 8 | 9 | public sealed class MqttSubscription 10 | { 11 | public MqttSubscription( 12 | string topic, 13 | bool noLocal, 14 | MqttRetainHandling retainHandling, 15 | bool retainAsPublished, 16 | MqttQualityOfServiceLevel qualityOfServiceLevel, 17 | uint identifier) 18 | { 19 | Topic = topic; 20 | NoLocal = noLocal; 21 | RetainHandling = retainHandling; 22 | RetainAsPublished = retainAsPublished; 23 | GrantedQualityOfServiceLevel = qualityOfServiceLevel; 24 | Identifier = identifier; 25 | 26 | MqttTopicHash.Calculate(Topic, out var hash, out var hashMask, out var hasWildcard); 27 | TopicHash = hash; 28 | TopicHashMask = hashMask; 29 | TopicHasWildcard = hasWildcard; 30 | } 31 | 32 | public MqttQualityOfServiceLevel GrantedQualityOfServiceLevel { get; } 33 | 34 | public uint Identifier { get; } 35 | 36 | public bool NoLocal { get; } 37 | 38 | public bool RetainAsPublished { get; } 39 | 40 | public MqttRetainHandling RetainHandling { get; } 41 | 42 | public string Topic { get; } 43 | 44 | public ulong TopicHash { get; } 45 | 46 | public ulong TopicHashMask { get; } 47 | 48 | public bool TopicHasWildcard { get; } 49 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/SubscribeResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal; 9 | 10 | public sealed class SubscribeResult 11 | { 12 | public SubscribeResult(int topicsCount) 13 | { 14 | ReasonCodes = new List(topicsCount); 15 | } 16 | 17 | public bool CloseConnection { get; set; } 18 | 19 | public List ReasonCodes { get; set; } 20 | 21 | public string ReasonString { get; set; } 22 | 23 | public List RetainedMessages { get; set; } 24 | 25 | public List UserProperties { get; set; } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/TopicHashMaskSubscriptions.cs: -------------------------------------------------------------------------------- 1 | namespace MQTTnet.Server.Internal; 2 | 3 | /// 4 | /// Helper class that stores subscriptions by their topic hash mask. 5 | /// 6 | public sealed class TopicHashMaskSubscriptions 7 | { 8 | public Dictionary> SubscriptionsByHashMask { get; } = new Dictionary>(); 9 | 10 | public void AddSubscription(MqttSubscription subscription) 11 | { 12 | if (!SubscriptionsByHashMask.TryGetValue(subscription.TopicHashMask, out var subscriptions)) 13 | { 14 | subscriptions = new HashSet(); 15 | SubscriptionsByHashMask.Add(subscription.TopicHashMask, subscriptions); 16 | } 17 | subscriptions.Add(subscription); 18 | } 19 | 20 | public void RemoveSubscription(MqttSubscription subscription) 21 | { 22 | if (SubscriptionsByHashMask.TryGetValue(subscription.TopicHashMask, out var subscriptions)) 23 | { 24 | subscriptions.Remove(subscription); 25 | if (subscriptions.Count == 0) 26 | { 27 | SubscriptionsByHashMask.Remove(subscription.TopicHashMask); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Internal/UnsubscribeResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server.Internal; 9 | 10 | public sealed class UnsubscribeResult 11 | { 12 | public List ReasonCodes { get; } = new List(128); 13 | 14 | public bool CloseConnection { get; set; } 15 | 16 | public List UserProperties { get; set; } 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/MQTTnet.Server.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  4 | True 6 | True 8 | True 10 | True 12 | True -------------------------------------------------------------------------------- /Source/MQTTnet.Server/MqttClientDisconnectType.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public enum MqttClientDisconnectType 8 | { 9 | Clean, 10 | NotClean, 11 | Takeover 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/MqttRetainedMessageMatch.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Protocol; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class MqttRetainedMessageMatch 10 | { 11 | public MqttRetainedMessageMatch(MqttApplicationMessage applicationMessage, MqttQualityOfServiceLevel subscriptionQualityOfServiceLevel) 12 | { 13 | ApplicationMessage = applicationMessage ?? throw new ArgumentNullException(nameof(applicationMessage)); 14 | SubscriptionQualityOfServiceLevel = subscriptionQualityOfServiceLevel; 15 | } 16 | 17 | public MqttApplicationMessage ApplicationMessage { get; } 18 | 19 | public MqttQualityOfServiceLevel SubscriptionQualityOfServiceLevel { get; set; } 20 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/IMqttServerCertificateCredentials.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public interface IMqttServerCertificateCredentials 8 | { 9 | string Password { get; } 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/MqttPendingMessagesOverflowStrategy.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public enum MqttPendingMessagesOverflowStrategy 8 | { 9 | DropOldestQueuedMessage, 10 | 11 | DropNewMessage 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/MqttServerCertificateCredentials.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public class MqttServerCertificateCredentials : IMqttServerCertificateCredentials 8 | { 9 | public string Password { get; set; } 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/MqttServerKeepAliveOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class MqttServerKeepAliveOptions 8 | { 9 | /// 10 | /// When this mode is enabled the MQTT server will not close a connection when the 11 | /// client is currently sending a (large) payload. This may lead to "dead" connections 12 | /// When this mode is disabled the MQTT server will disconnect a client when the keep 13 | /// alive timeout is reached even if the client is currently sending a (large) payload. 14 | /// 15 | public bool DisconnectClientWhenReadingPayload { get; set; } 16 | 17 | public TimeSpan MonitorInterval { get; set; } = TimeSpan.FromMilliseconds(500); 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/MqttServerTcpEndpointOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public class MqttServerTcpEndpointOptions : MqttServerTcpEndpointBaseOptions 8 | { 9 | public MqttServerTcpEndpointOptions() 10 | { 11 | Port = 1883; 12 | } 13 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Options/MqttServerTlsTcpEndpointOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Security.Authentication; 6 | using MQTTnet.Certificates; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public sealed class MqttServerTlsTcpEndpointOptions : MqttServerTcpEndpointBaseOptions 11 | { 12 | public MqttServerTlsTcpEndpointOptions() 13 | { 14 | Port = 8883; 15 | } 16 | 17 | public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } 18 | 19 | public ICertificateProvider CertificateProvider { get; set; } 20 | 21 | public bool ClientCertificateRequired { get; set; } 22 | 23 | public bool CheckCertificateRevocation { get; set; } 24 | 25 | /// 26 | /// The default value is SslProtocols.None, which allows the operating system to choose the best protocol to use, and to block protocols that are not secure. 27 | /// 28 | /// SslProtocols 29 | public SslProtocols SslProtocol { get; set; } = SslProtocols.None; 30 | 31 | public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get; set; } 32 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/PublishResponse.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public sealed class PublishResponse 11 | { 12 | public MqttPubAckReasonCode ReasonCode { get; set; } = MqttPubAckReasonCode.Success; 13 | 14 | public string ReasonString { get; set; } 15 | 16 | public List UserProperties { get; set; } 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Status/MqttClientStatusExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Protocol; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public static class MqttClientStatusExtensions 10 | { 11 | static readonly MqttServerClientDisconnectOptions DefaultDisconnectOptions = new() 12 | { 13 | ReasonCode = MqttDisconnectReasonCode.NormalDisconnection, 14 | ReasonString = null, 15 | UserProperties = null, 16 | ServerReference = null 17 | }; 18 | 19 | public static Task DisconnectAsync(this MqttClientStatus clientStatus) 20 | { 21 | ArgumentNullException.ThrowIfNull(clientStatus); 22 | 23 | return clientStatus.DisconnectAsync(DefaultDisconnectOptions); 24 | } 25 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Stopping/MqttServerStopOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Protocol; 6 | 7 | namespace MQTTnet.Server; 8 | 9 | public sealed class MqttServerStopOptions 10 | { 11 | /// 12 | /// These disconnect options are sent to every connected client via a DISCONNECT packet. 13 | /// MQTT 5.0.0+ feature. 14 | /// 15 | public MqttServerClientDisconnectOptions DefaultClientDisconnectOptions { get; set; } = new MqttServerClientDisconnectOptions 16 | { 17 | ReasonCode = MqttDisconnectReasonCode.ServerShuttingDown, 18 | UserProperties = null, 19 | ReasonString = null, 20 | ServerReference = null 21 | }; 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/Stopping/MqttServerStopOptionsBuilder.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Server; 6 | 7 | public sealed class MqttServerStopOptionsBuilder 8 | { 9 | readonly MqttServerStopOptions _options = new(); 10 | 11 | public MqttServerStopOptionsBuilder WithDefaultClientDisconnectOptions(MqttServerClientDisconnectOptions value) 12 | { 13 | _options.DefaultClientDisconnectOptions = value; 14 | return this; 15 | } 16 | 17 | public MqttServerStopOptionsBuilder WithDefaultClientDisconnectOptions(Action builder) 18 | { 19 | ArgumentNullException.ThrowIfNull(builder); 20 | 21 | var optionsBuilder = new MqttServerClientDisconnectOptionsBuilder(); 22 | builder(optionsBuilder); 23 | 24 | _options.DefaultClientDisconnectOptions = optionsBuilder.Build(); 25 | return this; 26 | } 27 | 28 | public MqttServerStopOptions Build() 29 | { 30 | return _options; 31 | } 32 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/SubscribeResponse.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public sealed class SubscribeResponse 11 | { 12 | /// 13 | /// Gets or sets the reason code which is sent to the client. 14 | /// The subscription is skipped when the value is not GrantedQoS_. 15 | /// MQTTv5 only. 16 | /// 17 | public MqttSubscribeReasonCode ReasonCode { get; set; } 18 | 19 | public string ReasonString { get; set; } 20 | 21 | public List UserProperties { get; } = []; 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Server/UnsubscribeResponse.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Server; 9 | 10 | public sealed class UnsubscribeResponse 11 | { 12 | /// 13 | /// Gets or sets the reason code which is sent to the client. 14 | /// MQTTv5 only. 15 | /// 16 | public MqttUnsubscribeReasonCode ReasonCode { get; set; } 17 | 18 | public string ReasonString { get; set; } 19 | 20 | public List UserProperties { get; } = []; 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet.TestApp/AsyncLockTest.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using MQTTnet.Exceptions; 9 | 10 | namespace MQTTnet.TestApp; 11 | 12 | public sealed class AsyncLockTest 13 | { 14 | public async Task Run() 15 | { 16 | try 17 | { 18 | var semaphore = new SemaphoreSlim(1, 1); 19 | 20 | await semaphore.WaitAsync(); 21 | try 22 | { 23 | // Wait for data from socket etc... 24 | // Then get an exception. 25 | semaphore.Dispose(); 26 | throw new MqttCommunicationException("Connection closed"); 27 | } 28 | finally 29 | { 30 | semaphore.Release(); 31 | } 32 | } 33 | catch (Exception exception) 34 | { 35 | Console.WriteLine(exception.ToString()); 36 | } 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | // var asyncLock = new AsyncLock(); 50 | // 51 | // using var cancellationToken = new CancellationTokenSource(); 52 | // for (var i = 0; i < 100000; i++) 53 | // { 54 | // using (await asyncLock.EnterAsync(cancellationToken.Token).ConfigureAwait(false)) 55 | // { 56 | // } 57 | // } 58 | } 59 | } -------------------------------------------------------------------------------- /Source/MQTTnet.TestApp/MQTTnet.TestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | Full 6 | net8.0 7 | false 8 | false 9 | false 10 | true 11 | 1591;NETSDK1138;NU1803;NU1901;NU1902 12 | true 13 | all 14 | true 15 | low 16 | latest-Recommended 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Source/MQTTnet.TestApp/ServerAndClientTest.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using MQTTnet.Diagnostics.Logger; 8 | using MQTTnet.Server; 9 | 10 | namespace MQTTnet.TestApp; 11 | 12 | public static class ServerAndClientTest 13 | { 14 | public static async Task RunAsync() 15 | { 16 | var logger = new MqttNetEventLogger(); 17 | MqttNetConsoleLogger.ForwardToConsole(logger); 18 | 19 | var mqttServerFactory = new MqttServerFactory(); 20 | var mqttClientFactory = new MqttClientFactory(logger); 21 | var server = mqttServerFactory.CreateMqttServer( new MqttServerOptionsBuilder().Build()); 22 | var client = mqttClientFactory.CreateMqttClient(); 23 | 24 | await server.StartAsync(); 25 | 26 | var clientOptions = new MqttClientOptionsBuilder().WithTcpServer("localhost").Build(); 27 | await client.ConnectAsync(clientOptions); 28 | 29 | await Task.Delay(Timeout.Infinite); 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/ASP/Mockups/ConnectionHandlerMockup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Connections; 8 | using MQTTnet.Adapter; 9 | using MQTTnet.AspNetCore; 10 | using MQTTnet.Diagnostics.Logger; 11 | using MQTTnet.Formatter; 12 | using MQTTnet.Server; 13 | 14 | namespace MQTTnet.Tests.ASP.Mockups; 15 | 16 | public sealed class ConnectionHandlerMockup : IMqttServerAdapter 17 | { 18 | public Func ClientHandler { get; set; } 19 | public TaskCompletionSource Context { get; } = new(); 20 | 21 | public void Dispose() 22 | { 23 | } 24 | 25 | public async Task OnConnectedAsync(ConnectionContext connection) 26 | { 27 | try 28 | { 29 | var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)); 30 | var context = new MqttConnectionContext(formatter, connection); 31 | Context.TrySetResult(context); 32 | 33 | await ClientHandler(context); 34 | } 35 | catch (Exception ex) 36 | { 37 | Context.TrySetException(ex); 38 | } 39 | } 40 | 41 | public Task StartAsync(MqttServerOptions options, IMqttNetLogger logger) 42 | { 43 | return Task.CompletedTask; 44 | } 45 | 46 | public Task StopAsync() 47 | { 48 | return Task.CompletedTask; 49 | } 50 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/ASP/Mockups/DuplexPipeMockup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO.Pipelines; 6 | 7 | namespace MQTTnet.Tests.ASP.Mockups; 8 | 9 | public sealed class DuplexPipeMockup : IDuplexPipe 10 | { 11 | public DuplexPipeMockup() 12 | { 13 | var pool = new LimitedMemoryPool(); 14 | var pipeOptions = new PipeOptions(pool); 15 | Receive = new Pipe(pipeOptions); 16 | Send = new Pipe(pipeOptions); 17 | } 18 | 19 | PipeReader IDuplexPipe.Input => Receive.Reader; 20 | 21 | PipeWriter IDuplexPipe.Output => Send.Writer; 22 | 23 | public Pipe Receive { get; } 24 | 25 | public Pipe Send { get; } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/ASP/Mockups/LimitedMemoryPool.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Buffers; 6 | 7 | namespace MQTTnet.Tests.ASP.Mockups; 8 | 9 | public sealed class LimitedMemoryPool : MemoryPool 10 | { 11 | protected override void Dispose(bool disposing) 12 | { 13 | } 14 | 15 | public override IMemoryOwner Rent(int minBufferSize = -1) 16 | { 17 | return new MemoryOwner(minBufferSize); 18 | } 19 | 20 | public override int MaxBufferSize { get; } = 1; 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/ASP/Mockups/MemoryOwner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | 8 | namespace MQTTnet.Tests.ASP.Mockups; 9 | 10 | public sealed class MemoryOwner : IMemoryOwner 11 | { 12 | readonly byte[] _raw; 13 | 14 | public MemoryOwner(int size) 15 | { 16 | if (size <= 0) 17 | { 18 | size = 1024; 19 | } 20 | 21 | if (size > 4096) 22 | { 23 | size = 4096; 24 | } 25 | 26 | _raw = ArrayPool.Shared.Rent(size); 27 | Memory = _raw; 28 | } 29 | 30 | public Memory Memory { get; } 31 | 32 | public void Dispose() 33 | { 34 | ArrayPool.Shared.Return(_raw); 35 | } 36 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/BaseTestClass.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | using MQTTnet.Formatter; 9 | using MQTTnet.Tests.Mockups; 10 | 11 | namespace MQTTnet.Tests; 12 | 13 | public abstract class BaseTestClass 14 | { 15 | public TestContext TestContext { get; set; } 16 | 17 | protected TestEnvironment CreateTestEnvironment( 18 | MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, bool trackUnobservedTaskException = true) 19 | { 20 | return new TestEnvironment(TestContext, protocolVersion, trackUnobservedTaskException); 21 | } 22 | 23 | protected Task LongTestDelay() 24 | { 25 | return Task.Delay(TimeSpan.FromSeconds(1)); 26 | } 27 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Clients/MqttClientOptionsBuilder_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Linq; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace MQTTnet.Tests.Clients; 9 | 10 | // ReSharper disable InconsistentNaming 11 | [TestClass] 12 | public class MqttClientOptionsBuilder_Tests 13 | { 14 | [TestMethod] 15 | public void WithConnectionUri_Credential_Test() 16 | { 17 | var options = new MqttClientOptionsBuilder() 18 | .WithConnectionUri("mqtt://user:password@127.0.0.1") 19 | .Build(); 20 | 21 | Assert.AreEqual("user", options.Credentials.GetUserName(null)); 22 | Assert.IsTrue("password"u8.ToArray().SequenceEqual(options.Credentials.GetPassword(null))); 23 | } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Diagnostics/SourceLogger_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using MQTTnet.Diagnostics.Logger; 7 | 8 | namespace MQTTnet.Tests.Diagnostics; 9 | 10 | // ReSharper disable InconsistentNaming 11 | [TestClass] 12 | public sealed class SourceLogger_Tests : BaseTestClass 13 | { 14 | [TestMethod] 15 | public void Log_With_Source() 16 | { 17 | MqttNetLogMessage logMessage = null; 18 | 19 | var logger = new MqttNetEventLogger(); 20 | logger.LogMessagePublished += (_, e) => 21 | { 22 | logMessage = e.LogMessage; 23 | }; 24 | 25 | var sourceLogger = logger.WithSource("The_Source"); 26 | sourceLogger.Info("MESSAGE", (object)null, (object)null); 27 | 28 | Assert.AreEqual("The_Source", logMessage.Source); 29 | } 30 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Helpers/MqttClientExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Tests.Mockups; 7 | 8 | namespace MQTTnet.Tests.Helpers; 9 | 10 | public static class MqttClientExtensions 11 | { 12 | public static TestApplicationMessageReceivedHandler TrackReceivedMessages(this IMqttClient client) 13 | { 14 | ArgumentNullException.ThrowIfNull(client); 15 | 16 | return new TestApplicationMessageReceivedHandler(client); 17 | } 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Helpers/MqttPacketWriterExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Formatter; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Tests.Helpers; 9 | 10 | public static class MqttPacketWriterExtensions 11 | { 12 | public static byte[] AddMqttHeader(this MqttBufferWriter writer, MqttControlPacketType header, byte[] body) 13 | { 14 | writer.WriteByte(MqttBufferWriter.BuildFixedHeader(header)); 15 | writer.WriteVariableByteInteger((uint)body.Length); 16 | writer.WriteBinary(body, 0, body.Length); 17 | return writer.GetBuffer(); 18 | } 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Helpers/ReflectionExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Reflection; 7 | 8 | namespace MQTTnet.Tests.Helpers; 9 | 10 | public static class ReflectionExtensions 11 | { 12 | public static object GetFieldValue(this object source, string fieldName) 13 | { 14 | ArgumentNullException.ThrowIfNull(source); 15 | 16 | var field = source.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); 17 | if (field == null) 18 | { 19 | throw new ArgumentException($"Field {fieldName} not found."); 20 | } 21 | 22 | return field.GetValue(source); 23 | } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Internal/MqttPacketBusItem_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using MQTTnet.Internal; 8 | using MQTTnet.Packets; 9 | 10 | namespace MQTTnet.Tests.Internal; 11 | 12 | // ReSharper disable InconsistentNaming 13 | [TestClass] 14 | public sealed class MqttPacketBusItem_Tests 15 | { 16 | [TestMethod] 17 | public void Fire_Completed_Event() 18 | { 19 | var eventFired = false; 20 | 21 | var item = new MqttPacketBusItem(new MqttPublishPacket()); 22 | item.Completed += (_, _) => 23 | { 24 | eventFired = true; 25 | }; 26 | 27 | item.Complete(); 28 | 29 | Assert.IsTrue(eventFired); 30 | } 31 | 32 | [TestMethod] 33 | [ExpectedException(typeof(TaskCanceledException))] 34 | public async Task Wait_Packet_Bus_Item_After_Already_Canceled() 35 | { 36 | var item = new MqttPacketBusItem(new MqttPublishPacket()); 37 | 38 | // Finish the item before the actual 39 | item.Cancel(); 40 | 41 | await item.WaitAsync().ConfigureAwait(false); 42 | } 43 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Mockups/TestLogger.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Diagnostics.Logger; 7 | 8 | namespace MQTTnet.Tests.Mockups; 9 | 10 | public sealed class TestLogger : IMqttNetLogger 11 | { 12 | public event EventHandler LogMessagePublished; 13 | 14 | public bool IsEnabled { get; } = true; 15 | 16 | public void Publish(MqttNetLogLevel logLevel, string source, string message, object[] parameters, Exception exception) 17 | { 18 | LogMessagePublished?.Invoke(this, new MqttNetLogMessagePublishedEventArgs(new MqttNetLogMessage 19 | { 20 | Level = logLevel, 21 | Message = string.Format(message, parameters), 22 | Exception = exception 23 | })); 24 | } 25 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/MqttPacketIdentifierProvider_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace MQTTnet.Tests; 8 | 9 | // ReSharper disable InconsistentNaming 10 | [TestClass] 11 | public class MqttPacketIdentifierProvider_Tests 12 | { 13 | [TestMethod] 14 | public void Reset() 15 | { 16 | var p = new MqttPacketIdentifierProvider(); 17 | Assert.AreEqual(1, p.GetNextPacketIdentifier()); 18 | Assert.AreEqual(2, p.GetNextPacketIdentifier()); 19 | p.Reset(); 20 | Assert.AreEqual(1, p.GetNextPacketIdentifier()); 21 | } 22 | 23 | [TestMethod] 24 | public void ReachBoundaries() 25 | { 26 | var p = new MqttPacketIdentifierProvider(); 27 | 28 | for (ushort i = 0; i < ushort.MaxValue; i++) 29 | { 30 | Assert.AreEqual(i + 1, p.GetNextPacketIdentifier()); 31 | } 32 | 33 | Assert.AreEqual(1, p.GetNextPacketIdentifier()); 34 | } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/MqttPacketWriter_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using MQTTnet.Formatter; 7 | 8 | namespace MQTTnet.Tests; 9 | 10 | // ReSharper disable InconsistentNaming 11 | [TestClass] 12 | public class MqttPacketWriter_Tests 13 | { 14 | protected virtual MqttBufferWriter WriterFactory() 15 | { 16 | return new MqttBufferWriter(4096, 65535); 17 | } 18 | 19 | [TestMethod] 20 | public void WritePacket() 21 | { 22 | var writer = WriterFactory(); 23 | Assert.AreEqual(0, writer.Length); 24 | 25 | writer.WriteString("1234567890"); 26 | Assert.AreEqual(10 + 2, writer.Length); 27 | 28 | writer.WriteBinary(new byte[300]); 29 | Assert.AreEqual(300 + 2 + 12, writer.Length); 30 | 31 | writer.WriteBinary(new byte[5000]); 32 | Assert.AreEqual(5000 + 2 + 300 + 2 + 12, writer.Length); 33 | } 34 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/MqttTopicValidator_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using MQTTnet.Exceptions; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Tests; 10 | 11 | // ReSharper disable InconsistentNaming 12 | [TestClass] 13 | public sealed class MqttTopicValidator_Tests 14 | { 15 | [TestMethod] 16 | [ExpectedException(typeof(MqttProtocolViolationException))] 17 | public void Invalid_Topic_Empty() 18 | { 19 | MqttTopicValidator.ThrowIfInvalid(string.Empty); 20 | } 21 | 22 | [TestMethod] 23 | [ExpectedException(typeof(MqttProtocolViolationException))] 24 | public void Invalid_Topic_Hash() 25 | { 26 | MqttTopicValidator.ThrowIfInvalid("/a/#/c"); 27 | } 28 | 29 | [TestMethod] 30 | [ExpectedException(typeof(MqttProtocolViolationException))] 31 | public void Invalid_Topic_Plus() 32 | { 33 | MqttTopicValidator.ThrowIfInvalid("/a/+/c"); 34 | } 35 | 36 | [TestMethod] 37 | public void Valid_Topic() 38 | { 39 | MqttTopicValidator.ThrowIfInvalid("/a/b/c"); 40 | } 41 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Server/MqttRetainedMessageManager_Tests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System.Threading.Tasks; 3 | using MQTTnet.Server.Internal; 4 | 5 | namespace MQTTnet.Tests.Server; 6 | 7 | // ReSharper disable InconsistentNaming 8 | [TestClass] 9 | public sealed class MqttRetainedMessageManager_Tests 10 | { 11 | [TestMethod] 12 | public async Task MqttRetainedMessageManager_GetUndefinedTopic() 13 | { 14 | var logger = new Mockups.TestLogger(); 15 | var eventContainer = new MqttServerEventContainer(); 16 | var retainedMessagesManager = new MqttRetainedMessagesManager(eventContainer, logger); 17 | var task = retainedMessagesManager.GetMessage("undefined"); 18 | Assert.IsNotNull(task, "Task should not be null"); 19 | var result = await task; 20 | Assert.IsNull(result, "Null result expected"); 21 | } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet.Tests/Server/Server_Reference_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using MQTTnet.Formatter; 8 | using MQTTnet.Internal; 9 | using MQTTnet.Protocol; 10 | 11 | namespace MQTTnet.Tests.Server; 12 | 13 | // ReSharper disable InconsistentNaming 14 | [TestClass] 15 | public sealed class Server_Reference_Tests : BaseTestClass 16 | { 17 | [TestMethod] 18 | public async Task Server_Reports_With_Reference_Server() 19 | { 20 | using var testEnvironment = CreateTestEnvironment(); 21 | testEnvironment.IgnoreClientLogErrors = true; 22 | 23 | var server = await testEnvironment.StartServer(); 24 | 25 | server.ValidatingConnectionAsync += e => 26 | { 27 | e.ReasonCode = MqttConnectReasonCode.ServerMoved; 28 | e.ServerReference = "new_server"; 29 | return CompletedTask.Instance; 30 | }; 31 | 32 | var client = testEnvironment.CreateClient(); 33 | 34 | var response = await client.ConnectAsync( 35 | new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500).WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build()); 36 | 37 | Assert.AreEqual(MqttClientConnectResultCode.ServerMoved, response.ResultCode); 38 | Assert.AreEqual("new_server", response.ServerReference); 39 | } 40 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Adapter/IMqttChannelAdapter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Net; 7 | using System.Security.Cryptography.X509Certificates; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using MQTTnet.Formatter; 11 | using MQTTnet.Packets; 12 | 13 | namespace MQTTnet.Adapter; 14 | 15 | public interface IMqttChannelAdapter : IDisposable 16 | { 17 | long BytesReceived { get; } 18 | 19 | long BytesSent { get; } 20 | 21 | X509Certificate2 ClientCertificate { get; } 22 | 23 | EndPoint RemoteEndPoint { get; } 24 | 25 | bool IsSecureConnection { get; } 26 | 27 | MqttPacketFormatterAdapter PacketFormatterAdapter { get; } 28 | 29 | Task ConnectAsync(CancellationToken cancellationToken); 30 | 31 | Task DisconnectAsync(CancellationToken cancellationToken); 32 | 33 | Task ReceivePacketAsync(CancellationToken cancellationToken); 34 | 35 | void ResetStatistics(); 36 | 37 | Task SendPacketAsync(MqttPacket packet, CancellationToken cancellationToken); 38 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Adapter/IMqttClientAdapterFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Diagnostics.Logger; 6 | 7 | namespace MQTTnet.Adapter; 8 | 9 | public interface IMqttClientAdapterFactory 10 | { 11 | IMqttChannelAdapter CreateClientAdapter(MqttClientOptions options, MqttPacketInspector packetInspector, IMqttNetLogger logger); 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Adapter/MqttConnectingFailedException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Exceptions; 7 | 8 | namespace MQTTnet.Adapter; 9 | 10 | public sealed class MqttConnectingFailedException : MqttCommunicationException 11 | { 12 | public MqttConnectingFailedException(string message, Exception innerException) : base(message, innerException) 13 | { 14 | } 15 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Adapter/ReceivedMqttPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Adapter; 8 | 9 | public readonly struct ReceivedMqttPacket 10 | { 11 | public static readonly ReceivedMqttPacket Empty; 12 | 13 | public ReceivedMqttPacket(byte fixedHeader, ArraySegment body, int totalLength) 14 | { 15 | FixedHeader = fixedHeader; 16 | Body = body; 17 | TotalLength = totalLength; 18 | } 19 | 20 | public byte FixedHeader { get; } 21 | 22 | public ArraySegment Body { get; } 23 | 24 | public int TotalLength { get; } 25 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Certificates/BlobCertificateProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace MQTTnet.Certificates; 9 | 10 | public class BlobCertificateProvider(byte[] blob) : ICertificateProvider 11 | { 12 | public byte[] Blob { get; } = blob ?? throw new ArgumentNullException(nameof(blob)); 13 | 14 | public string Password { get; set; } 15 | 16 | public X509Certificate2 GetCertificate() 17 | { 18 | if (string.IsNullOrEmpty(Password)) 19 | { 20 | // Use a different overload when no password is specified. Otherwise, the constructor will fail. 21 | return new X509Certificate2(Blob); 22 | } 23 | 24 | return new X509Certificate2(Blob, Password); 25 | } 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Certificates/ICertificateProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Security.Cryptography.X509Certificates; 6 | 7 | namespace MQTTnet.Certificates; 8 | 9 | public interface ICertificateProvider 10 | { 11 | X509Certificate2 GetCertificate(); 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Certificates/X509CertificateProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace MQTTnet.Certificates; 9 | 10 | public class X509CertificateProvider(X509Certificate2 certificate) : ICertificateProvider 11 | { 12 | readonly X509Certificate2 _certificate = certificate ?? throw new ArgumentNullException(nameof(certificate)); 13 | 14 | public X509Certificate2 GetCertificate() 15 | { 16 | return _certificate; 17 | } 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Channel/IMqttChannel.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.Net; 8 | using System.Security.Cryptography.X509Certificates; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace MQTTnet.Channel; 13 | 14 | public interface IMqttChannel : IDisposable 15 | { 16 | X509Certificate2 ClientCertificate { get; } 17 | EndPoint RemoteEndPoint { get; } 18 | 19 | bool IsSecureConnection { get; } 20 | 21 | Task ConnectAsync(CancellationToken cancellationToken); 22 | 23 | Task DisconnectAsync(CancellationToken cancellationToken); 24 | 25 | Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); 26 | 27 | Task WriteAsync(ReadOnlySequence buffer, bool isEndOfPacket, CancellationToken cancellationToken); 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Connecting/MqttClientConnectResultCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientConnectResultCode 8 | { 9 | Success = 0, 10 | UnspecifiedError = 128, 11 | MalformedPacket = 129, 12 | ProtocolError = 130, 13 | ImplementationSpecificError = 131, 14 | UnsupportedProtocolVersion = 132, 15 | ClientIdentifierNotValid = 133, 16 | BadUserNameOrPassword = 134, 17 | NotAuthorized = 135, 18 | ServerUnavailable = 136, 19 | ServerBusy = 137, 20 | Banned = 138, 21 | BadAuthenticationMethod = 140, 22 | TopicNameInvalid = 144, 23 | PacketTooLarge = 149, 24 | QuotaExceeded = 151, 25 | PayloadFormatInvalid = 153, 26 | RetainNotSupported = 154, 27 | QoSNotSupported = 155, 28 | UseAnotherServer = 156, 29 | ServerMoved = 157, 30 | ConnectionRateExceeded = 159 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Connecting/MqttClientConnectedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet; 8 | 9 | public sealed class MqttClientConnectedEventArgs : EventArgs 10 | { 11 | public MqttClientConnectedEventArgs(MqttClientConnectResult connectResult) 12 | { 13 | ConnectResult = connectResult ?? throw new ArgumentNullException(nameof(connectResult)); 14 | } 15 | 16 | /// 17 | /// Gets the authentication result. 18 | /// MQTT 5.0.0+ feature. 19 | /// 20 | public MqttClientConnectResult ConnectResult { get; } 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Connecting/MqttClientConnectingEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet; 8 | 9 | public sealed class MqttClientConnectingEventArgs : EventArgs 10 | { 11 | public MqttClientConnectingEventArgs(MqttClientOptions clientOptions) 12 | { 13 | ClientOptions = clientOptions; 14 | } 15 | 16 | public MqttClientOptions ClientOptions { get; } 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/IMqttNetLogger.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.Logger; 8 | 9 | public interface IMqttNetLogger 10 | { 11 | bool IsEnabled { get; } 12 | 13 | void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception); 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/MqttNetLogLevel.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Diagnostics.Logger; 6 | 7 | public enum MqttNetLogLevel 8 | { 9 | Verbose, 10 | 11 | Info, 12 | 13 | Warning, 14 | 15 | Error 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/MqttNetLogMessage.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.Logger; 8 | 9 | public sealed class MqttNetLogMessage 10 | { 11 | public string LogId { get; set; } 12 | 13 | public DateTime Timestamp { get; set; } 14 | 15 | public int ThreadId { get; set; } 16 | 17 | public string Source { get; set; } 18 | 19 | public MqttNetLogLevel Level { get; set; } 20 | 21 | public string Message { get; set; } 22 | 23 | public Exception Exception { get; set; } 24 | 25 | public override string ToString() 26 | { 27 | var result = $"[{Timestamp:O}] [{LogId}] [{ThreadId}] [{Source}] [{Level}]: {Message}"; 28 | if (Exception != null) 29 | { 30 | result += Environment.NewLine + Exception; 31 | } 32 | 33 | return result; 34 | } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/MqttNetLogMessagePublishedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.Logger; 8 | 9 | public sealed class MqttNetLogMessagePublishedEventArgs(MqttNetLogMessage logMessage) : EventArgs 10 | { 11 | public MqttNetLogMessage LogMessage { get; } = logMessage ?? throw new ArgumentNullException(nameof(logMessage)); 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/MqttNetNullLogger.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.Logger; 8 | 9 | /// 10 | /// This logger does nothing with the messages. 11 | /// 12 | public sealed class MqttNetNullLogger : IMqttNetLogger 13 | { 14 | public static MqttNetNullLogger Instance { get; } = new(); 15 | 16 | public bool IsEnabled { get; } 17 | 18 | public void Publish(MqttNetLogLevel level, string source, string message, object[] parameters, Exception exception) 19 | { 20 | } 21 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/Logger/MqttNetSourceLogger.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.Logger; 8 | 9 | public sealed class MqttNetSourceLogger(IMqttNetLogger logger, string source) 10 | { 11 | readonly IMqttNetLogger _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 12 | 13 | public bool IsEnabled => _logger.IsEnabled; 14 | 15 | public void Publish(MqttNetLogLevel logLevel, string message, object[] parameters, Exception exception) 16 | { 17 | _logger.Publish(logLevel, source, message, parameters, exception); 18 | } 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/PacketInspection/InspectMqttPacketEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Diagnostics.PacketInspection; 8 | 9 | public sealed class InspectMqttPacketEventArgs : EventArgs 10 | { 11 | public InspectMqttPacketEventArgs(MqttPacketFlowDirection direction, byte[] buffer) 12 | { 13 | Direction = direction; 14 | Buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); 15 | } 16 | 17 | public byte[] Buffer { get; } 18 | 19 | public MqttPacketFlowDirection Direction { get; } 20 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Diagnostics/PacketInspection/MqttPacketFlowDirection.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Diagnostics.PacketInspection; 6 | 7 | public enum MqttPacketFlowDirection 8 | { 9 | Inbound, 10 | 11 | Outbound 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Disconnecting/MqttClientDisconnectOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class MqttClientDisconnectOptions 11 | { 12 | /// 13 | /// Gets or sets the reason code. 14 | /// MQTT 5.0.0+ feature. 15 | /// 16 | public MqttClientDisconnectOptionsReason Reason { get; set; } = MqttClientDisconnectOptionsReason.NormalDisconnection; 17 | 18 | /// 19 | /// Gets or sets the reason string. 20 | /// MQTT 5.0.0+ feature. 21 | /// 22 | public string ReasonString { get; set; } 23 | 24 | /// 25 | /// Gets or sets the session expiry interval. 26 | /// MQTT 5.0.0+ feature. 27 | /// 28 | public uint SessionExpiryInterval { get; set; } 29 | 30 | /// 31 | /// Gets or sets the user properties. 32 | /// MQTT 5.0.0+ feature. 33 | /// 34 | public List UserProperties { get; set; } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Disconnecting/MqttClientDisconnectOptionsReason.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | /// 8 | /// This enum only contains values which are valid when a client sends the reason to the server. 9 | /// 10 | public enum MqttClientDisconnectOptionsReason 11 | { 12 | NormalDisconnection = 0, 13 | DisconnectWithWillMessage = 4, 14 | UnspecifiedError = 128, 15 | MalformedPacket = 129, 16 | ProtocolError = 130, 17 | ImplementationSpecificError = 131, 18 | TopicNameInvalid = 144, 19 | ReceiveMaximumExceeded = 147, 20 | TopicAliasInvalid = 148, 21 | PacketTooLarge = 149, 22 | MessageRateTooHigh = 150, 23 | QuotaExceeded = 151, 24 | AdministrativeAction = 152, 25 | PayloadFormatInvalid = 153 26 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Disconnecting/MqttClientDisconnectOptionsValidator.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Formatter; 7 | 8 | namespace MQTTnet; 9 | 10 | public static class MqttClientDisconnectOptionsValidator 11 | { 12 | public static void ThrowIfNotSupported(MqttClientDisconnectOptions options, MqttProtocolVersion protocolVersion) 13 | { 14 | ArgumentNullException.ThrowIfNull(options); 15 | 16 | if (protocolVersion == MqttProtocolVersion.V500) 17 | { 18 | // Everything is supported. 19 | return; 20 | } 21 | 22 | if (options.ReasonString?.Length > 0) 23 | { 24 | Throw(nameof(options.ReasonString)); 25 | } 26 | 27 | if (options.Reason != MqttClientDisconnectOptionsReason.NormalDisconnection) 28 | { 29 | Throw(nameof(options.Reason)); 30 | } 31 | } 32 | 33 | static void Throw(string featureName) 34 | { 35 | throw new NotSupportedException($"Feature {featureName} requires MQTT version 5.0.0."); 36 | } 37 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Disconnecting/MqttClientDisconnectReason.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientDisconnectReason 8 | { 9 | NormalDisconnection = 0, 10 | DisconnectWithWillMessage = 4, 11 | UnspecifiedError = 128, 12 | MalformedPacket = 129, 13 | ProtocolError = 130, 14 | ImplementationSpecificError = 131, 15 | NotAuthorized = 135, 16 | ServerBusy = 137, 17 | ServerShuttingDown = 139, 18 | BadAuthenticationMethod = 140, 19 | KeepAliveTimeout = 141, 20 | SessionTakenOver = 142, 21 | TopicFilterInvalid = 143, 22 | TopicNameInvalid = 144, 23 | ReceiveMaximumExceeded = 147, 24 | TopicAliasInvalid = 148, 25 | PacketTooLarge = 149, 26 | MessageRateTooHigh = 150, 27 | QuotaExceeded = 151, 28 | AdministrativeAction = 152, 29 | PayloadFormatInvalid = 153, 30 | RetainNotSupported = 154, 31 | QosNotSupported = 155, 32 | UseAnotherServer = 156, 33 | ServerMoved = 157, 34 | SharedSubscriptionsNotSupported = 158, 35 | ConnectionRateExceeded = 159, 36 | MaximumConnectTime = 160, 37 | SubscriptionIdentifiersNotSupported = 161, 38 | WildcardSubscriptionsNotSupported = 162 39 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Disconnecting/MqttClientDisconnectedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using MQTTnet.Packets; 8 | 9 | namespace MQTTnet; 10 | 11 | public sealed class MqttClientDisconnectedEventArgs : EventArgs 12 | { 13 | public MqttClientDisconnectedEventArgs( 14 | bool clientWasConnected, 15 | MqttClientConnectResult connectResult, 16 | MqttClientDisconnectReason reason, 17 | string reasonString, 18 | List userProperties, 19 | Exception exception) 20 | { 21 | ClientWasConnected = clientWasConnected; 22 | ConnectResult = connectResult; 23 | Exception = exception; 24 | Reason = reason; 25 | ReasonString = reasonString; 26 | UserProperties = userProperties; 27 | } 28 | 29 | public bool ClientWasConnected { get; } 30 | 31 | /// 32 | /// Gets the authentication result. 33 | /// MQTT 5.0.0+ feature. 34 | /// 35 | public MqttClientConnectResult ConnectResult { get; } 36 | 37 | public Exception Exception { get; } 38 | 39 | /// 40 | /// Gets or sets the reason. 41 | /// MQTT 5.0.0+ feature. 42 | /// 43 | public MqttClientDisconnectReason Reason { get; } 44 | 45 | public string ReasonString { get; } 46 | 47 | public List UserProperties { get; } 48 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttClientDisconnectedException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Exceptions; 8 | 9 | public sealed class MqttClientDisconnectedException : MqttCommunicationException 10 | { 11 | public MqttClientDisconnectedException(Exception innerException) : base("The MQTT client is disconnected.", innerException) 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttClientNotConnectedException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Exceptions; 6 | 7 | public class MqttClientNotConnectedException : MqttCommunicationException 8 | { 9 | public MqttClientNotConnectedException() : base("The MQTT client is not connected.") 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttClientUnexpectedDisconnectReceivedException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using MQTTnet.Packets; 8 | using MQTTnet.Protocol; 9 | 10 | namespace MQTTnet.Exceptions; 11 | 12 | public sealed class MqttClientUnexpectedDisconnectReceivedException(MqttDisconnectPacket disconnectPacket, Exception innerException = null) : MqttCommunicationException( 13 | $"Unexpected DISCONNECT (Reason code={disconnectPacket.ReasonCode}) received.", 14 | innerException) 15 | { 16 | public MqttDisconnectReasonCode? ReasonCode { get; } = disconnectPacket.ReasonCode; 17 | 18 | public string ReasonString { get; } = disconnectPacket.ReasonString; 19 | 20 | public string ServerReference { get; } = disconnectPacket.ServerReference; 21 | 22 | public uint? SessionExpiryInterval { get; } = disconnectPacket.SessionExpiryInterval; 23 | 24 | public List UserProperties { get; } = disconnectPacket.UserProperties; 25 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttCommunicationException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Exceptions; 8 | 9 | public class MqttCommunicationException : Exception 10 | { 11 | public MqttCommunicationException(Exception innerException) 12 | : base(innerException?.Message ?? "MQTT communication failed.", innerException) 13 | { 14 | } 15 | 16 | public MqttCommunicationException(string message, Exception innerException = null) 17 | : base(message, innerException) 18 | { 19 | } 20 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttCommunicationTimedOutException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Exceptions; 8 | 9 | public sealed class MqttCommunicationTimedOutException : MqttCommunicationException 10 | { 11 | public MqttCommunicationTimedOutException() : base("The operation has timed out.") 12 | { 13 | } 14 | 15 | public MqttCommunicationTimedOutException(Exception innerException) : base("The operation has timed out.", innerException) 16 | { 17 | } 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttConfigurationException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Exceptions; 8 | 9 | public class MqttConfigurationException : Exception 10 | { 11 | protected MqttConfigurationException() 12 | { 13 | } 14 | 15 | public MqttConfigurationException(Exception innerException) 16 | : base(innerException.Message, innerException) 17 | { 18 | } 19 | 20 | public MqttConfigurationException(string message) 21 | : base(message) 22 | { 23 | } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Exceptions/MqttProtocolViolationException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Exceptions; 8 | 9 | public class MqttProtocolViolationException(string message) : Exception(message); -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/IMqttPacketFormatter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Adapter; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public interface IMqttPacketFormatter 11 | { 12 | MqttPacket Decode(ReceivedMqttPacket receivedPacket); 13 | 14 | MqttPacketBuffer Encode(MqttPacket packet); 15 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttApplicationMessageFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public static class MqttApplicationMessageFactory 11 | { 12 | public static MqttApplicationMessage Create(MqttPublishPacket publishPacket) 13 | { 14 | ArgumentNullException.ThrowIfNull(publishPacket); 15 | 16 | return new MqttApplicationMessage 17 | { 18 | Topic = publishPacket.Topic, 19 | Payload = publishPacket.Payload, 20 | QualityOfServiceLevel = publishPacket.QualityOfServiceLevel, 21 | Retain = publishPacket.Retain, 22 | Dup = publishPacket.Dup, 23 | ResponseTopic = publishPacket.ResponseTopic, 24 | ContentType = publishPacket.ContentType, 25 | CorrelationData = publishPacket.CorrelationData, 26 | MessageExpiryInterval = publishPacket.MessageExpiryInterval, 27 | SubscriptionIdentifiers = publishPacket.SubscriptionIdentifiers, 28 | TopicAlias = publishPacket.TopicAlias, 29 | PayloadFormatIndicator = publishPacket.PayloadFormatIndicator, 30 | UserProperties = publishPacket.UserProperties 31 | }; 32 | } 33 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttDisconnectPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public static class MqttDisconnectPacketFactory 11 | { 12 | static readonly MqttDisconnectPacket DefaultNormalDisconnection = new() 13 | { 14 | ReasonCode = MqttDisconnectReasonCode.NormalDisconnection, 15 | UserProperties = null, 16 | ReasonString = null, 17 | ServerReference = null, 18 | SessionExpiryInterval = 0 19 | }; 20 | 21 | public static MqttDisconnectPacket Create(MqttClientDisconnectOptions clientDisconnectOptions) 22 | { 23 | if (clientDisconnectOptions == null) 24 | { 25 | return DefaultNormalDisconnection; 26 | } 27 | 28 | return new MqttDisconnectPacket 29 | { 30 | ReasonCode = (MqttDisconnectReasonCode)clientDisconnectOptions.Reason, 31 | UserProperties = clientDisconnectOptions.UserProperties, 32 | SessionExpiryInterval = clientDisconnectOptions.SessionExpiryInterval 33 | }; 34 | } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttFixedHeader.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Formatter; 6 | 7 | public struct MqttFixedHeader(byte flags, int remainingLength, int totalLength) 8 | { 9 | public byte Flags { get; } = flags; 10 | 11 | public int RemainingLength { get; } = remainingLength; 12 | 13 | public int TotalLength { get; } = totalLength; 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPacketBuffer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Internal; 6 | using System; 7 | using System.Buffers; 8 | 9 | namespace MQTTnet.Formatter; 10 | 11 | public readonly struct MqttPacketBuffer 12 | { 13 | public MqttPacketBuffer(ArraySegment packet, ReadOnlySequence payload) 14 | { 15 | Packet = packet; 16 | Payload = payload; 17 | 18 | Length = Packet.Count + (int)Payload.Length; 19 | } 20 | 21 | public MqttPacketBuffer(ArraySegment packet) 22 | { 23 | Packet = packet; 24 | Payload = EmptyBuffer.ReadOnlySequence; 25 | 26 | Length = Packet.Count; 27 | } 28 | 29 | public int Length { get; } 30 | 31 | public ArraySegment Packet { get; } 32 | 33 | public ReadOnlySequence Payload { get; } 34 | 35 | public byte[] ToArray() 36 | { 37 | if (Payload.Length == 0) 38 | { 39 | return Packet.ToArray(); 40 | } 41 | 42 | var buffer = GC.AllocateUninitializedArray(Length); 43 | MqttMemoryHelper.Copy(Packet.Array, Packet.Offset, buffer, 0, Packet.Count); 44 | MqttMemoryHelper.Copy(Payload, 0, buffer, Packet.Count, (int)Payload.Length); 45 | 46 | return buffer; 47 | } 48 | 49 | public ArraySegment Join() 50 | { 51 | if (Payload.Length == 0) 52 | { 53 | return Packet; 54 | } 55 | 56 | return new ArraySegment(ToArray()); 57 | } 58 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttProtocolVersion.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Formatter; 6 | 7 | public enum MqttProtocolVersion 8 | { 9 | Unknown = 0, 10 | 11 | V310 = 3, 12 | V311 = 4, 13 | V500 = 5 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPubAckPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Formatter; 10 | 11 | public static class MqttPubAckPacketFactory 12 | { 13 | public static MqttPubAckPacket Create(MqttApplicationMessageReceivedEventArgs applicationMessageReceivedEventArgs) 14 | { 15 | ArgumentNullException.ThrowIfNull(applicationMessageReceivedEventArgs); 16 | 17 | var pubAckPacket = new MqttPubAckPacket 18 | { 19 | PacketIdentifier = applicationMessageReceivedEventArgs.PublishPacket.PacketIdentifier, 20 | ReasonCode = (MqttPubAckReasonCode)(int)applicationMessageReceivedEventArgs.ReasonCode, 21 | UserProperties = applicationMessageReceivedEventArgs.ResponseUserProperties, 22 | ReasonString = applicationMessageReceivedEventArgs.ResponseReasonString 23 | }; 24 | 25 | return pubAckPacket; 26 | } 27 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPubCompPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Formatter; 10 | 11 | public static class MqttPubCompPacketFactory 12 | { 13 | public static MqttPubCompPacket Create(MqttPubRelPacket pubRelPacket, MqttApplicationMessageReceivedReasonCode reasonCode) 14 | { 15 | ArgumentNullException.ThrowIfNull(pubRelPacket); 16 | 17 | return new MqttPubCompPacket 18 | { 19 | PacketIdentifier = pubRelPacket.PacketIdentifier, 20 | ReasonCode = (MqttPubCompReasonCode)(int)reasonCode 21 | }; 22 | } 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPubRecPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Formatter; 10 | 11 | public static class MqttPubRecPacketFactory 12 | { 13 | public static MqttPubRecPacket Create(MqttApplicationMessageReceivedEventArgs applicationMessageReceivedEventArgs) 14 | { 15 | ArgumentNullException.ThrowIfNull(applicationMessageReceivedEventArgs); 16 | 17 | var pubRecPacket = Create(applicationMessageReceivedEventArgs.PublishPacket, applicationMessageReceivedEventArgs.ReasonCode); 18 | pubRecPacket.UserProperties = applicationMessageReceivedEventArgs.ResponseUserProperties; 19 | 20 | return pubRecPacket; 21 | } 22 | 23 | static MqttPubRecPacket Create(MqttPublishPacket publishPacket, MqttApplicationMessageReceivedReasonCode applicationMessageReceivedReasonCode) 24 | { 25 | var pubRecPacket = new MqttPubRecPacket 26 | { 27 | PacketIdentifier = publishPacket.PacketIdentifier, 28 | ReasonCode = (MqttPubRecReasonCode)(int)applicationMessageReceivedReasonCode 29 | }; 30 | 31 | return pubRecPacket; 32 | } 33 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPubRelPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Formatter; 10 | 11 | public static class MqttPubRelPacketFactory 12 | { 13 | public static MqttPubRelPacket Create(MqttPubRecPacket pubRecPacket, MqttApplicationMessageReceivedReasonCode reasonCode) 14 | { 15 | ArgumentNullException.ThrowIfNull(pubRecPacket); 16 | 17 | return new MqttPubRelPacket 18 | { 19 | PacketIdentifier = pubRecPacket.PacketIdentifier, 20 | ReasonCode = (MqttPubRelReasonCode)(int)reasonCode 21 | }; 22 | } 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttPublishPacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public static class MqttPublishPacketFactory 11 | { 12 | public static MqttPublishPacket Create(MqttApplicationMessage applicationMessage) 13 | { 14 | ArgumentNullException.ThrowIfNull(applicationMessage); 15 | 16 | // Copy all values to their matching counterparts. 17 | // The not supported values in MQTT 3.1.1 are not serialized (excluded) later. 18 | var packet = new MqttPublishPacket 19 | { 20 | Topic = applicationMessage.Topic, 21 | Payload = applicationMessage.Payload, 22 | QualityOfServiceLevel = applicationMessage.QualityOfServiceLevel, 23 | Retain = applicationMessage.Retain, 24 | Dup = applicationMessage.Dup, 25 | ContentType = applicationMessage.ContentType, 26 | CorrelationData = applicationMessage.CorrelationData, 27 | MessageExpiryInterval = applicationMessage.MessageExpiryInterval, 28 | PayloadFormatIndicator = applicationMessage.PayloadFormatIndicator, 29 | ResponseTopic = applicationMessage.ResponseTopic, 30 | TopicAlias = applicationMessage.TopicAlias, 31 | SubscriptionIdentifiers = applicationMessage.SubscriptionIdentifiers, 32 | UserProperties = applicationMessage.UserProperties 33 | }; 34 | 35 | return packet; 36 | } 37 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttSubscribePacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public static class MqttSubscribePacketFactory 11 | { 12 | public static MqttSubscribePacket Create(MqttClientSubscribeOptions clientSubscribeOptions) 13 | { 14 | ArgumentNullException.ThrowIfNull(clientSubscribeOptions); 15 | 16 | var packet = new MqttSubscribePacket 17 | { 18 | TopicFilters = clientSubscribeOptions.TopicFilters, 19 | SubscriptionIdentifier = clientSubscribeOptions.SubscriptionIdentifier, 20 | UserProperties = clientSubscribeOptions.UserProperties 21 | }; 22 | 23 | return packet; 24 | } 25 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/MqttUnsubscribePacketFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter; 9 | 10 | public static class MqttUnsubscribePacketFactory 11 | { 12 | public static MqttUnsubscribePacket Create(MqttClientUnsubscribeOptions clientUnsubscribeOptions) 13 | { 14 | ArgumentNullException.ThrowIfNull(clientUnsubscribeOptions); 15 | 16 | var packet = new MqttUnsubscribePacket 17 | { 18 | UserProperties = clientUnsubscribeOptions.UserProperties 19 | }; 20 | 21 | if (clientUnsubscribeOptions.TopicFilters != null) 22 | { 23 | packet.TopicFilters.AddRange(clientUnsubscribeOptions.TopicFilters); 24 | } 25 | 26 | return packet; 27 | } 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/ReadFixedHeaderResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Formatter; 6 | 7 | public struct ReadFixedHeaderResult 8 | { 9 | public static ReadFixedHeaderResult Canceled { get; } = new() 10 | { 11 | IsCanceled = true 12 | }; 13 | 14 | public static ReadFixedHeaderResult ConnectionClosed { get; } = new() 15 | { 16 | IsConnectionClosed = true 17 | }; 18 | 19 | public bool IsCanceled { get; set; } 20 | 21 | public bool IsConnectionClosed { get; init; } 22 | 23 | public MqttFixedHeader FixedHeader { get; init; } 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Formatter/V5/MqttV5PacketFormatter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Adapter; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet.Formatter.V5; 9 | 10 | public sealed class MqttV5PacketFormatter : IMqttPacketFormatter 11 | { 12 | readonly MqttV5PacketDecoder _decoder; 13 | readonly MqttV5PacketEncoder _encoder; 14 | 15 | public MqttV5PacketFormatter(MqttBufferWriter bufferWriter) 16 | { 17 | _decoder = new MqttV5PacketDecoder(); 18 | _encoder = new MqttV5PacketEncoder(bufferWriter); 19 | } 20 | 21 | public MqttPacket Decode(ReceivedMqttPacket receivedPacket) 22 | { 23 | return _decoder.Decode(receivedPacket); 24 | } 25 | 26 | public MqttPacketBuffer Encode(MqttPacket packet) 27 | { 28 | return _encoder.Encode(packet); 29 | } 30 | } -------------------------------------------------------------------------------- /Source/MQTTnet/IMqttClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using MQTTnet.Diagnostics.PacketInspection; 5 | 6 | namespace MQTTnet; 7 | 8 | public interface IMqttClient : IDisposable 9 | { 10 | event Func ApplicationMessageReceivedAsync; 11 | 12 | event Func ConnectedAsync; 13 | 14 | event Func ConnectingAsync; 15 | 16 | event Func DisconnectedAsync; 17 | 18 | event Func InspectPacketAsync; 19 | 20 | bool IsConnected { get; } 21 | 22 | MqttClientOptions Options { get; } 23 | 24 | Task ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken = default); 25 | 26 | Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken = default); 27 | 28 | Task PingAsync(CancellationToken cancellationToken = default); 29 | 30 | Task PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default); 31 | 32 | Task SendEnhancedAuthenticationExchangeDataAsync(MqttEnhancedAuthenticationExchangeData data, CancellationToken cancellationToken = default); 33 | 34 | Task SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken = default); 35 | 36 | Task UnsubscribeAsync(MqttClientUnsubscribeOptions options, CancellationToken cancellationToken = default); 37 | } -------------------------------------------------------------------------------- /Source/MQTTnet/InjectMqttApplicationMessageResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public class InjectMqttApplicationMessageResult 8 | { 9 | public ushort PacketIdentifier { get; init; } 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/AsyncEventInvocator.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace MQTTnet.Internal; 9 | 10 | public readonly struct AsyncEventInvocator 11 | { 12 | readonly Action _handler; 13 | readonly Func _asyncHandler; 14 | 15 | public AsyncEventInvocator(Action handler, Func asyncHandler) 16 | { 17 | _handler = handler; 18 | _asyncHandler = asyncHandler; 19 | } 20 | 21 | public bool WrapsHandler(Action handler1) 22 | { 23 | // Do not use ReferenceEquals! It will not work with delegates. 24 | return handler1 == _handler; 25 | } 26 | 27 | public bool WrapsHandler(Func handler) 28 | { 29 | // Do not use ReferenceEquals! It will not work with delegates. 30 | return handler == _asyncHandler; 31 | } 32 | 33 | public Task InvokeAsync(TEventArgs eventArgs) 34 | { 35 | if (_handler != null) 36 | { 37 | _handler(eventArgs); 38 | return CompletedTask.Instance; 39 | } 40 | 41 | if (_asyncHandler != null) 42 | { 43 | return _asyncHandler(eventArgs); 44 | } 45 | 46 | throw new InvalidOperationException(); 47 | } 48 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/AsyncQueueDequeueResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Internal; 6 | 7 | public sealed class AsyncQueueDequeueResult(bool isSuccess, TItem item) 8 | { 9 | public static readonly AsyncQueueDequeueResult NonSuccess = new(false, default); 10 | 11 | public bool IsSuccess { get; } = isSuccess; 12 | 13 | public TItem Item { get; } = item; 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/AsyncTaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace MQTTnet.Internal; 9 | 10 | public sealed class AsyncTaskCompletionSource 11 | { 12 | readonly TaskCompletionSource _taskCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); 13 | 14 | public Task Task => _taskCompletionSource.Task; 15 | 16 | public void TrySetCanceled() 17 | { 18 | _taskCompletionSource.TrySetCanceled(); 19 | } 20 | 21 | public void TrySetException(Exception exception) 22 | { 23 | _taskCompletionSource.TrySetException(exception); 24 | } 25 | 26 | public bool TrySetResult(TResult result) 27 | { 28 | return _taskCompletionSource.TrySetResult(result); 29 | } 30 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/CancellationTokenSourceExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading; 7 | 8 | namespace MQTTnet.Internal; 9 | 10 | public static class CancellationTokenSourceExtensions 11 | { 12 | public static bool TryCancel(this CancellationTokenSource cancellationTokenSource, bool throwOnFirstException = false) 13 | { 14 | if (cancellationTokenSource == null) 15 | { 16 | return false; 17 | } 18 | 19 | try 20 | { 21 | // Checking the _IsCancellationRequested_ here will not throw an 22 | // "ObjectDisposedException" as the getter of the property "Token" will do! 23 | if (cancellationTokenSource.IsCancellationRequested) 24 | { 25 | return false; 26 | } 27 | 28 | cancellationTokenSource.Cancel(throwOnFirstException); 29 | return true; 30 | } 31 | catch (ObjectDisposedException) 32 | { 33 | return false; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/CompletedTask.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | 7 | namespace MQTTnet.Internal; 8 | 9 | public static class CompletedTask 10 | { 11 | public static readonly Task Instance = Task.CompletedTask; 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/Disposable.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Internal; 8 | 9 | public abstract class Disposable : IDisposable 10 | { 11 | protected bool IsDisposed { get; private set; } 12 | 13 | protected void ThrowIfDisposed() 14 | { 15 | ObjectDisposedException.ThrowIf(IsDisposed, GetType()); 16 | } 17 | 18 | protected virtual void Dispose(bool disposing) 19 | { 20 | } 21 | 22 | // This code added to correctly implement the disposable pattern. 23 | public void Dispose() 24 | { 25 | // Do not change this code. Put cleanup code in Dispose(bool disposing) above. 26 | 27 | if (IsDisposed) 28 | { 29 | return; 30 | } 31 | 32 | IsDisposed = true; 33 | 34 | Dispose(true); 35 | GC.SuppressFinalize(this); 36 | } 37 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/EmptyBuffer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | 8 | namespace MQTTnet.Internal; 9 | 10 | public static class EmptyBuffer 11 | { 12 | public static readonly byte[] Array = []; 13 | 14 | public static readonly ArraySegment ArraySegment = new(Array, 0, 0); 15 | 16 | public static readonly ReadOnlySequence ReadOnlySequence = ReadOnlySequence.Empty; 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/MqttClientEvents.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Diagnostics.PacketInspection; 6 | 7 | namespace MQTTnet.Internal; 8 | 9 | public sealed class MqttClientEvents 10 | { 11 | public AsyncEvent ApplicationMessageReceivedEvent { get; } = new(); 12 | public AsyncEvent ConnectedEvent { get; } = new(); 13 | public AsyncEvent ConnectingEvent { get; } = new(); 14 | public AsyncEvent DisconnectedEvent { get; } = new(); 15 | public AsyncEvent InspectPacketEvent { get; } = new(); 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/MqttPacketBusItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using MQTTnet.Packets; 8 | 9 | namespace MQTTnet.Internal; 10 | 11 | public sealed class MqttPacketBusItem 12 | { 13 | readonly AsyncTaskCompletionSource _promise = new(); 14 | 15 | public MqttPacketBusItem(MqttPacket packet) 16 | { 17 | Packet = packet ?? throw new ArgumentNullException(nameof(packet)); 18 | } 19 | 20 | public event EventHandler Completed; 21 | 22 | public MqttPacket Packet { get; } 23 | 24 | public void Cancel() 25 | { 26 | _promise.TrySetCanceled(); 27 | } 28 | 29 | public void Complete() 30 | { 31 | _promise.TrySetResult(Packet); 32 | Completed?.Invoke(this, EventArgs.Empty); 33 | } 34 | 35 | public void Fail(Exception exception) 36 | { 37 | _promise.TrySetException(exception); 38 | } 39 | 40 | public Task WaitAsync() 41 | { 42 | return _promise.Task; 43 | } 44 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Internal/MqttPacketBusPartition.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Internal; 6 | 7 | public enum MqttPacketBusPartition 8 | { 9 | Data, 10 | 11 | Control, 12 | 13 | Health 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/LowLevelClient/ILowLevelMqttClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using MQTTnet.Diagnostics.PacketInspection; 5 | using MQTTnet.Packets; 6 | 7 | namespace MQTTnet.LowLevelClient; 8 | 9 | public interface ILowLevelMqttClient : IDisposable 10 | { 11 | event Func InspectPacketAsync; 12 | 13 | bool IsConnected { get; } 14 | 15 | Task ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken = default); 16 | 17 | Task DisconnectAsync(CancellationToken cancellationToken = default); 18 | 19 | Task ReceiveAsync(CancellationToken cancellationToken = default); 20 | 21 | Task SendAsync(MqttPacket packet, CancellationToken cancellationToken = default); 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet/MqttApplicationMessageExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Text; 7 | 8 | namespace MQTTnet; 9 | 10 | public static class MqttApplicationMessageExtensions 11 | { 12 | public static string ConvertPayloadToString(this MqttApplicationMessage applicationMessage) 13 | { 14 | ArgumentNullException.ThrowIfNull(applicationMessage); 15 | 16 | if (applicationMessage.Payload.Length == 0) 17 | { 18 | return null; 19 | } 20 | 21 | return Encoding.UTF8.GetString(applicationMessage.Payload); 22 | } 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet/MqttClientConnectionStatus.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientConnectionStatus 8 | { 9 | Disconnected, 10 | Disconnecting, 11 | Connected, 12 | Connecting 13 | } -------------------------------------------------------------------------------- /Source/MQTTnet/MqttPacketIdentifierProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public sealed class MqttPacketIdentifierProvider 8 | { 9 | readonly object _syncRoot = new(); 10 | 11 | ushort _value; 12 | 13 | public ushort GetNextPacketIdentifier() 14 | { 15 | lock (_syncRoot) 16 | { 17 | _value++; 18 | 19 | if (_value == 0) 20 | { 21 | // As per official MQTT documentation the package identifier should never be 0. 22 | _value = 1; 23 | } 24 | 25 | return _value; 26 | } 27 | } 28 | 29 | public void Reset() 30 | { 31 | lock (_syncRoot) 32 | { 33 | _value = 0; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Source/MQTTnet/MqttTopicFilterCompareResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttTopicFilterCompareResult 8 | { 9 | NoMatch, 10 | 11 | IsMatch, 12 | 13 | FilterInvalid, 14 | 15 | TopicInvalid 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/DefaultMqttCertificatesProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class DefaultMqttCertificatesProvider : IMqttClientCertificatesProvider 11 | { 12 | readonly X509Certificate2Collection _certificates; 13 | 14 | public DefaultMqttCertificatesProvider(X509Certificate2Collection certificates) 15 | { 16 | _certificates = certificates; 17 | } 18 | 19 | public DefaultMqttCertificatesProvider(IEnumerable certificates) 20 | { 21 | if (certificates != null) 22 | { 23 | _certificates = []; 24 | foreach (var certificate in certificates) 25 | { 26 | _certificates.Add(certificate); 27 | } 28 | } 29 | } 30 | 31 | public X509CertificateCollection GetCertificates() 32 | { 33 | return _certificates; 34 | } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/IMqttClientCertificatesProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Security.Cryptography.X509Certificates; 6 | 7 | namespace MQTTnet; 8 | 9 | public interface IMqttClientCertificatesProvider 10 | { 11 | X509CertificateCollection GetCertificates(); 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/IMqttClientChannelOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public interface IMqttClientChannelOptions 8 | { 9 | MqttClientTlsOptions TlsOptions { get; } 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/IMqttClientCredentialsProvider.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public interface IMqttClientCredentialsProvider 8 | { 9 | byte[] GetPassword(MqttClientOptions clientOptions); 10 | string GetUserName(MqttClientOptions clientOptions); 11 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/IMqttEnhancedAuthenticationHandler.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | 7 | namespace MQTTnet; 8 | 9 | public interface IMqttEnhancedAuthenticationHandler 10 | { 11 | Task HandleEnhancedAuthenticationAsync(MqttEnhancedAuthenticationEventArgs eventArgs); 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/MqttClientCertificateSelectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class MqttClientCertificateSelectionEventArgs : EventArgs 11 | { 12 | public MqttClientCertificateSelectionEventArgs( 13 | string targetHost, 14 | X509CertificateCollection localCertificates, 15 | X509Certificate remoteCertificate, 16 | string[] acceptableIssuers, 17 | MqttClientTcpOptions tcpOptions) 18 | { 19 | TargetHost = targetHost; 20 | LocalCertificates = localCertificates; 21 | RemoveCertificate = remoteCertificate; 22 | AcceptableIssuers = acceptableIssuers; 23 | TcpOptions = tcpOptions ?? throw new ArgumentNullException(nameof(tcpOptions)); 24 | } 25 | 26 | public string[] AcceptableIssuers { get; } 27 | 28 | public X509CertificateCollection LocalCertificates { get; } 29 | 30 | public X509Certificate RemoveCertificate { get; } 31 | 32 | public string TargetHost { get; } 33 | 34 | public MqttClientTcpOptions TcpOptions { get; } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/MqttClientCertificateValidationEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Net.Security; 7 | using System.Security.Cryptography.X509Certificates; 8 | 9 | namespace MQTTnet; 10 | 11 | public sealed class MqttClientCertificateValidationEventArgs : EventArgs 12 | { 13 | public MqttClientCertificateValidationEventArgs(X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors, IMqttClientChannelOptions clientOptions) 14 | { 15 | Certificate = certificate; 16 | Chain = chain; 17 | SslPolicyErrors = sslPolicyErrors; 18 | ClientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); 19 | } 20 | 21 | public X509Certificate Certificate { get; } 22 | 23 | public X509Chain Chain { get; } 24 | 25 | public IMqttClientChannelOptions ClientOptions { get; } 26 | 27 | public SslPolicyErrors SslPolicyErrors { get; } 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/MqttClientCredentials.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public sealed class MqttClientCredentials : IMqttClientCredentialsProvider 8 | { 9 | readonly byte[] _password; 10 | readonly string _userName; 11 | 12 | public MqttClientCredentials(string userName, byte[] password = null) 13 | { 14 | _userName = userName; 15 | _password = password; 16 | } 17 | 18 | public byte[] GetPassword(MqttClientOptions clientOptions) 19 | { 20 | return _password; 21 | } 22 | 23 | public string GetUserName(MqttClientOptions clientOptions) 24 | { 25 | return _userName; 26 | } 27 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/MqttClientDefaultCertificateValidationHandler.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Linq; 6 | using System.Net.Security; 7 | using System.Security.Cryptography.X509Certificates; 8 | 9 | namespace MQTTnet; 10 | 11 | public sealed class MqttClientDefaultCertificateValidationHandler 12 | { 13 | public static bool Handle(MqttClientCertificateValidationEventArgs eventArgs) 14 | { 15 | if (eventArgs.SslPolicyErrors == SslPolicyErrors.None) 16 | { 17 | return true; 18 | } 19 | 20 | if (eventArgs.Chain.ChainStatus.Any( 21 | c => c.Status is X509ChainStatusFlags.RevocationStatusUnknown or X509ChainStatusFlags.Revoked or X509ChainStatusFlags.OfflineRevocation)) 22 | { 23 | if (eventArgs.ClientOptions?.TlsOptions?.IgnoreCertificateRevocationErrors != true) 24 | { 25 | return false; 26 | } 27 | } 28 | 29 | if (eventArgs.Chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.PartialChain)) 30 | { 31 | if (eventArgs.ClientOptions?.TlsOptions?.IgnoreCertificateChainErrors != true) 32 | { 33 | return false; 34 | } 35 | } 36 | 37 | return eventArgs.ClientOptions?.TlsOptions?.AllowUntrustedCertificates == true; 38 | } 39 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/MqttClientWebSocketProxyOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public sealed class MqttClientWebSocketProxyOptions 8 | { 9 | public string Address { get; set; } 10 | 11 | public string[] BypassList { get; set; } 12 | 13 | public bool BypassOnLocal { get; set; } 14 | 15 | public string Domain { get; set; } 16 | 17 | public string Password { get; set; } 18 | 19 | public bool UseDefaultCredentials { get; set; } 20 | 21 | public string Username { get; set; } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/ReceiveMqttEnhancedAuthenticationDataResult.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Packets; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet; 10 | 11 | public sealed class ReceiveMqttEnhancedAuthenticationDataResult 12 | { 13 | public byte[] AuthenticationData { get; init; } 14 | 15 | public string AuthenticationMethod { get; init; } 16 | 17 | public MqttAuthenticateReasonCode ReasonCode { get; init; } 18 | 19 | public string ReasonString { get; init; } 20 | 21 | public List UserProperties { get; init; } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Options/SendMqttEnhancedAuthenticationDataOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class SendMqttEnhancedAuthenticationDataOptions 11 | { 12 | public byte[] Data { get; init; } 13 | 14 | public string ReasonString { get; init; } 15 | 16 | public List UserProperties { get; init; } 17 | } -------------------------------------------------------------------------------- /Source/MQTTnet/PacketDispatcher/IMqttPacketAwaitable.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MQTTnet.Packets; 6 | using System; 7 | 8 | namespace MQTTnet.PacketDispatcher; 9 | 10 | public interface IMqttPacketAwaitable : IDisposable 11 | { 12 | MqttPacketAwaitableFilter Filter { get; } 13 | 14 | void Complete(MqttPacket packet); 15 | 16 | void Fail(Exception exception); 17 | 18 | void Cancel(); 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet/PacketDispatcher/MqttPacketAwaitableFilter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.PacketDispatcher; 8 | 9 | public sealed class MqttPacketAwaitableFilter 10 | { 11 | public Type Type { get; set; } 12 | 13 | public ushort Identifier { get; set; } 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttAuthPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | /// Added in MQTTv5.0.0. 11 | public sealed class MqttAuthPacket : MqttPacket 12 | { 13 | public byte[] AuthenticationData { get; set; } 14 | 15 | public string AuthenticationMethod { get; set; } 16 | 17 | public MqttAuthenticateReasonCode ReasonCode { get; set; } 18 | 19 | public string ReasonString { get; set; } 20 | 21 | public List UserProperties { get; set; } 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttDisconnectPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttDisconnectPacket : MqttPacket 11 | { 12 | /// 13 | /// Added in MQTTv5. 14 | /// 15 | public MqttDisconnectReasonCode ReasonCode { get; set; } = MqttDisconnectReasonCode.NormalDisconnection; 16 | 17 | /// 18 | /// Added in MQTTv5. 19 | /// 20 | public string ReasonString { get; set; } 21 | 22 | /// 23 | /// Added in MQTTv5. 24 | /// 25 | public string ServerReference { get; set; } 26 | 27 | /// 28 | /// Added in MQTTv5. 29 | /// 30 | public uint SessionExpiryInterval { get; set; } 31 | 32 | /// 33 | /// Added in MQTTv5. 34 | /// 35 | public List UserProperties { get; set; } 36 | 37 | public override string ToString() 38 | { 39 | return $"Disconnect: [ReasonCode={ReasonCode}] [ReasonString={ReasonString}] [ServerReference={ServerReference}] [SessionExpiryInterval={SessionExpiryInterval}]"; 40 | } 41 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Packets; 6 | 7 | public abstract class MqttPacket; -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPacketExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Packets; 8 | 9 | public static class MqttPacketExtensions 10 | { 11 | public static string GetRfcName(this MqttPacket packet) 12 | { 13 | ArgumentNullException.ThrowIfNull(packet); 14 | 15 | return packet switch 16 | { 17 | MqttConnectPacket => "CONNECT", 18 | MqttConnAckPacket => "CONNACK", 19 | MqttAuthPacket => "AUTH", 20 | MqttDisconnectPacket => "DISCONNECT", 21 | MqttPingReqPacket => "PINGREQ", 22 | MqttPingRespPacket => "PINGRESP", 23 | MqttSubscribePacket => "SUBSCRIBE", 24 | MqttSubAckPacket => "SUBACK", 25 | MqttUnsubscribePacket => "UNSUBSCRIBE", 26 | MqttUnsubAckPacket => "UNSUBACK", 27 | MqttPublishPacket => "PUBLISH", 28 | MqttPubAckPacket => "PUBACK", 29 | MqttPubRelPacket => "PUBREL", 30 | MqttPubRecPacket => "PUBREC", 31 | MqttPubCompPacket => "PUBCOMP", 32 | _ => packet.GetType().Name 33 | }; 34 | } 35 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPacketWithIdentifier.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Packets; 6 | 7 | public abstract class MqttPacketWithIdentifier : MqttPacket 8 | { 9 | public ushort PacketIdentifier { get; set; } 10 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPingReqPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Packets; 6 | 7 | public sealed class MqttPingReqPacket : MqttPacket 8 | { 9 | // This is a minor performance improvement. 10 | public static readonly MqttPingReqPacket Instance = new(); 11 | 12 | public override string ToString() 13 | { 14 | return "PingReq"; 15 | } 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPingRespPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Packets; 6 | 7 | public sealed class MqttPingRespPacket : MqttPacket 8 | { 9 | // This is a minor performance improvement. 10 | public static readonly MqttPingRespPacket Instance = new(); 11 | 12 | public override string ToString() 13 | { 14 | return "PingResp"; 15 | } 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPubAckPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttPubAckPacket : MqttPacketWithIdentifier 11 | { 12 | /// 13 | /// Added in MQTTv5. 14 | /// 15 | public MqttPubAckReasonCode ReasonCode { get; set; } = MqttPubAckReasonCode.Success; 16 | 17 | /// 18 | /// Added in MQTTv5. 19 | /// 20 | public string ReasonString { get; set; } 21 | 22 | /// 23 | /// Added in MQTTv5. 24 | /// 25 | public List UserProperties { get; set; } 26 | 27 | public override string ToString() 28 | { 29 | return $"PubAck: [PacketIdentifier={PacketIdentifier}] [ReasonCode={ReasonCode}]"; 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPubCompPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttPubCompPacket : MqttPacketWithIdentifier 11 | { 12 | /// 13 | /// Added in MQTTv5. 14 | /// 15 | public MqttPubCompReasonCode ReasonCode { get; set; } = MqttPubCompReasonCode.Success; 16 | 17 | /// 18 | /// Added in MQTTv5. 19 | /// 20 | public string ReasonString { get; set; } 21 | 22 | /// 23 | /// Added in MQTTv5. 24 | /// 25 | public List UserProperties { get; set; } 26 | 27 | public override string ToString() 28 | { 29 | return $"PubComp: [PacketIdentifier={PacketIdentifier}] [ReasonCode={ReasonCode}]"; 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPubRecPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttPubRecPacket : MqttPacketWithIdentifier 11 | { 12 | /// 13 | /// Added in MQTTv5. 14 | /// 15 | public MqttPubRecReasonCode ReasonCode { get; set; } = MqttPubRecReasonCode.Success; 16 | 17 | /// 18 | /// Added in MQTTv5. 19 | /// 20 | public string ReasonString { get; set; } 21 | 22 | /// 23 | /// Added in MQTTv5. 24 | /// 25 | public List UserProperties { get; set; } 26 | 27 | public override string ToString() 28 | { 29 | return $"PubRec: [PacketIdentifier={PacketIdentifier}] [ReasonCode={ReasonCode}]"; 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPubRelPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Protocol; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttPubRelPacket : MqttPacketWithIdentifier 11 | { 12 | /// 13 | /// Added in MQTTv5. 14 | /// 15 | public MqttPubRelReasonCode ReasonCode { get; set; } = MqttPubRelReasonCode.Success; 16 | 17 | /// 18 | /// Added in MQTTv5. 19 | /// 20 | public string ReasonString { get; set; } 21 | 22 | /// 23 | /// Added in MQTTv5. 24 | /// 25 | public List UserProperties { get; set; } 26 | 27 | public override string ToString() 28 | { 29 | return $"PubRel: [PacketIdentifier={PacketIdentifier}] [ReasonCode={ReasonCode}]"; 30 | } 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttPublishPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.Collections.Generic; 8 | using MQTTnet.Protocol; 9 | 10 | namespace MQTTnet.Packets; 11 | 12 | public sealed class MqttPublishPacket : MqttPacketWithIdentifier 13 | { 14 | public string ContentType { get; set; } 15 | 16 | public byte[] CorrelationData { get; set; } 17 | 18 | public bool Dup { get; set; } 19 | 20 | public uint MessageExpiryInterval { get; set; } 21 | 22 | public MqttPayloadFormatIndicator PayloadFormatIndicator { get; set; } = MqttPayloadFormatIndicator.Unspecified; 23 | 24 | public ArraySegment PayloadSegment { set => Payload = new ReadOnlySequence(value); } 25 | 26 | public ReadOnlySequence Payload { get; set; } 27 | 28 | public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; } = MqttQualityOfServiceLevel.AtMostOnce; 29 | 30 | public string ResponseTopic { get; set; } 31 | 32 | public bool Retain { get; set; } 33 | 34 | public List SubscriptionIdentifiers { get; set; } 35 | 36 | public string Topic { get; set; } 37 | 38 | public ushort TopicAlias { get; set; } 39 | 40 | public List UserProperties { get; set; } 41 | 42 | public override string ToString() 43 | { 44 | return 45 | $"Publish: [Topic={Topic}] [PayloadLength={Payload.Length}] [QoSLevel={QualityOfServiceLevel}] [Dup={Dup}] [Retain={Retain}] [PacketIdentifier={PacketIdentifier}]"; 46 | } 47 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttSubAckPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Packets; 10 | 11 | public sealed class MqttSubAckPacket : MqttPacketWithIdentifier 12 | { 13 | /// 14 | /// Reason Code is used in MQTTv5.0.0 and backward compatible to v.3.1.1. Return Code is used in MQTTv3.1.1 15 | /// 16 | public List ReasonCodes { get; set; } 17 | 18 | /// 19 | /// Added in MQTTv5. 20 | /// 21 | public string ReasonString { get; set; } 22 | 23 | /// 24 | /// Added in MQTTv5. 25 | /// 26 | public List UserProperties { get; set; } 27 | 28 | public override string ToString() 29 | { 30 | var reasonCodesText = string.Join(",", ReasonCodes.Select(f => f.ToString())); 31 | 32 | return $"SubAck: [PacketIdentifier={PacketIdentifier}] [ReasonCode={reasonCodesText}]"; 33 | } 34 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttSubscribePacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace MQTTnet.Packets; 9 | 10 | public sealed class MqttSubscribePacket : MqttPacketWithIdentifier 11 | { 12 | /// 13 | /// It is a Protocol Error if the Subscription Identifier has a value of 0. 14 | /// 15 | public uint SubscriptionIdentifier { get; set; } 16 | 17 | public List TopicFilters { get; set; } = []; 18 | 19 | /// 20 | /// Added in MQTTv5. 21 | /// 22 | public List UserProperties { get; set; } 23 | 24 | public override string ToString() 25 | { 26 | var topicFiltersText = string.Join(",", TopicFilters.Select(f => f.Topic + "@" + f.QualityOfServiceLevel)); 27 | return $"Subscribe: [PacketIdentifier={PacketIdentifier}] [TopicFilters={topicFiltersText}]"; 28 | } 29 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttUnsubAckPacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using MQTTnet.Protocol; 8 | 9 | namespace MQTTnet.Packets; 10 | 11 | public sealed class MqttUnsubAckPacket : MqttPacketWithIdentifier 12 | { 13 | /// 14 | /// Added in MQTTv5. 15 | /// 16 | public List ReasonCodes { get; set; } 17 | 18 | /// 19 | /// Added in MQTTv5. 20 | /// 21 | public string ReasonString { get; set; } 22 | 23 | /// 24 | /// Added in MQTTv5. 25 | /// 26 | public List UserProperties { get; set; } 27 | 28 | public override string ToString() 29 | { 30 | var reasonCodesText = string.Empty; 31 | if (ReasonCodes != null) 32 | { 33 | reasonCodesText = string.Join(",", ReasonCodes?.Select(f => f.ToString())); 34 | } 35 | 36 | return $"UnsubAck: [PacketIdentifier={PacketIdentifier}] [ReasonCodes={reasonCodesText}] [ReasonString={ReasonString}]"; 37 | } 38 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttUnsubscribePacket.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace MQTTnet.Packets; 8 | 9 | public sealed class MqttUnsubscribePacket : MqttPacketWithIdentifier 10 | { 11 | public List TopicFilters { get; set; } = []; 12 | 13 | /// 14 | /// Added in MQTTv5. 15 | /// 16 | public List UserProperties { get; set; } 17 | 18 | public override string ToString() 19 | { 20 | var topicFiltersText = string.Join(",", TopicFilters); 21 | return $"Unsubscribe: [PacketIdentifier={PacketIdentifier}] [TopicFilters={topicFiltersText}]"; 22 | } 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Packets/MqttUserProperty.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet.Packets; 8 | 9 | public sealed class MqttUserProperty 10 | { 11 | public MqttUserProperty(string name, string value) 12 | { 13 | Name = name ?? throw new ArgumentNullException(nameof(name)); 14 | Value = value ?? throw new ArgumentNullException(nameof(value)); 15 | } 16 | 17 | public string Name { get; } 18 | 19 | public string Value { get; } 20 | 21 | public override bool Equals(object obj) 22 | { 23 | return Equals(obj as MqttUserProperty); 24 | } 25 | 26 | public bool Equals(MqttUserProperty other) 27 | { 28 | if (other == null) 29 | { 30 | return false; 31 | } 32 | 33 | if (ReferenceEquals(other, this)) 34 | { 35 | return true; 36 | } 37 | 38 | return string.Equals(Name, other.Name, StringComparison.Ordinal) && string.Equals(Value, other.Value, StringComparison.Ordinal); 39 | } 40 | 41 | public override int GetHashCode() 42 | { 43 | return Name.GetHashCode() ^ Value.GetHashCode(); 44 | } 45 | 46 | public override string ToString() 47 | { 48 | return $"{Name} = {Value}"; 49 | } 50 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttAuthenticateReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttAuthenticateReasonCode 8 | { 9 | Success = 0, 10 | ContinueAuthentication = 24, 11 | ReAuthenticate = 25 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttConnectReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttConnectReasonCode 8 | { 9 | Success = 0, 10 | UnspecifiedError = 128, 11 | MalformedPacket = 129, 12 | ProtocolError = 130, 13 | ImplementationSpecificError = 131, 14 | UnsupportedProtocolVersion = 132, 15 | ClientIdentifierNotValid = 133, 16 | BadUserNameOrPassword = 134, 17 | NotAuthorized = 135, 18 | ServerUnavailable = 136, 19 | ServerBusy = 137, 20 | Banned = 138, 21 | BadAuthenticationMethod = 140, 22 | TopicNameInvalid = 144, 23 | PacketTooLarge = 149, 24 | QuotaExceeded = 151, 25 | PayloadFormatInvalid = 153, 26 | RetainNotSupported = 154, 27 | QoSNotSupported = 155, 28 | UseAnotherServer = 156, 29 | ServerMoved = 157, 30 | ConnectionRateExceeded = 159 31 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttConnectReturnCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttConnectReturnCode 8 | { 9 | ConnectionAccepted = 0x00, 10 | ConnectionRefusedUnacceptableProtocolVersion = 0x01, 11 | ConnectionRefusedIdentifierRejected = 0x02, 12 | ConnectionRefusedServerUnavailable = 0x03, 13 | ConnectionRefusedBadUsernameOrPassword = 0x04, 14 | ConnectionRefusedNotAuthorized = 0x05 15 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttControlPacketType.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttControlPacketType 8 | { 9 | Connect = 1, 10 | ConnAck = 2, 11 | Publish = 3, 12 | PubAck = 4, 13 | PubRec = 5, 14 | PubRel = 6, 15 | PubComp = 7, 16 | Subscribe = 8, 17 | SubAck = 9, 18 | Unsubscribe = 10, 19 | UnsubAck = 11, 20 | PingReq = 12, 21 | PingResp = 13, 22 | Disconnect = 14, 23 | Auth = 15 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttDisconnectReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttDisconnectReasonCode 8 | { 9 | NormalDisconnection = 0, 10 | DisconnectWithWillMessage = 4, 11 | UnspecifiedError = 128, 12 | MalformedPacket = 129, 13 | ProtocolError = 130, 14 | ImplementationSpecificError = 131, 15 | NotAuthorized = 135, 16 | ServerBusy = 137, 17 | ServerShuttingDown = 139, 18 | KeepAliveTimeout = 141, 19 | SessionTakenOver = 142, 20 | TopicFilterInvalid = 143, 21 | TopicNameInvalid = 144, 22 | ReceiveMaximumExceeded = 147, 23 | TopicAliasInvalid = 148, 24 | PacketTooLarge = 149, 25 | MessageRateTooHigh = 150, 26 | QuotaExceeded = 151, 27 | AdministrativeAction = 152, 28 | PayloadFormatInvalid = 153, 29 | RetainNotSupported = 154, 30 | QoSNotSupported = 155, 31 | UseAnotherServer = 156, 32 | ServerMoved = 157, 33 | SharedSubscriptionsNotSupported = 158, 34 | ConnectionRateExceeded = 159, 35 | MaximumConnectTime = 160, 36 | SubscriptionIdentifiersNotSupported = 161, 37 | WildcardSubscriptionsNotSupported = 162 38 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPayloadFormatIndicator.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPayloadFormatIndicator 8 | { 9 | Unspecified = 0, 10 | CharacterData = 1 11 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPorts.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public static class MqttPorts 8 | { 9 | public const int Default = 1883; 10 | 11 | public const int Secure = 8883; 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPropertyId.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPropertyId 8 | { 9 | None = 0, 10 | 11 | PayloadFormatIndicator = 1, 12 | MessageExpiryInterval = 2, 13 | ContentType = 3, 14 | ResponseTopic = 8, 15 | CorrelationData = 9, 16 | SubscriptionIdentifier = 11, 17 | SessionExpiryInterval = 17, 18 | AssignedClientIdentifier = 18, 19 | ServerKeepAlive = 19, 20 | AuthenticationMethod = 21, 21 | AuthenticationData = 22, 22 | RequestProblemInformation = 23, 23 | WillDelayInterval = 24, 24 | RequestResponseInformation = 25, 25 | ResponseInformation = 26, 26 | ServerReference = 28, 27 | ReasonString = 31, 28 | ReceiveMaximum = 33, 29 | TopicAliasMaximum = 34, 30 | TopicAlias = 35, 31 | MaximumQoS = 36, 32 | RetainAvailable = 37, 33 | UserProperty = 38, 34 | MaximumPacketSize = 39, 35 | WildcardSubscriptionAvailable = 40, 36 | SubscriptionIdentifiersAvailable = 41, 37 | SharedSubscriptionAvailable = 42 38 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPubAckReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPubAckReasonCode 8 | { 9 | Success = 0, 10 | 11 | /// 12 | /// The message is accepted but there are no subscribers. This is sent only by the Server. If the Server knows that there are no matching subscribers, it MAY use this Reason Code instead of 0x00 (Success). 13 | /// 14 | NoMatchingSubscribers = 16, 15 | 16 | UnspecifiedError = 128, 17 | ImplementationSpecificError = 131, 18 | NotAuthorized = 135, 19 | TopicNameInvalid = 144, 20 | PacketIdentifierInUse = 145, 21 | QuotaExceeded = 151, 22 | PayloadFormatInvalid = 153 23 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPubCompReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPubCompReasonCode 8 | { 9 | Success = 0, 10 | PacketIdentifierNotFound = 146 11 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPubRecReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPubRecReasonCode 8 | { 9 | Success = 0, 10 | NoMatchingSubscribers = 16, 11 | UnspecifiedError = 128, 12 | ImplementationSpecificError = 131, 13 | NotAuthorized = 135, 14 | TopicNameInvalid = 144, 15 | PacketIdentifierInUse = 145, 16 | QuotaExceeded = 151, 17 | PayloadFormatInvalid = 153 18 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttPubRelReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttPubRelReasonCode 8 | { 9 | Success = 0, 10 | PacketIdentifierNotFound = 146 11 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttQualityOfServiceLevel.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttQualityOfServiceLevel 8 | { 9 | AtMostOnce = 0x00, 10 | AtLeastOnce = 0x01, 11 | ExactlyOnce = 0x02 12 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttRetainHandling.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttRetainHandling 8 | { 9 | SendAtSubscribe = 0, 10 | 11 | SendAtSubscribeIfNewSubscriptionOnly = 1, 12 | 13 | DoNotSendOnSubscribe = 2 14 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttSubscribeReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttSubscribeReasonCode 8 | { 9 | // Compatible with MQTTv3.1.1. 10 | GrantedQoS0 = 0x00, 11 | GrantedQoS1 = 0x01, 12 | GrantedQoS2 = 0x02, 13 | UnspecifiedError = 0x80, 14 | 15 | // New in MQTTv5. 16 | ImplementationSpecificError = 131, 17 | NotAuthorized = 135, 18 | TopicFilterInvalid = 143, 19 | PacketIdentifierInUse = 145, 20 | QuotaExceeded = 151, 21 | SharedSubscriptionsNotSupported = 158, 22 | SubscriptionIdentifiersNotSupported = 161, 23 | WildcardSubscriptionsNotSupported = 162 24 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttSubscribeReturnCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttSubscribeReturnCode 8 | { 9 | SuccessMaximumQoS0 = 0x00, 10 | SuccessMaximumQoS1 = 0x01, 11 | SuccessMaximumQoS2 = 0x02, 12 | Failure = 0x80 13 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Protocol/MqttUnsubscribeReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet.Protocol; 6 | 7 | public enum MqttUnsubscribeReasonCode 8 | { 9 | Success = 0, 10 | NoSubscriptionExisted = 17, 11 | UnspecifiedError = 128, 12 | ImplementationSpecificError = 131, 13 | NotAuthorized = 135, 14 | TopicFilterInvalid = 143, 15 | PacketIdentifierInUse = 145 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Publishing/MqttClientPublishReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientPublishReasonCode 8 | { 9 | Success = 0, 10 | 11 | NoMatchingSubscribers = 16, 12 | UnspecifiedError = 128, 13 | ImplementationSpecificError = 131, 14 | NotAuthorized = 135, 15 | TopicNameInvalid = 144, 16 | PacketIdentifierInUse = 145, 17 | QuotaExceeded = 151, 18 | PayloadFormatInvalid = 153 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Receiving/MqttApplicationMessageReceivedReasonCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttApplicationMessageReceivedReasonCode 8 | { 9 | Success = 0, 10 | NoMatchingSubscribers = 16, 11 | UnspecifiedError = 128, 12 | ImplementationSpecificError = 131, 13 | NotAuthorized = 135, 14 | TopicNameInvalid = 144, 15 | PacketIdentifierInUse = 145, 16 | PacketIdentifierNotFound = 146, 17 | QuotaExceeded = 151, 18 | PayloadFormatInvalid = 153 19 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Subscribing/MqttClientSubscribeResultCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientSubscribeResultCode 8 | { 9 | GrantedQoS0 = 0x00, 10 | GrantedQoS1 = 0x01, 11 | GrantedQoS2 = 0x02, 12 | UnspecifiedError = 0x80, 13 | 14 | ImplementationSpecificError = 131, 15 | NotAuthorized = 135, 16 | TopicFilterInvalid = 143, 17 | PacketIdentifierInUse = 145, 18 | QuotaExceeded = 151, 19 | SharedSubscriptionsNotSupported = 158, 20 | SubscriptionIdentifiersNotSupported = 161, 21 | WildcardSubscriptionsNotSupported = 162 22 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Subscribing/MqttClientSubscribeResultItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class MqttClientSubscribeResultItem 11 | { 12 | public MqttClientSubscribeResultItem(MqttTopicFilter topicFilter, MqttClientSubscribeResultCode resultCode) 13 | { 14 | TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter)); 15 | ResultCode = resultCode; 16 | } 17 | 18 | /// 19 | /// Gets or sets the result code. 20 | /// MQTT 5.0.0+ feature. 21 | /// 22 | public MqttClientSubscribeResultCode ResultCode { get; } 23 | 24 | /// 25 | /// Gets or sets the topic filter. 26 | /// The topic filter can contain topics and wildcards. 27 | /// 28 | public MqttTopicFilter TopicFilter { get; } 29 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Unsubscribing/MqttClientUnsubscribeOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MQTTnet.Packets; 7 | 8 | namespace MQTTnet; 9 | 10 | public sealed class MqttClientUnsubscribeOptions 11 | { 12 | /// 13 | /// Gets or sets a list of topic filters the client wants to unsubscribe from. 14 | /// Topic filters can include regular topics or wild cards. 15 | /// 16 | public List TopicFilters { get; set; } = []; 17 | 18 | /// 19 | /// Gets or sets the user properties. 20 | /// In MQTT 5, user properties are basic UTF-8 string key-value pairs that you can append to almost every type of MQTT 21 | /// packet. 22 | /// As long as you don’t exceed the maximum message size, you can use an unlimited number of user properties to add 23 | /// metadata to MQTT messages and pass information between publisher, broker, and subscriber. 24 | /// The feature is very similar to the HTTP header concept. 25 | /// MQTT 5.0.0+ feature. 26 | /// 27 | public List UserProperties { get; set; } 28 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Unsubscribing/MqttClientUnsubscribeOptionsValidator.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using MQTTnet.Formatter; 7 | 8 | namespace MQTTnet; 9 | 10 | public static class MqttClientUnsubscribeOptionsValidator 11 | { 12 | public static void ThrowIfNotSupported(MqttClientUnsubscribeOptions options, MqttProtocolVersion protocolVersion) 13 | { 14 | ArgumentNullException.ThrowIfNull(options); 15 | 16 | if (protocolVersion == MqttProtocolVersion.V500) 17 | { 18 | // Everything is supported. 19 | return; 20 | } 21 | 22 | if (options.UserProperties?.Count > 0) 23 | { 24 | Throw(nameof(options.UserProperties)); 25 | } 26 | } 27 | 28 | static void Throw(string featureName) 29 | { 30 | throw new NotSupportedException($"Feature {featureName} requires MQTT version 5.0.0."); 31 | } 32 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Unsubscribing/MqttClientUnsubscribeResultCode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace MQTTnet; 6 | 7 | public enum MqttClientUnsubscribeResultCode 8 | { 9 | Success = 0, 10 | NoSubscriptionExisted = 17, 11 | UnspecifiedError = 128, 12 | ImplementationSpecificError = 131, 13 | NotAuthorized = 135, 14 | TopicFilterInvalid = 143, 15 | PacketIdentifierInUse = 145 16 | } -------------------------------------------------------------------------------- /Source/MQTTnet/Unsubscribing/MqttClientUnsubscribeResultItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace MQTTnet; 8 | 9 | public sealed class MqttClientUnsubscribeResultItem 10 | { 11 | public MqttClientUnsubscribeResultItem(string topicFilter, MqttClientUnsubscribeResultCode resultCode) 12 | { 13 | TopicFilter = topicFilter ?? throw new ArgumentNullException(nameof(topicFilter)); 14 | ResultCode = resultCode; 15 | } 16 | 17 | /// 18 | /// Gets or sets the result code. 19 | /// MQTT 5.0.0+ feature. 20 | /// 21 | public MqttClientUnsubscribeResultCode ResultCode { get; } 22 | 23 | /// 24 | /// Gets or sets the topic filter. 25 | /// The topic filter can contain topics and wildcards. 26 | /// 27 | public string TopicFilter { get; } 28 | } -------------------------------------------------------------------------------- /Source/ReleaseNotes.md: -------------------------------------------------------------------------------- 1 | * Core: Used new language features across the entire library 2 | * Core: Performance improvements 3 | --------------------------------------------------------------------------------