From 103e884160a9b02451ee9baa2eabd896965a795f Mon Sep 17 00:00:00 2001 From: jasperd Date: Tue, 9 Feb 2021 01:21:18 +0100 Subject: [PATCH 1/6] Fix ipv4 support - Throw NATSConnectionException w/ original socket exception as inner ex --- src/NATS.Client/Conn.cs | 26 +++++++++++-------- src/NATS.sln | 7 ++++++ src/Samples/IpTests/IpTests.csproj | 12 +++++++++ src/Samples/IpTests/Program.cs | 40 ++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 src/Samples/IpTests/IpTests.csproj create mode 100644 src/Samples/IpTests/Program.cs diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs index 3977d8ac9..a99efb964 100644 --- a/src/NATS.Client/Conn.cs +++ b/src/NATS.Client/Conn.cs @@ -25,6 +25,7 @@ using System.Security.Authentication; using System.Globalization; using System.Diagnostics; +using System.Runtime.ExceptionServices; using NATS.Client.Internals; namespace NATS.Client @@ -377,8 +378,10 @@ internal void open(Srv s, int timeoutMillis) sslStream = null; } - client = new TcpClient(AddressFamily.InterNetworkV6); - client.Client.DualMode = true; + client = new TcpClient(Socket.OSSupportsIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork); + if(Socket.OSSupportsIPv6) + client.Client.DualMode = true; + var task = client.ConnectAsync(s.url.Host, s.url.Port); // avoid raising TaskScheduler.UnobservedTaskException if the timeout occurs first task.ContinueWith(t => GC.KeepAlive(t.Exception), TaskContinuationOptions.OnlyOnFaulted); @@ -389,6 +392,8 @@ internal void open(Srv s, int timeoutMillis) throw new NATSConnectionException("timeout"); } + Debug.Assert(client.Client.IsBound, "Socket not bound"); + client.NoDelay = false; client.ReceiveBufferSize = Defaults.defaultBufSize*2; @@ -811,8 +816,9 @@ private void setupServerPool() // createConn will connect to the server and wrap the appropriate // bufio structures. It will do the right thing when an existing // connection is in place. - private bool createConn(Srv s) + private bool createConn(Srv s, out Exception ex) { + ex = null; try { conn.open(s, opts.Timeout); @@ -832,8 +838,9 @@ private bool createConn(Srv s) bw = conn.getWriteBufferedStream(Defaults.defaultBufSize); br = conn.getReadBufferedStream(); } - catch (Exception) + catch (Exception e) { + ex = e; return false; } @@ -1120,7 +1127,7 @@ internal bool connect(Srv s, out Exception exToThrow) { lock (mu) { - if (!createConn(s)) + if (!createConn(s, out exToThrow)) return false; processConnectInit(s); @@ -1175,10 +1182,9 @@ internal void connect() { if (status != ConnState.CONNECTED) { - if (exToThrow == null) - exToThrow = new NATSNoServersException("Unable to connect to a server."); - - throw exToThrow; + if (exToThrow != null) + throw new NATSConnectionException("Failed to connect", exToThrow); + throw new NATSNoServersException("Unable to connect to a server."); } } } @@ -1617,7 +1623,7 @@ private void doReconnect() try { // try to create a new connection - if(!createConn(cur)) + if(!createConn(cur, out lastEx)) continue; } catch (Exception) diff --git a/src/NATS.sln b/src/NATS.sln index 0aa19f0af..e4d774402 100644 --- a/src/NATS.sln +++ b/src/NATS.sln @@ -38,6 +38,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroBenchmarks", "Benchmar EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{A4CB6D96-6357-40DC-B198-50568A7E45C7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IpTests", "Samples\IpTests\IpTests.csproj", "{8A5515F9-199C-4E1D-BF90-85EF74998B52}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -92,6 +94,10 @@ Global {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Release|Any CPU.Build.0 = Release|Any CPU + {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -108,6 +114,7 @@ Global {C21CBF59-9884-436C-8A24-0248F8598979} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} {10ED0146-1701-4BC9-9E26-824B22D18CB8} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} {8D181EED-3FF7-4CC0-9C85-331EF20B7688} = {A4CB6D96-6357-40DC-B198-50568A7E45C7} + {8A5515F9-199C-4E1D-BF90-85EF74998B52} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0972F03C-E4DF-483A-B767-9216F4434F11} diff --git a/src/Samples/IpTests/IpTests.csproj b/src/Samples/IpTests/IpTests.csproj new file mode 100644 index 000000000..fdbbb48ef --- /dev/null +++ b/src/Samples/IpTests/IpTests.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Samples/IpTests/Program.cs b/src/Samples/IpTests/Program.cs new file mode 100644 index 000000000..2902817ba --- /dev/null +++ b/src/Samples/IpTests/Program.cs @@ -0,0 +1,40 @@ +using System; +using System.Net.Sockets; +using System.Text; +using NATS.Client; + +namespace IpTests +{ + class Program + { + static void Main(string[] args) + { + string uri = "nats://localhost:4222"; + if (args.Length == 1) + { + uri = args[0]; + } + + Console.WriteLine($"IPv6 supported: {Socket.OSSupportsIPv6}"); + + var options = ConnectionFactory.GetDefaultOptions(); + options.Url = uri; + + Console.WriteLine($"Attempting to connect to {uri}"); + + try + { + var conn = new ConnectionFactory().CreateConnection(options); + conn.Publish("foo", Encoding.ASCII.GetBytes("Hello World!")); + conn.Flush(100); + Console.WriteLine("Connected! 🙂"); + } + catch (Exception ex) + { + Console.WriteLine("That didn't work 😞"); + Console.WriteLine($"{ex.ToString()}"); + } + + } + } +} From 15cf100b7ca8be3caa92d13e8cc5e24b7616033d Mon Sep 17 00:00:00 2001 From: Jasper Date: Mon, 15 Feb 2021 20:14:52 +0100 Subject: [PATCH 2/6] Delete test app --- src/NATS.sln | 7 ------ src/Samples/IpTests/IpTests.csproj | 12 --------- src/Samples/IpTests/Program.cs | 40 ------------------------------ 3 files changed, 59 deletions(-) delete mode 100644 src/Samples/IpTests/IpTests.csproj delete mode 100644 src/Samples/IpTests/Program.cs diff --git a/src/NATS.sln b/src/NATS.sln index e4d774402..0aa19f0af 100644 --- a/src/NATS.sln +++ b/src/NATS.sln @@ -38,8 +38,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroBenchmarks", "Benchmar EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{A4CB6D96-6357-40DC-B198-50568A7E45C7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IpTests", "Samples\IpTests\IpTests.csproj", "{8A5515F9-199C-4E1D-BF90-85EF74998B52}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -94,10 +92,6 @@ Global {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D181EED-3FF7-4CC0-9C85-331EF20B7688}.Release|Any CPU.Build.0 = Release|Any CPU - {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A5515F9-199C-4E1D-BF90-85EF74998B52}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -114,7 +108,6 @@ Global {C21CBF59-9884-436C-8A24-0248F8598979} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} {10ED0146-1701-4BC9-9E26-824B22D18CB8} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} {8D181EED-3FF7-4CC0-9C85-331EF20B7688} = {A4CB6D96-6357-40DC-B198-50568A7E45C7} - {8A5515F9-199C-4E1D-BF90-85EF74998B52} = {776C2E80-958B-4C0D-BCC4-67D39DB4570B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0972F03C-E4DF-483A-B767-9216F4434F11} diff --git a/src/Samples/IpTests/IpTests.csproj b/src/Samples/IpTests/IpTests.csproj deleted file mode 100644 index fdbbb48ef..000000000 --- a/src/Samples/IpTests/IpTests.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - Exe - netcoreapp3.1 - - - - - - - diff --git a/src/Samples/IpTests/Program.cs b/src/Samples/IpTests/Program.cs deleted file mode 100644 index 2902817ba..000000000 --- a/src/Samples/IpTests/Program.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Net.Sockets; -using System.Text; -using NATS.Client; - -namespace IpTests -{ - class Program - { - static void Main(string[] args) - { - string uri = "nats://localhost:4222"; - if (args.Length == 1) - { - uri = args[0]; - } - - Console.WriteLine($"IPv6 supported: {Socket.OSSupportsIPv6}"); - - var options = ConnectionFactory.GetDefaultOptions(); - options.Url = uri; - - Console.WriteLine($"Attempting to connect to {uri}"); - - try - { - var conn = new ConnectionFactory().CreateConnection(options); - conn.Publish("foo", Encoding.ASCII.GetBytes("Hello World!")); - conn.Flush(100); - Console.WriteLine("Connected! 🙂"); - } - catch (Exception ex) - { - Console.WriteLine("That didn't work 😞"); - Console.WriteLine($"{ex.ToString()}"); - } - - } - } -} From 3071945a1775ff128262c5b052cebb587a83db0a Mon Sep 17 00:00:00 2001 From: jasperd Date: Mon, 15 Feb 2021 20:30:45 +0100 Subject: [PATCH 3/6] Fix tests --- src/NATS.Client/Conn.cs | 2 ++ src/Tests/IntegrationTests/TestBasic.cs | 5 ++++- src/Tests/IntegrationTests/TestCluster.cs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs index a99efb964..d6ee09b9b 100644 --- a/src/NATS.Client/Conn.cs +++ b/src/NATS.Client/Conn.cs @@ -1182,6 +1182,8 @@ internal void connect() { if (status != ConnState.CONNECTED) { + if (exToThrow is NATSException) + throw exToThrow; if (exToThrow != null) throw new NATSConnectionException("Failed to connect", exToThrow); throw new NATSNoServersException("Unable to connect to a server."); diff --git a/src/Tests/IntegrationTests/TestBasic.cs b/src/Tests/IntegrationTests/TestBasic.cs index 0286b6155..0d5addbe3 100644 --- a/src/Tests/IntegrationTests/TestBasic.cs +++ b/src/Tests/IntegrationTests/TestBasic.cs @@ -1962,7 +1962,10 @@ public void TestNoEcho() [Fact] public void TestServersOption() { - Assert.ThrowsAny(() => Context.ConnectionFactory.CreateConnection()); + var exception = Record.Exception(() => Context.ConnectionFactory.CreateConnection()); + + Assert.IsType(exception); + Assert.Equal("timeout", exception.Message); } /// diff --git a/src/Tests/IntegrationTests/TestCluster.cs b/src/Tests/IntegrationTests/TestCluster.cs index 32110b631..72f3ff3b1 100644 --- a/src/Tests/IntegrationTests/TestCluster.cs +++ b/src/Tests/IntegrationTests/TestCluster.cs @@ -36,7 +36,7 @@ public void TestServersOption() o.NoRandomize = true; o.Servers = Context.GetTestServersUrls(); - Assert.ThrowsAny(() => cf.CreateConnection(o)); + Assert.ThrowsAny(() => cf.CreateConnection(o)); // Make sure we can connect to first server if running using (NATSServer ns = NATSServer.Create(Context.Server1.Port)) From e23ffef14af06fa1a6f1f47fb1b6e57d69a5ddf5 Mon Sep 17 00:00:00 2001 From: jasperd Date: Mon, 15 Feb 2021 21:33:37 +0100 Subject: [PATCH 4/6] Remove assertion --- src/NATS.Client/Conn.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs index d6ee09b9b..6ffb4e88b 100644 --- a/src/NATS.Client/Conn.cs +++ b/src/NATS.Client/Conn.cs @@ -392,8 +392,6 @@ internal void open(Srv s, int timeoutMillis) throw new NATSConnectionException("timeout"); } - Debug.Assert(client.Client.IsBound, "Socket not bound"); - client.NoDelay = false; client.ReceiveBufferSize = Defaults.defaultBufSize*2; From 4c8f05bae4bd50f640a0ff316acac5eb5d4db6cb Mon Sep 17 00:00:00 2001 From: jasperd Date: Mon, 15 Feb 2021 21:34:29 +0100 Subject: [PATCH 5/6] Remove superfluous using directive --- src/NATS.Client/Conn.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs index 6ffb4e88b..9e25c4e09 100644 --- a/src/NATS.Client/Conn.cs +++ b/src/NATS.Client/Conn.cs @@ -25,7 +25,6 @@ using System.Security.Authentication; using System.Globalization; using System.Diagnostics; -using System.Runtime.ExceptionServices; using NATS.Client.Internals; namespace NATS.Client From d563bd4518335a95bf12822ef716e53a996e6dea Mon Sep 17 00:00:00 2001 From: Jasper Date: Tue, 16 Feb 2021 20:05:46 +0100 Subject: [PATCH 6/6] Fix whitespace Co-authored-by: Christopher Watford --- src/NATS.Client/Conn.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs index 9e25c4e09..73d539081 100644 --- a/src/NATS.Client/Conn.cs +++ b/src/NATS.Client/Conn.cs @@ -378,7 +378,7 @@ internal void open(Srv s, int timeoutMillis) } client = new TcpClient(Socket.OSSupportsIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork); - if(Socket.OSSupportsIPv6) + if (Socket.OSSupportsIPv6) client.Client.DualMode = true; var task = client.ConnectAsync(s.url.Host, s.url.Port);