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

Method try_read_close_notify_socket

crates/stdlib/src/ssl.rs:4352–4419  ·  view source on GitHub ↗

Socket-mode close_notify reader that respects TLS record boundaries. Uses MSG_PEEK to inspect data before consuming, preventing accidental consumption of post-TLS cleartext data during STARTTLS transitions. Equivalent to OpenSSL's `SSL_set_read_ahead(ssl, 0)` — rustls has no such knob, so we enforce record-level reads manually via peek.

(
            &self,
            conn: &mut TlsConnection,
            vm: &VirtualMachine,
        )

Source from the content-addressed store, hash-verified

4350 /// Equivalent to OpenSSL's `SSL_set_read_ahead(ssl, 0)` — rustls has no
4351 /// such knob, so we enforce record-level reads manually via peek.
4352 fn try_read_close_notify_socket(
4353 &self,
4354 conn: &mut TlsConnection,
4355 vm: &VirtualMachine,
4356 ) -> PyResult<bool> {
4357 // Peek at the first 5 bytes (TLS record header size)
4358 let peeked_obj = match self.sock_peek(5, vm) {
4359 Ok(obj) => obj,
4360 Err(e) => {
4361 if is_blocking_io_error(&e, vm) {
4362 return Ok(false);
4363 }
4364 return Ok(true);
4365 }
4366 };
4367
4368 let peeked = ArgBytesLike::try_from_object(vm, peeked_obj)?;
4369 let peek_data = peeked.borrow_buf();
4370
4371 if peek_data.is_empty() {
4372 return Ok(true); // EOF
4373 }
4374
4375 // TLS record content types: ChangeCipherSpec(20), Alert(21),
4376 // Handshake(22), ApplicationData(23)
4377 let content_type = peek_data[0];
4378 if !(20..=23).contains(&content_type) {
4379 // Not a TLS record - post-TLS cleartext data.
4380 // Peer has completed TLS shutdown; don't consume this data.
4381 return Ok(true);
4382 }
4383
4384 // Determine how many bytes to read for exactly one TLS record
4385 let recv_size = if peek_data.len() >= 5 {
4386 let record_length = u16::from_be_bytes([peek_data[3], peek_data[4]]) as usize;
4387 5 + record_length
4388 } else {
4389 // Partial header available - read just these bytes for now
4390 peek_data.len()
4391 };
4392
4393 drop(peek_data);
4394 drop(peeked);
4395
4396 // Now consume exactly one TLS record from the socket
4397 match self.sock_recv(recv_size, vm) {
4398 Ok(bytes_obj) => {
4399 let bytes = ArgBytesLike::try_from_object(vm, bytes_obj)?;
4400 let data = bytes.borrow_buf();
4401
4402 if data.is_empty() {
4403 return Ok(true);
4404 }
4405
4406 let data_slice: &[u8] = data.as_ref();
4407 let mut cursor = std::io::Cursor::new(data_slice);
4408 let _ = conn.read_tls(&mut cursor);
4409 let _ = conn.process_new_packets();

Callers 1

try_read_close_notifyMethod · 0.80

Calls 11

is_blocking_io_errorFunction · 0.85
newFunction · 0.85
sock_peekMethod · 0.80
read_tlsMethod · 0.80
process_new_packetsMethod · 0.80
borrow_bufMethod · 0.45
is_emptyMethod · 0.45
containsMethod · 0.45
lenMethod · 0.45
sock_recvMethod · 0.45
as_refMethod · 0.45

Tested by

no test coverage detected