Skip to content

Commit

Permalink
Add ClientIP Connection property (#374)
Browse files Browse the repository at this point in the history
* Add ClientIP Connection property

Signed-off-by: Colin Sullivan <[email protected]>

Co-authored-by: Christopher Watford <[email protected]>
  • Loading branch information
ColinSullivan1 and watfordgnf authored May 4, 2020
1 parent a99ae1d commit b41cc30
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 25 deletions.
22 changes: 22 additions & 0 deletions src/NATS.Client/Conn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -987,6 +988,27 @@ public string ConnectedUrl
}
}

/// <summary>
/// Gets the IP of client as known by the NATS server, otherwise <c>null</c>.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public IPAddress ClientIP
{
get
{
string clientIp;
lock (mu)
{
clientIp = info.client_ip;
}

return !String.IsNullOrEmpty(clientIp) ? IPAddress.Parse(clientIp) : null;
}
}

/// <summary>
/// Gets the server ID of the NATS server to which this instance
/// is connected, otherwise <c>null</c>.
Expand Down
10 changes: 10 additions & 0 deletions src/NATS.Client/IConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.

using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -27,6 +28,15 @@ public interface IConnection : IDisposable
/// </summary>
Options Opts { get; }

/// <summary>
/// Gets the IP of client as known by the NATS server, otherwise <c>null</c>.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
IPAddress ClientIP { get; }

/// <summary>
/// Gets the URL of the NATS server to which this instance
/// is connected, otherwise <c>null</c>.
Expand Down
3 changes: 3 additions & 0 deletions src/NATS.Client/Info.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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,
Expand Down
54 changes: 29 additions & 25 deletions src/Tests/IntegrationTests/TestConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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();
}
}
Expand All @@ -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);
Expand All @@ -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"),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -450,7 +450,7 @@ public void TestCallbacksOrder()
}
}
}

[Fact]
public void TestConnectionCloseAndDispose()
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<ConnectionSecuritySuiteContext>
Expand Down Expand Up @@ -779,12 +789,6 @@ public void TestUserPassTokenOptions()
Assert.Throws<NATSConnectionException>(() => Context.ConnectionFactory.CreateConnection(opts));
}
}

[Fact(Skip = "WorkInProgress")]
public void TestJwtFunctionality()
{
//using (NATSServer.CreateFastAndVerify(Context.Server1.Port)) { }
}
}

public class TestConnectionDrain : TestSuite<ConnectionDrainSuiteContext>
Expand Down

0 comments on commit b41cc30

Please sign in to comment.