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

Function ssl_ensure_data_available

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

Ensure TLS data is available for reading Returns the number of bytes read from the socket

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

Source from the content-addressed store, hash-verified

2115/// Ensure TLS data is available for reading
2116/// Returns the number of bytes read from the socket
2117fn ssl_ensure_data_available(
2118 conn: &mut TlsConnection,
2119 socket: &PySSLSocket,
2120 vm: &VirtualMachine,
2121) -> SslResult<usize> {
2122 // Unlike OpenSSL's SSL_read, rustls requires explicit I/O
2123 if conn.wants_read() {
2124 let is_bio = socket.is_bio_mode();
2125
2126 // For non-BIO mode (regular sockets), check if socket is ready first
2127 // PERFORMANCE OPTIMIZATION: Only use select for sockets with timeout
2128 // - Blocking sockets (timeout=None): Skip select, recv() will block naturally
2129 // - Timeout sockets: Use select to enforce timeout
2130 // - Non-blocking sockets: Skip select, recv() will return EAGAIN immediately
2131 if !is_bio {
2132 let timeout = socket.get_socket_timeout(vm).map_err(SslError::Py)?;
2133
2134 // Only use select if socket has a positive timeout
2135 if let Some(t) = timeout
2136 && !t.is_zero()
2137 {
2138 // Socket has timeout - use select to enforce it
2139 let timed_out = socket
2140 .sock_wait_for_io_impl(SelectKind::Read, vm)
2141 .map_err(SslError::Py)?;
2142 if timed_out {
2143 // Socket not ready within timeout - raise socket.timeout
2144 return Err(SslError::Timeout(
2145 "The read operation timed out".to_string(),
2146 ));
2147 }
2148 }
2149 // else: non-blocking socket (timeout=0) or blocking socket (timeout=None) - skip select
2150 }
2151
2152 // Read one TLS record at a time for non-BIO sockets (matching
2153 // OpenSSL's default no-read-ahead behaviour). This prevents
2154 // consuming a close_notify that arrives alongside application data,
2155 // keeping it in the kernel buffer where select() can detect it.
2156 let data = if !is_bio {
2157 recv_one_tls_record_for_data(conn, socket, vm)?
2158 } else {
2159 match socket.sock_recv(2048, vm) {
2160 Ok(data) => data,
2161 Err(e) => {
2162 if is_blocking_io_error(&e, vm) {
2163 return Err(SslError::WantRead);
2164 }
2165 if let Err(rustls_err) = conn.process_new_packets() {
2166 return Err(SslError::from_rustls(rustls_err));
2167 }
2168 if is_connection_closed_error(&e, vm) {
2169 return Err(SslError::Eof);
2170 }
2171 return Err(SslError::Py(e));
2172 }
2173 }
2174 };

Callers 1

ssl_readFunction · 0.85

Calls 15

TimeoutClass · 0.85
is_blocking_io_errorFunction · 0.85
PyClass · 0.85
ssl_read_tls_recordsFunction · 0.85
wants_readMethod · 0.80
is_bio_modeMethod · 0.80
get_socket_timeoutMethod · 0.80
sock_wait_for_io_implMethod · 0.80
to_stringMethod · 0.80
process_new_packetsMethod · 0.80

Tested by

no test coverage detected