def _handshake(self):
self._ssl = None<EOL>self._rbio = None<EOL>self._wbio = None<EOL>try:<EOL><INDENT>self._ssl = libssl.SSL_new(self._session._ssl_ctx)<EOL>if is_null(self._ssl):<EOL><INDENT>self._ssl = None<EOL>handle_openssl_error(<NUM_LIT:0>)<EOL><DEDENT>mem_bio = libssl.BIO_s_mem()<EOL>self._rbio = libssl.BIO_new(mem_bio)<EOL>if is_null(self._rbio):<EOL><INDENT>handle_openssl_error(<NUM_LIT:0>)<EOL><DEDENT>self._wbio = libssl.BIO_new(mem_bio)<EOL>if is_null(self._wbio):<EOL><INDENT>handle_openssl_error(<NUM_LIT:0>)<EOL><DEDENT>libssl.SSL_set_bio(self._ssl, self._rbio, self._wbio)<EOL>utf8_domain = self._hostname.encode('<STR_LIT:utf-8>')<EOL>libssl.SSL_ctrl(<EOL>self._ssl,<EOL>LibsslConst.SSL_CTRL_SET_TLSEXT_HOSTNAME,<EOL>LibsslConst.TLSEXT_NAMETYPE_host_name,<EOL>utf8_domain<EOL>)<EOL>libssl.SSL_set_connect_state(self._ssl)<EOL>if self._session._ssl_session:<EOL><INDENT>libssl.SSL_set_session(self._ssl, self._session._ssl_session)<EOL><DEDENT>self._bio_write_buffer = buffer_from_bytes(self._buffer_size)<EOL>self._read_buffer = buffer_from_bytes(self._buffer_size)<EOL>handshake_server_bytes = b'<STR_LIT>'<EOL>handshake_client_bytes = b'<STR_LIT>'<EOL>while True:<EOL><INDENT>result = libssl.SSL_do_handshake(self._ssl)<EOL>handshake_client_bytes += self._raw_write()<EOL>if result == <NUM_LIT:1>:<EOL><INDENT>break<EOL><DEDENT>error = libssl.SSL_get_error(self._ssl, result)<EOL>if error == LibsslConst.SSL_ERROR_WANT_READ:<EOL><INDENT>chunk = self._raw_read()<EOL>if chunk == b'<STR_LIT>':<EOL><INDENT>if handshake_server_bytes == b'<STR_LIT>':<EOL><INDENT>raise_disconnection()<EOL><DEDENT>if detect_client_auth_request(handshake_server_bytes):<EOL><INDENT>raise_client_auth()<EOL><DEDENT>raise_protocol_error(handshake_server_bytes)<EOL><DEDENT>handshake_server_bytes += chunk<EOL><DEDENT>elif error == LibsslConst.SSL_ERROR_WANT_WRITE:<EOL><INDENT>handshake_client_bytes += self._raw_write()<EOL><DEDENT>elif error == LibsslConst.SSL_ERROR_ZERO_RETURN:<EOL><INDENT>self._gracefully_closed = True<EOL>self._shutdown(False)<EOL>self._raise_closed()<EOL><DEDENT>else:<EOL><INDENT>info = peek_openssl_error()<EOL>if libcrypto_version_info < (<NUM_LIT:1>, <NUM_LIT:1>):<EOL><INDENT>dh_key_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,<EOL>LibsslConst.SSL_R_DH_KEY_TOO_SMALL<EOL>)<EOL><DEDENT>else:<EOL><INDENT>dh_key_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_TLS_PROCESS_SKE_DHE,<EOL>LibsslConst.SSL_R_DH_KEY_TOO_SMALL<EOL>)<EOL><DEDENT>if info == dh_key_info:<EOL><INDENT>raise_dh_params()<EOL><DEDENT>if libcrypto_version_info < (<NUM_LIT:1>, <NUM_LIT:1>):<EOL><INDENT>unknown_protocol_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO,<EOL>LibsslConst.SSL_R_UNKNOWN_PROTOCOL<EOL>)<EOL><DEDENT>else:<EOL><INDENT>unknown_protocol_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL3_GET_RECORD,<EOL>LibsslConst.SSL_R_WRONG_VERSION_NUMBER<EOL>)<EOL><DEDENT>if info == unknown_protocol_info:<EOL><INDENT>raise_protocol_error(handshake_server_bytes)<EOL><DEDENT>tls_version_info_error = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO,<EOL>LibsslConst.SSL_R_TLSV1_ALERT_PROTOCOL_VERSION<EOL>)<EOL>if info == tls_version_info_error:<EOL><INDENT>raise_protocol_version()<EOL><DEDENT>handshake_error_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL23_GET_SERVER_HELLO,<EOL>LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE<EOL>)<EOL>if info == handshake_error_info:<EOL><INDENT>raise_handshake()<EOL><DEDENT>handshake_failure_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL3_READ_BYTES,<EOL>LibsslConst.SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE<EOL>)<EOL>if info == handshake_failure_info:<EOL><INDENT>raise_client_auth()<EOL><DEDENT>if libcrypto_version_info < (<NUM_LIT:1>, <NUM_LIT:1>):<EOL><INDENT>cert_verify_failed_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_SSL3_GET_SERVER_CERTIFICATE,<EOL>LibsslConst.SSL_R_CERTIFICATE_VERIFY_FAILED<EOL>)<EOL><DEDENT>else:<EOL><INDENT>cert_verify_failed_info = (<EOL><NUM_LIT:20>,<EOL>LibsslConst.SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,<EOL>LibsslConst.SSL_R_CERTIFICATE_VERIFY_FAILED<EOL>)<EOL><DEDENT>if info == cert_verify_failed_info:<EOL><INDENT>verify_result = libssl.SSL_get_verify_result(self._ssl)<EOL>chain = extract_chain(handshake_server_bytes)<EOL>self_signed = False<EOL>time_invalid = False<EOL>no_issuer = False<EOL>cert = None<EOL>oscrypto_cert = None<EOL>if chain:<EOL><INDENT>cert = chain[<NUM_LIT:0>]<EOL>oscrypto_cert = load_certificate(cert)<EOL>self_signed = oscrypto_cert.self_signed<EOL>issuer_error_codes = set([<EOL>LibsslConst.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,<EOL>LibsslConst.X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,<EOL>LibsslConst.X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY<EOL>])<EOL>if verify_result in issuer_error_codes:<EOL><INDENT>no_issuer = not self_signed<EOL><DEDENT>time_error_codes = set([<EOL>LibsslConst.X509_V_ERR_CERT_HAS_EXPIRED,<EOL>LibsslConst.X509_V_ERR_CERT_NOT_YET_VALID<EOL>])<EOL>time_invalid = verify_result in time_error_codes<EOL><DEDENT>if time_invalid:<EOL><INDENT>raise_expired_not_yet_valid(cert)<EOL><DEDENT>if no_issuer:<EOL><INDENT>raise_no_issuer(cert)<EOL><DEDENT>if self_signed:<EOL><INDENT>raise_self_signed(cert)<EOL><DEDENT>if oscrypto_cert and oscrypto_cert.asn1.hash_algo in set(['<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>raise_weak_signature(oscrypto_cert)<EOL><DEDENT>raise_verification(cert)<EOL><DEDENT>handle_openssl_error(<NUM_LIT:0>, TLSError)<EOL><DEDENT><DEDENT>session_info = parse_session_info(<EOL>handshake_server_bytes,<EOL>handshake_client_bytes<EOL>)<EOL>self._protocol = session_info['<STR_LIT>']<EOL>self._cipher_suite = session_info['<STR_LIT>']<EOL>self._compression = session_info['<STR_LIT>']<EOL>self._session_id = session_info['<STR_LIT>']<EOL>self._session_ticket = session_info['<STR_LIT>']<EOL>if self._cipher_suite.find('<STR_LIT>') != -<NUM_LIT:1>:<EOL><INDENT>dh_params_length = get_dh_params_length(handshake_server_bytes)<EOL>if dh_params_length < <NUM_LIT>:<EOL><INDENT>self.close()<EOL>raise_dh_params()<EOL><DEDENT><DEDENT>if self._session_id == '<STR_LIT>' or self._session_ticket == '<STR_LIT>':<EOL><INDENT>if self._session._ssl_session:<EOL><INDENT>libssl.SSL_SESSION_free(self._session._ssl_session)<EOL><DEDENT>self._session._ssl_session = libssl.SSL_get1_session(self._ssl)<EOL><DEDENT>if not self._session._manual_validation:<EOL><INDENT>if self.certificate.hash_algo in set(['<STR_LIT>', '<STR_LIT>']):<EOL><INDENT>raise_weak_signature(self.certificate)<EOL><DEDENT>if not self.certificate.is_valid_domain_ip(self._hostname):<EOL><INDENT>raise_hostname(self.certificate, self._hostname)<EOL><DEDENT><DEDENT><DEDENT>except (OSError, socket_.error):<EOL><INDENT>if self._ssl:<EOL><INDENT>libssl.SSL_free(self._ssl)<EOL>self._ssl = None<EOL>self._rbio = None<EOL>self._wbio = None<EOL><DEDENT>else:<EOL><INDENT>if self._rbio:<EOL><INDENT>libssl.BIO_free(self._rbio)<EOL>self._rbio = None<EOL><DEDENT>if self._wbio:<EOL><INDENT>libssl.BIO_free(self._wbio)<EOL>self._wbio = None<EOL><DEDENT><DEDENT>self.close()<EOL>raise<EOL><DEDENT>
Perform an initial TLS handshake