'Actually performs the TLS handshake. This is run automatically by
wrapped socket, and shouldn\'t be needed in user code.'

def handshake(self, server_hostname, verify, trust_bundle, min_version, max_version, client_cert, client_key, client_key_passphrase):

    self.context = Security.SSLCreateContext(None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType)
    result = Security.SSLSetIOFuncs(self.context, _read_callback_pointer, _write_callback_pointer)
    _assert_no_error(result)
    with _connection_ref_lock:
        handle = (id(self) % 2147483647)
        while (handle in _connection_refs):
            handle = ((handle + 1) % 2147483647)
        _connection_refs[handle] = self
    result = Security.SSLSetConnection(self.context, handle)
    _assert_no_error(result)
    if server_hostname:
        if (not isinstance(server_hostname, bytes)):
            server_hostname = server_hostname.encode('utf-8')
        result = Security.SSLSetPeerDomainName(self.context, server_hostname, len(server_hostname))
        _assert_no_error(result)
    self._set_ciphers()
    result = Security.SSLSetProtocolVersionMin(self.context, min_version)
    _assert_no_error(result)
    result = Security.SSLSetProtocolVersionMax(self.context, max_version)
    _assert_no_error(result)
    if ((not verify) or (trust_bundle is not None)):
        result = Security.SSLSetSessionOption(self.context, SecurityConst.kSSLSessionOptionBreakOnServerAuth, True)
        _assert_no_error(result)
    if client_cert:
        (self._keychain, self._keychain_dir) = _temporary_keychain()
        self._client_cert_chain = _load_client_cert_chain(self._keychain, client_cert, client_key)
        result = Security.SSLSetCertificate(self.context, self._client_cert_chain)
        _assert_no_error(result)
    while True:
        with self._raise_on_error():
            result = Security.SSLHandshake(self.context)
            if (result == SecurityConst.errSSLWouldBlock):
                raise socket.timeout('handshake    timed    out')
            elif (result == SecurityConst.errSSLServerAuthCompleted):
                self._custom_validate(verify, trust_bundle)
                continue
            else:
                _assert_no_error(result)
                break
