(
cmsgs: &[(i32, i32, ArgBytesLike)],
vm: &VirtualMachine,
)
| 2115 | // based on nix's implementation |
| 2116 | #[cfg(all(unix, not(target_os = "redox")))] |
| 2117 | fn pack_cmsgs_to_send( |
| 2118 | cmsgs: &[(i32, i32, ArgBytesLike)], |
| 2119 | vm: &VirtualMachine, |
| 2120 | ) -> PyResult<Vec<u8>> { |
| 2121 | use core::{mem, ptr}; |
| 2122 | |
| 2123 | if cmsgs.is_empty() { |
| 2124 | return Ok(vec![]); |
| 2125 | } |
| 2126 | |
| 2127 | let capacity = cmsgs |
| 2128 | .iter() |
| 2129 | .map(|(_, _, buf)| buf.len()) |
| 2130 | .try_fold(0, |sum, len| { |
| 2131 | let space = checked_cmsg_space(len).ok_or_else(|| { |
| 2132 | vm.new_os_error("ancillary data item too large".to_owned()) |
| 2133 | })?; |
| 2134 | usize::checked_add(sum, space) |
| 2135 | .ok_or_else(|| vm.new_os_error("too much ancillary data".to_owned())) |
| 2136 | })?; |
| 2137 | |
| 2138 | let mut cmsg_buffer = vec![0u8; capacity]; |
| 2139 | |
| 2140 | // make a dummy msghdr so we can use the CMSG_* apis |
| 2141 | let mut mhdr = unsafe { mem::zeroed::<libc::msghdr>() }; |
| 2142 | mhdr.msg_control = cmsg_buffer.as_mut_ptr().cast(); |
| 2143 | mhdr.msg_controllen = capacity as _; |
| 2144 | |
| 2145 | let mut pmhdr: *mut libc::cmsghdr = unsafe { libc::CMSG_FIRSTHDR(&mhdr) }; |
| 2146 | for (lvl, typ, buf) in cmsgs { |
| 2147 | if pmhdr.is_null() { |
| 2148 | return Err(vm.new_runtime_error( |
| 2149 | "unexpected NULL result from CMSG_FIRSTHDR/CMSG_NXTHDR", |
| 2150 | )); |
| 2151 | } |
| 2152 | let data = &*buf.borrow_buf(); |
| 2153 | assert_eq!(data.len(), buf.len()); |
| 2154 | // Safe because we know that pmhdr is valid, and we initialized it with |
| 2155 | // sufficient space |
| 2156 | unsafe { |
| 2157 | (*pmhdr).cmsg_level = *lvl; |
| 2158 | (*pmhdr).cmsg_type = *typ; |
| 2159 | (*pmhdr).cmsg_len = libc::CMSG_LEN(data.len() as _) as _; |
| 2160 | ptr::copy_nonoverlapping(data.as_ptr(), libc::CMSG_DATA(pmhdr), data.len()); |
| 2161 | } |
| 2162 | |
| 2163 | // Safe because mhdr is valid |
| 2164 | pmhdr = unsafe { libc::CMSG_NXTHDR(&mhdr, pmhdr) }; |
| 2165 | } |
| 2166 | |
| 2167 | Ok(cmsg_buffer) |
| 2168 | } |
| 2169 | |
| 2170 | #[pymethod] |
| 2171 | fn close(&self) -> io::Result<()> { |
nothing calls this directly
no test coverage detected