public async Task OpenAsync()

in MySQL.Data/src/NativeDriver.cs [182:328]


    public async Task OpenAsync(bool execAsync, CancellationToken cancellationToken)
    {
      cancellationToken.ThrowIfCancellationRequested();

      // connect to one of our specified hosts
      try
      {
        var result = await StreamCreator.GetStreamAsync(Settings, cancellationToken, execAsync).ConfigureAwait(false);

        baseStream = result.Item1;
        networkStream = result.Item2;

        if (Settings.IncludeSecurityAsserts)
          MySqlSecurityPermission.CreatePermissionSet(false).Assert();
      }
      catch (System.Security.SecurityException) { throw; }
      catch (TimeoutException) { throw; }
      catch (AggregateException ae)
      {
        ae.Handle(ex =>
        {
          if (ex is System.Net.Sockets.SocketException)
            throw new MySqlException(Resources.UnableToConnectToHost, (int)MySqlErrorCode.UnableToConnectToHost, ex);
          return ex is MySqlException;
        });
      }
      catch (Exception ex)
      {
        throw new MySqlException(Resources.UnableToConnectToHost, (int)MySqlErrorCode.UnableToConnectToHost, ex);
      }

      if (baseStream == null)
        throw new MySqlException(Resources.UnableToConnectToHost, (int)MySqlErrorCode.UnableToConnectToHost);

      int maxSinglePacket = 255 * 255 * 255;
      stream = new MySqlStream(baseStream, Encoding, false, networkStream?.Socket);

      stream.ResetTimeout((int)Settings.ConnectionTimeout * 1000);

      // read off the welcome packet and parse out it's values
      packet = await stream.ReadPacketAsync(execAsync).ConfigureAwait(false);

      int protocol = packet.ReadByte();
      if (protocol != 10)
        throw new MySqlException("Unsupported protocol version.");
      string versionString = packet.ReadString();
      version = DBVersion.Parse(versionString);
      threadId = packet.ReadInteger(4);

      byte[] seedPart1 = packet.ReadStringAsBytes();

      maxSinglePacket = (256 * 256 * 256) - 1;

      // read in Server capabilities if they are provided
      ClientFlags serverCaps = 0;
      if (packet.HasMoreData)
        serverCaps = (ClientFlags)packet.ReadInteger(2);

      /* New protocol with 16 bytes to describe server characteristics */
      owner.ConnectionCharSetIndex = (int)packet.ReadByte();

      serverStatus = (ServerStatusFlags)packet.ReadInteger(2);

      // Since 5.5, high bits of server caps are stored after status.
      // Previously, it was part of reserved always 0x00 13-byte filler.
      uint serverCapsHigh = (uint)packet.ReadInteger(2);
      serverCaps |= (ClientFlags)(serverCapsHigh << 16);

      packet.Position += 11;
      byte[] seedPart2 = packet.ReadStringAsBytes();
      encryptionSeed = new byte[seedPart1.Length + seedPart2.Length];
      seedPart1.CopyTo(encryptionSeed, 0);
      seedPart2.CopyTo(encryptionSeed, seedPart1.Length);

      string authenticationMethod = Settings.DefaultAuthenticationPlugin;
      if (string.IsNullOrWhiteSpace(authenticationMethod))
      {
        if ((serverCaps & ClientFlags.PLUGIN_AUTH) != 0)
          authenticationMethod = packet.ReadString();
        else
          // Some MySql versions like 5.1, don't give name of plugin, default to native password.
          authenticationMethod = "mysql_native_password";
      }

      // based on our settings, set our connection flags
      SetConnectionFlags(serverCaps);

      packet.Clear();
      await packet.WriteIntegerAsync((int)connectionFlags, 4, execAsync).ConfigureAwait(false);
      await packet.WriteIntegerAsync(maxSinglePacket, 4, execAsync).ConfigureAwait(false);
      packet.WriteByte(33); //character set utf-8
      await packet.WriteAsync(new byte[23], execAsync).ConfigureAwait(false);

      // Server doesn't support SSL connections
      if ((serverCaps & ClientFlags.SSL) == 0)
      {
        if (Settings.SslMode != MySqlSslMode.Disabled && Settings.SslMode != MySqlSslMode.Prefered)
          throw new MySqlException(string.Format(Resources.NoServerSSLSupport, Settings.Server));
      }
      // Current connection doesn't support SSL connections
      else if ((connectionFlags & ClientFlags.SSL) == 0)
      {
        if (Settings.SslMode != MySqlSslMode.Disabled && Settings.SslMode != MySqlSslMode.Prefered)
          throw new MySqlException(string.Format(Resources.SslNotAllowedForConnectionProtocol, Settings.ConnectionProtocol));
      }
      // Server and connection supports SSL connections and Client are requisting a secure connection
      else
      {
        await stream.SendPacketAsync(packet, execAsync).ConfigureAwait(false);
        var result = await new Ssl(Settings).StartSSLAsync(baseStream, Encoding, Settings.ToString(), cancellationToken, execAsync).ConfigureAwait(false);
        stream = result.Item1;
        baseStream = result.Item2;
        packet.Clear();
        await packet.WriteIntegerAsync((int)connectionFlags, 4, execAsync).ConfigureAwait(false);
        await packet.WriteIntegerAsync(maxSinglePacket, 4, execAsync).ConfigureAwait(false);
        packet.WriteByte(33); //character set utf-8
        await packet.WriteAsync(new byte[23], execAsync).ConfigureAwait(false);
      }

      try
      {
        await AuthenticateAsync(authenticationMethod, false, execAsync).ConfigureAwait(false);
      }
      catch (Exception)
      {
        // If the authenticationMethod is kerberos and KerberosAuthMode is on AUTO, it will retry the connection using GSSAPI mode
        if ((authenticationMethod == "authentication_kerberos_client" || authPlugin.SwitchedPlugin == "authentication_kerberos_client")
          && Settings.KerberosAuthMode == KerberosAuthMode.AUTO)
        {
          Settings.KerberosAuthMode = KerberosAuthMode.GSSAPI;
          await OpenAsync(execAsync, cancellationToken).ConfigureAwait(false);
        }
        else
          throw;
      }

      // if we are using compression, then we use our CompressedStream class
      // to hide the ugliness of managing the compression
      if ((connectionFlags & ClientFlags.COMPRESS) != 0)
        stream = new MySqlStream(baseStream, Encoding, true, networkStream?.Socket);

      // give our stream the server version we are connected to.  
      // We may have some fields that are read differently based 
      // on the version of the server we are connected to.
      packet.Version = version;
      stream.MaxBlockSize = maxSinglePacket;
    }