From 3ef7f60a18d80495fcb152632ea223c0631f090f Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Mon, 6 May 2019 20:26:39 +0200 Subject: [PATCH 1/5] Fix wrong IsSessionPresent flag. --- Source/MQTTnet/Server/MqttClientConnection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/MQTTnet/Server/MqttClientConnection.cs b/Source/MQTTnet/Server/MqttClientConnection.cs index 4d870d55..d88d9739 100644 --- a/Source/MQTTnet/Server/MqttClientConnection.cs +++ b/Source/MQTTnet/Server/MqttClientConnection.cs @@ -138,7 +138,7 @@ namespace MQTTnet.Server { ReturnCode = MqttConnectReturnCode.ConnectionAccepted, ReasonCode = MqttConnectReasonCode.Success, - IsSessionPresent = Session.IsCleanSession + IsSessionPresent = !Session.IsCleanSession }).ConfigureAwait(false); Session.IsCleanSession = false; From 5980cbd9441eab1690f7460bb7358b46dd8c18d4 Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Mon, 6 May 2019 20:27:06 +0200 Subject: [PATCH 2/5] Fix build scripts to use 4.6 binaries. --- Build/MQTTnet.Extensions.ManagedClient.nuspec | 9 ++-- Build/MQTTnet.Extensions.Rpc.nuspec | 9 ++-- Build/MQTTnet.nuspec | 45 +++---------------- 3 files changed, 14 insertions(+), 49 deletions(-) diff --git a/Build/MQTTnet.Extensions.ManagedClient.nuspec b/Build/MQTTnet.Extensions.ManagedClient.nuspec index 70fcd44b..edec7696 100644 --- a/Build/MQTTnet.Extensions.ManagedClient.nuspec +++ b/Build/MQTTnet.Extensions.ManagedClient.nuspec @@ -34,10 +34,9 @@ - - - - - + + + + diff --git a/Build/MQTTnet.Extensions.Rpc.nuspec b/Build/MQTTnet.Extensions.Rpc.nuspec index 13d3d4c1..ce81cb6e 100644 --- a/Build/MQTTnet.Extensions.Rpc.nuspec +++ b/Build/MQTTnet.Extensions.Rpc.nuspec @@ -34,10 +34,9 @@ - - - - - + + + + diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index c2f91e42..86992c52 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -11,36 +11,8 @@ false MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). -* [Core] Added support for MQTTv5 packages. -* [Core] Performance improvements. -* [Core] Removed obsolete methods. -* [Core] Fixed a memory leak when processing lots of messages (thanks to @tschanko) -* [Core] Added more overloads for MQTT factory. -* [Core] The client password is now hidden from the logs (replaced with **** if set). -* [Core] Fixed a memory leak when using SSL connections (thanks to @biovoid). -* [Client] Added validation of topics before publishing. -* [Client] Added new MQTTv5 features to options builder. -* [Client] Added uniform API across all supported MQTT versions (BREAKING CHANGE!) -* [Client] The client will now avoid sending an ACK if an exception has been thrown in message handler (thanks to @ramonsmits). -* [Client] Fixed issues in QoS 2 handling which leads to message loss. -* [Client] Replaced all events with proper async compatible handlers (BREAKING CHANGE!). -* [Client] Added more configuration values to TCP endpoint options. -* [Client] Added used PacketIdentifier to publish result. -* [ManagedClient] Replaced all events with proper async compatible handlers (BREAKING CHANGE!). -* [ManagedClient] The log ID is now propagated to the internal client (thanks to @vbBerni). -* [ManagedClient] Added validation of topics before publishing. -* [ManagedClient] The internal MQTT client is now closed properly (thanks to @vbBerni). -* [Server] Added support for MQTTv5 clients. The server will still return _success_ for all cases at the moment even if more granular codes are available. -* [Server] Fixed issues in QoS 2 handling which leads to message loss. -* [Server] Replaced all events with proper async compatible handlers (BREAKING CHANGE!). -* [Server] The used logger instance is now propagated to the WebSocket server adapter. -* [Server] Added the flag "IsSecureConnection" which is set to true when the connection is encrypted. -* [Server] Fixed wrong will message behavior when stopping server (thanks to @JohBa) -* [Server] Added validation of topics before publishing. -* [Server] Added more configuration values to TCP endpoint options. -* [MQTTnet Server] Added as first Alpha version of standalone cross platform MQTT server. - -* [Note] Due to MQTTv5 a lot of new classes were introduced. This required adding new namespaces as well. Most classes are backward compatible but new namespaces must be added. +* [Server] Fixed a bug which returns wrong flag for existing sessions (thanks to @avengerstark). +* [nuget] .NET Framework builds are now using 4.5.2 or 4.6.1 builds instead of netstandard 2.0. Copyright Christian Kratky 2016-2019 MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin @@ -60,10 +32,6 @@ - - - - @@ -83,10 +51,9 @@ - - - - - + + + + \ No newline at end of file From 664549ab9303523325db1e2868375f8fa047cb7d Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Wed, 8 May 2019 00:12:27 +0200 Subject: [PATCH 3/5] Fix message encoding bugs. --- Build/MQTTnet.nuspec | 4 +++- Source/MQTTnet/Formatter/V5/MqttV500DataConverter.cs | 7 +++++++ Source/MQTTnet/Formatter/V5/MqttV500PacketEncoder.cs | 12 +++++------- .../MQTTnet/Formatter/V5/MqttV500PropertiesWriter.cs | 3 +++ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index 86992c52..a7902e02 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -11,7 +11,9 @@ false MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). -* [Server] Fixed a bug which returns wrong flag for existing sessions (thanks to @avengerstark). +* [Core] Fixed missing properties from PUBLISH packet in _MqttApplicationMessage_ (thanks to @pcbing). +* [Core] Fixed wrong encoding of PUBREL and PUBCOMP packets for MQTTv5 (thanks to @perphilipp). +* [Server] Fixed a bug which returns wrong flag for existing session in CONNACK packet (thanks to @avengerstark). * [nuget] .NET Framework builds are now using 4.5.2 or 4.6.1 builds instead of netstandard 2.0. Copyright Christian Kratky 2016-2019 diff --git a/Source/MQTTnet/Formatter/V5/MqttV500DataConverter.cs b/Source/MQTTnet/Formatter/V5/MqttV500DataConverter.cs index 8071fc32..3866dd8e 100644 --- a/Source/MQTTnet/Formatter/V5/MqttV500DataConverter.cs +++ b/Source/MQTTnet/Formatter/V5/MqttV500DataConverter.cs @@ -63,6 +63,13 @@ namespace MQTTnet.Formatter.V5 Payload = publishPacket.Payload, QualityOfServiceLevel = publishPacket.QualityOfServiceLevel, Retain = publishPacket.Retain, + ResponseTopic = publishPacket.Properties?.ResponseTopic, + ContentType = publishPacket.Properties?.ContentType, + CorrelationData = publishPacket.Properties?.CorrelationData, + MessageExpiryInterval = publishPacket.Properties?.MessageExpiryInterval, + SubscriptionIdentifier = publishPacket.Properties?.SubscriptionIdentifier, + TopicAlias = publishPacket.Properties?.TopicAlias, + PayloadFormatIndicator = publishPacket.Properties?.PayloadFormatIndicator, UserProperties = publishPacket.Properties?.UserProperties ?? new List() }; } diff --git a/Source/MQTTnet/Formatter/V5/MqttV500PacketEncoder.cs b/Source/MQTTnet/Formatter/V5/MqttV500PacketEncoder.cs index 5800d30f..acb4202c 100644 --- a/Source/MQTTnet/Formatter/V5/MqttV500PacketEncoder.cs +++ b/Source/MQTTnet/Formatter/V5/MqttV500PacketEncoder.cs @@ -343,9 +343,6 @@ namespace MQTTnet.Formatter.V5 ThrowReasonCodeNotSetException(); } - packetWriter.Write(packet.PacketIdentifier.Value); - packetWriter.Write((byte)packet.ReasonCode.Value); - var propertiesWriter = new MqttV500PropertiesWriter(); if (packet.Properties != null) { @@ -353,7 +350,9 @@ namespace MQTTnet.Formatter.V5 propertiesWriter.WriteUserProperties(packet.Properties.UserProperties); } - if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubRelReasonCode.Success) + packetWriter.Write(packet.PacketIdentifier.Value); + + if (propertiesWriter.Length > 0 || packet.ReasonCode.Value != MqttPubRelReasonCode.Success) { packetWriter.Write((byte)packet.ReasonCode.Value); propertiesWriter.WriteToPacket(packetWriter); @@ -372,8 +371,7 @@ namespace MQTTnet.Formatter.V5 } packetWriter.Write(packet.PacketIdentifier.Value); - packetWriter.Write((byte)packet.ReasonCode.Value); - + var propertiesWriter = new MqttV500PropertiesWriter(); if (packet.Properties != null) { @@ -381,7 +379,7 @@ namespace MQTTnet.Formatter.V5 propertiesWriter.WriteUserProperties(packet.Properties.UserProperties); } - if (packetWriter.Length > 0 || packet.ReasonCode.Value != MqttPubCompReasonCode.Success) + if (propertiesWriter.Length > 0 || packet.ReasonCode.Value != MqttPubCompReasonCode.Success) { packetWriter.Write((byte)packet.ReasonCode.Value); propertiesWriter.WriteToPacket(packetWriter); diff --git a/Source/MQTTnet/Formatter/V5/MqttV500PropertiesWriter.cs b/Source/MQTTnet/Formatter/V5/MqttV500PropertiesWriter.cs index 9e5fe39a..a7cb89f3 100644 --- a/Source/MQTTnet/Formatter/V5/MqttV500PropertiesWriter.cs +++ b/Source/MQTTnet/Formatter/V5/MqttV500PropertiesWriter.cs @@ -7,8 +7,11 @@ namespace MQTTnet.Formatter.V5 { public class MqttV500PropertiesWriter { + // TODO: Consider lazy init on first write to avoid useless allocations. private readonly MqttPacketWriter _packetWriter = new MqttPacketWriter(); + public int Length => _packetWriter.Length; + public void WriteUserProperties(List userProperties) { if (userProperties == null || userProperties.Count == 0) From 1a8bcae47cd2aa05a703bc89c9eaf331d4d2c0b8 Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Thu, 9 May 2019 22:08:56 +0200 Subject: [PATCH 4/5] Add authentication result to disconnected handler. --- Build/MQTTnet.nuspec | 1 + .../MqttClientDisconnectedEventArgs.cs | 6 +++++- Source/MQTTnet/Client/MqttClient.cs | 20 ++++++++++--------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index a7902e02..d3bd632d 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -13,6 +13,7 @@ * [Core] Fixed missing properties from PUBLISH packet in _MqttApplicationMessage_ (thanks to @pcbing). * [Core] Fixed wrong encoding of PUBREL and PUBCOMP packets for MQTTv5 (thanks to @perphilipp). +* [Client] Added the authentication result to the disconnected handler (only set when connecting failed). * [Server] Fixed a bug which returns wrong flag for existing session in CONNACK packet (thanks to @avengerstark). * [nuget] .NET Framework builds are now using 4.5.2 or 4.6.1 builds instead of netstandard 2.0. diff --git a/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectedEventArgs.cs b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectedEventArgs.cs index 7506042c..7658e157 100644 --- a/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectedEventArgs.cs +++ b/Source/MQTTnet/Client/Disconnecting/MqttClientDisconnectedEventArgs.cs @@ -1,17 +1,21 @@ using System; +using MQTTnet.Client.Connecting; namespace MQTTnet.Client.Disconnecting { public class MqttClientDisconnectedEventArgs : EventArgs { - public MqttClientDisconnectedEventArgs(bool clientWasConnected, Exception exception) + public MqttClientDisconnectedEventArgs(bool clientWasConnected, Exception exception, MqttClientAuthenticateResult authenticateResult) { ClientWasConnected = clientWasConnected; Exception = exception; + AuthenticateResult = authenticateResult; } public bool ClientWasConnected { get; } public Exception Exception { get; } + + public MqttClientAuthenticateResult AuthenticateResult { get; } } } diff --git a/Source/MQTTnet/Client/MqttClient.cs b/Source/MQTTnet/Client/MqttClient.cs index 10387bc7..8db55134 100644 --- a/Source/MQTTnet/Client/MqttClient.cs +++ b/Source/MQTTnet/Client/MqttClient.cs @@ -61,6 +61,8 @@ namespace MQTTnet.Client ThrowIfConnected("It is not allowed to connect with a server after the connection is established."); + MqttClientAuthenticateResult authenticateResult = null; + try { Options = options; @@ -81,7 +83,7 @@ namespace MQTTnet.Client _packetReceiverTask = Task.Run(() => TryReceivePacketsAsync(backgroundCancellationToken), backgroundCancellationToken); - var authenticateResult = await AuthenticateAsync(adapter, options.WillMessage, cancellationToken).ConfigureAwait(false); + authenticateResult = await AuthenticateAsync(adapter, options.WillMessage, cancellationToken).ConfigureAwait(false); _sendTracker.Restart(); @@ -108,7 +110,7 @@ namespace MQTTnet.Client if (!DisconnectIsPending()) { - await DisconnectInternalAsync(null, exception).ConfigureAwait(false); + await DisconnectInternalAsync(null, exception, authenticateResult).ConfigureAwait(false); } throw; @@ -131,7 +133,7 @@ namespace MQTTnet.Client { if (!DisconnectIsPending()) { - await DisconnectInternalAsync(null, null).ConfigureAwait(false); + await DisconnectInternalAsync(null, null, null).ConfigureAwait(false); } } } @@ -232,7 +234,7 @@ namespace MQTTnet.Client if (IsConnected) throw new MqttProtocolViolationException(message); } - private async Task DisconnectInternalAsync(Task sender, Exception exception) + private async Task DisconnectInternalAsync(Task sender, Exception exception, MqttClientAuthenticateResult authenticateResult) { var clientWasConnected = IsConnected; @@ -267,7 +269,7 @@ namespace MQTTnet.Client var disconnectedHandler = DisconnectedHandler; if (disconnectedHandler != null) { - await disconnectedHandler.HandleDisconnectedAsync(new MqttClientDisconnectedEventArgs(clientWasConnected, exception)).ConfigureAwait(false); + await disconnectedHandler.HandleDisconnectedAsync(new MqttClientDisconnectedEventArgs(clientWasConnected, exception, authenticateResult)).ConfigureAwait(false); } } } @@ -376,7 +378,7 @@ namespace MQTTnet.Client if (!DisconnectIsPending()) { - await DisconnectInternalAsync(_keepAlivePacketsSenderTask, exception).ConfigureAwait(false); + await DisconnectInternalAsync(_keepAlivePacketsSenderTask, exception, null).ConfigureAwait(false); } } finally @@ -404,7 +406,7 @@ namespace MQTTnet.Client { if (!DisconnectIsPending()) { - await DisconnectInternalAsync(_packetReceiverTask, null).ConfigureAwait(false); + await DisconnectInternalAsync(_packetReceiverTask, null, null).ConfigureAwait(false); } return; @@ -436,7 +438,7 @@ namespace MQTTnet.Client if (!DisconnectIsPending()) { - await DisconnectInternalAsync(_packetReceiverTask, exception).ConfigureAwait(false); + await DisconnectInternalAsync(_packetReceiverTask, exception, null).ConfigureAwait(false); } } finally @@ -497,7 +499,7 @@ namespace MQTTnet.Client if (!DisconnectIsPending()) { - await DisconnectInternalAsync(_packetReceiverTask, exception).ConfigureAwait(false); + await DisconnectInternalAsync(_packetReceiverTask, exception, null).ConfigureAwait(false); } } } From b02f30844c436ce5a7bf8e60116a8192861243ed Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Fri, 10 May 2019 21:55:46 +0200 Subject: [PATCH 5/5] Add new options for _MqttClientOptionsBuilder_. --- Build/MQTTnet.nuspec | 1 + .../Options/MqttClientOptionsBuilder.cs | 40 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index d3bd632d..28ac47c3 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -14,6 +14,7 @@ * [Core] Fixed missing properties from PUBLISH packet in _MqttApplicationMessage_ (thanks to @pcbing). * [Core] Fixed wrong encoding of PUBREL and PUBCOMP packets for MQTTv5 (thanks to @perphilipp). * [Client] Added the authentication result to the disconnected handler (only set when connecting failed). +* [Client] Added new overloads for _MqttClientOptionsBuilder_. * [Server] Fixed a bug which returns wrong flag for existing session in CONNACK packet (thanks to @avengerstark). * [nuget] .NET Framework builds are now using 4.5.2 or 4.6.1 builds instead of netstandard 2.0. diff --git a/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs b/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs index 20e008a3..c4d7e6cb 100644 --- a/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs +++ b/Source/MQTTnet/Client/Options/MqttClientOptionsBuilder.cs @@ -136,6 +136,16 @@ namespace MQTTnet.Client.Options return this; } + public MqttClientOptionsBuilder WithTcpServer(Action optionsBuilder) + { + if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder)); + + _tcpOptions = new MqttClientTcpOptions(); + optionsBuilder.Invoke(_tcpOptions); + + return this; + } + public MqttClientOptionsBuilder WithProxy(string address, string username = null, string password = null, string domain = null, bool bypassOnLocal = false, string[] bypassList = null) { _proxyOptions = new MqttClientWebSocketProxyOptions @@ -151,6 +161,15 @@ namespace MQTTnet.Client.Options return this; } + public MqttClientOptionsBuilder WithProxy(Action optionsBuilder) + { + if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder)); + + _proxyOptions = new MqttClientWebSocketProxyOptions(); + optionsBuilder(_proxyOptions); + return this; + } + public MqttClientOptionsBuilder WithWebSocketServer(string uri, MqttClientOptionsBuilderWebSocketParameters parameters = null) { _webSocketOptions = new MqttClientWebSocketOptions @@ -163,9 +182,19 @@ namespace MQTTnet.Client.Options return this; } + public MqttClientOptionsBuilder WithWebSocketServer(Action optionsBuilder) + { + if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder)); + + _webSocketOptions = new MqttClientWebSocketOptions(); + optionsBuilder.Invoke(_webSocketOptions); + + return this; + } + public MqttClientOptionsBuilder WithTls(MqttClientOptionsBuilderTlsParameters parameters) { - _tlsParameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); + _tlsParameters = parameters; return this; } @@ -174,6 +203,15 @@ namespace MQTTnet.Client.Options return WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = true }); } + public MqttClientOptionsBuilder WithTls(Action optionsBuilder) + { + if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder)); + + _tlsParameters = new MqttClientOptionsBuilderTlsParameters(); + optionsBuilder(_tlsParameters); + return this; + } + public IMqttClientOptions Build() { if (_tcpOptions == null && _webSocketOptions == null)