Skip to content

Commit 036ee48

Browse files
committed
flush
1 parent da1bdfc commit 036ee48

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
@@ -3440,44 +3440,56 @@ mod _ssl {
34403440
.as_mut()
34413441
.ok_or_else(|| vm.new_value_error("Connection not established"))?;
34423442

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

3449-
// Flush to get TLS-encrypted data (writer automatically flushed on drop)
3450-
// Send encrypted data to socket
3451-
if conn.wants_write() {
3452-
let is_bio = self.is_bio_mode();
3446+
// Write data in chunks to avoid filling the internal TLS buffer
3447+
// rustls has a limited internal buffer, so we need to flush periodically
3448+
const CHUNK_SIZE: usize = 16384; // 16KB chunks (typical TLS record size)
3449+
let mut written = 0;
34533450

3454-
if is_bio {
3455-
// BIO mode: Write ALL pending TLS data to outgoing BIO
3456-
// This prevents hangs where Python's ssl_io_loop waits for data
3457-
self.write_pending_tls(conn, vm)?;
3458-
} else {
3459-
// Socket mode: Try once and may return SSLWantWriteError
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-
// Wait for socket to be ready for writing
3466-
let timed_out = 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-
}
3451+
while written < data.len() {
3452+
let chunk_end = std::cmp::min(written + CHUNK_SIZE, data.len());
3453+
let chunk = &data[written..chunk_end];
3454+
3455+
// Write chunk to TLS layer
3456+
{
3457+
let mut writer = conn.writer();
3458+
use std::io::Write;
3459+
writer
3460+
.write_all(chunk)
3461+
.map_err(|e| vm.new_os_error(format!("Write failed: {e}")))?;
3462+
}
3463+
3464+
written = chunk_end;
3465+
3466+
// Flush TLS data to socket after each chunk
3467+
if conn.wants_write() {
3468+
if is_bio {
3469+
self.write_pending_tls(conn, vm)?;
3470+
} else {
3471+
// Socket mode: flush all pending TLS data
3472+
while conn.wants_write() {
3473+
let mut buf = Vec::new();
3474+
conn.write_tls(&mut buf)
3475+
.map_err(|e| vm.new_os_error(format!("TLS write failed: {e}")))?;
3476+
3477+
if !buf.is_empty() {
3478+
let timed_out =
3479+
self.sock_wait_for_io_impl(SelectKind::Write, vm)?;
3480+
if timed_out {
3481+
return Err(vm.new_os_error("Write operation timed out"));
3482+
}
34703483

3471-
// Send encrypted data to socket
3472-
// Convert BlockingIOError to SSLWantWriteError
3473-
match self.sock_send(buf, vm) {
3474-
Ok(_) => {}
3475-
Err(e) => {
3476-
if is_blocking_io_error(&e, vm) {
3477-
// Non-blocking socket would block - return SSLWantWriteError
3478-
return Err(create_ssl_want_write_error(vm));
3484+
match self.sock_send(buf, vm) {
3485+
Ok(_) => {}
3486+
Err(e) => {
3487+
if is_blocking_io_error(&e, vm) {
3488+
return Err(create_ssl_want_write_error(vm));
3489+
}
3490+
return Err(e);
3491+
}
34793492
}
3480-
return Err(e);
34813493
}
34823494
}
34833495
}

0 commit comments

Comments
 (0)