8000 Fix install ujson by youknowone · Pull Request #6502 · RustPython/RustPython · GitHub
[go: up one dir, main page]

Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 76 additions & 20 deletions crates/stdlib/src/ssl/compat.rs
8000
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,50 @@ pub(super) fn ssl_read(
return Err(SslError::Eof);
}
}

// For non-blocking sockets, return WantRead so caller can poll and retry.
// For blocking sockets (or sockets with timeout), wait for more data.
if !is_bio {
let timeout = socket.get_socket_timeout(vm).map_err(SslError::Py)?;
if let Some(t) = timeout
&& t.is_zero()
{
// Non-blocking socket: return immediately
return Err(SslError::WantRead);
}
// Blocking socket or socket with timeout: try to read more data from socket.
// Even though rustls says it doesn't want to read, more TLS records may arrive.
// This handles the case where rustls processed all buffered TLS records but
// more data is coming over the network.
let data = match socket.sock_recv(2048, vm) {
Ok(data) => data,
Err(e) => {
if is_connection_closed_error(&e, vm) {
return Err(SslError::Eof);
}
return Err(SslError::Py(e));
}
};

let bytes_read = data
.clone()
.try_into_value::<rustpython_vm::builtins::PyBytes>(vm)
.map(|b| b.as_bytes().len())
.unwrap_or(0);

if bytes_read == 0 {
// No more data available - connection might be closed
return Err(SslError::Eof);
}

// Feed data to rustls and process
ssl_read_tls_records(conn, data, false, vm)?;
conn.process_new_packets().map_err(SslError::from_rustls)?;

// Continue loop to try reading plaintext
continue;
}

return Err(SslError::WantRead);
}

Expand All @@ -1432,20 +1476,9 @@ pub(super) fn ssl_read(
// Continue loop to try reading plaintext
}
Err(SslError::Io(ref io_err)) if io_err.to_string().contains("message buffer full") => {
// Buffer is full - we need to consume plaintext before reading more
// Try to read plaintext now
match try_read_plaintext(conn, buf)? {
Some(n) if n > 0 => {
// Have plaintext - return it
// Python will call read() again if it needs more data
return Ok(n);
}
_ => {
// No plaintext available yet - this is unusual
// Return WantRead to let Python retry
return Err(SslError::WantRead);
}
}
// This case should be rare now that ssl_read_tls_records handles buffer full
// Just continue loop to try again
continue;
}
Err(e) => {
// Other errors - check for buffered plaintext before propagating
Expand Down Expand Up @@ -1524,7 +1557,7 @@ fn ssl_read_tls_records(
}

// Feed all received data to read_tls - loop to consume all data
// read_tls may not consume all data in one call
// read_tls may not consume all data in one call, and buffer may become full
let mut offset = 0;
while offset < bytes_data.len() {
let remaining = &bytes_data[offset..];
Expand All @@ -1533,12 +1566,33 @@ fn ssl_read_tls_records(
match conn.read_tls(&mut cursor) {
Ok(read_bytes) => {
if read_bytes == 0 {
// No more data can be consumed
break;
// Buffer is full - process existing packets to make room
conn.process_new_packets().map_err(SslError::from_rustls)?;

// Try again - if we still can't consume, break
let mut retry_cursor = std::io::Cursor::new(remaining);
match conn.read_tls(&mut retry_cursor) {
Ok(0) => {
// Still can't consume - break to avoid infinite loop
break;
}
Ok(n) => {
offset += n;
}
Err(e) => {
return Err(SslError::Io(e));
}
}
} else {
offset += read_bytes;
}
offset += read_bytes;
}
Err(e) => {
// Check if it's a buffer full error (unlikely but handle it)
if e.to_string().contains("buffer full") {
conn.process_new_packets().map_err(SslError::from_rustls)?;
continue;
}
// Real error - propagate it
return Err(SslError::Io(e));
}
Expand Down Expand Up @@ -1599,8 +1653,10 @@ fn ssl_ensure_data_available(
.sock_wait_for_io_impl(SelectKind::Read, vm)
.map_err(SslError::Py)?;
if timed_out {
// Socket not ready within timeout
return Err(SslError::WantRead);
// Socket not ready within timeout - raise socket.timeout
return Err(SslError::Timeout(
"The read operation timed out".to_string(),
));
}
}
// else: non-blocking socket (timeout=0) or blocking socket (timeout=None) - skip select
Expand Down
Loading
0