Skip to content

Commit 959ae7c

Browse files
committed
Store session state in MySqlSession. Fixes #269
"Modifying" the ConnectionSettings object passed to this method (by creating a clone with updated properties) didn't persist the changes anywhere. Now, all state specific to this session is stored in its fields, so a session retrieved from the pool has the right state.
1 parent fb8a7e4 commit 959ae7c

File tree

3 files changed

+19
-63
lines changed

3 files changed

+19
-63
lines changed

src/MySqlConnector/Serialization/ConnectionSettings.cs

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -59,50 +59,6 @@ public ConnectionSettings(MySqlConnectionStringBuilder csb)
5959
UseCompression = csb.UseCompression;
6060
}
6161

62-
public ConnectionSettings WithSecureConnection(bool isSecureConnection) => new ConnectionSettings(this, isSecureConnection: isSecureConnection);
63-
public ConnectionSettings WithUseCompression(bool useCompression) => new ConnectionSettings(this, useCompression: useCompression);
64-
65-
private ConnectionSettings(ConnectionSettings other, bool? useCompression = null, bool? isSecureConnection = null)
66-
{
67-
// Base Options
68-
ConnectionString = other.ConnectionString;
69-
ConnectionType = other.ConnectionType;
70-
Hostnames = other.Hostnames;
71-
Port = other.Port;
72-
UnixSocket = other.UnixSocket;
73-
UserID = other.UserID;
74-
Password = other.Password;
75-
Database = other.Database;
76-
77-
// SSL/TLS Options
78-
SslMode = other.SslMode;
79-
CertificateFile = other.CertificateFile;
80-
CertificatePassword = other.CertificatePassword;
81-
IsSecureConnection = isSecureConnection ?? other.IsSecureConnection;
82-
83-
// Connection Pooling Options
84-
Pooling = other.Pooling;
85-
ConnectionLifeTime = other.ConnectionLifeTime;
86-
ConnectionReset = other.ConnectionReset;
87-
ConnectionIdleTimeout = other.ConnectionIdleTimeout;
88-
MinimumPoolSize = other.MinimumPoolSize;
89-
MaximumPoolSize = other.MaximumPoolSize;
90-
91-
// Other Options
92-
AllowUserVariables = other.AllowUserVariables;
93-
AutoEnlist = other.AutoEnlist;
94-
BufferResultSets = other.BufferResultSets;
95-
ConnectionTimeout = other.ConnectionTimeout;
96-
ConvertZeroDateTime = other.ConvertZeroDateTime;
97-
ForceSynchronous = other.ForceSynchronous;
98-
Keepalive = other.Keepalive;
99-
OldGuids = other.OldGuids;
100-
PersistSecurityInfo = other.PersistSecurityInfo;
101-
TreatTinyAsBoolean = other.TreatTinyAsBoolean;
102-
UseAffectedRows = other.UseAffectedRows;
103-
UseCompression = useCompression ?? other.UseCompression;
104-
}
105-
10662
// Base Options
10763
internal readonly string ConnectionString;
10864
internal readonly ConnectionType ConnectionType;
@@ -117,7 +73,6 @@ private ConnectionSettings(ConnectionSettings other, bool? useCompression = null
11773
internal readonly MySqlSslMode SslMode;
11874
internal readonly string CertificateFile;
11975
internal readonly string CertificatePassword;
120-
internal readonly bool IsSecureConnection;
12176

12277
// Connection Pooling Options
12378
internal readonly bool Pooling;

src/MySqlConnector/Serialization/HandshakeResponse41Packet.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
internal sealed class HandshakeResponse41Packet
44
{
5-
private static PayloadWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, ProtocolCapabilities additionalCapabilities=0)
5+
private static PayloadWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, ProtocolCapabilities additionalCapabilities=0)
66
{
77
var writer = new PayloadWriter();
88

@@ -18,7 +18,7 @@ private static PayloadWriter CreateCapabilitiesPayload(ProtocolCapabilities serv
1818
ProtocolCapabilities.LocalFiles |
1919
(string.IsNullOrWhiteSpace(cs.Database) ? 0 : ProtocolCapabilities.ConnectWithDatabase) |
2020
(cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) |
21-
(cs.UseCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) |
21+
(useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) |
2222
additionalCapabilities));
2323
writer.WriteInt32(0x4000_0000);
2424
writer.WriteByte((byte) CharacterSet.Utf8Mb4Binary);
@@ -27,16 +27,16 @@ private static PayloadWriter CreateCapabilitiesPayload(ProtocolCapabilities serv
2727
return writer;
2828
}
2929

30-
public static byte[] InitSsl(ProtocolCapabilities serverCapabilities, ConnectionSettings cs)
30+
public static byte[] InitSsl(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression)
3131
{
32-
return CreateCapabilitiesPayload(serverCapabilities, cs, ProtocolCapabilities.Ssl).ToBytes();
32+
return CreateCapabilitiesPayload(serverCapabilities, cs, useCompression, ProtocolCapabilities.Ssl).ToBytes();
3333
}
3434

35-
public static byte[] Create(InitialHandshakePacket handshake, ConnectionSettings cs)
35+
public static byte[] Create(InitialHandshakePacket handshake, ConnectionSettings cs, bool useCompression)
3636
{
3737
// TODO: verify server capabilities
3838

39-
var writer = CreateCapabilitiesPayload(handshake.ProtocolCapabilities, cs);
39+
var writer = CreateCapabilitiesPayload(handshake.ProtocolCapabilities, cs, useCompression);
4040
writer.WriteNullTerminatedString(cs.UserID);
4141
var authenticationResponse = AuthenticationUtility.CreateAuthenticationResponse(handshake.AuthPluginData, 0, cs.Password);
4242
writer.WriteByte((byte) authenticationResponse.Length);

src/MySqlConnector/Serialization/MySqlSession.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,33 +222,31 @@ public async Task ConnectAsync(ConnectionSettings cs, IOBehavior ioBehavior, Can
222222
ServerVersion = new ServerVersion(Encoding.ASCII.GetString(initialHandshake.ServerVersion));
223223
ConnectionId = initialHandshake.ConnectionId;
224224
AuthPluginData = initialHandshake.AuthPluginData;
225-
if (cs.UseCompression && (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Compress) == 0)
226-
cs = cs.WithUseCompression(false);
225+
m_useCompression = cs.UseCompression && (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Compress) != 0;
227226

228227
var serverSupportsSsl = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Ssl) != 0;
229228
if (cs.SslMode != MySqlSslMode.None && (cs.SslMode != MySqlSslMode.Preferred || serverSupportsSsl))
230229
{
231230
if (!serverSupportsSsl)
232231
throw new MySqlException("Server does not support SSL");
233232
await InitSslAsync(initialHandshake.ProtocolCapabilities, cs, ioBehavior, cancellationToken).ConfigureAwait(false);
234-
cs = cs.WithSecureConnection(true);
235233
}
236234

237-
var response = HandshakeResponse41Packet.Create(initialHandshake, cs);
235+
var response = HandshakeResponse41Packet.Create(initialHandshake, cs, m_useCompression);
238236
payload = new PayloadData(new ArraySegment<byte>(response));
239237
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
240238
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
241239

242240
// if server doesn't support the authentication fast path, it will send a new challenge
243241
if (payload.HeaderByte == AuthenticationMethodSwitchRequestPayload.Signature)
244242
{
245-
await SwitchAuthenticationAsync(payload, cs, ioBehavior, cancellationToken).ConfigureAwait(false);
243+
await SwitchAuthenticationAsync(payload, cs.Password, ioBehavior, cancellationToken).ConfigureAwait(false);
246244
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
247245
}
248246

249247
OkPayload.Create(payload);
250248

251-
if (cs.UseCompression)
249+
if (m_useCompression)
252250
m_payloadHandler = new CompressedPayloadHandler(m_payloadHandler.ByteHandler);
253251
}
254252

@@ -276,30 +274,30 @@ public async Task ResetConnectionAsync(ConnectionSettings cs, IOBehavior ioBehav
276274
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
277275
if (payload.HeaderByte == AuthenticationMethodSwitchRequestPayload.Signature)
278276
{
279-
await SwitchAuthenticationAsync(payload, cs, ioBehavior, cancellationToken);
277+
await SwitchAuthenticationAsync(payload, cs.Password, ioBehavior, cancellationToken);
280278
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
281279
}
282280
OkPayload.Create(payload);
283281
}
284282
}
285283

286-
private async Task SwitchAuthenticationAsync(PayloadData payload, ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
284+
private async Task SwitchAuthenticationAsync(PayloadData payload, string password, IOBehavior ioBehavior, CancellationToken cancellationToken)
287285
{
288286
// if the server didn't support the hashed password; rehash with the new challenge
289287
var switchRequest = AuthenticationMethodSwitchRequestPayload.Create(payload);
290288
switch (switchRequest.Name)
291289
{
292290
case "mysql_native_password":
293291
AuthPluginData = switchRequest.Data;
294-
var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
292+
var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, password);
295293
payload = new PayloadData(new ArraySegment<byte>(hashedPassword));
296294
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
297295
break;
298296

299297
case "mysql_clear_password":
300-
if (!cs.IsSecureConnection)
298+
if (!m_isSecureConnection)
301299
throw new MySqlException("Authentication method '{0}' requires a secure connection.".FormatInvariant(switchRequest.Name));
302-
payload = new PayloadData(new ArraySegment<byte>(Encoding.UTF8.GetBytes(cs.Password)));
300+
payload = new PayloadData(new ArraySegment<byte>(Encoding.UTF8.GetBytes(password)));
303301
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
304302
break;
305303

@@ -577,7 +575,7 @@ private async Task InitSslAsync(ProtocolCapabilities serverCapabilities, Connect
577575

578576
var checkCertificateRevocation = cs.SslMode == MySqlSslMode.VerifyFull;
579577

580-
var initSsl = new PayloadData(new ArraySegment<byte>(HandshakeResponse41Packet.InitSsl(serverCapabilities, cs)));
578+
var initSsl = new PayloadData(new ArraySegment<byte>(HandshakeResponse41Packet.InitSsl(serverCapabilities, cs, m_useCompression)));
581579
await SendReplyAsync(initSsl, ioBehavior, cancellationToken).ConfigureAwait(false);
582580

583581
try
@@ -596,6 +594,7 @@ private async Task InitSslAsync(ProtocolCapabilities serverCapabilities, Connect
596594
}
597595
var sslByteHandler = new StreamByteHandler(sslStream);
598596
m_payloadHandler.ByteHandler = sslByteHandler;
597+
m_isSecureConnection = true;
599598
}
600599
catch (Exception ex)
601600
{
@@ -730,5 +729,7 @@ private enum State
730729
IPayloadHandler m_payloadHandler;
731730
MySqlCommand m_activeCommand;
732731
MySqlDataReader m_activeReader;
732+
bool m_useCompression;
733+
bool m_isSecureConnection;
733734
}
734735
}

0 commit comments

Comments
 (0)