@@ -4,13 +4,19 @@ use std::{
4
4
net:: { IpAddr , Ipv4Addr } ,
5
5
os:: windows:: io:: AsRawSocket ,
6
6
ptr,
7
- sync:: Mutex ,
7
+ sync:: { LazyLock , Mutex } ,
8
8
time:: Instant ,
9
9
} ;
10
10
11
11
use libc:: { c_int, c_uint} ;
12
12
use once_cell:: sync:: Lazy ;
13
- use windows_sys:: Win32 :: Networking :: WinSock ;
13
+ use windows_sys:: Win32 :: {
14
+ Networking :: WinSock ,
15
+ System :: {
16
+ SystemInformation :: IMAGE_FILE_MACHINE_ARM64 ,
17
+ Threading :: { GetCurrentProcess , IsWow64Process2 } ,
18
+ } ,
19
+ } ;
14
20
15
21
use crate :: {
16
22
cmsg:: { self , CMsgHdr } ,
@@ -107,16 +113,33 @@ impl UdpSocketState {
107
113
) ?;
108
114
}
109
115
110
- // Opportunistically try to enable GRO
111
- _ = set_socket_option (
112
- & * socket. 0 ,
113
- WinSock :: IPPROTO_UDP ,
114
- WinSock :: UDP_RECV_MAX_COALESCED_SIZE ,
115
- // u32 per
116
- // https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options.
117
- // Choice of 2^16 - 1 inspired by msquic.
118
- u16:: MAX as u32 ,
119
- ) ;
116
+ match & * IS_WINDOWS_ON_ARM {
117
+ Ok ( true ) => {
118
+ // Bug on Windows on ARM, not receiving `UDP_COALESCED_INFO` `CMSG`
119
+ // when _Virtual Machine Platform_ feature enabled. See
120
+ // <https://github.com/quinn-rs/quinn/issues/2041> for details.
121
+ debug ! ( "detected Windows on ARM host thus not enabling URO" )
122
+ }
123
+ Ok ( false ) => {
124
+ // Opportunistically try to enable URO
125
+ let result = set_socket_option (
126
+ & * socket. 0 ,
127
+ WinSock :: IPPROTO_UDP ,
128
+ WinSock :: UDP_RECV_MAX_COALESCED_SIZE ,
129
+ // u32 per
130
+ // https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-udp-socket-options.
131
+ // Choice of 2^16 - 1 inspired by msquic.
132
+ u16:: MAX as u32 ,
133
+ ) ;
134
+
135
+ if let Err ( e) = result {
136
+ debug ! ( "failed to enable URO: {}" , e) ;
137
+ }
138
+ }
139
+ Err ( e) => {
140
+ debug ! ( "failed to detect host system thus not enabling URO: {}" , e) ;
141
+ }
142
+ }
120
143
121
144
let now = Instant :: now ( ) ;
122
145
Ok ( Self {
@@ -470,3 +493,28 @@ static MAX_GSO_SEGMENTS: Lazy<usize> = Lazy::new(|| {
470
493
Err ( _) => 1 ,
471
494
}
472
495
} ) ;
496
+
497
+ /// Evaluates to [`Ok(true)`] if executed either directly on Windows on ARM, or
498
+ /// on an emulator which itself executes on Windows on ARM.
499
+ ///
500
+ /// See
501
+ /// <https://learn.microsoft.com/en-us/windows/arm/apps-on-arm-x86-emulation#detecting-emulation>
502
+ /// for details.
503
+ static IS_WINDOWS_ON_ARM : LazyLock < io:: Result < bool > > = LazyLock :: new ( || {
504
+ let mut process_machine: u16 = 0 ;
505
+ let mut native_machine: u16 = 0 ;
506
+
507
+ let result = unsafe {
508
+ IsWow64Process2 (
509
+ GetCurrentProcess ( ) ,
510
+ & mut process_machine as * mut u16 ,
511
+ & mut native_machine as * mut u16 ,
512
+ )
513
+ } ;
514
+
515
+ if result == 0 {
516
+ return Err ( io:: Error :: last_os_error ( ) ) ;
517
+ }
518
+
519
+ Ok ( native_machine == IMAGE_FILE_MACHINE_ARM64 )
520
+ } ) ;
0 commit comments