Skip to content

Commit

Permalink
Use 'utf8' if the server doesn't support 'utf8mb4'.
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrainger committed Nov 26, 2018
1 parent 2991acc commit 6d3b244
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 11 deletions.
8 changes: 5 additions & 3 deletions src/MySqlConnector/Core/ServerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ public async Task ConnectAsync(ConnectionSettings cs, ILoadBalancer loadBalancer
m_supportsConnectionAttributes = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.ConnectionAttributes) != 0;
m_supportsDeprecateEof = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.DeprecateEof) != 0;
var serverSupportsSsl = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.Ssl) != 0;
m_characterSet = ServerVersion.Version >= ServerVersions.SupportsUtf8Mb4 ? CharacterSet.Utf8Mb4GeneralCaseInsensitive : CharacterSet.Utf8GeneralCaseInsensitive;

Log.Info("Session{0} made connection; ServerVersion={1}; ConnectionId={2}; Compression={3}; Attributes={4}; DeprecateEof={5}; Ssl={6}",
m_logArguments[0], ServerVersion.OriginalString, ConnectionId,
Expand Down Expand Up @@ -351,7 +352,7 @@ public async Task ConnectAsync(ConnectionSettings cs, ILoadBalancer loadBalancer
if (m_supportsConnectionAttributes && cs.ConnectionAttributes == null)
cs.ConnectionAttributes = CreateConnectionAttributes(cs.ApplicationName);

using (var handshakeResponsePayload = HandshakeResponse41Payload.Create(initialHandshake, cs, m_useCompression, m_supportsConnectionAttributes ? cs.ConnectionAttributes : null))
using (var handshakeResponsePayload = HandshakeResponse41Payload.Create(initialHandshake, cs, m_useCompression, m_characterSet, m_supportsConnectionAttributes ? cs.ConnectionAttributes : null))
await SendReplyAsync(handshakeResponsePayload, ioBehavior, cancellationToken).ConfigureAwait(false);
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

Expand Down Expand Up @@ -418,7 +419,7 @@ public async Task<bool> TryResetConnectionAsync(ConnectionSettings cs, IOBehavio
DatabaseOverride = null;
}
var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
using (var changeUserPayload = ChangeUserPayload.Create(cs.UserID, hashedPassword, cs.Database, m_supportsConnectionAttributes ? cs.ConnectionAttributes : null))
using (var changeUserPayload = ChangeUserPayload.Create(cs.UserID, hashedPassword, cs.Database, m_characterSet, m_supportsConnectionAttributes ? cs.ConnectionAttributes : null))
await SendAsync(changeUserPayload, ioBehavior, cancellationToken).ConfigureAwait(false);
var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
if (payload.HeaderByte == AuthenticationMethodSwitchRequestPayload.Signature)
Expand Down Expand Up @@ -1068,7 +1069,7 @@ bool ValidateRemoteCertificate(object rcbSender, X509Certificate rcbCertificate,

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

using (var initSsl = HandshakeResponse41Payload.CreateWithSsl(serverCapabilities, cs, m_useCompression))
using (var initSsl = HandshakeResponse41Payload.CreateWithSsl(serverCapabilities, cs, m_useCompression, m_characterSet))
await SendReplyAsync(initSsl, ioBehavior, cancellationToken).ConfigureAwait(false);

try
Expand Down Expand Up @@ -1408,6 +1409,7 @@ private enum State
bool m_isSecureConnection;
bool m_supportsConnectionAttributes;
bool m_supportsDeprecateEof;
CharacterSet m_characterSet;
Dictionary<string, PreparedStatements> m_preparedStatements;
}
}
3 changes: 3 additions & 0 deletions src/MySqlConnector/Core/ServerVersions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ namespace MySqlConnector.Core
{
internal static class ServerVersions
{
// https://dev.mysql.com/doc/relnotes/mysql/5.5/en/news-5-5-3.html
public static readonly Version SupportsUtf8Mb4 = new Version(5, 5, 3);

// https://dev.mysql.com/doc/refman/5.7/en/mysql-reset-connection.html
public static readonly Version SupportsResetConnection = new Version(5, 7, 3);

Expand Down
4 changes: 2 additions & 2 deletions src/MySqlConnector/Protocol/Payloads/ChangeUserPayload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace MySqlConnector.Protocol.Payloads
{
internal static class ChangeUserPayload
{
public static PayloadData Create(string user, byte[] authResponse, string schemaName, byte[] connectionAttributes)
public static PayloadData Create(string user, byte[] authResponse, string schemaName, CharacterSet characterSet, byte[] connectionAttributes)
{
var writer = new ByteBufferWriter();

Expand All @@ -13,7 +13,7 @@ public static PayloadData Create(string user, byte[] authResponse, string schema
writer.Write(checked((byte) authResponse.Length));
writer.Write(authResponse);
writer.WriteNullTerminatedString(schemaName ?? "");
writer.Write((byte) CharacterSet.Utf8Mb4GeneralCaseInsensitive);
writer.Write((byte) characterSet);
writer.Write((byte) 0);
writer.WriteNullTerminatedString("mysql_native_password");
if (connectionAttributes != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace MySqlConnector.Protocol.Payloads
{
internal static class HandshakeResponse41Payload
{
private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, ProtocolCapabilities additionalCapabilities=0)
private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, ProtocolCapabilities additionalCapabilities = 0)
{
var writer = new ByteBufferWriter();

Expand All @@ -28,19 +28,19 @@ private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities s
(serverCapabilities & ProtocolCapabilities.DeprecateEof) |
additionalCapabilities));
writer.Write(0x4000_0000);
writer.Write((byte) CharacterSet.Utf8Mb4GeneralCaseInsensitive);
writer.Write((byte) characterSet);
writer.Write(s_padding);

return writer;
}

public static PayloadData CreateWithSsl(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression) =>
CreateCapabilitiesPayload(serverCapabilities, cs, useCompression, ProtocolCapabilities.Ssl).ToPayloadData();
public static PayloadData CreateWithSsl(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet) =>
CreateCapabilitiesPayload(serverCapabilities, cs, useCompression, characterSet, ProtocolCapabilities.Ssl).ToPayloadData();

public static PayloadData Create(InitialHandshakePayload handshake, ConnectionSettings cs, bool useCompression, byte[] connectionAttributes)
public static PayloadData Create(InitialHandshakePayload handshake, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, byte[] connectionAttributes)
{
// TODO: verify server capabilities
var writer = CreateCapabilitiesPayload(handshake.ProtocolCapabilities, cs, useCompression);
var writer = CreateCapabilitiesPayload(handshake.ProtocolCapabilities, cs, useCompression, characterSet);
writer.WriteNullTerminatedString(cs.UserID);
var authenticationResponse = AuthenticationUtility.CreateAuthenticationResponse(handshake.AuthPluginData, 0, cs.Password);
writer.Write((byte) authenticationResponse.Length);
Expand Down

1 comment on commit 6d3b244

@bgrainger
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.