diff options
| author | joboet <jonasboettiger@icloud.com> | 2025-09-23 17:13:35 +0200 |
|---|---|---|
| committer | joboet <jonasboettiger@icloud.com> | 2025-09-23 17:13:35 +0200 |
| commit | af1b14bb9b1b3d301c1e8e0a989d814deaf054c9 (patch) | |
| tree | a781e8973ad82780c91ae8fc28fa49cf92136496 /library | |
| parent | 9f32ccf35fb877270bc44a86a126440f04d676d0 (diff) | |
| download | rust-af1b14bb9b1b3d301c1e8e0a989d814deaf054c9.tar.gz rust-af1b14bb9b1b3d301c1e8e0a989d814deaf054c9.zip | |
std: move WinSock abstractions to `sys::pal`
Diffstat (limited to 'library')
| -rw-r--r-- | library/std/src/sys/net/connection/socket/windows.rs | 80 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/mod.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/winsock.rs | 80 |
3 files changed, 84 insertions, 77 deletions
diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs index b71d8b1357b..5b6f4cedf1b 100644 --- a/library/std/src/sys/net/connection/socket/windows.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -8,9 +8,8 @@ use crate::net::{Shutdown, SocketAddr}; use crate::os::windows::io::{ AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket, }; -use crate::sync::atomic::Atomic; -use crate::sync::atomic::Ordering::{AcqRel, Relaxed}; use crate::sys::c; +use crate::sys::pal::winsock::last_error; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, mem, ptr, sys}; @@ -112,84 +111,11 @@ pub(super) mod netc { } } +pub use crate::sys::pal::winsock::{cleanup, cvt, cvt_gai, cvt_r, startup as init}; + #[expect(missing_debug_implementations)] pub struct Socket(OwnedSocket); -static WSA_INITIALIZED: Atomic<bool> = Atomic::<bool>::new(false); - -/// Checks whether the Windows socket interface has been started already, and -/// if not, starts it. -#[inline] -pub fn init() { - if !WSA_INITIALIZED.load(Relaxed) { - wsa_startup(); - } -} - -#[cold] -fn wsa_startup() { - unsafe { - let mut data: c::WSADATA = mem::zeroed(); - let ret = c::WSAStartup( - 0x202, // version 2.2 - &mut data, - ); - assert_eq!(ret, 0); - if WSA_INITIALIZED.swap(true, AcqRel) { - // If another thread raced with us and called WSAStartup first then call - // WSACleanup so it's as though WSAStartup was only called once. - c::WSACleanup(); - } - } -} - -pub fn cleanup() { - // We don't need to call WSACleanup here because exiting the process will cause - // the OS to clean everything for us, which is faster than doing it manually. - // See #141799. -} - -/// Returns the last error from the Windows socket interface. -fn last_error() -> io::Error { - io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() }) -} - -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 - } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) -/// and if so, returns the last error from the Windows socket interface. This -/// function must be called before another call to the socket API is made. -pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { - if t.is_minus_one() { Err(last_error()) } else { Ok(t) } -} - -/// A variant of `cvt` for `getaddrinfo` which return 0 for a success. -pub fn cvt_gai(err: c_int) -> io::Result<()> { - if err == 0 { Ok(()) } else { Err(last_error()) } -} - -/// Just to provide the same interface as sys/pal/unix/net.rs -pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> -where - T: IsMinusOne, - F: FnMut() -> T, -{ - cvt(f()) -} - impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { let family = match *addr { diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 3357946b8f7..85a4d3ca6db 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -30,6 +30,7 @@ cfg_select! { pub use self::stack_overflow_uwp as stack_overflow; } } +pub mod winsock; /// Map a [`Result<T, WinError>`] to [`io::Result<T>`](crate::io::Result<T>). pub trait IoResult<T> { diff --git a/library/std/src/sys/pal/windows/winsock.rs b/library/std/src/sys/pal/windows/winsock.rs new file mode 100644 index 00000000000..b110a43ef3a --- /dev/null +++ b/library/std/src/sys/pal/windows/winsock.rs @@ -0,0 +1,80 @@ +use super::c; +use crate::ffi::c_int; +use crate::sync::atomic::Atomic; +use crate::sync::atomic::Ordering::{AcqRel, Relaxed}; +use crate::{io, mem}; + +static WSA_STARTED: Atomic<bool> = Atomic::<bool>::new(false); + +/// Checks whether the Windows socket interface has been started already, and +/// if not, starts it. +#[inline] +pub fn startup() { + if !WSA_STARTED.load(Relaxed) { + wsa_startup(); + } +} + +#[cold] +fn wsa_startup() { + unsafe { + let mut data: c::WSADATA = mem::zeroed(); + let ret = c::WSAStartup( + 0x202, // version 2.2 + &mut data, + ); + assert_eq!(ret, 0); + if WSA_STARTED.swap(true, AcqRel) { + // If another thread raced with us and called WSAStartup first then call + // WSACleanup so it's as though WSAStartup was only called once. + c::WSACleanup(); + } + } +} + +pub fn cleanup() { + // We don't need to call WSACleanup here because exiting the process will cause + // the OS to clean everything for us, which is faster than doing it manually. + // See #141799. +} + +/// Returns the last error from the Windows socket interface. +pub fn last_error() -> io::Error { + io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() }) +} + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) +/// and if so, returns the last error from the Windows socket interface. This +/// function must be called before another call to the socket API is made. +pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { + if t.is_minus_one() { Err(last_error()) } else { Ok(t) } +} + +/// A variant of `cvt` for `getaddrinfo` which return 0 for a success. +pub fn cvt_gai(err: c_int) -> io::Result<()> { + if err == 0 { Ok(()) } else { Err(last_error()) } +} + +/// Just to provide the same interface as sys/pal/unix/net.rs +pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> +where + T: IsMinusOne, + F: FnMut() -> T, +{ + cvt(f()) +} |
