Skip to content

Commit 17ad067

Browse files
committed
Fix OK payload parsing.
Server Session State Change information should only be read if CLIENT_SESSION_TRACK was set in the initial handshake. Fixes #603.
1 parent 2bf280a commit 17ad067

File tree

4 files changed

+18
-17
lines changed

4 files changed

+18
-17
lines changed

src/MySqlConnector/Core/ResultSet.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
4545
var firstByte = payload.HeaderByte;
4646
if (firstByte == OkPayload.Signature)
4747
{
48-
var ok = OkPayload.Create(payload.AsSpan());
48+
var ok = OkPayload.Create(payload.AsSpan(), Session.SupportsDeprecateEof, Session.SupportsDeprecateEof);
4949
RecordsAffected = (RecordsAffected ?? 0) + ok.AffectedRowCount;
5050
LastInsertId = unchecked((long) ok.LastInsertId);
5151
WarningCount = ok.WarningCount;
@@ -231,7 +231,7 @@ Row ScanRowAsyncRemainder(PayloadData payload, Row row_)
231231
var span = payload.AsSpan();
232232
if (Session.SupportsDeprecateEof && OkPayload.IsOk(span, Session.SupportsDeprecateEof))
233233
{
234-
var ok = OkPayload.Create(span, Session.SupportsDeprecateEof);
234+
var ok = OkPayload.Create(span, Session.SupportsDeprecateEof, Session.SupportsSessionTrack);
235235
BufferState = (ok.ServerStatus & ServerStatus.MoreResultsExist) == 0 ? ResultSetState.NoMoreData : ResultSetState.HasMoreData;
236236
m_rowBuffered = null;
237237
return null;

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public ServerSession(ConnectionPool pool, int poolGeneration, int id)
6060
public IPAddress IPAddress => (m_tcpClient?.Client.RemoteEndPoint as IPEndPoint)?.Address;
6161
public WeakReference<MySqlConnection> OwningConnection { get; set; }
6262
public bool SupportsDeprecateEof => m_supportsDeprecateEof;
63+
public bool SupportsSessionTrack => m_supportsSessionTrack;
6364
public bool ProcAccessDenied { get; set; }
6465

6566
public void ReturnToPool()
@@ -186,7 +187,7 @@ public void FinishQuerying()
186187
var payload = QueryPayload.Create("DO SLEEP(0);");
187188
SendAsync(payload, IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
188189
payload = ReceiveReplyAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
189-
OkPayload.Create(payload.AsSpan());
190+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
190191
}
191192

192193
lock (m_lock)
@@ -310,12 +311,13 @@ public async Task ConnectAsync(ConnectionSettings cs, ILoadBalancer loadBalancer
310311

311312
m_supportsConnectionAttributes = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.ConnectionAttributes) != 0;
312313
m_supportsDeprecateEof = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.DeprecateEof) != 0;
314+
m_supportsSessionTrack = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.SessionTrack) != 0;
313315
var serverSupportsSsl = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Ssl) != 0;
314316
m_characterSet = ServerVersion.Version >= ServerVersions.SupportsUtf8Mb4 ? CharacterSet.Utf8Mb4GeneralCaseInsensitive : CharacterSet.Utf8GeneralCaseInsensitive;
315317

316-
Log.Info("Session{0} made connection; ServerVersion={1}; ConnectionId={2}; Compression={3}; Attributes={4}; DeprecateEof={5}; Ssl={6}",
318+
Log.Info("Session{0} made connection; ServerVersion={1}; ConnectionId={2}; Compression={3}; Attributes={4}; DeprecateEof={5}; Ssl={6}; SessionTrack={7}",
317319
m_logArguments[0], ServerVersion.OriginalString, ConnectionId,
318-
m_useCompression, m_supportsConnectionAttributes, m_supportsDeprecateEof, serverSupportsSsl);
320+
m_useCompression, m_supportsConnectionAttributes, m_supportsDeprecateEof, serverSupportsSsl, m_supportsSessionTrack);
319321

320322
if (cs.SslMode != MySqlSslMode.None && (cs.SslMode != MySqlSslMode.Preferred || serverSupportsSsl))
321323
{
@@ -363,7 +365,7 @@ public async Task ConnectAsync(ConnectionSettings cs, ILoadBalancer loadBalancer
363365
payload = await SwitchAuthenticationAsync(cs, payload, ioBehavior, cancellationToken).ConfigureAwait(false);
364366
}
365367

366-
OkPayload.Create(payload.AsSpan());
368+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
367369

368370
if (m_useCompression)
369371
m_payloadHandler = new CompressedPayloadHandler(m_payloadHandler.ByteHandler);
@@ -398,12 +400,12 @@ public async Task<bool> TryResetConnectionAsync(ConnectionSettings cs, IOBehavio
398400
Log.Debug("Session{0} ServerVersion={1} supports reset connection; sending reset connection request", m_logArguments);
399401
await SendAsync(ResetConnectionPayload.Instance, ioBehavior, cancellationToken).ConfigureAwait(false);
400402
var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
401-
OkPayload.Create(payload.AsSpan());
403+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
402404

403405
// the "reset connection" packet also resets the connection charset, so we need to change that back to our default
404406
await SendAsync(s_setNamesUtf8mb4Payload, ioBehavior, cancellationToken).ConfigureAwait(false);
405407
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
406-
OkPayload.Create(payload.AsSpan());
408+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
407409
}
408410
else
409411
{
@@ -428,7 +430,7 @@ public async Task<bool> TryResetConnectionAsync(ConnectionSettings cs, IOBehavio
428430
Log.Debug("Session{0} optimistic reauthentication failed; logging in again", m_logArguments);
429431
payload = await SwitchAuthenticationAsync(cs, payload, ioBehavior, cancellationToken).ConfigureAwait(false);
430432
}
431-
OkPayload.Create(payload.AsSpan());
433+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
432434
}
433435

434436
return true;
@@ -609,7 +611,7 @@ public async ValueTask<bool> TryPingAsync(IOBehavior ioBehavior, CancellationTok
609611
Log.Debug("Session{0} pinging server", m_logArguments);
610612
await SendAsync(PingPayload.Instance, ioBehavior, cancellationToken).ConfigureAwait(false);
611613
var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
612-
OkPayload.Create(payload.AsSpan());
614+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
613615
Log.Info("Session{0} successfully pinged server", m_logArguments);
614616
return true;
615617
}
@@ -1163,7 +1165,7 @@ void ReadRow(ReadOnlySpan<byte> span, out int? connectionId_, out string serverV
11631165
// OK/EOF payload
11641166
payload = await ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
11651167
if (OkPayload.IsOk(payload.AsSpan(), SupportsDeprecateEof))
1166-
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof);
1168+
OkPayload.Create(payload.AsSpan(), SupportsDeprecateEof, SupportsSessionTrack);
11671169
else
11681170
EofPayload.Create(payload.AsSpan());
11691171

@@ -1410,6 +1412,7 @@ private enum State
14101412
bool m_isSecureConnection;
14111413
bool m_supportsConnectionAttributes;
14121414
bool m_supportsDeprecateEof;
1415+
bool m_supportsSessionTrack;
14131416
CharacterSet m_characterSet;
14141417
Dictionary<string, PreparedStatements> m_preparedStatements;
14151418
}

src/MySqlConnector/MySql.Data.MySqlClient/MySqlConnection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private async Task ChangeDatabaseAsync(IOBehavior ioBehavior, string databaseNam
188188
using (var initDatabasePayload = InitDatabasePayload.Create(databaseName))
189189
await m_session.SendAsync(initDatabasePayload, ioBehavior, cancellationToken).ConfigureAwait(false);
190190
var payload = await m_session.ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
191-
OkPayload.Create(payload.AsSpan());
191+
OkPayload.Create(payload.AsSpan(), m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
192192
m_session.DatabaseOverride = databaseName;
193193
}
194194

src/MySqlConnector/Protocol/Payloads/OkPayload.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal sealed class OkPayload
1616
public const byte Signature = 0x00;
1717

1818
/* See
19-
* http://web.archive.org/web/20160604101747/http://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
19+
* https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
2020
* https://mariadb.com/kb/en/the-mariadb-library/resultset/
2121
* https://github.com/MariaDB/mariadb-connector-j/blob/5fa814ac6e1b4c9cb6d141bd221cbd5fc45c8a78/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java#L443-L444
2222
*/
@@ -25,9 +25,7 @@ public static bool IsOk(ReadOnlySpan<byte> span, bool deprecateEof) =>
2525
(span.Length > 6 && span[0] == Signature ||
2626
deprecateEof && span.Length < 0xFF_FFFF && span[0] == EofPayload.Signature);
2727

28-
public static OkPayload Create(ReadOnlySpan<byte> span) => Create(span, false);
29-
30-
public static OkPayload Create(ReadOnlySpan<byte> span, bool deprecateEof)
28+
public static OkPayload Create(ReadOnlySpan<byte> span, bool deprecateEof, bool clientSessionTrack)
3129
{
3230
var reader = new ByteArrayReader(span);
3331
var signature = reader.ReadByte();
@@ -39,7 +37,7 @@ public static OkPayload Create(ReadOnlySpan<byte> span, bool deprecateEof)
3937
var warningCount = (int) reader.ReadUInt16();
4038
string newSchema = null;
4139

42-
if ((serverStatus & ServerStatus.SessionStateChanged) == ServerStatus.SessionStateChanged)
40+
if (clientSessionTrack && (serverStatus & ServerStatus.SessionStateChanged) == ServerStatus.SessionStateChanged)
4341
{
4442
reader.ReadLengthEncodedByteString(); // human-readable info
4543

0 commit comments

Comments
 (0)