@@ -1038,7 +1038,6 @@ fn register_internal_tools(
10381038 tools. register ( "__hl_sleep" , move |args| {
10391039 let ns = args[ "ns" ] . as_u64 ( ) . unwrap_or ( 0 ) . min ( MAX_SLEEP_NS ) ;
10401040 if ns > 0 {
1041- #[ cfg( unix) ]
10421041 if let Some ( ref table) = st_for_sleep {
10431042 return hl_sleep_poll_sockets ( & sc, table, ns) ;
10441043 }
@@ -1699,11 +1698,80 @@ fn handle_net_poll(
16991698 Ok ( json ! ( { "ready" : ready} ) )
17001699}
17011700
1701+ #[ cfg( windows) ]
1702+ fn handle_net_poll (
1703+ table : & Mutex < SocketTable > ,
1704+ args : & serde_json:: Value ,
1705+ ) -> Result < serde_json:: Value > {
1706+ use serde_json:: json;
1707+ use std:: os:: windows:: io:: AsRawSocket ;
1708+ use windows_sys:: Win32 :: Networking :: WinSock :: { WSAPoll , POLLNVAL , WSAPOLLFD } ;
1709+
1710+ let fds_val = args
1711+ . get ( "fds" )
1712+ . and_then ( |v| v. as_array ( ) )
1713+ . ok_or_else ( || anyhow ! ( "net_poll: missing 'fds' array" ) ) ?;
1714+ let timeout_ms = args
1715+ . get ( "timeout_ms" )
1716+ . and_then ( |v| v. as_i64 ( ) )
1717+ . unwrap_or ( 0 )
1718+ . clamp ( 0 , i32:: MAX as i64 ) as i32 ;
1719+
1720+ let tbl = table. lock ( ) . unwrap ( ) ;
1721+ let mut pollfds: Vec < WSAPOLLFD > = Vec :: new ( ) ;
1722+ let mut guest_fds: Vec < u64 > = Vec :: new ( ) ;
1723+ let mut ready = Vec :: new ( ) ;
1724+
1725+ for entry in fds_val {
1726+ let fd = entry
1727+ . get ( "fd" )
1728+ . and_then ( |v| v. as_u64 ( ) )
1729+ . ok_or_else ( || anyhow ! ( "net_poll: entry missing 'fd'" ) ) ?;
1730+ let raw_events = entry. get ( "events" ) . and_then ( |v| v. as_i64 ( ) ) . unwrap_or ( 0 ) ;
1731+ if !( 0 ..=i16:: MAX as i64 ) . contains ( & raw_events) {
1732+ return Err ( anyhow ! ( "net_poll: events {raw_events} out of i16 range" ) ) ;
1733+ }
1734+ let events = raw_events as i16 ;
1735+ if let Ok ( sock) = tbl. get_socket ( fd) {
1736+ pollfds. push ( WSAPOLLFD {
1737+ fd : sock. as_raw_socket ( ) as usize ,
1738+ events,
1739+ revents : 0 ,
1740+ } ) ;
1741+ guest_fds. push ( fd) ;
1742+ } else {
1743+ ready. push ( json ! ( { "fd" : fd, "revents" : POLLNVAL as i64 } ) ) ;
1744+ }
1745+ }
1746+ drop ( tbl) ;
1747+
1748+ if pollfds. is_empty ( ) {
1749+ return Ok ( json ! ( { "ready" : ready} ) ) ;
1750+ }
1751+
1752+ let ret = unsafe { WSAPoll ( pollfds. as_mut_ptr ( ) , pollfds. len ( ) as u32 , timeout_ms) } ;
1753+
1754+ if ret < 0 {
1755+ let err = std:: io:: Error :: last_os_error ( ) ;
1756+ return Err ( anyhow ! ( "net_poll: WSAPoll() failed: {err}" ) ) ;
1757+ }
1758+
1759+ for ( i, pfd) in pollfds. iter ( ) . enumerate ( ) {
1760+ if pfd. revents != 0 {
1761+ ready. push ( json ! ( {
1762+ "fd" : guest_fds[ i] ,
1763+ "revents" : pfd. revents as i64 ,
1764+ } ) ) ;
1765+ }
1766+ }
1767+ Ok ( json ! ( { "ready" : ready} ) )
1768+ }
1769+
17021770/// `__hl_sleep` variant: poll all sockets in the table while sleeping.
17031771/// Returns early if any socket becomes ready.
17041772#[ cfg( unix) ]
17051773fn hl_sleep_poll_sockets (
1706- sc : & SleepCancel ,
1774+ _sc : & SleepCancel ,
17071775 table : & Mutex < SocketTable > ,
17081776 ns : u64 ,
17091777) -> Result < serde_json:: Value > {
@@ -1723,7 +1791,7 @@ fn hl_sleep_poll_sockets(
17231791 drop ( tbl) ;
17241792
17251793 if pollfds. is_empty ( ) {
1726- sc . wait ( Duration :: from_nanos ( ns) ) ;
1794+ _sc . wait ( Duration :: from_nanos ( ns) ) ;
17271795 return Ok ( json ! ( { } ) ) ;
17281796 }
17291797
@@ -1746,6 +1814,46 @@ fn hl_sleep_poll_sockets(
17461814 Ok ( json ! ( { "socket_ready" : ret > 0 } ) )
17471815}
17481816
1817+ #[ cfg( windows) ]
1818+ fn hl_sleep_poll_sockets (
1819+ _sc : & SleepCancel ,
1820+ table : & Mutex < SocketTable > ,
1821+ ns : u64 ,
1822+ ) -> Result < serde_json:: Value > {
1823+ use serde_json:: json;
1824+ use std:: os:: windows:: io:: AsRawSocket ;
1825+ use windows_sys:: Win32 :: Networking :: WinSock :: {
1826+ WSAPoll , POLLERR , POLLRDNORM , POLLWRNORM , WSAPOLLFD ,
1827+ } ;
1828+
1829+ let tbl = table. lock ( ) . unwrap ( ) ;
1830+ let mut pollfds: Vec < WSAPOLLFD > = tbl
1831+ . sockets
1832+ . values ( )
1833+ . map ( |hs| WSAPOLLFD {
1834+ fd : hs. socket . as_raw_socket ( ) as usize ,
1835+ events : ( POLLRDNORM | POLLWRNORM | POLLERR ) as i16 ,
1836+ revents : 0 ,
1837+ } )
1838+ . collect ( ) ;
1839+ drop ( tbl) ;
1840+
1841+ if pollfds. is_empty ( ) {
1842+ _sc. wait ( Duration :: from_nanos ( ns) ) ;
1843+ return Ok ( json ! ( { } ) ) ;
1844+ }
1845+
1846+ let timeout_ms = ( ( ns / 1_000_000 ) as i32 ) . clamp ( 1 , 30_000 ) ;
1847+ let ret = unsafe { WSAPoll ( pollfds. as_mut_ptr ( ) , pollfds. len ( ) as u32 , timeout_ms) } ;
1848+
1849+ if ret < 0 {
1850+ let err = std:: io:: Error :: last_os_error ( ) ;
1851+ return Err ( anyhow ! ( "hl_sleep WSAPoll failed: {err}" ) ) ;
1852+ }
1853+
1854+ Ok ( json ! ( { "socket_ready" : ret > 0 } ) )
1855+ }
1856+
17491857// ---------------------------------------------------------------------------
17501858
17511859fn register_net_tools (
@@ -1819,7 +1927,6 @@ fn register_net_tools(
18191927 handle_net_getsockname ( & t, & args)
18201928 } ) ;
18211929
1822- #[ cfg( unix) ]
18231930 {
18241931 let t = table. clone ( ) ;
18251932 tools. register ( "net_poll" , move |args| handle_net_poll ( & t, & args) ) ;
0 commit comments