(
zelf: PyRef<Self>,
args: WrapSocketArgs,
vm: &VirtualMachine,
)
| 2094 | |
| 2095 | #[pymethod] |
| 2096 | fn _wrap_socket( |
| 2097 | zelf: PyRef<Self>, |
| 2098 | args: WrapSocketArgs, |
| 2099 | vm: &VirtualMachine, |
| 2100 | ) -> PyResult<PyObjectRef> { |
| 2101 | // Use common helper function |
| 2102 | let (ssl, socket_type, server_hostname) = |
| 2103 | Self::new_py_ssl_socket(zelf.clone(), args.server_side, args.server_hostname, vm)?; |
| 2104 | |
| 2105 | // Create SslStream with socket |
| 2106 | let stream = ssl::SslStream::new(ssl, SocketStream(args.sock.clone())) |
| 2107 | .map_err(|e| convert_openssl_error(vm, e))?; |
| 2108 | |
| 2109 | let py_ssl_socket = PySslSocket { |
| 2110 | ctx: PyRwLock::new(zelf.clone()), |
| 2111 | connection: PyRwLock::new(SslConnection::Socket(stream)), |
| 2112 | socket_type, |
| 2113 | server_hostname, |
| 2114 | owner: PyRwLock::new(args.owner.map(|o| o.downgrade(None, vm)).transpose()?), |
| 2115 | }; |
| 2116 | |
| 2117 | // Convert to PyRef (heap allocation) to avoid use-after-free |
| 2118 | let py_ref = |
| 2119 | py_ssl_socket.into_ref_with_type(vm, PySslSocket::class(&vm.ctx).to_owned())?; |
| 2120 | |
| 2121 | // Check if SNI callback is configured (minimize lock time) |
| 2122 | let has_sni_callback = zelf.sni_callback.lock().is_some(); |
| 2123 | |
| 2124 | // Set up ex_data for callbacks |
| 2125 | unsafe { |
| 2126 | let ssl_ptr = py_ref.connection.read().ssl().as_ptr(); |
| 2127 | |
| 2128 | // Clone and store via into_raw() - increments refcount and returns stable pointer |
| 2129 | // The refcount will be decremented by msg_callback_data_free when SSL is freed |
| 2130 | let cloned: PyObjectRef = py_ref.clone().into(); |
| 2131 | let raw_ptr = cloned.into_raw(); |
| 2132 | let msg_cb_idx = get_msg_callback_ex_data_index(); |
| 2133 | sys::SSL_set_ex_data(ssl_ptr, msg_cb_idx, raw_ptr.as_ptr() as *mut _); |
| 2134 | |
| 2135 | // Set SNI callback data if needed |
| 2136 | if has_sni_callback { |
| 2137 | let ssl_socket_weak = py_ref.as_object().downgrade(None, vm)?; |
| 2138 | // Store callback data in SSL ex_data - use weak reference to avoid cycle |
| 2139 | let callback_data = Box::new(SniCallbackData { |
| 2140 | ssl_context: zelf.clone(), |
| 2141 | ssl_socket_weak, |
| 2142 | }); |
| 2143 | let sni_idx = get_sni_ex_data_index(); |
| 2144 | sys::SSL_set_ex_data(ssl_ptr, sni_idx, Box::into_raw(callback_data) as *mut _); |
| 2145 | } |
| 2146 | } |
| 2147 | |
| 2148 | // Set session if provided |
| 2149 | if let Some(session) = args.session |
| 2150 | && !vm.is_none(&session) |
| 2151 | { |
| 2152 | py_ref.set_session(session, vm)?; |
| 2153 | } |
nothing calls this directly
no test coverage detected