@@ -1421,6 +1421,50 @@ pub(super) fn ssl_read(
14211421 return Err ( SslError :: Eof ) ;
14221422 }
14231423 }
1424+
1425+ // For non-blocking sockets, return WantRead so caller can poll and retry.
1426+ // For blocking sockets (or sockets with timeout), wait for more data.
1427+ if !is_bio {
1428+ let timeout = socket. get_socket_timeout ( vm) . map_err ( SslError :: Py ) ?;
1429+ if let Some ( t) = timeout
1430+ && t. is_zero ( )
1431+ {
1432+ // Non-blocking socket: return immediately
1433+ return Err ( SslError :: WantRead ) ;
1434+ }
1435+ // Blocking socket or socket with timeout: try to read more data from socket.
1436+ // Even though rustls says it doesn't want to read, more TLS records may arrive.
1437+ // This handles the case where rustls processed all buffered TLS records but
1438+ // more data is coming over the network.
1439+ let data = match socket. sock_recv ( 2048 , vm) {
1440+ Ok ( data) => data,
1441+ Err ( e) => {
1442+ if is_connection_closed_error ( & e, vm) {
1443+ return Err ( SslError :: Eof ) ;
1444+ }
1445+ return Err ( SslError :: Py ( e) ) ;
1446+ }
1447+ } ;
1448+
1449+ let bytes_read = data
1450+ . clone ( )
1451+ . try_into_value :: < rustpython_vm:: builtins:: PyBytes > ( vm)
1452+ . map ( |b| b. as_bytes ( ) . len ( ) )
1453+ . unwrap_or ( 0 ) ;
1454+
1455+ if bytes_read == 0 {
1456+ // No more data available - connection might be closed
1457+ return Err ( SslError :: Eof ) ;
1458+ }
1459+
1460+ // Feed data to rustls and process
1461+ ssl_read_tls_records ( conn, data, false , vm) ?;
1462+ conn. process_new_packets ( ) . map_err ( SslError :: from_rustls) ?;
1463+
1464+ // Continue loop to try reading plaintext
1465+ continue ;
1466+ }
1467+
14241468 return Err ( SslError :: WantRead ) ;
14251469 }
14261470
@@ -1432,20 +1476,9 @@ pub(super) fn ssl_read(
14321476 // Continue loop to try reading plaintext
14331477 }
14341478 Err ( SslError :: Io ( ref io_err) ) if io_err. to_string ( ) . contains ( "message buffer full" ) => {
1435- // Buffer is full - we need to consume plaintext before reading more
1436- // Try to read plaintext now
1437- match try_read_plaintext ( conn, buf) ? {
1438- Some ( n) if n > 0 => {
1439- // Have plaintext - return it
1440- // Python will call read() again if it needs more data
1441- return Ok ( n) ;
1442- }
1443- _ => {
1444- // No plaintext available yet - this is unusual
1445- // Return WantRead to let Python retry
1446- return Err ( SslError :: WantRead ) ;
1447- }
1448- }
1479+ // This case should be rare now that ssl_read_tls_records handles buffer full
1480+ // Just continue loop to try again
1481+ continue ;
14491482 }
14501483 Err ( e) => {
14511484 // Other errors - check for buffered plaintext before propagating
@@ -1524,7 +1557,7 @@ fn ssl_read_tls_records(
15241557 }
15251558
15261559 // Feed all received data to read_tls - loop to consume all data
1527- // read_tls may not consume all data in one call
1560+ // read_tls may not consume all data in one call, and buffer may become full
15281561 let mut offset = 0 ;
15291562 while offset < bytes_data. len ( ) {
15301563 let remaining = & bytes_data[ offset..] ;
@@ -1533,12 +1566,33 @@ fn ssl_read_tls_records(
15331566 match conn. read_tls ( & mut cursor) {
15341567 Ok ( read_bytes) => {
15351568 if read_bytes == 0 {
1536- // No more data can be consumed
1537- break ;
1569+ // Buffer is full - process existing packets to make room
1570+ conn. process_new_packets ( ) . map_err ( SslError :: from_rustls) ?;
1571+
1572+ // Try again - if we still can't consume, break
1573+ let mut retry_cursor = std:: io:: Cursor :: new ( remaining) ;
1574+ match conn. read_tls ( & mut retry_cursor) {
1575+ Ok ( 0 ) => {
1576+ // Still can't consume - break to avoid infinite loop
1577+ break ;
1578+ }
1579+ Ok ( n) => {
1580+ offset += n;
1581+ }
1582+ Err ( e) => {
1583+ return Err ( SslError :: Io ( e) ) ;
1584+ }
1585+ }
1586+ } else {
1587+ offset += read_bytes;
15381588 }
1539- offset += read_bytes;
15401589 }
15411590 Err ( e) => {
1591+ // Check if it's a buffer full error (unlikely but handle it)
1592+ if e. to_string ( ) . contains ( "buffer full" ) {
1593+ conn. process_new_packets ( ) . map_err ( SslError :: from_rustls) ?;
1594+ continue ;
1595+ }
15421596 // Real error - propagate it
15431597 return Err ( SslError :: Io ( e) ) ;
15441598 }
@@ -1599,8 +1653,10 @@ fn ssl_ensure_data_available(
15991653 . sock_wait_for_io_impl ( SelectKind :: Read , vm)
16001654 . map_err ( SslError :: Py ) ?;
16011655 if timed_out {
1602- // Socket not ready within timeout
1603- return Err ( SslError :: WantRead ) ;
1656+ // Socket not ready within timeout - raise socket.timeout
1657+ return Err ( SslError :: Timeout (
1658+ "The read operation timed out" . to_string ( ) ,
1659+ ) ) ;
16041660 }
16051661 }
16061662 // else: non-blocking socket (timeout=0) or blocking socket (timeout=None) - skip select
0 commit comments