(
&self,
len: OptionalArg<isize>,
buffer: OptionalArg<ArgMemoryBuffer>,
vm: &VirtualMachine,
)
| 3472 | |
| 3473 | #[pymethod] |
| 3474 | fn read( |
| 3475 | &self, |
| 3476 | len: OptionalArg<isize>, |
| 3477 | buffer: OptionalArg<ArgMemoryBuffer>, |
| 3478 | vm: &VirtualMachine, |
| 3479 | ) -> PyResult { |
| 3480 | // Convert len to usize, defaulting to 1024 if not provided |
| 3481 | // -1 means read all available data (treat as large buffer size) |
| 3482 | let len_val = len.unwrap_or(PEM_BUFSIZE as isize); |
| 3483 | let mut len = if len_val == -1 { |
| 3484 | // -1 is only valid when a buffer is provided |
| 3485 | match &buffer { |
| 3486 | OptionalArg::Present(buf_arg) => buf_arg.len(), |
| 3487 | OptionalArg::Missing => { |
| 3488 | return Err(vm.new_value_error("negative read length")); |
| 3489 | } |
| 3490 | } |
| 3491 | } else if len_val < 0 { |
| 3492 | return Err(vm.new_value_error("negative read length")); |
| 3493 | } else { |
| 3494 | len_val as usize |
| 3495 | }; |
| 3496 | |
| 3497 | // if buffer is provided, limit len to buffer size |
| 3498 | if let OptionalArg::Present(buf_arg) = &buffer { |
| 3499 | let buf_len = buf_arg.len(); |
| 3500 | if len_val <= 0 || len > buf_len { |
| 3501 | len = buf_len; |
| 3502 | } |
| 3503 | } |
| 3504 | |
| 3505 | // return empty bytes immediately for len=0 |
| 3506 | if len == 0 { |
| 3507 | return match buffer { |
| 3508 | OptionalArg::Present(_) => Ok(vm.ctx.new_int(0).into()), |
| 3509 | OptionalArg::Missing => Ok(vm.ctx.new_bytes(vec![]).into()), |
| 3510 | }; |
| 3511 | } |
| 3512 | |
| 3513 | // Ensure handshake is done - if not, complete it first |
| 3514 | // This matches OpenSSL behavior where SSL_read() auto-completes handshake |
| 3515 | if !*self.handshake_done.lock() { |
| 3516 | self.do_handshake(vm)?; |
| 3517 | } |
| 3518 | |
| 3519 | // Check if connection has been shut down |
| 3520 | // Only block after shutdown is COMPLETED, not during shutdown process |
| 3521 | let shutdown_state = *self.shutdown_state.lock(); |
| 3522 | if shutdown_state == ShutdownState::Completed { |
| 3523 | return Err(vm |
| 3524 | .new_os_subtype_error( |
| 3525 | PySSLError::class(&vm.ctx).to_owned(), |
| 3526 | None, |
| 3527 | "cannot read after shutdown", |
| 3528 | ) |
| 3529 | .upcast()); |
| 3530 | } |
| 3531 |
no test coverage detected