diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-03-01 03:41:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-01 03:41:50 +0100 |
| commit | 06d47a414bdf6be59fe8393fdd1ccb0247dce6f2 (patch) | |
| tree | a210e0af1072c1d2a643249d0edc9a4549a6d2e5 | |
| parent | daed86445de99e6dfcf128948bf34fff96c733ef (diff) | |
| parent | b02698c7e6843d6feacc394cb7f83f3fc347c3e2 (diff) | |
| download | rust-06d47a414bdf6be59fe8393fdd1ccb0247dce6f2.tar.gz rust-06d47a414bdf6be59fe8393fdd1ccb0247dce6f2.zip | |
Rollup merge of #94094 - chrisnc:tcp-nodelay-windows-bool, r=dtolnay
use BOOL for TCP_NODELAY setsockopt value on Windows This issue was found by the Wine project and mitigated there [^1]. Windows' setsockopt expects a BOOL (a typedef for int) for TCP_NODELAY [^2]. Windows itself is forgiving and will accept any positive optlen and interpret the first byte of *optval as the value, so this bug does not affect Windows itself, but does affect systems implementing Windows' interface more strictly, such as Wine. Wine was previously passing this through to the host's setsockopt, where, e.g., Linux requires that optlen be correct for the chosen option, and TCP_NODELAY expects an int. [^1]: https://source.winehq.org/git/wine.git/commit/d6ea38f32dfd3edbe107a255c37e9f7f3da06ae7 [^2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt
| -rw-r--r-- | library/std/src/sys/windows/net.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys_common/net.rs | 33 |
2 files changed, 26 insertions, 11 deletions
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index aa6400aeefa..5de12313784 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -407,11 +407,11 @@ impl Socket { } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { - net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE) + net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) } pub fn nodelay(&self) -> io::Result<bool> { - let raw: c::BYTE = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; + let raw: c::BOOL = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; Ok(raw != 0) } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 70b29d4a92e..3b7cdd55a08 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -58,21 +58,36 @@ cfg_if::cfg_if! { // sockaddr and misc bindings //////////////////////////////////////////////////////////////////////////////// -pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { +pub fn setsockopt<T>( + sock: &Socket, + level: c_int, + option_name: c_int, + option_value: T, +) -> io::Result<()> { unsafe { - let payload = &payload as *const T as *const c_void; - cvt(c::setsockopt(sock.as_raw(), opt, val, payload, mem::size_of::<T>() as c::socklen_t))?; + cvt(c::setsockopt( + sock.as_raw(), + level, + option_name, + &option_value as *const T as *const _, + mem::size_of::<T>() as c::socklen_t, + ))?; Ok(()) } } -pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<T> { +pub fn getsockopt<T: Copy>(sock: &Socket, level: c_int, option_name: c_int) -> io::Result<T> { unsafe { - let mut slot: T = mem::zeroed(); - let mut len = mem::size_of::<T>() as c::socklen_t; - cvt(c::getsockopt(sock.as_raw(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?; - assert_eq!(len as usize, mem::size_of::<T>()); - Ok(slot) + let mut option_value: T = mem::zeroed(); + let mut option_len = mem::size_of::<T>() as c::socklen_t; + cvt(c::getsockopt( + sock.as_raw(), + level, + option_name, + &mut option_value as *mut T as *mut _, + &mut option_len, + ))?; + Ok(option_value) } } |
