Ejemplo n.º 1
0
        public void FinishQuerying()
        {
            bool clearConnection = false;

            lock (m_lock)
            {
                if (m_state == State.CancelingQuery)
                {
                    m_state         = State.ClearingPendingCancellation;
                    clearConnection = true;
                }
            }

            if (clearConnection)
            {
                // KILL QUERY will kill a subsequent query if the command it was intended to cancel has already completed.
                // In order to handle this case, we issue a dummy query that will consume the pending cancellation.
                // See https://bugs.mysql.com/bug.php?id=45679
                var payload = new PayloadData(new ArraySegment <byte>(PayloadUtilities.CreateEofStringPayload(CommandKind.Query, "DO SLEEP(0);")));
                SendAsync(payload, IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
                payload = ReceiveReplyAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
                OkPayload.Create(payload);
            }

            lock (m_lock)
            {
                VerifyState(State.Querying, State.ClearingPendingCancellation);
                m_state           = State.Connected;
                m_activeCommandId = 0;
            }
        }
Ejemplo n.º 2
0
        public async Task <bool> TryResetConnectionAsync(ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
        {
            VerifyState(State.Connected);

            try
            {
                if (ServerVersion.Version.CompareTo(ServerVersions.SupportsResetConnection) >= 0)
                {
                    await SendAsync(ResetConnectionPayload.Create(), ioBehavior, cancellationToken).ConfigureAwait(false);

                    var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                    OkPayload.Create(payload);

                    // the "reset connection" packet also resets the connection charset, so we need to change that back to our default
                    payload = new PayloadData(new ArraySegment <byte>(PayloadUtilities.CreateEofStringPayload(CommandKind.Query, "SET NAMES utf8mb4 COLLATE utf8mb4_bin;")));
                    await SendAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                    payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                    OkPayload.Create(payload);
                }
                else
                {
                    // optimistically hash the password with the challenge from the initial handshake (supported by MariaDB; doesn't appear to be supported by MySQL)
                    var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
                    var payload        = ChangeUserPayload.Create(cs.UserID, hashedPassword, cs.Database, m_supportsConnectionAttributes ? s_connectionAttributes : null);
                    await SendAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                    payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                    if (payload.HeaderByte == AuthenticationMethodSwitchRequestPayload.Signature)
                    {
                        await SwitchAuthenticationAsync(cs, payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                        payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
                    }
                    OkPayload.Create(payload);
                }

                return(true);
            }
            catch (EndOfStreamException)
            {
            }
            catch (IOException)
            {
            }
            catch (SocketException)
            {
            }

            return(false);
        }
Ejemplo n.º 3
0
        public async Task ResetConnectionAsync(ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
        {
            if (ServerVersion.Version.CompareTo(ServerVersions.SupportsResetConnection) >= 0)
            {
                await SendAsync(ResetConnectionPayload.Create(), ioBehavior, cancellationToken).ConfigureAwait(false);

                var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                OkPayload.Create(payload);

                // the "reset connection" packet also resets the connection charset, so we need to change that back to our default
                payload = new PayloadData(new ArraySegment <byte>(PayloadUtilities.CreateEofStringPayload(CommandKind.Query, "SET NAMES utf8mb4;")));
                await SendAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                OkPayload.Create(payload);
            }
            else
            {
                // optimistically hash the password with the challenge from the initial handshake (supported by MariaDB; doesn't appear to be supported by MySQL)
                var hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(AuthPluginData, 0, cs.Password);
                var payload        = ChangeUserPayload.Create(cs.UserID, hashedPassword, cs.Database);
                await SendAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);

                if (payload.HeaderByte == AuthenticationMethodSwitchRequestPayload.Signature)
                {
                    // if the server didn't support the hashed password; rehash with the new challenge
                    var switchRequest = AuthenticationMethodSwitchRequestPayload.Create(payload);
                    if (switchRequest.Name != "mysql_native_password")
                    {
                        throw new NotSupportedException("Authentication method '{0}' is not supported.".FormatInvariant(switchRequest.Name));
                    }
                    hashedPassword = AuthenticationUtility.CreateAuthenticationResponse(switchRequest.Data, 0, cs.Password);
                    payload        = new PayloadData(new ArraySegment <byte>(hashedPassword));
                    await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);

                    payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
                }
                OkPayload.Create(payload);
            }
        }