Skip to content

Commit cb38edc

Browse files
committed
Validate hostname in SocketFrameHandler to restore expectation that an exception will be thrown. Ugh.
1 parent ef39afb commit cb38edc

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

projects/RabbitMQ.Client/client/api/DefaultEndpointResolver.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ namespace RabbitMQ.Client
3737
{
3838
public class DefaultEndpointResolver : IEndpointResolver
3939
{
40+
#if !NET6_0_OR_GREATER
41+
private static readonly Random s_rnd = new Random();
42+
#endif
4043
private readonly List<AmqpTcpEndpoint> _endpoints;
41-
private readonly Random _rnd = new Random();
4244

4345
public DefaultEndpointResolver(IEnumerable<AmqpTcpEndpoint> tcpEndpoints)
4446
{
@@ -50,7 +52,7 @@ public IEnumerable<AmqpTcpEndpoint> All()
5052
#if NET6_0_OR_GREATER
5153
return _endpoints.OrderBy(item => Random.Shared.Next());
5254
#else
53-
return _endpoints.OrderBy(item => _rnd.Next());
55+
return _endpoints.OrderBy(item => s_rnd.Next());
5456
#endif
5557
}
5658
}

projects/RabbitMQ.Client/client/impl/SocketFrameHandler.cs

+12-5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace RabbitMQ.Client.Impl
4545
internal sealed class SocketFrameHandler : IFrameHandler
4646
{
4747
private readonly AmqpTcpEndpoint _amqpTcpEndpoint;
48+
private readonly IPAddress[] _amqpTcpEndpointAddresses;
4849
private readonly Func<AddressFamily, ITcpClient> _socketFactory;
4950
private readonly TimeSpan _connectionTimeout;
5051

@@ -74,6 +75,15 @@ public SocketFrameHandler(AmqpTcpEndpoint amqpTcpEndpoint,
7475
_readTimeout = readTimeout;
7576
_writeTimeout = writeTimeout;
7677

78+
/*
79+
* Resolve the hostname early to validate.
80+
* Used by SelectOne in EndpointResolverExtensions, which catches the thrown exception
81+
* if the hostname does not resolve. It's set up this way so that CreateFrameHandler captures
82+
* various configuration values when selecting a SocketFrameHandler for the Connection to use.
83+
* TODO this is not ideal, because it does not allow using Dns.GetHostAddressesAsync
84+
*/
85+
_amqpTcpEndpointAddresses = Dns.GetHostAddresses(_amqpTcpEndpoint.HostName);
86+
7787
var channel = Channel.CreateBounded<RentedMemory>(
7888
new BoundedChannelOptions(128)
7989
{
@@ -138,11 +148,8 @@ public TimeSpan WriteTimeout
138148

139149
public async Task ConnectAsync(CancellationToken cancellationToken)
140150
{
141-
// Resolve the hostname to know if it's even possible to even try IPv6
142151
// TODO cancellation token
143-
IPAddress[] adds = await Dns.GetHostAddressesAsync(_amqpTcpEndpoint.HostName)
144-
.ConfigureAwait(false);
145-
IPAddress ipv6 = TcpClientAdapter.GetMatchingHost(adds, AddressFamily.InterNetworkV6);
152+
IPAddress ipv6 = TcpClientAdapter.GetMatchingHost(_amqpTcpEndpointAddresses, AddressFamily.InterNetworkV6);
146153

147154
if (ipv6 == default(IPAddress))
148155
{
@@ -168,7 +175,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
168175

169176
if (_socket is null)
170177
{
171-
IPAddress ipv4 = TcpClientAdapter.GetMatchingHost(adds, AddressFamily.InterNetwork);
178+
IPAddress ipv4 = TcpClientAdapter.GetMatchingHost(_amqpTcpEndpointAddresses, AddressFamily.InterNetwork);
172179
if (ipv4 == default(IPAddress))
173180
{
174181
throw new ConnectFailureException("Connection failed", new ArgumentException($"No ip address could be resolved for {_amqpTcpEndpoint.HostName}"));

0 commit comments

Comments
 (0)