MCPcopy Index your code
hub / github.com/RustPython/RustPython / shutdown

Method shutdown

crates/stdlib/src/ssl.rs:4032–4268  ·  view source on GitHub ↗
(&self, vm: &VirtualMachine)

Source from the content-addressed store, hash-verified

4030
4031 #[pymethod]
4032 fn shutdown(&self, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
4033 // Check current shutdown state
4034 let current_state = *self.shutdown_state.lock();
4035
4036 // If already completed, return immediately
4037 if current_state == ShutdownState::Completed {
4038 if self.is_bio_mode() {
4039 return Ok(vm.ctx.none());
4040 }
4041 return Ok(self.sock.clone());
4042 }
4043
4044 // Get connection
4045 let mut conn_guard = self.connection.lock();
4046 let conn = conn_guard
4047 .as_mut()
4048 .ok_or_else(|| vm.new_value_error("Connection not established"))?;
4049
4050 let is_bio = self.is_bio_mode();
4051
4052 // Step 1: Send our close_notify if not already sent
4053 if current_state == ShutdownState::NotStarted {
4054 // First, flush ALL pending TLS data BEFORE sending close_notify
4055 // This is CRITICAL - close_notify must come AFTER all application data
4056 // Otherwise data loss occurs when peer receives close_notify first
4057
4058 // Step 1a: Flush any pending TLS records from rustls internal buffer
4059 // This ensures all application data is converted to TLS records
4060 while conn.wants_write() {
4061 let mut buf = Vec::new();
4062 conn.write_tls(&mut buf)
4063 .map_err(|e| vm.new_os_error(format!("TLS write failed: {e}")))?;
4064 if !buf.is_empty() {
4065 self.send_tls_output(buf, vm)?;
4066 }
4067 }
4068
4069 // Step 1b: Flush pending_tls_output buffer to socket
4070 if !is_bio {
4071 // Socket mode: blocking flush to ensure data order
4072 // Must complete before sending close_notify
4073 self.blocking_flush_all_pending(vm)?;
4074 } else {
4075 // BIO mode: non-blocking flush (caller handles pending data)
4076 let _ = self.flush_pending_tls_output(vm, None);
4077 }
4078
4079 conn.send_close_notify();
4080
4081 // Write close_notify to outgoing buffer/BIO
4082 self.write_pending_tls(conn, vm)?;
4083 // Ensure close_notify and any pending TLS data are flushed
4084 if !is_bio {
4085 self.flush_pending_tls_output(vm, None)?;
4086 }
4087
4088 // Update state
4089 *self.shutdown_state.lock() = ShutdownState::SentCloseNotify;

Callers

nothing calls this directly

Calls 15

newFunction · 0.85
timeout_error_msgFunction · 0.85
is_bio_modeMethod · 0.80
noneMethod · 0.80
ok_or_elseMethod · 0.80
wants_writeMethod · 0.80
write_tlsMethod · 0.80
new_os_errorMethod · 0.80
send_tls_outputMethod · 0.80

Tested by

no test coverage detected