Skip to content

Commit 9d17f7f

Browse files
committed
Use correct hostname when cancelling query. Fixes #1514
Connect directly to the cancelled command's session's IP address but maintain the hostname for SSL certificate validation. Signed-off-by: Bradley Grainger <[email protected]>
1 parent f74ce0b commit 9d17f7f

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

src/MySqlConnector/Core/ConnectionSettings.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if NETCOREAPP3_0_OR_GREATER
22
using System.Net.Security;
33
#endif
4+
using System.Net;
45
using System.Security.Authentication;
56
using MySqlConnector.Utilities;
67

@@ -150,7 +151,9 @@ public ConnectionSettings(MySqlConnectionStringBuilder csb)
150151
static int ToSigned(uint value) => value >= int.MaxValue ? int.MaxValue : (int) value;
151152
}
152153

153-
public ConnectionSettings CloneWith(string host, int port, string userId) => new(this, host, port, userId);
154+
public ConnectionSettings CloneWith(string host, int port, string userId) => new(this, host, port, userId, null);
155+
156+
public ConnectionSettings CloneWith(IPAddress ipAddress) => new(this, HostNames![0], Port, UserID, ipAddress);
154157

155158
private static MySqlGuidFormat GetEffectiveGuidFormat(MySqlGuidFormat guidFormat, bool oldGuids)
156159
{
@@ -182,6 +185,7 @@ private static MySqlGuidFormat GetEffectiveGuidFormat(MySqlGuidFormat guidFormat
182185
public string ConnectionString { get; }
183186
public MySqlConnectionProtocol ConnectionProtocol { get; }
184187
public IReadOnlyList<string>? HostNames { get; }
188+
public IPAddress? IPAddress { get; }
185189
public MySqlLoadBalance LoadBalance { get; }
186190
public int Port { get; }
187191
public string PipeName { get; }
@@ -268,17 +272,18 @@ public int ConnectionTimeoutMilliseconds
268272
}
269273
}
270274

271-
private ConnectionSettings(ConnectionSettings other, string host, int port, string userId)
275+
private ConnectionSettings(ConnectionSettings other, string host, int port, string userId, IPAddress? ipAddress)
272276
{
273277
ConnectionStringBuilder = new MySqlConnectionStringBuilder(other.ConnectionString);
274-
ConnectionStringBuilder.Port = (uint)port;
278+
ConnectionStringBuilder.Port = (uint) port;
275279
ConnectionStringBuilder.Server = host;
276280
ConnectionStringBuilder.UserID = userId;
277281

278282
ConnectionString = ConnectionStringBuilder.ConnectionString;
279283

280284
ConnectionProtocol = MySqlConnectionProtocol.Sockets;
281285
HostNames = [host];
286+
IPAddress = ipAddress;
282287
LoadBalance = other.LoadBalance;
283288
Port = port;
284289
PipeName = other.PipeName;

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,13 +1164,20 @@ private async Task<bool> OpenTcpSocketAsync(ConnectionSettings cs, ILoadBalancer
11641164
IPAddress[] ipAddresses;
11651165
try
11661166
{
1167-
ipAddresses = ioBehavior == IOBehavior.Asynchronous
1167+
if (cs.IPAddress is { } ipAddress)
1168+
{
1169+
ipAddresses = [ipAddress];
1170+
}
1171+
else
1172+
{
1173+
ipAddresses = ioBehavior == IOBehavior.Asynchronous
11681174
#if NET6_0_OR_GREATER
1169-
? await Dns.GetHostAddressesAsync(hostName, cancellationToken).ConfigureAwait(false)
1175+
? await Dns.GetHostAddressesAsync(hostName, cancellationToken).ConfigureAwait(false)
11701176
#else
1171-
? await Dns.GetHostAddressesAsync(hostName).ConfigureAwait(false)
1177+
? await Dns.GetHostAddressesAsync(hostName).ConfigureAwait(false)
11721178
#endif
1173-
: Dns.GetHostAddresses(hostName);
1179+
: Dns.GetHostAddresses(hostName);
1180+
}
11741181
}
11751182
catch (SocketException ex)
11761183
{

src/MySqlConnector/MySqlConnection.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,16 +896,27 @@ internal void Cancel(ICancellableCommand command, int commandId, bool isCancel)
896896
AutoEnlist = false,
897897
Pooling = false,
898898
};
899-
if (session.IPEndPoint is { Address: { } ipAddress, Port: { } port })
899+
900+
// connect directly to the session's IP address to ensure we're cancelling the query on the right server (in a load-balanced scenario)
901+
IPAddress? ipAddress = null;
902+
if (session.IPEndPoint is { Address: { } sessionIpAddress, Port: { } port })
900903
{
901-
csb.Server = ipAddress.ToString();
904+
// set the hostname to the existing session's hostname (for SSL validation)
905+
csb.Server = session.HostName;
902906
csb.Port = (uint) port;
907+
ipAddress = sessionIpAddress;
903908
}
904909
csb.UserID = session.UserID;
905910
var cancellationTimeout = GetConnectionSettings().CancellationTimeout;
906911
csb.ConnectionTimeout = cancellationTimeout < 1 ? 3u : (uint) cancellationTimeout;
907912

913+
// forcibly set the IP address the new connection should use
914+
var connectionSettings = new ConnectionSettings(csb);
915+
if (ipAddress is not null)
916+
connectionSettings = connectionSettings.CloneWith(ipAddress);
917+
908918
using var connection = CloneWith(csb.ConnectionString);
919+
connection.m_connectionSettings = connectionSettings;
909920
connection.Open();
910921
#if NET6_0_OR_GREATER
911922
var killQuerySql = string.Create(CultureInfo.InvariantCulture, $"KILL QUERY {command.Connection!.ServerThread}");

0 commit comments

Comments
 (0)