diff --git a/.github/workflows/ReleaseNotes.md b/.github/workflows/ReleaseNotes.md index 452829c95..aab7f1e86 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 c6421edb1..628b7b1fe 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.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 @@ public async Task Connect_Disconnect_Connect() await client.ConnectAsync(clientOptions); } } - + [TestMethod] [ExpectedException(typeof(InvalidOperationException))] public async Task Connect_Multiple_Times_Should_Fail() @@ -748,8 +749,8 @@ public async Task Send_Reply_In_Message_Handler() { 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 @@ public async Task Subscribe_With_QoS2() 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 4b6402cff..62f87eeb5 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 @@ public sealed class MqttClientTcpOptions : IMqttClientChannelOptions /// 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