8000 flush · RustPython/RustPython@2092aad · GitHub
[go: up one dir, main page]

Skip to content

Commit 2092aad

Browse files
committed
flush
1 parent 21ac766 commit 2092aad

File tree

1 file changed

+46
-34
lines changed

1 file changed

+46
-34
lines changed

crates/stdlib/src/ssl.rs

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,44 +3427,56 @@ mod _ssl {
34273427
.as_mut()
34283428
.ok_or_else(|| vm.new_value_error("Connection not established"))?;
34293429

3430-
// Unified write logic - no need to match on Client/Server anymore
3431-
let mut writer = conn.writer();
3432-
writer
3433-
.write_all(data_bytes.as_ref())
3434-
.map_err(|e| vm.new_os_error(format!("Write failed: {e}")))?;
3430+
let is_bio = self.is_bio_mode();
3431+
let data: &[u8] = data_bytes.as_ref();
34353432

3436-
// Flush to get TLS-encrypted data (writer automatically flushed on drop)
3437-
// Send encrypted data to socket
3438-
if conn.wants_write() {
3439-
let is_bio = self.is_bio_mode();
3433+
// Write data in chunks to avoid filling the internal TLS buffer
3434+
// rustls has a limited internal buffer, so we need to flush periodically
3435+
const CHUNK_SIZE: usize = 16384; // 16KB chunks (typical TLS record size)
3436+
let mut written = 0;
34403437

3441-
if is_bio {
3442-
// BIO mode: Write ALL pending TLS data to outgoing BIO
3443-
// This prevents hangs where Python's ssl_io_loop waits for data
3444-
self.write_pending_tls(conn, vm)?;
3445-
} else {
3446-
// Socket mode: Try once and may return SSLWantWriteError
3447-
let mut buf = Vec::new();
3448-
conn.write_tls(&mut buf)
3449-
.map_err(|e| vm.new_os_error(format!("TLS write failed: {e}")))?;
3450-
3451-
if !buf.is_empty() {
3452-
// Wait for socket to be ready for writing
3453-
let timed_out = self.sock_wait_for_io_impl(SelectKind::Write, vm)?;
3454-
if timed_out {
3455-
return Err(vm.new_os_error("Write operation timed out"));
3456-
}
3438+
while written < data.len() {
3439+
let chunk_end = std::cmp::min(written + CHUNK_SIZE, data.len());
3440+
let chunk = &data[writt 10000 en..chunk_end];
3441+
3442+
// Write chunk to TLS layer
3443+
{
3444+
let mut writer = conn.writer();
3445+
use std::io::Write;
3446+
writer
3447+
.write_all(chunk)
3448+
.map_err(|e| vm.new_os_error(format!("Write failed: {e}")))?;
3449+
}
3450+
3451+
written = chunk_end;
3452+
3453+
// Flush TLS data to socket after each chunk
3454+
if conn.wants_write() {
3455+
if is_bio {
3456+
self.write_pending_tls(conn, vm)?;
3457+
} else {
3458+
// Socket mode: flush all pending TLS data
3459+
while conn.wants_write() {
3460+
let mut buf = Vec::new();
3461+
conn.write_tls(&mut buf)
3462+
.map_err(|e| vm.new_os_error(format!("TLS write failed: {e}")))?;
3463+
3464+
if !buf.is_empty() {
3465+
let timed_out =
3466+
self.sock_wait_for_io_impl(SelectKind::Write, vm)?;
3467+
if timed_out {
3468+
return Err(vm.new_os_error("Write operation timed out"));
3469+
}
34573470

3458-
// Send encrypted data to socket
3459-
// Convert BlockingIOError to SSLWantWriteError
3460-
match self.sock_send(buf, vm) {
3461-
Ok(_) => {}
3462-
Err(e) => {
3463-
if is_blocking_io_error(&e, vm) {
3464-
// Non-blocking socket would block - return SSLWantWriteError
3465-
return Err(create_ssl_want_write_error(vm));
3471+
match self.sock_send(buf, vm) {
3472+
Ok(_) => {}
3473+
Err(e) => {
3474+
if is_blocking_io_error(&e, vm) {
3475+
return Err(create_ssl_want_write_error(vm));
3476+
}
3477+
return Err(e);
3478+
}
34663479
}
3467-
return Err(e);
34683480
}
34693481
}
34703482
}

0 commit comments

Comments
 (0)
0