Skip to content

Commit 3d6052a

Browse files
committed
Detect proxy and get underlying server details.
1 parent 5415469 commit 3d6052a

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ public async Task ConnectAsync(ConnectionSettings cs, ILoadBalancer loadBalancer
263263

264264
if (m_useCompression)
265265
m_payloadHandler = new CompressedPayloadHandler(m_payloadHandler.ByteHandler);
266+
267+
if (ShouldGetRealServerDetails())
268+
await GetRealServerDetailsAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
266269
}
267270
catch (IOException ex)
268271
{
@@ -810,6 +813,65 @@ bool ValidateRemoteCertificate(object rcbSender, X509Certificate rcbCertificate,
810813
}
811814
}
812815

816+
// Some servers are exposed through a proxy, which handles the initial handshake and gives the proxy's
817+
// server version and thread ID. Detect this situation and return `true` if the real server's details should
818+
// be requested after connecting (which takes an extra roundtrip).
819+
private bool ShouldGetRealServerDetails()
820+
{
821+
// currently hardcoded to the version returned by the Azure Database for MySQL proxy
822+
return ServerVersion.OriginalString == "5.6.26.0";
823+
}
824+
825+
private async Task GetRealServerDetailsAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
826+
{
827+
try
828+
{
829+
await SendAsync(QueryPayload.Create("SELECT CONNECTION_ID(), VERSION();"), ioBehavior, cancellationToken).ConfigureAwait(false);
830+
831+
// column count: 2
832+
await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
833+
834+
// CONNECTION_ID() and VERSION() columns
835+
await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
836+
await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
837+
838+
PayloadData payload;
839+
if (!SupportsDeprecateEof)
840+
{
841+
payload = await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
842+
EofPayload.Create(payload);
843+
}
844+
845+
// first (and only) row
846+
int? connectionId = default;
847+
string serverVersion = null;
848+
payload = await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
849+
var reader = new ByteArrayReader(payload.ArraySegment);
850+
var length = reader.ReadLengthEncodedIntegerOrNull();
851+
if (length != -1)
852+
connectionId = int.Parse(Encoding.UTF8.GetString(reader.ReadByteString(length)), CultureInfo.InvariantCulture);
853+
length = reader.ReadLengthEncodedIntegerOrNull();
854+
if (length != -1)
855+
serverVersion = Encoding.UTF8.GetString(reader.ReadByteString(length));
856+
857+
// OK/EOF payload
858+
payload = await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
859+
if (OkPayload.IsOk(payload, SupportsDeprecateEof))
860+
OkPayload.Create(payload, SupportsDeprecateEof);
861+
else
862+
EofPayload.Create(payload);
863+
864+
if (connectionId.HasValue && serverVersion != null)
865+
{
866+
ConnectionId = connectionId.Value;
867+
ServerVersion = new ServerVersion(serverVersion);
868+
}
869+
}
870+
catch (MySqlException)
871+
{
872+
}
873+
}
874+
813875
private void ShutdownSocket()
814876
{
815877
Utility.Dispose(ref m_payloadHandler);

0 commit comments

Comments
 (0)