diff --git a/src/NATS.Client/Conn.cs b/src/NATS.Client/Conn.cs
index 00ba028c3..f299f40bc 100644
--- a/src/NATS.Client/Conn.cs
+++ b/src/NATS.Client/Conn.cs
@@ -18,6 +18,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
@@ -987,6 +988,27 @@ public string ConnectedUrl
}
}
+ ///
+ /// Gets the IP of client as known by the NATS server, otherwise null.
+ ///
+ ///
+ /// Supported in the NATS server version 2.1.6 and above. If the client is connected to
+ /// an older server or is in the process of connecting, null will be returned.
+ ///
+ public IPAddress ClientIP
+ {
+ get
+ {
+ string clientIp;
+ lock (mu)
+ {
+ clientIp = info.client_ip;
+ }
+
+ return !String.IsNullOrEmpty(clientIp) ? IPAddress.Parse(clientIp) : null;
+ }
+ }
+
///
/// Gets the server ID of the NATS server to which this instance
/// is connected, otherwise null.
diff --git a/src/NATS.Client/IConnection.cs b/src/NATS.Client/IConnection.cs
index 22ef52da1..41b34d3c0 100644
--- a/src/NATS.Client/IConnection.cs
+++ b/src/NATS.Client/IConnection.cs
@@ -12,6 +12,7 @@
// limitations under the License.
using System;
+using System.Net;
using System.Threading;
using System.Threading.Tasks;
@@ -27,6 +28,15 @@ public interface IConnection : IDisposable
///
Options Opts { get; }
+ ///
+ /// Gets the IP of client as known by the NATS server, otherwise null.
+ ///
+ ///
+ /// Supported in the NATS server version 2.1.6 and above. If the client is connected to
+ /// an older server or is in the process of connecting, null will be returned.
+ ///
+ IPAddress ClientIP { get; }
+
///
/// Gets the URL of the NATS server to which this instance
/// is connected, otherwise null.
diff --git a/src/NATS.Client/Info.cs b/src/NATS.Client/Info.cs
index 5ec4a7a84..fe43e1624 100644
--- a/src/NATS.Client/Info.cs
+++ b/src/NATS.Client/Info.cs
@@ -21,6 +21,8 @@ internal class ServerInfo
{
public string server_id { get; private set; }
+ public string client_ip { get; private set; }
+
public string host { get; private set; }
public int port { get; private set; }
@@ -46,6 +48,7 @@ public static ServerInfo CreateFromJson(string json)
return new ServerInfo
{
server_id = x["server_id"].Value,
+ client_ip = x["client_ip"].Value,
host = x["host"].Value,
port = x["port"].AsInt,
version = x["version"].Value,
diff --git a/src/Tests/IntegrationTests/TestConnection.cs b/src/Tests/IntegrationTests/TestConnection.cs
index f154951c7..6c9dc0b51 100644
--- a/src/Tests/IntegrationTests/TestConnection.cs
+++ b/src/Tests/IntegrationTests/TestConnection.cs
@@ -116,14 +116,14 @@ public void TestErrorHandlerWhenNotAllowingReconnectErrorShouldBeProvided()
opts.AllowReconnect = false;
opts.ClosedEventHandler = (sender, args) =>
{
- if(args.Error != null)
+ if (args.Error != null)
errors.Enqueue(args.Error);
closedEv.Set();
};
opts.DisconnectedEventHandler = (sender, args) =>
{
- if(args.Error != null)
+ if (args.Error != null)
errors.Enqueue(args.Error);
disconEv.Set();
@@ -154,21 +154,21 @@ public void TestErrorHandlerWhenAllowingReconnectErrorShouldNotBeProvided()
opts.MaxReconnect = 1;
opts.ClosedEventHandler = (sender, args) =>
{
- if(args.Error != null)
+ if (args.Error != null)
errors.Enqueue(args.Error);
closedEv.Set();
};
opts.DisconnectedEventHandler = (sender, args) =>
{
- if(args.Error != null)
+ if (args.Error != null)
errors.Enqueue(args.Error);
disconEv.Set();
};
opts.ReconnectedEventHandler = (sender, args) =>
{
- if(args.Error != null)
+ if (args.Error != null)
errors.Enqueue(args.Error);
reconEv.Set();
@@ -220,7 +220,7 @@ public void TestClosedConnections()
{
using (var c = Context.OpenConnection(Context.Server1.Port))
{
- using(var s = c.SubscribeSync("foo"))
+ using (var s = c.SubscribeSync("foo"))
{
c.Close();
@@ -260,7 +260,7 @@ public void TestConnectVerbose()
var o = Context.GetTestOptions(Context.Server1.Port);
o.Verbose = true;
- using(var c = Context.ConnectionFactory.CreateConnection(o))
+ using (var c = Context.ConnectionFactory.CreateConnection(o))
c.Close();
}
}
@@ -279,7 +279,7 @@ public void TestServerDiscoveredHandlerNotCalledOnConnect()
serverDiscoveredCalled = true;
};
- using(var c = Context.ConnectionFactory.CreateConnection(o))
+ using (var c = Context.ConnectionFactory.CreateConnection(o))
c.Close();
Assert.False(serverDiscoveredCalled);
@@ -303,12 +303,12 @@ public void TestCallbacksOrder()
long ctime = orig;
AutoResetEvent reconnected = new AutoResetEvent(false);
- AutoResetEvent closed = new AutoResetEvent(false);
- AutoResetEvent asyncErr1 = new AutoResetEvent(false);
- AutoResetEvent asyncErr2 = new AutoResetEvent(false);
- AutoResetEvent recvCh = new AutoResetEvent(false);
- AutoResetEvent recvCh1 = new AutoResetEvent(false);
- AutoResetEvent recvCh2 = new AutoResetEvent(false);
+ AutoResetEvent closed = new AutoResetEvent(false);
+ AutoResetEvent asyncErr1 = new AutoResetEvent(false);
+ AutoResetEvent asyncErr2 = new AutoResetEvent(false);
+ AutoResetEvent recvCh = new AutoResetEvent(false);
+ AutoResetEvent recvCh1 = new AutoResetEvent(false);
+ AutoResetEvent recvCh2 = new AutoResetEvent(false);
using (NATSServer
serverAuth = NATSServer.CreateWithConfig(Context.Server1.Port, "auth.conf"),
@@ -360,7 +360,7 @@ public void TestCallbacksOrder()
o.ReconnectWait = 500;
o.NoRandomize = true;
- o.Servers = new [] { Context.Server2.Url, Context.Server1.Url };
+ o.Servers = new[] { Context.Server2.Url, Context.Server1.Url };
o.SubChannelLength = 1;
using (IConnection
@@ -450,7 +450,7 @@ public void TestCallbacksOrder()
}
}
}
-
+
[Fact]
public void TestConnectionCloseAndDispose()
{
@@ -506,7 +506,7 @@ public void TestInfineReconnect()
{
var reconnectEv = new AutoResetEvent(false);
var closedEv = new AutoResetEvent(false);
-
+
var opts = Context.GetTestOptionsWithDefaultTimeout(Context.Server1.Port);
opts.Timeout = 500;
@@ -571,8 +571,18 @@ public void CanConnectWhenHandshakeTimeoutIsSpecified()
}
}
- /// NOT IMPLEMENTED:
- /// TestErrOnMaxPayloadLimit
+ [Fact]
+ [Trait("Category", "NATS 2.1.6+")]
+ public void TestClientIP()
+ {
+ IConnection conn;
+ using (NATSServer.CreateFastAndVerify(Context.Server1.Port))
+ {
+ conn = Context.ConnectionFactory.CreateConnection("nats://127.0.0.1:" + Context.Server1.Port);
+ Assert.Equal(conn.ClientIP.MapToIPv4(), System.Net.IPAddress.Parse("127.0.0.1"));
+ conn.Close();
+ }
+ }
}
public class TestConnectionSecurity : TestSuite
@@ -779,12 +789,6 @@ public void TestUserPassTokenOptions()
Assert.Throws(() => Context.ConnectionFactory.CreateConnection(opts));
}
}
-
- [Fact(Skip = "WorkInProgress")]
- public void TestJwtFunctionality()
- {
- //using (NATSServer.CreateFastAndVerify(Context.Server1.Port)) { }
- }
}
public class TestConnectionDrain : TestSuite