mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
host_env: export remaining Windows socket and fault constants (#8736)
* host_env: export remaining Windows socket and fault constants Publish AF_HYPERV/AF_BLUETOOTH, HV_* GUIDs, SIO_TCP_SET_ACK_FREQUENCY, EXCEPTION_CONTINUE_SEARCH, and winreg ERROR_FILE_NOT_FOUND/INVALID_DATA. os.socket pack/unpack Hyper-V and RFCOMM addresses through host_env. Assisted-by: Claude * socket: publish HV_GUID_* as string attributes Assisted-by: Claude * host_env: cast SIO_TCP_SET_ACK_FREQUENCY to i32 The WinSock constant is u32 and does not fit i32 without a wrapping cast. Socket module attributes are i32. Assisted-by: Claude * socket: use socklen_t width for Windows SockAddr::new Windows socklen_t is i32; a u32 cast does not match socket2. Assisted-by: Claude * socket: drop unused Windows AF_* imports from c AF_BTH, AF_IRDA, and AF_SNA are published via host_socket pyattr and are not read through the Windows c alias module. Assisted-by: Claude * host_env: export Windows faulthandler exception codes Route stdlib _EXCEPTION_* pyattrs and exception_description through named host_env constants instead of hex literals. Assisted-by: Claude
This commit is contained in:
1 parent
0c5a47bae5
commit
a7c0500a42
6 files changed
+356
-45
No files matched your search
@@ -81,6 +81,7 @@ memchr.workspace = true
|
||||
junction = { workspace = true }
|
||||
schannel = { workspace = true }
|
||||
windows-sys = { workspace = true, features = [
|
||||
"Win32_Devices_Bluetooth",
|
||||
"Win32_Foundation",
|
||||
"Win32_Globalization",
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
|
||||
@@ -490,18 +490,55 @@ pub fn ignore_exception(code: u32) -> bool {
|
||||
#[cfg(windows)]
|
||||
pub fn exception_description(code: u32) -> Option<&'static str> {
|
||||
match code {
|
||||
0xC0000005 => Some("access violation"),
|
||||
0xC000008C => Some("float divide by zero"),
|
||||
0xC0000091 => Some("float overflow"),
|
||||
0xC0000094 => Some("int divide by zero"),
|
||||
0xC0000095 => Some("integer overflow"),
|
||||
0xC0000006 => Some("page error"),
|
||||
0xC00000FD => Some("stack overflow"),
|
||||
0xC000001D => Some("illegal instruction"),
|
||||
EXCEPTION_ACCESS_VIOLATION => Some("access violation"),
|
||||
EXCEPTION_FLT_DIVIDE_BY_ZERO => Some("float divide by zero"),
|
||||
EXCEPTION_FLT_OVERFLOW => Some("float overflow"),
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO => Some("int divide by zero"),
|
||||
EXCEPTION_INT_OVERFLOW => Some("integer overflow"),
|
||||
EXCEPTION_IN_PAGE_ERROR => Some("page error"),
|
||||
EXCEPTION_STACK_OVERFLOW => Some("stack overflow"),
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => Some("illegal instruction"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// `EXCEPTION_CONTINUE_SEARCH`: this handler only reports; later
|
||||
/// handlers decide the process fate.
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_CONTINUE_SEARCH: i32 =
|
||||
windows_sys::Win32::System::Diagnostics::Debug::EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_ACCESS_VIOLATION: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_ACCESS_VIOLATION as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_FLT_DIVIDE_BY_ZERO: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_FLT_DIVIDE_BY_ZERO as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_FLT_OVERFLOW: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_FLT_OVERFLOW as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_INT_DIVIDE_BY_ZERO: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_INT_DIVIDE_BY_ZERO as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_INT_OVERFLOW: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_INT_OVERFLOW as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_IN_PAGE_ERROR: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_IN_PAGE_ERROR as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_STACK_OVERFLOW: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_STACK_OVERFLOW as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_ILLEGAL_INSTRUCTION: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_ILLEGAL_INSTRUCTION as u32;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_NONCONTINUABLE: u32 =
|
||||
windows_sys::Win32::System::SystemServices::EXCEPTION_NONCONTINUABLE;
|
||||
#[cfg(windows)]
|
||||
pub const EXCEPTION_NONCONTINUABLE_EXCEPTION: u32 =
|
||||
windows_sys::Win32::Foundation::EXCEPTION_NONCONTINUABLE_EXCEPTION as u32;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub unsafe fn exception_code(exc_info: *mut EXCEPTION_POINTERS) -> u32 {
|
||||
let record = unsafe { &*(*exc_info).ExceptionRecord };
|
||||
@@ -511,5 +548,5 @@ pub unsafe fn exception_code(exc_info: *mut EXCEPTION_POINTERS) -> u32 {
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub fn is_access_violation(code: u32) -> bool {
|
||||
code == 0xC0000005
|
||||
code == EXCEPTION_ACCESS_VIOLATION
|
||||
}
|
||||
@@ -571,8 +571,8 @@ pub use windows_sys::Win32::Networking::WinSock::{
|
||||
SIO_LOOPBACK_FAST_PATH, SIO_RCVALL, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER,
|
||||
SO_OOBINLINE, SO_RCVBUF, SO_REUSEADDR, SO_SNDBUF, SO_TYPE, SO_USELOOPBACK, SOCK_DGRAM,
|
||||
SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOCKET_ERROR as SOCKET_ERROR_CODE, SOL_SOCKET,
|
||||
SOMAXCONN, TCP_NODELAY, WSAEBADF, WSAECONNRESET, WSAENOTSOCK, WSAEWOULDBLOCK, getprotobyname,
|
||||
getservbyname, getservbyport, getsockopt, setsockopt,
|
||||
SOMAXCONN, TCP_NODELAY, WSAEBADF, WSAECONNABORTED, WSAECONNRESET, WSAENOTSOCK, WSAEWOULDBLOCK,
|
||||
getprotobyname, getservbyname, getservbyport, getsockopt, setsockopt,
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -953,3 +953,123 @@ pub fn uuid_to_string_w(guid: &windows_sys::core::GUID) -> Result<String, u32> {
|
||||
unsafe { RpcStringFreeW(&mut raw) };
|
||||
Ok(text)
|
||||
}
|
||||
|
||||
/// Address families the Windows SDK exposes beyond the older MSVC census.
|
||||
#[cfg(windows)]
|
||||
pub const AF_SNA: i32 = 11;
|
||||
#[cfg(windows)]
|
||||
pub const AF_IRDA: i32 = 26;
|
||||
#[cfg(windows)]
|
||||
pub const AF_HYPERV: i32 = windows_sys::Win32::Networking::WinSock::AF_HYPERV as i32;
|
||||
#[cfg(windows)]
|
||||
pub const AF_BLUETOOTH: i32 = windows_sys::Win32::Devices::Bluetooth::AF_BTH as i32;
|
||||
#[cfg(windows)]
|
||||
pub const AF_BTH: i32 = AF_BLUETOOTH;
|
||||
#[cfg(windows)]
|
||||
pub const BTHPROTO_RFCOMM: i32 = windows_sys::Win32::Devices::Bluetooth::BTHPROTO_RFCOMM as i32;
|
||||
|
||||
/// `hvsocket.h`: the only protocol an `AF_HYPERV` socket is opened with.
|
||||
#[cfg(windows)]
|
||||
pub const HV_PROTOCOL_RAW: i32 = 1;
|
||||
#[cfg(windows)]
|
||||
pub const HVSOCKET_CONNECT_TIMEOUT: i32 = 0x01;
|
||||
#[cfg(windows)]
|
||||
pub const HVSOCKET_CONNECT_TIMEOUT_MAX: i32 = 300_000;
|
||||
#[cfg(windows)]
|
||||
pub const HVSOCKET_CONNECTED_SUSPEND: i32 = 0x04;
|
||||
#[cfg(windows)]
|
||||
pub const HVSOCKET_ADDRESS_FLAG_PASSTHRU: i32 = 0x01;
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_ZERO: &str = "00000000-0000-0000-0000-000000000000";
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_WILDCARD: &str = "00000000-0000-0000-0000-000000000000";
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_BROADCAST: &str = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF";
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_CHILDREN: &str = "90DB8B89-0D35-4F79-8CE9-49EA0AC8B7CD";
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_LOOPBACK: &str = "E0E16197-DD56-4A10-9195-5EE7A155A838";
|
||||
#[cfg(windows)]
|
||||
pub const HV_GUID_PARENT: &str = "A42E7CDA-D03F-480C-9CC2-A4DE20ABB878";
|
||||
|
||||
#[cfg(windows)]
|
||||
pub const SIO_TCP_SET_ACK_FREQUENCY: i32 =
|
||||
windows_sys::Win32::Networking::WinSock::SIO_TCP_SET_ACK_FREQUENCY as i32;
|
||||
|
||||
/// `SOCKADDR_HV` (`hvsocket.h`).
|
||||
#[cfg(windows)]
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SockaddrHv {
|
||||
pub family: u16,
|
||||
pub reserved: u16,
|
||||
pub vm_id: windows_sys::core::GUID,
|
||||
pub service_id: windows_sys::core::GUID,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn sockaddr_hv(
|
||||
vm_id: windows_sys::core::GUID,
|
||||
service_id: windows_sys::core::GUID,
|
||||
) -> SockaddrHv {
|
||||
SockaddrHv {
|
||||
family: AF_HYPERV as u16,
|
||||
reserved: 0,
|
||||
vm_id,
|
||||
service_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// `SOCKADDR_BTH`.
|
||||
#[cfg(windows)]
|
||||
pub fn sockaddr_bth_rfcomm(
|
||||
bd_addr: u64,
|
||||
port: u32,
|
||||
) -> windows_sys::Win32::Devices::Bluetooth::SOCKADDR_BTH {
|
||||
windows_sys::Win32::Devices::Bluetooth::SOCKADDR_BTH {
|
||||
addressFamily: AF_BTH as u16,
|
||||
btAddr: bd_addr,
|
||||
serviceClassId: Default::default(),
|
||||
port,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn unpack_sockaddr_bth(ptr: *const u8) -> (u64, u32) {
|
||||
let bth = unsafe { &*(ptr.cast::<windows_sys::Win32::Devices::Bluetooth::SOCKADDR_BTH>()) };
|
||||
(bth.btAddr, bth.port)
|
||||
}
|
||||
|
||||
/// `setbdaddr`: six hex octets separated by `:`.
|
||||
#[cfg(windows)]
|
||||
pub fn parse_bdaddr(name: &str) -> Option<u64> {
|
||||
let mut parts = name.split(':');
|
||||
let mut value = 0u64;
|
||||
for _ in 0..6 {
|
||||
let part = parts.next()?;
|
||||
if part.is_empty() || part.len() > 2 {
|
||||
return None;
|
||||
}
|
||||
let octet = u8::from_str_radix(part, 16).ok()?;
|
||||
value = (value << 8) | u64::from(octet);
|
||||
}
|
||||
if parts.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
Some(value)
|
||||
}
|
||||
|
||||
/// `makebdaddr`: `XX:XX:XX:XX:XX:XX`, most significant octet first.
|
||||
#[cfg(windows)]
|
||||
pub fn format_bdaddr(bdaddr: u64) -> String {
|
||||
let octet = |i: u32| (bdaddr >> (8 * i)) & 0xFF;
|
||||
alloc::format!(
|
||||
"{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
|
||||
octet(5),
|
||||
octet(4),
|
||||
octet(3),
|
||||
octet(2),
|
||||
octet(1),
|
||||
octet(0)
|
||||
)
|
||||
}
|
||||
@@ -24,6 +24,8 @@ use windows_sys::Win32::{
|
||||
pub type HKEY = Registry::HKEY;
|
||||
pub const ERROR_MORE_DATA: u32 = Foundation::ERROR_MORE_DATA;
|
||||
pub const ERROR_INVALID_HANDLE: u32 = Foundation::ERROR_INVALID_HANDLE;
|
||||
pub const ERROR_FILE_NOT_FOUND: u32 = Foundation::ERROR_FILE_NOT_FOUND;
|
||||
pub const ERROR_INVALID_DATA: u32 = Foundation::ERROR_INVALID_DATA;
|
||||
pub const HKEY_CLASSES_ROOT: HKEY = Registry::HKEY_CLASSES_ROOT;
|
||||
pub const HKEY_CURRENT_USER: HKEY = Registry::HKEY_CURRENT_USER;
|
||||
pub const HKEY_LOCAL_MACHINE: HKEY = Registry::HKEY_LOCAL_MACHINE;
|
||||
|
||||
@@ -467,16 +467,14 @@ mod decl {
|
||||
unsafe extern "system" fn faulthandler_exc_handler(
|
||||
exc_info: *mut host_faulthandler::ExceptionPointers,
|
||||
) -> i32 {
|
||||
const EXCEPTION_CONTINUE_SEARCH: i32 = 0;
|
||||
|
||||
if !FATAL_ERROR.enabled.load(Ordering::Relaxed) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
return host_faulthandler::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
let code = unsafe { host_faulthandler::exception_code(exc_info) };
|
||||
|
||||
if faulthandler_ignore_exception(code) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
return host_faulthandler::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
let fd = FATAL_ERROR.fd.load(Ordering::Relaxed);
|
||||
@@ -498,7 +496,7 @@ mod decl {
|
||||
let all_threads = FATAL_ERROR.all_threads.load(Ordering::Relaxed);
|
||||
faulthandler_dump_traceback(fd, all_threads);
|
||||
|
||||
EXCEPTION_CONTINUE_SEARCH
|
||||
host_faulthandler::EXCEPTION_CONTINUE_SEARCH
|
||||
}
|
||||
|
||||
// faulthandler_enable
|
||||
@@ -1005,23 +1003,24 @@ mod decl {
|
||||
// Windows-specific constants
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const _EXCEPTION_ACCESS_VIOLATION: u32 = 0xC0000005;
|
||||
const _EXCEPTION_ACCESS_VIOLATION: u32 = host_faulthandler::EXCEPTION_ACCESS_VIOLATION;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const _EXCEPTION_INT_DIVIDE_BY_ZERO: u32 = 0xC0000094;
|
||||
const _EXCEPTION_INT_DIVIDE_BY_ZERO: u32 = host_faulthandler::EXCEPTION_INT_DIVIDE_BY_ZERO;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const _EXCEPTION_STACK_OVERFLOW: u32 = 0xC00000FD;
|
||||
const _EXCEPTION_STACK_OVERFLOW: u32 = host_faulthandler::EXCEPTION_STACK_OVERFLOW;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const _EXCEPTION_NONCONTINUABLE: u32 = 0x00000001;
|
||||
const _EXCEPTION_NONCONTINUABLE: u32 = host_faulthandler::EXCEPTION_NONCONTINUABLE;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const _EXCEPTION_NONCONTINUABLE_EXCEPTION: u32 = 0xC0000025;
|
||||
const _EXCEPTION_NONCONTINUABLE_EXCEPTION: u32 =
|
||||
host_faulthandler::EXCEPTION_NONCONTINUABLE_EXCEPTION;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[derive(FromArgs)]
|
||||
|
||||
+176
-24
@@ -32,6 +32,8 @@ mod _socket {
|
||||
use rustpython_host_env::socket as host_socket;
|
||||
#[cfg(windows)]
|
||||
use rustpython_host_env::windows as host_windows;
|
||||
#[cfg(windows)]
|
||||
use rustpython_host_env::windows::ToWideString;
|
||||
|
||||
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
|
||||
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
|
||||
@@ -61,28 +63,28 @@ mod _socket {
|
||||
#[cfg(windows)]
|
||||
mod c {
|
||||
pub(super) use rustpython_host_env::socket::{
|
||||
AF_APPLETALK, AF_DECnet, AF_INET, AF_INET6, AF_IPX, AF_LINK, AF_UNSPEC, AI_ADDRCONFIG,
|
||||
AI_ALL, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV, AI_PASSIVE, AI_V4MAPPED,
|
||||
EAI_AGAIN, EAI_BADFLAGS, EAI_FAIL, EAI_FAMILY, EAI_MEMORY, EAI_NODATA, EAI_NONAME,
|
||||
EAI_SERVICE, EAI_SOCKTYPE, INADDR_ANY, INADDR_BROADCAST, INADDR_LOOPBACK, INADDR_NONE,
|
||||
IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_HDRINCL, IP_MULTICAST_IF, IP_MULTICAST_LOOP,
|
||||
IP_MULTICAST_TTL, IP_OPTIONS, IP_RECVDSTADDR, IP_TOS, IP_TTL, IPPORT_RESERVED,
|
||||
IPPROTO_AH, IPPROTO_DSTOPTS, IPPROTO_EGP, IPPROTO_ESP, IPPROTO_FRAGMENT, IPPROTO_GGP,
|
||||
IPPROTO_HOPOPTS, IPPROTO_ICMP, IPPROTO_ICMPV6, IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP,
|
||||
IPPROTO_IP as IPPROTO_IPIP, IPPROTO_IPV4, IPPROTO_IPV6, IPPROTO_ND, IPPROTO_NONE,
|
||||
IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING, IPPROTO_TCP, IPPROTO_UDP,
|
||||
IPV6_CHECKSUM, IPV6_DONTFRAG, IPV6_HOPLIMIT, IPV6_HOPOPTS, IPV6_JOIN_GROUP,
|
||||
IPV6_LEAVE_GROUP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP,
|
||||
IPV6_PKTINFO, IPV6_RECVRTHDR, IPV6_RECVTCLASS, IPV6_RTHDR, IPV6_TCLASS,
|
||||
IPV6_UNICAST_HOPS, IPV6_V6ONLY, MSG_BCAST, MSG_CTRUNC, MSG_DONTROUTE, MSG_MCAST,
|
||||
MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, NI_DGRAM, NI_MAXHOST, NI_MAXSERV,
|
||||
NI_NAMEREQD, NI_NOFQDN, NI_NUMERICHOST, NI_NUMERICSERV, RCVALL_IPLEVEL, RCVALL_OFF,
|
||||
RCVALL_ON, RCVALL_SOCKETLEVELONLY, SD_BOTH as SHUT_RDWR, SD_RECEIVE as SHUT_RD,
|
||||
SD_SEND as SHUT_WR, SIO_KEEPALIVE_VALS, SIO_LOOPBACK_FAST_PATH, SIO_RCVALL,
|
||||
SO_BROADCAST, SO_ERROR, SO_EXCLUSIVEADDRUSE, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE,
|
||||
SO_RCVBUF, SO_REUSEADDR, SO_SNDBUF, SO_TYPE, SO_USELOOPBACK, SOCK_DGRAM, SOCK_RAW,
|
||||
SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SOMAXCONN, TCP_NODELAY, WSAEBADF,
|
||||
WSAENOTSOCK, WSAEWOULDBLOCK, getprotobyname, getservbyname, getservbyport,
|
||||
AF_APPLETALK, AF_BLUETOOTH, AF_DECnet, AF_HYPERV, AF_INET, AF_INET6, AF_IPX, AF_LINK,
|
||||
AF_UNSPEC, AI_ADDRCONFIG, AI_ALL, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV,
|
||||
AI_PASSIVE, AI_V4MAPPED, EAI_AGAIN, EAI_BADFLAGS, EAI_FAIL, EAI_FAMILY, EAI_MEMORY,
|
||||
EAI_NODATA, EAI_NONAME, EAI_SERVICE, EAI_SOCKTYPE, INADDR_ANY, INADDR_BROADCAST,
|
||||
INADDR_LOOPBACK, INADDR_NONE, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_HDRINCL,
|
||||
IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_OPTIONS, IP_RECVDSTADDR,
|
||||
IP_TOS, IP_TTL, IPPORT_RESERVED, IPPROTO_AH, IPPROTO_DSTOPTS, IPPROTO_EGP, IPPROTO_ESP,
|
||||
IPPROTO_FRAGMENT, IPPROTO_GGP, IPPROTO_HOPOPTS, IPPROTO_ICMP, IPPROTO_ICMPV6,
|
||||
IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IP as IPPROTO_IPIP, IPPROTO_IPV4,
|
||||
IPPROTO_IPV6, IPPROTO_ND, IPPROTO_NONE, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW,
|
||||
IPPROTO_ROUTING, IPPROTO_TCP, IPPROTO_UDP, IPV6_CHECKSUM, IPV6_DONTFRAG, IPV6_HOPLIMIT,
|
||||
IPV6_HOPOPTS, IPV6_JOIN_GROUP, IPV6_LEAVE_GROUP, IPV6_MULTICAST_HOPS,
|
||||
IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_PKTINFO, IPV6_RECVRTHDR, IPV6_RECVTCLASS,
|
||||
IPV6_RTHDR, IPV6_TCLASS, IPV6_UNICAST_HOPS, IPV6_V6ONLY, MSG_BCAST, MSG_CTRUNC,
|
||||
MSG_DONTROUTE, MSG_MCAST, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, NI_DGRAM,
|
||||
NI_MAXHOST, NI_MAXSERV, NI_NAMEREQD, NI_NOFQDN, NI_NUMERICHOST, NI_NUMERICSERV,
|
||||
RCVALL_IPLEVEL, RCVALL_OFF, RCVALL_ON, RCVALL_SOCKETLEVELONLY, SD_BOTH as SHUT_RDWR,
|
||||
SD_RECEIVE as SHUT_RD, SD_SEND as SHUT_WR, SIO_KEEPALIVE_VALS, SIO_LOOPBACK_FAST_PATH,
|
||||
SIO_RCVALL, SO_BROADCAST, SO_ERROR, SO_EXCLUSIVEADDRUSE, SO_KEEPALIVE, SO_LINGER,
|
||||
SO_OOBINLINE, SO_RCVBUF, SO_REUSEADDR, SO_SNDBUF, SO_TYPE, SO_USELOOPBACK, SOCK_DGRAM,
|
||||
SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SOMAXCONN, TCP_NODELAY,
|
||||
WSAEBADF, WSAENOTSOCK, WSAEWOULDBLOCK, getprotobyname, getservbyname, getservbyport,
|
||||
};
|
||||
}
|
||||
// constants
|
||||
@@ -823,10 +825,31 @@ mod _socket {
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
use host_socket::{
|
||||
IPPROTO_CBT, IPPROTO_ICLFXBM, IPPROTO_IGP, IPPROTO_L2TP, IPPROTO_PGM, IPPROTO_RDP,
|
||||
IPPROTO_SCTP, IPPROTO_ST,
|
||||
AF_BLUETOOTH, AF_HYPERV, AF_IRDA, AF_SNA, BTHPROTO_RFCOMM, HV_PROTOCOL_RAW,
|
||||
HVSOCKET_ADDRESS_FLAG_PASSTHRU, HVSOCKET_CONNECT_TIMEOUT, HVSOCKET_CONNECT_TIMEOUT_MAX,
|
||||
HVSOCKET_CONNECTED_SUSPEND, IPPROTO_CBT, IPPROTO_ICLFXBM, IPPROTO_IGP, IPPROTO_L2TP,
|
||||
IPPROTO_PGM, IPPROTO_RDP, IPPROTO_SCTP, IPPROTO_ST, SIO_TCP_SET_ACK_FREQUENCY,
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_ZERO: &str = host_socket::HV_GUID_ZERO;
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_WILDCARD: &str = host_socket::HV_GUID_WILDCARD;
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_BROADCAST: &str = host_socket::HV_GUID_BROADCAST;
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_CHILDREN: &str = host_socket::HV_GUID_CHILDREN;
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_LOOPBACK: &str = host_socket::HV_GUID_LOOPBACK;
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
const HV_GUID_PARENT: &str = host_socket::HV_GUID_PARENT;
|
||||
|
||||
#[pyattr]
|
||||
fn error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.ctx.exceptions.os_error.to_owned()
|
||||
@@ -1184,6 +1207,108 @@ mod _socket {
|
||||
}
|
||||
Ok(addr6.into())
|
||||
}
|
||||
#[cfg(windows)]
|
||||
family if family == c::AF_HYPERV => {
|
||||
if self.proto.load() != host_socket::HV_PROTOCOL_RAW {
|
||||
return Err(vm
|
||||
.new_os_error(format!(
|
||||
"{caller}(): unsupported AF_HYPERV protocol: {}",
|
||||
self.proto.load()
|
||||
))
|
||||
.into());
|
||||
}
|
||||
let tuple: PyTupleRef = addr.downcast().map_err(|obj| {
|
||||
vm.new_type_error(format!(
|
||||
"{caller}(): AF_HYPERV address must be tuple, not {}",
|
||||
obj.class().name()
|
||||
))
|
||||
})?;
|
||||
if tuple.len() != 2 {
|
||||
return Err(vm
|
||||
.new_type_error(
|
||||
"AF_HYPERV address must be a str tuple (vm_id, service_id)",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
let vm_id: PyStrRef = tuple[0].clone().downcast().map_err(|_| {
|
||||
vm.new_type_error(
|
||||
"AF_HYPERV address must be a str tuple (vm_id, service_id)",
|
||||
)
|
||||
})?;
|
||||
let service_id: PyStrRef = tuple[1].clone().downcast().map_err(|_| {
|
||||
vm.new_type_error(
|
||||
"AF_HYPERV address must be a str tuple (vm_id, service_id)",
|
||||
)
|
||||
})?;
|
||||
let vm_wide = vm_id.as_wtf8().to_wide_cstring().map_err(|_| {
|
||||
vm.new_value_error(format!(
|
||||
"{caller}(): AF_HYPERV address vm_id is not a valid UUID string"
|
||||
))
|
||||
})?;
|
||||
let service_wide = service_id.as_wtf8().to_wide_cstring().map_err(|_| {
|
||||
vm.new_value_error(format!(
|
||||
"{caller}(): AF_HYPERV address service_id is not a valid UUID string"
|
||||
))
|
||||
})?;
|
||||
let vm_guid = host_socket::uuid_from_string_w(&vm_wide).map_err(|_| {
|
||||
vm.new_value_error(format!(
|
||||
"{caller}(): AF_HYPERV address vm_id is not a valid UUID string"
|
||||
))
|
||||
})?;
|
||||
let service_guid =
|
||||
host_socket::uuid_from_string_w(&service_wide).map_err(|_| {
|
||||
vm.new_value_error(format!(
|
||||
"{caller}(): AF_HYPERV address service_id is not a valid UUID string"
|
||||
))
|
||||
})?;
|
||||
let hv = host_socket::sockaddr_hv(vm_guid, service_guid);
|
||||
let mut storage: host_socket::raw::SockAddrStorage =
|
||||
unsafe { core::mem::zeroed() };
|
||||
unsafe {
|
||||
core::ptr::write(core::ptr::from_mut(&mut storage).cast(), hv);
|
||||
}
|
||||
Ok(unsafe {
|
||||
host_socket::raw::SockAddr::new(storage, core::mem::size_of_val(&hv) as _)
|
||||
})
|
||||
}
|
||||
#[cfg(windows)]
|
||||
family if family == c::AF_BLUETOOTH => {
|
||||
if self.proto.load() != host_socket::BTHPROTO_RFCOMM {
|
||||
return Err(vm
|
||||
.new_os_error(format!("{caller}(): unknown Bluetooth protocol"))
|
||||
.into());
|
||||
}
|
||||
let tuple: PyTupleRef = addr
|
||||
.downcast()
|
||||
.map_err(|_| vm.new_os_error(format!("{caller}(): wrong format")))?;
|
||||
if tuple.len() != 2 {
|
||||
return Err(vm.new_os_error(format!("{caller}(): wrong format")).into());
|
||||
}
|
||||
let name: PyStrRef = tuple[0]
|
||||
.clone()
|
||||
.downcast()
|
||||
.map_err(|_| vm.new_os_error(format!("{caller}(): wrong format")))?;
|
||||
let channel = i64::try_from_object(vm, tuple[1].clone())
|
||||
.map_err(|_| vm.new_os_error(format!("{caller}(): wrong format")))?;
|
||||
let name = name
|
||||
.try_into_utf8(vm)
|
||||
.map_err(|_| vm.new_os_error(format!("{caller}(): wrong format")))?;
|
||||
let name = name.as_str();
|
||||
if name.contains('\0') {
|
||||
return Err(vm.new_os_error(format!("{caller}(): wrong format")).into());
|
||||
}
|
||||
let bd_addr = host_socket::parse_bdaddr(name)
|
||||
.ok_or_else(|| vm.new_os_error("bad bluetooth address"))?;
|
||||
let bth = host_socket::sockaddr_bth_rfcomm(bd_addr, channel as u32);
|
||||
let mut storage: host_socket::raw::SockAddrStorage =
|
||||
unsafe { core::mem::zeroed() };
|
||||
unsafe {
|
||||
core::ptr::write(core::ptr::from_mut(&mut storage).cast(), bth);
|
||||
}
|
||||
Ok(unsafe {
|
||||
host_socket::raw::SockAddr::new(storage, core::mem::size_of_val(&bth) as _)
|
||||
})
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
c::AF_CAN => {
|
||||
let tuple: PyTupleRef = addr.downcast().map_err(|obj| {
|
||||
@@ -2316,6 +2441,33 @@ mod _socket {
|
||||
.into();
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let family = addr.family() as i32;
|
||||
if family == c::AF_HYPERV {
|
||||
let hv = unsafe { &*(addr.as_ptr() as *const host_socket::SockaddrHv) };
|
||||
let vm_id = host_socket::uuid_to_string_w(&hv.vm_id).unwrap_or_default();
|
||||
let service_id = host_socket::uuid_to_string_w(&hv.service_id).unwrap_or_default();
|
||||
return vm
|
||||
.ctx
|
||||
.new_tuple(vec![
|
||||
vm.ctx.new_str(vm_id).into(),
|
||||
vm.ctx.new_str(service_id).into(),
|
||||
])
|
||||
.into();
|
||||
}
|
||||
if family == c::AF_BLUETOOTH {
|
||||
let (bd_addr, port) = host_socket::unpack_sockaddr_bth(addr.as_ptr().cast());
|
||||
let name = host_socket::format_bdaddr(bd_addr);
|
||||
return vm
|
||||
.ctx
|
||||
.new_tuple(vec![
|
||||
vm.ctx.new_str(name).into(),
|
||||
vm.ctx.new_int(port).into(),
|
||||
])
|
||||
.into();
|
||||
}
|
||||
}
|
||||
// TODO: support more address families
|
||||
(String::new(), 0).to_pyobject(vm)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user