Parse a Python address tuple to SOCKADDR
(addr_obj: &PyTupleRef, vm: &VirtualMachine)
| 298 | |
| 299 | /// Parse a Python address tuple to SOCKADDR |
| 300 | fn parse_address(addr_obj: &PyTupleRef, vm: &VirtualMachine) -> PyResult<(Vec<u8>, i32)> { |
| 301 | use windows_sys::Win32::Networking::WinSock::{WSAGetLastError, WSAStringToAddressW}; |
| 302 | |
| 303 | match addr_obj.len() { |
| 304 | 2 => { |
| 305 | // IPv4: (host, port) |
| 306 | let host: PyStrRef = addr_obj[0].clone().try_into_value(vm)?; |
| 307 | let port: u16 = addr_obj[1].clone().try_to_value(vm)?; |
| 308 | |
| 309 | let mut addr: SOCKADDR_IN = unsafe { core::mem::zeroed() }; |
| 310 | addr.sin_family = AF_INET; |
| 311 | |
| 312 | let host_wide: Vec<u16> = host.as_wtf8().encode_wide().chain([0]).collect(); |
| 313 | let mut addr_len = core::mem::size_of::<SOCKADDR_IN>() as i32; |
| 314 | |
| 315 | let ret = unsafe { |
| 316 | WSAStringToAddressW( |
| 317 | host_wide.as_ptr(), |
| 318 | AF_INET as i32, |
| 319 | core::ptr::null(), |
| 320 | &mut addr as *mut _ as *mut SOCKADDR, |
| 321 | &mut addr_len, |
| 322 | ) |
| 323 | }; |
| 324 | |
| 325 | if ret < 0 { |
| 326 | let err = unsafe { WSAGetLastError() } as u32; |
| 327 | return Err(set_from_windows_err(err, vm)); |
| 328 | } |
| 329 | |
| 330 | // Restore port (WSAStringToAddressW overwrites it) |
| 331 | addr.sin_port = port.to_be(); |
| 332 | |
| 333 | let bytes = unsafe { |
| 334 | core::slice::from_raw_parts( |
| 335 | &addr as *const _ as *const u8, |
| 336 | core::mem::size_of::<SOCKADDR_IN>(), |
| 337 | ) |
| 338 | }; |
| 339 | Ok((bytes.to_vec(), addr_len)) |
| 340 | } |
| 341 | 4 => { |
| 342 | // IPv6: (host, port, flowinfo, scope_id) |
| 343 | let host: PyStrRef = addr_obj[0].clone().try_into_value(vm)?; |
| 344 | let port: u16 = addr_obj[1].clone().try_to_value(vm)?; |
| 345 | let flowinfo: u32 = addr_obj[2].clone().try_to_value(vm)?; |
| 346 | let scope_id: u32 = addr_obj[3].clone().try_to_value(vm)?; |
| 347 | |
| 348 | let mut addr: SOCKADDR_IN6 = unsafe { core::mem::zeroed() }; |
| 349 | addr.sin6_family = AF_INET6; |
| 350 | |
| 351 | let host_wide: Vec<u16> = host.as_wtf8().encode_wide().chain([0]).collect(); |
| 352 | let mut addr_len = core::mem::size_of::<SOCKADDR_IN6>() as i32; |
| 353 | |
| 354 | let ret = unsafe { |
| 355 | WSAStringToAddressW( |
| 356 | host_wide.as_ptr(), |
| 357 | AF_INET6 as i32, |
no test coverage detected