MCPcopy Index your code
hub / github.com/RustPython/RustPython / ssl_do_handshake

Function ssl_do_handshake

crates/stdlib/src/ssl/compat.rs:1444–1603  ·  view source on GitHub ↗

Equivalent to OpenSSL's SSL_do_handshake() Performs TLS handshake by exchanging data with the peer until completion. This abstracts away the low-level rustls read_tls/write_tls loop. = SSL_do_handshake()

(
    conn: &mut TlsConnection,
    socket: &PySSLSocket,
    vm: &VirtualMachine,
)

Source from the content-addressed store, hash-verified

1442///
1443/// = SSL_do_handshake()
1444pub(super) fn ssl_do_handshake(
1445 conn: &mut TlsConnection,
1446 socket: &PySSLSocket,
1447 vm: &VirtualMachine,
1448) -> SslResult<()> {
1449 // Check if handshake is already done
1450 if !conn.is_handshaking() {
1451 return Ok(());
1452 }
1453
1454 let is_bio = socket.is_bio_mode();
1455 let is_server = matches!(conn, TlsConnection::Server(_));
1456 let mut first_iteration = true; // Track if this is the first loop iteration
1457 let mut iteration_count = 0;
1458
1459 loop {
1460 iteration_count += 1;
1461 let mut made_progress = false;
1462
1463 // IMPORTANT: In BIO mode, force initial write even if wants_write() is false
1464 // rustls requires write_tls() to be called to generate ClientHello/ServerHello
1465 let force_initial_write = is_bio && first_iteration;
1466
1467 // Write TLS handshake data to socket/BIO
1468 let write_progress = handshake_write_loop(conn, socket, force_initial_write, vm)?;
1469 made_progress |= write_progress;
1470
1471 // Read TLS handshake data from socket/BIO
1472 let (read_progress, is_first_sni_read) =
1473 handshake_read_data(conn, socket, is_bio, is_server, vm)?;
1474 made_progress |= read_progress;
1475
1476 // Process TLS packets (state machine)
1477 if let Err(e) = conn.process_new_packets() {
1478 // Send close_notify on error
1479 if !is_bio {
1480 conn.send_close_notify();
1481 // Flush any pending TLS data before sending close_notify
1482 let _ = socket.flush_pending_tls_output(vm, None);
1483 // Actually send the close_notify alert using send_all_bytes
1484 // for proper partial send handling and retry logic
1485 if let Ok(alert_data) = ssl_write_tls_records(conn)
1486 && !alert_data.is_empty()
1487 {
1488 let _ = send_all_bytes(socket, alert_data, vm, None);
1489 }
1490 }
1491
1492 // InvalidMessage during handshake means non-TLS data was received
1493 // before the handshake completed (e.g., HTTP request to TLS server)
1494 if matches!(e, rustls::Error::InvalidMessage(_)) {
1495 return Err(SslError::PreauthData);
1496 }
1497
1498 // Certificate verification errors are already handled by from_rustls
1499
1500 return Err(SslError::from_rustls(e));
1501 }

Callers 1

do_handshakeMethod · 0.85

Calls 15

handshake_write_loopFunction · 0.85
handshake_read_dataFunction · 0.85
ssl_write_tls_recordsFunction · 0.85
send_all_bytesFunction · 0.85
is_handshakingMethod · 0.80
is_bio_modeMethod · 0.80
process_new_packetsMethod · 0.80
send_close_notifyMethod · 0.80
has_sni_callbackMethod · 0.80
wants_writeMethod · 0.80

Tested by

no test coverage detected