class_docstr: The Main Server controller class
class_docstr_tok: ["The","Main","Server","controller","class"]
code: def handshake(self):
      def switch_auth(method="mysql_native_password"):
          self.packet(
              SwitchOutPacket, seed=self.salt, method=method
          ).send()
          switch_out_answer = self.packet(SwitchOutResponse)
          switch_out_answer.get()
          password = switch_out_answer.password
          if method == "mysql_native_password" and len(password) == 0:
              password = scramble_func("", self.salt)
          return password
  
      def get_fast_auth_password():
          logger.debug("Asking for fast auth password")
          self.packet(FastAuthFail).send()
          password_answer = self.packet(PasswordAnswer)
          password_answer.get()
          try:
              password = password_answer.password.value.decode()
          except Exception:
              logger.warning("error: no password in Fast Auth answer")
              self.packet(
                  ErrPacket,
                  err_code=ERR.ER_PASSWORD_NO_MATCH,
                  msg="Is not password in connection query.",
              ).send()
              return None
          return password
  
      username = None
      password = None
  
      logger.debug("send HandshakePacket")
      self.packet(HandshakePacket).send()
  
      handshake_resp = self.packet(HandshakeResponsePacket)
      handshake_resp.get()
      if handshake_resp.length == 0:
          logger.debug("HandshakeResponsePacket empty")
          self.packet(OkPacket).send()
          return False
      self.client_capabilities = ClentCapabilities(
          handshake_resp.capabilities.value
      )
  
      client_auth_plugin = (
          handshake_resp.client_auth_plugin.value.decode()
      )
  
      self.session.is_ssl = False
  
      if handshake_resp.type == "SSLRequest":
          logger.debug("switch to SSL")
          self.session.is_ssl = True
  
          ssl_context = ssl.SSLContext()
          ssl_context.load_cert_chain(self.server.cert_path)
          ssl_socket = ssl_context.wrap_socket(
              self.socket,
              server_side=True,
              do_handshake_on_connect=True,
          )
  
          self.socket = ssl_socket
          handshake_resp = self.packet(HandshakeResponsePacket)
          handshake_resp.get()
          client_auth_plugin = (
              handshake_resp.client_auth_plugin.value.decode()
          )
  
      username = handshake_resp.username.value.decode()
  
      if client_auth_plugin != DEFAULT_AUTH_METHOD:
          if client_auth_plugin == "mysql_native_password":
              password = switch_auth("mysql_native_password")
          else:
              new_method = (
                  "caching_sha2_password"
                  if client_auth_plugin == "caching_sha2_password"
                  else "mysql_native_password"
              )
  
              if (
                  new_method == "caching_sha2_password"
                  and self.session.is_ssl is False
              ):
                  logger.warning(
                      f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
                      "error: cant switch to caching_sha2_password without SSL"
                  )
                  self.packet(
                      ErrPacket,
                      err_code=ERR.ER_PASSWORD_NO_MATCH,
                      msg="caching_sha2_password without SSL not supported",
                  ).send()
                  return False
  
              logger.debug(
                  f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
                  f"switch auth method to {new_method}"
              )
              password = switch_auth(new_method)
  
              if new_method == "caching_sha2_password":
                  if password == b"\x00":
                      password = ""
                  else:
                      password = get_fast_auth_password()
      elif "caching_sha2_password" in client_auth_plugin:
          logger.debug(
              f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
              "check auth using caching_sha2_password"
          )
          password = handshake_resp.enc_password.value
          if password == b"\x00":
              password = ""
          else:
              # FIXME https://github.com/mindsdb/mindsdb/issues/1374
              # if self.session.is_ssl:
              #     password = get_fast_auth_password()
              # else:
              password = switch_auth()
      elif "mysql_native_password" in client_auth_plugin:
          logger.debug(
              f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
              "check auth using mysql_native_password"
          )
          password = handshake_resp.enc_password.value
      else:
          logger.debug(
              f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
              "unknown method, possible ERROR. Try to switch to mysql_native_password"
          )
          password = switch_auth("mysql_native_password")
  
      try:
          self.session.database = handshake_resp.database.value.decode()
      except Exception:
          self.session.database = None
      logger.debug(
          f"Check auth, user={username}, ssl={self.session.is_ssl}, auth_method={client_auth_plugin}: "
          f"connecting to database {self.session.database}"
      )
  
      auth_data = self.server.check_auth(
          username, password, scramble_func, self.salt, ctx.company_id
      )
      if auth_data["success"]:
          self.session.username = auth_data["username"]
          self.session.auth = True
          self.packet(OkPacket).send()
          return True
      else:
          self.packet(
              ErrPacket,
              err_code=ERR.ER_PASSWORD_NO_MATCH,
              msg=f"Access denied for user {username}",
          ).send()
          logger.warning(f"Access denied for user {username}")
          return False
  
imports: import atexit
  import base64
  import os
  import select
  import socket
  import socketserver
  import ssl
  import struct
  import sys
  import tempfile
  import traceback
  from functools import partial
  from typing import Dict, List
  from numpy import dtype
  from pandas.api import types
  import mindsdb.utilities.hooks
  import mindsdb.utilities.profiler
  from mindsdb.api.mysql.mysql_proxy.classes.client_capabilities import ClentCapabilities
  from mindsdb.api.mysql.mysql_proxy.classes.server_capabilities import server_capabilities
  from mindsdb.api.mysql.mysql_proxy.classes.sql_statement_parser import SqlStatementParser
  from mindsdb.api.executor.controllers import SessionController
  from mindsdb.api.mysql.mysql_proxy.data_types.mysql_packet import Packet
  from mindsdb.api.mysql.mysql_proxy.data_types.mysql_packets import BinaryResultsetRowPacket, ColumnCountPacket, ColumnDefenitionPacket, CommandPacket, EofPacket, ErrPacket, FastAuthFail, HandshakePacket, HandshakeResponsePacket, OkPacket, PasswordAnswer, ResultsetRowPacket, STMTPrepareHeaderPacket, SwitchOutPacket, SwitchOutResponse
  from mindsdb.api.mysql.mysql_proxy.executor import Executor
  from mindsdb.api.mysql.mysql_proxy.external_libs.mysql_scramble import scramble
  from mindsdb.api.mysql.mysql_proxy.libs.constants.mysql import CAPABILITIES, CHARSET_NUMBERS, COMMANDS, DEFAULT_AUTH_METHOD, ERR, SERVER_STATUS, TYPES, getConstName
  from mindsdb.api.executor.data_types.response_type import RESPONSE_TYPE
  from mindsdb.api.mysql.mysql_proxy.utilities import ErWrongCharset, SqlApiException
  from mindsdb.api.executor import exceptions
  from mindsdb.api.mysql.mysql_proxy.utilities.lightwood_dtype import dtype
  from mindsdb.utilities import log
  from mindsdb.utilities.config import Config
  from mindsdb.utilities.context import context
  from mindsdb.utilities.wizards import make_ssl_cert
label_desc: Use image node_id 4 for calling the MysqlProxy obj's underlying member method code with example usage: obj.handshake() and returns: password, password, False, True, False, None, False