From 25c1da6a213b91a536ce7b7ed26f3ffe39e61ca3 Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Thu, 23 May 2024 19:32:22 +0200 Subject: [PATCH] Restore behavior of _Server_ and _Port_ in client options (#2009) * Restore old server and port behavior * Fix unit test --- .github/workflows/ReleaseNotes.md | 3 +- .../Clients/MqttClient/MqttClient_Tests.cs | 56 ++++++++++++++++++- .../Client/Options/MqttClientTcpOptions.cs | 49 +++++++++++++++- 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ReleaseNotes.md b/.github/workflows/ReleaseNotes.md index 452829c9..aab7f1e8 100644 --- a/.github/workflows/ReleaseNotes.md +++ b/.github/workflows/ReleaseNotes.md @@ -1,2 +1 @@ -* [Client] Fix _None of the discovered or specified addresses match the socket address family._ (#1997). -* [Client] Remove the obsolete attribute from the _WithConnectionUri_ methods (#1979). +* [Client] Restored _Server_ and _Port_ behavior of client options (#2005). diff --git a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs index c6421edb..628b7b1f 100644 --- a/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs +++ b/Source/MQTTnet.Tests/Clients/MqttClient/MqttClient_Tests.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; @@ -86,7 +87,7 @@ namespace MQTTnet.Tests.Clients.MqttClient await client.ConnectAsync(clientOptions); } } - + [TestMethod] [ExpectedException(typeof(InvalidOperationException))] public async Task Connect_Multiple_Times_Should_Fail() @@ -748,8 +749,8 @@ namespace MQTTnet.Tests.Clients.MqttClient { if (e.ApplicationMessage.Topic == "request") { - // Use AtMostOnce here because with QoS 1 or even QoS 2 the process waits for - // the ACK etc. The problem is that the SpinUntil below only waits until the + // Use AtMostOnce here because with QoS 1 or even QoS 2 the process waits for + // the ACK etc. The problem is that the SpinUntil below only waits until the // flag is set. It does not wait until the client has sent the ACK await client2.PublishStringAsync("reply"); } @@ -925,5 +926,54 @@ namespace MQTTnet.Tests.Clients.MqttClient Assert.IsFalse(disconnectedFired); } } + + [TestMethod] + public void Backward_compatible_TCP_options() + { + var options = new MqttClientOptionsBuilder().WithTcpServer("host", 3).Build(); + + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port); + + options = new MqttClientOptions + { + ChannelOptions = new MqttClientTcpOptions + { + Server = "host", + Port = 3 + } + }; + + Assert.AreEqual("host:3", options.ChannelOptions.ToString()); + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port); + + options = new MqttClientOptionsBuilder().WithEndPoint(new DnsEndPoint("host", 3)).Build(); + Assert.AreEqual("Unspecified/host:3", options.ChannelOptions.ToString()); + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(3, ((MqttClientTcpOptions)options.ChannelOptions).Port); + + options = new MqttClientOptionsBuilder().WithTcpServer("host").Build(); + + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(1883, ((MqttClientTcpOptions)options.ChannelOptions).Port); + Assert.AreEqual("Unspecified/host:1883", options.ChannelOptions.ToString()); + + options = new MqttClientOptionsBuilder().WithTlsOptions(o => o.UseTls()).WithTcpServer("host").Build(); + + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(8883, ((MqttClientTcpOptions)options.ChannelOptions).Port); + + options = new MqttClientOptions + { + ChannelOptions = new MqttClientTcpOptions + { + Server = "host" + } + }; + + Assert.AreEqual("host", ((MqttClientTcpOptions)options.ChannelOptions).Server); + Assert.AreEqual(null, ((MqttClientTcpOptions)options.ChannelOptions).Port); + } } } \ No newline at end of file diff --git a/Source/MQTTnet/Client/Options/MqttClientTcpOptions.cs b/Source/MQTTnet/Client/Options/MqttClientTcpOptions.cs index 4b6402cf..62f87eeb 100644 --- a/Source/MQTTnet/Client/Options/MqttClientTcpOptions.cs +++ b/Source/MQTTnet/Client/Options/MqttClientTcpOptions.cs @@ -5,11 +5,13 @@ using System; using System.Net; using System.Net.Sockets; +using MQTTnet.Protocol; namespace MQTTnet.Client { public sealed class MqttClientTcpOptions : IMqttClientChannelOptions { + EndPoint _remoteEndpoint; public AddressFamily AddressFamily { get; set; } = AddressFamily.Unspecified; public int BufferSize { get; set; } = 8192; @@ -49,13 +51,56 @@ namespace MQTTnet.Client /// public ProtocolType ProtocolType { get; set; } = ProtocolType.Tcp; - public EndPoint RemoteEndpoint { get; set; } + public EndPoint RemoteEndpoint + { + get => _remoteEndpoint; + set + { + _remoteEndpoint = value; + + if (_remoteEndpoint is DnsEndPoint dnsEndPoint) + { + Server = dnsEndPoint.Host; + Port = dnsEndPoint.Port; + } + else if (_remoteEndpoint is IPEndPoint ipEndPoint) + { + Server = ipEndPoint.Address.ToString(); + Port = ipEndPoint.Port; + } + } + } public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions(); public override string ToString() { - return RemoteEndpoint?.ToString() ?? string.Empty; + if (RemoteEndpoint != null) + { + return RemoteEndpoint.ToString(); + } + + if (!string.IsNullOrEmpty(Server)) + { + return $"{Server}:{GetPort()}"; + } + + return string.Empty; + } + + int GetPort() + { + if (Port.HasValue) + { + return Port.Value; + } + + if (TlsOptions?.UseTls == true) + { + return MqttPorts.Secure; + } + + return MqttPorts.Default; } } } \ No newline at end of file