Skip to content

Commit

Permalink
format ipv6 endpoints correctly (#2813)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgravell authored Oct 31, 2024
1 parent d7ca832 commit c8a7265
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 32 deletions.
15 changes: 14 additions & 1 deletion src/StackExchange.Redis/Format.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,20 @@ internal static string ToString(EndPoint? endpoint)
if (dns.Port == 0) return dns.Host;
return dns.Host + ":" + Format.ToString(dns.Port);
case IPEndPoint ip:
if (ip.Port == 0) return ip.Address.ToString();
var addr = ip.Address.ToString();

if (ip.Port == 0)
{
// no port specified; use naked IP
return addr;
}

if (addr.IndexOf(':') >= 0)
{
// ipv6 with port; use "[IP]:port" notation
return "[" + addr + "]:" + Format.ToString(ip.Port);
}
// ipv4 with port; use "IP:port" notation
return ip.Address + ":" + Format.ToString(ip.Port);
#if UNIX_SOCKET
case UnixDomainSocketEndPoint uds:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ public async Task CheckFailureRecovered()
{
using var conn = Create(keepAlive: 1, connectTimeout: 10000, allowAdmin: true, log: Writer, shared: false);

await RunBlockingSynchronousWithExtraThreadAsync(innerScenario).ForAwait();
void innerScenario()
await RunBlockingSynchronousWithExtraThreadAsync(InnerScenario).ForAwait();
void InnerScenario()
{
conn.GetDatabase();
var server = conn.GetServer(conn.GetEndPoints()[0]);
Expand Down
10 changes: 3 additions & 7 deletions tests/StackExchange.Redis.Tests/FailoverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,7 @@ public async Task SubscriptionsSurviveConnectionFailureAsync()
var sub = conn.GetSubscriber();
int counter = 0;
Assert.True(sub.IsConnected());
await sub.SubscribeAsync(channel, delegate
{
Interlocked.Increment(ref counter);
}).ConfigureAwait(false);
await sub.SubscribeAsync(channel, (arg1, arg2) => Interlocked.Increment(ref counter)).ConfigureAwait(false);

var profile1 = Log(profiler);

Expand Down Expand Up @@ -257,8 +254,7 @@ await sub.SubscribeAsync(channel, delegate

// Ensure we've sent the subscribe command after reconnecting
var profile2 = Log(profiler);
//Assert.Equal(1, profile2.Count(p => p.Command == nameof(RedisCommand.SUBSCRIBE)));

// Assert.Equal(1, profile2.Count(p => p.Command == nameof(RedisCommand.SUBSCRIBE)));
Log("Issuing ping after reconnected");
sub.Ping();

Expand Down Expand Up @@ -395,7 +391,7 @@ public async Task SubscriptionsSurvivePrimarySwitchAsync()
Log(" IsReplica: " + !server.IsReplica);
Log(" Type: " + server.ServerType);
}
//Skip.Inconclusive("Not enough latency.");
// Skip.Inconclusive("Not enough latency.");
}
Assert.True(sanityCheck, $"B Connection: {TestConfig.Current.FailoverPrimaryServerAndPort} should be a replica");
Assert.False(bConn.GetServer(TestConfig.Current.FailoverReplicaServerAndPort).IsReplica, $"B Connection: {TestConfig.Current.FailoverReplicaServerAndPort} should be a primary");
Expand Down
52 changes: 30 additions & 22 deletions tests/StackExchange.Redis.Tests/FormatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,46 @@ public class FormatTests : TestBase
{
public FormatTests(ITestOutputHelper output) : base(output) { }

public static IEnumerable<object[]> EndpointData()
public static IEnumerable<object?[]> EndpointData()
{
// note: the 3rd arg is for formatting; null means "expect the original string"

// DNS
yield return new object[] { "localhost", new DnsEndPoint("localhost", 0) };
yield return new object[] { "localhost:6390", new DnsEndPoint("localhost", 6390) };
yield return new object[] { "bob.the.builder.com", new DnsEndPoint("bob.the.builder.com", 0) };
yield return new object[] { "bob.the.builder.com:6390", new DnsEndPoint("bob.the.builder.com", 6390) };
yield return new object?[] { "localhost", new DnsEndPoint("localhost", 0), null };
yield return new object?[] { "localhost:6390", new DnsEndPoint("localhost", 6390), null };
yield return new object?[] { "bob.the.builder.com", new DnsEndPoint("bob.the.builder.com", 0), null };
yield return new object?[] { "bob.the.builder.com:6390", new DnsEndPoint("bob.the.builder.com", 6390), null };
// IPv4
yield return new object[] { "0.0.0.0", new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0) };
yield return new object[] { "127.0.0.1", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0) };
yield return new object[] { "127.1", new IPEndPoint(IPAddress.Parse("127.1"), 0) };
yield return new object[] { "127.1:6389", new IPEndPoint(IPAddress.Parse("127.1"), 6389) };
yield return new object[] { "127.0.0.1:6389", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6389) };
yield return new object[] { "127.0.0.1:1", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1) };
yield return new object[] { "127.0.0.1:2", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2) };
yield return new object[] { "10.10.9.18:2", new IPEndPoint(IPAddress.Parse("10.10.9.18"), 2) };
yield return new object?[] { "0.0.0.0", new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0), null };
yield return new object?[] { "127.0.0.1", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0), null };
yield return new object?[] { "127.1", new IPEndPoint(IPAddress.Parse("127.1"), 0), "127.0.0.1" };
yield return new object?[] { "127.1:6389", new IPEndPoint(IPAddress.Parse("127.1"), 6389), "127.0.0.1:6389" };
yield return new object?[] { "127.0.0.1:6389", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6389), null };
yield return new object?[] { "127.0.0.1:1", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1), null };
yield return new object?[] { "127.0.0.1:2", new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2), null };
yield return new object?[] { "10.10.9.18:2", new IPEndPoint(IPAddress.Parse("10.10.9.18"), 2), null };
// IPv6
yield return new object[] { "::1", new IPEndPoint(IPAddress.Parse("::1"), 0) };
yield return new object[] { "::1:6379", new IPEndPoint(IPAddress.Parse("::0.1.99.121"), 0) }; // remember your brackets!
yield return new object[] { "[::1]:6379", new IPEndPoint(IPAddress.Parse("::1"), 6379) };
yield return new object[] { "[::1]", new IPEndPoint(IPAddress.Parse("::1"), 0) };
yield return new object[] { "[::1]:1000", new IPEndPoint(IPAddress.Parse("::1"), 1000) };
yield return new object[] { "[2001:db7:85a3:8d2:1319:8a2e:370:7348]", new IPEndPoint(IPAddress.Parse("2001:db7:85a3:8d2:1319:8a2e:370:7348"), 0) };
yield return new object[] { "[2001:db7:85a3:8d2:1319:8a2e:370:7348]:1000", new IPEndPoint(IPAddress.Parse("2001:db7:85a3:8d2:1319:8a2e:370:7348"), 1000) };
yield return new object?[] { "::1", new IPEndPoint(IPAddress.Parse("::1"), 0), null };
yield return new object?[] { "::1:6379", new IPEndPoint(IPAddress.Parse("::0.1.99.121"), 0), "::0.1.99.121" }; // remember your brackets!
yield return new object?[] { "[::1]:6379", new IPEndPoint(IPAddress.Parse("::1"), 6379), null };
yield return new object?[] { "[::1]", new IPEndPoint(IPAddress.Parse("::1"), 0), "::1" };
yield return new object?[] { "[::1]:1000", new IPEndPoint(IPAddress.Parse("::1"), 1000), null };
yield return new object?[] { "2001:db7:85a3:8d2:1319:8a2e:370:7348", new IPEndPoint(IPAddress.Parse("2001:db7:85a3:8d2:1319:8a2e:370:7348"), 0), null };
yield return new object?[] { "[2001:db7:85a3:8d2:1319:8a2e:370:7348]", new IPEndPoint(IPAddress.Parse("2001:db7:85a3:8d2:1319:8a2e:370:7348"), 0), "2001:db7:85a3:8d2:1319:8a2e:370:7348" };
yield return new object?[] { "[2001:db7:85a3:8d2:1319:8a2e:370:7348]:1000", new IPEndPoint(IPAddress.Parse("2001:db7:85a3:8d2:1319:8a2e:370:7348"), 1000), null };
}

[Theory]
[MemberData(nameof(EndpointData))]
public void ParseEndPoint(string data, EndPoint expected)
public void ParseEndPoint(string data, EndPoint expected, string? expectedFormat)
{
_ = Format.TryParseEndPoint(data, out var result);
Assert.True(Format.TryParseEndPoint(data, out var result));
Assert.Equal(expected, result);

// and write again
var s = Format.ToString(result);
expectedFormat ??= data;
Assert.Equal(expectedFormat, s);
}

[Theory]
Expand Down

0 comments on commit c8a7265

Please sign in to comment.