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

Function ssl_read_tls_records

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

Read TLS records from socket to rustls

(
    conn: &mut TlsConnection,
    data: PyObjectRef,
    is_bio: bool,
    vm: &VirtualMachine,
)

Source from the content-addressed store, hash-verified

2000
2001/// Read TLS records from socket to rustls
2002fn ssl_read_tls_records(
2003 conn: &mut TlsConnection,
2004 data: PyObjectRef,
2005 is_bio: bool,
2006 vm: &VirtualMachine,
2007) -> SslResult<()> {
2008 // Convert PyObject to bytes-like (supports bytes, bytearray, etc.)
2009 let bytes = ArgBytesLike::try_from_object(vm, data)
2010 .map_err(|_| SslError::Syscall("Expected bytes-like object".to_string()))?;
2011
2012 let bytes_data = bytes.borrow_buf();
2013
2014 if bytes_data.is_empty() {
2015 // different error for BIO vs socket mode
2016 if is_bio {
2017 // In BIO mode, no data means WANT_READ
2018 return Err(SslError::WantRead);
2019 } else {
2020 // In socket mode, empty recv() means TCP EOF (FIN received)
2021 // Need to distinguish:
2022 // 1. Clean shutdown: received TLS close_notify → return ZeroReturn (0 bytes)
2023 // 2. Unexpected EOF: no close_notify → return Eof (SSLEOFError)
2024 //
2025 // SSL_ERROR_ZERO_RETURN vs SSL_ERROR_EOF logic
2026 // CPython checks SSL_get_shutdown() & SSL_RECEIVED_SHUTDOWN
2027 //
2028 // Process any buffered TLS records (may contain close_notify)
2029 match conn.process_new_packets() {
2030 Ok(io_state) => {
2031 if io_state.peer_has_closed() {
2032 // Received close_notify - normal SSL closure (SSL_ERROR_ZERO_RETURN)
2033 return Err(SslError::ZeroReturn);
2034 } else {
2035 // No close_notify - ragged EOF (SSL_ERROR_EOF → SSLEOFError)
2036 // CPython raises SSLEOFError here, which SSLSocket.read() handles
2037 // based on suppress_ragged_eofs setting
2038 return Err(SslError::Eof);
2039 }
2040 }
2041 Err(e) => return Err(SslError::from_rustls(e)),
2042 }
2043 }
2044 }
2045
2046 // Feed all received data to read_tls - loop to consume all data
2047 // read_tls may not consume all data in one call, and buffer may become full
2048 let mut offset = 0;
2049 while offset < bytes_data.len() {
2050 let remaining = &bytes_data[offset..];
2051 let mut cursor = std::io::Cursor::new(remaining);
2052
2053 match conn.read_tls(&mut cursor) {
2054 Ok(read_bytes) => {
2055 if read_bytes == 0 {
2056 // Buffer is full - process existing packets to make room
2057 conn.process_new_packets().map_err(SslError::from_rustls)?;
2058
2059 // Try again - if we still can't consume, break

Callers 4

handshake_read_dataFunction · 0.85
ssl_readFunction · 0.85
ssl_writeFunction · 0.85

Calls 9

newFunction · 0.85
to_stringMethod · 0.80
process_new_packetsMethod · 0.80
read_tlsMethod · 0.80
ErrClass · 0.50
borrow_bufMethod · 0.45
is_emptyMethod · 0.45
lenMethod · 0.45
containsMethod · 0.45

Tested by

no test coverage detected