Flush all pending TLS output data, respecting socket timeout Used during handshake completion and shutdown() to ensure all data is sent
(&self, vm: &VirtualMachine)
| 2974 | /// Flush all pending TLS output data, respecting socket timeout |
| 2975 | /// Used during handshake completion and shutdown() to ensure all data is sent |
| 2976 | pub(crate) fn blocking_flush_all_pending(&self, vm: &VirtualMachine) -> PyResult<()> { |
| 2977 | // Get socket timeout to respect during flush |
| 2978 | let timeout = self.get_socket_timeout(vm)?; |
| 2979 | if timeout.map(|t| t.is_zero()).unwrap_or(false) { |
| 2980 | return self.flush_pending_tls_output(vm, None); |
| 2981 | } |
| 2982 | |
| 2983 | loop { |
| 2984 | let pending_data = { |
| 2985 | let pending = self.pending_tls_output.lock(); |
| 2986 | if pending.is_empty() { |
| 2987 | return Ok(()); |
| 2988 | } |
| 2989 | pending.clone() |
| 2990 | }; |
| 2991 | |
| 2992 | // Wait for socket to be writable, respecting socket timeout |
| 2993 | let py_socket: PyRef<PySocket> = self.sock.clone().try_into_value(vm)?; |
| 2994 | let socket = py_socket |
| 2995 | .sock() |
| 2996 | .map_err(|e| vm.new_os_error(format!("Failed to get socket: {e}")))?; |
| 2997 | let timed_out = sock_select(&socket, SelectKind::Write, timeout) |
| 2998 | .map_err(|e| vm.new_os_error(format!("select failed: {e}")))?; |
| 2999 | |
| 3000 | if timed_out { |
| 3001 | return Err( |
| 3002 | timeout_error_msg(vm, "The write operation timed out".to_string()).upcast(), |
| 3003 | ); |
| 3004 | } |
| 3005 | |
| 3006 | // Try to send pending data (use raw to avoid recursion) |
| 3007 | match self.sock_send(&pending_data, vm) { |
| 3008 | Ok(result) => { |
| 3009 | let sent: usize = result.try_to_value::<isize>(vm)?.try_into().unwrap_or(0); |
| 3010 | if sent > 0 { |
| 3011 | let mut pending = self.pending_tls_output.lock(); |
| 3012 | pending.drain(..sent); |
| 3013 | } |
| 3014 | // If sent == 0, loop will retry with sock_select |
| 3015 | } |
| 3016 | Err(e) => { |
| 3017 | if is_blocking_io_error(&e, vm) { |
| 3018 | continue; |
| 3019 | } |
| 3020 | return Err(e); |
| 3021 | } |
| 3022 | } |
| 3023 | } |
| 3024 | } |
| 3025 | |
| 3026 | // Helper function to convert Python PROTO_* constants to rustls versions |
| 3027 | fn get_rustls_versions( |
no test coverage detected