Skip to content

Commit af1b14b

Browse files
committed
std: move WinSock abstractions to sys::pal
1 parent 9f32ccf commit af1b14b

File tree

3 files changed

+84
-77
lines changed

3 files changed

+84
-77
lines changed

library/std/src/sys/net/connection/socket/windows.rs

Lines changed: 3 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ use crate::net::{Shutdown, SocketAddr};
88
use crate::os::windows::io::{
99
AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
1010
};
11-
use crate::sync::atomic::Atomic;
12-
use crate::sync::atomic::Ordering::{AcqRel, Relaxed};
1311
use crate::sys::c;
12+
use crate::sys::pal::winsock::last_error;
1413
use crate::sys_common::{AsInner, FromInner, IntoInner};
1514
use crate::time::Duration;
1615
use crate::{cmp, mem, ptr, sys};
@@ -112,84 +111,11 @@ pub(super) mod netc {
112111
}
113112
}
114113

114+
pub use crate::sys::pal::winsock::{cleanup, cvt, cvt_gai, cvt_r, startup as init};
115+
115116
#[expect(missing_debug_implementations)]
116117
pub struct Socket(OwnedSocket);
117118

118-
static WSA_INITIALIZED: Atomic<bool> = Atomic::<bool>::new(false);
119-
120-
/// Checks whether the Windows socket interface has been started already, and
121-
/// if not, starts it.
122-
#[inline]
123-
pub fn init() {
124-
if !WSA_INITIALIZED.load(Relaxed) {
125-
wsa_startup();
126-
}
127-
}
128-
129-
#[cold]
130-
fn wsa_startup() {
131-
unsafe {
132-
let mut data: c::WSADATA = mem::zeroed();
133-
let ret = c::WSAStartup(
134-
0x202, // version 2.2
135-
&mut data,
136-
);
137-
assert_eq!(ret, 0);
138-
if WSA_INITIALIZED.swap(true, AcqRel) {
139-
// If another thread raced with us and called WSAStartup first then call
140-
// WSACleanup so it's as though WSAStartup was only called once.
141-
c::WSACleanup();
142-
}
143-
}
144-
}
145-
146-
pub fn cleanup() {
147-
// We don't need to call WSACleanup here because exiting the process will cause
148-
// the OS to clean everything for us, which is faster than doing it manually.
149-
// See #141799.
150-
}
151-
152-
/// Returns the last error from the Windows socket interface.
153-
fn last_error() -> io::Error {
154-
io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
155-
}
156-
157-
#[doc(hidden)]
158-
pub trait IsMinusOne {
159-
fn is_minus_one(&self) -> bool;
160-
}
161-
162-
macro_rules! impl_is_minus_one {
163-
($($t:ident)*) => ($(impl IsMinusOne for $t {
164-
fn is_minus_one(&self) -> bool {
165-
*self == -1
166-
}
167-
})*)
168-
}
169-
170-
impl_is_minus_one! { i8 i16 i32 i64 isize }
171-
172-
/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
173-
/// and if so, returns the last error from the Windows socket interface. This
174-
/// function must be called before another call to the socket API is made.
175-
pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
176-
if t.is_minus_one() { Err(last_error()) } else { Ok(t) }
177-
}
178-
179-
/// A variant of `cvt` for `getaddrinfo` which return 0 for a success.
180-
pub fn cvt_gai(err: c_int) -> io::Result<()> {
181-
if err == 0 { Ok(()) } else { Err(last_error()) }
182-
}
183-
184-
/// Just to provide the same interface as sys/pal/unix/net.rs
185-
pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
186-
where
187-
T: IsMinusOne,
188-
F: FnMut() -> T,
189-
{
190-
cvt(f())
191-
}
192-
193119
impl Socket {
194120
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
195121
let family = match *addr {

library/std/src/sys/pal/windows/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ cfg_select! {
3030
pub use self::stack_overflow_uwp as stack_overflow;
3131
}
3232
}
33+
pub mod winsock;
3334

3435
/// Map a [`Result<T, WinError>`] to [`io::Result<T>`](crate::io::Result<T>).
3536
pub trait IoResult<T> {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use super::c;
2+
use crate::ffi::c_int;
3+
use crate::sync::atomic::Atomic;
4+
use crate::sync::atomic::Ordering::{AcqRel, Relaxed};
5+
use crate::{io, mem};
6+
7+
static WSA_STARTED: Atomic<bool> = Atomic::<bool>::new(false);
8+
9+
/// Checks whether the Windows socket interface has been started already, and
10+
/// if not, starts it.
11+
#[inline]
12+
pub fn startup() {
13+
if !WSA_STARTED.load(Relaxed) {
14+
wsa_startup();
15+
}
16+
}
17+
18+
#[cold]
19+
fn wsa_startup() {
20+
unsafe {
21+
let mut data: c::WSADATA = mem::zeroed();
22+
let ret = c::WSAStartup(
23+
0x202, // version 2.2
24+
&mut data,
25+
);
26+
assert_eq!(ret, 0);
27+
if WSA_STARTED.swap(true, AcqRel) {
28+
// If another thread raced with us and called WSAStartup first then call
29+
// WSACleanup so it's as though WSAStartup was only called once.
30+
c::WSACleanup();
31+
}
32+
}
33+
}
34+
35+
pub fn cleanup() {
36+
// We don't need to call WSACleanup here because exiting the process will cause
37+
// the OS to clean everything for us, which is faster than doing it manually.
38+
// See #141799.
39+
}
40+
41+
/// Returns the last error from the Windows socket interface.
42+
pub fn last_error() -> io::Error {
43+
io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
44+
}
45+
46+
#[doc(hidden)]
47+
pub trait IsMinusOne {
48+
fn is_minus_one(&self) -> bool;
49+
}
50+
51+
macro_rules! impl_is_minus_one {
52+
($($t:ident)*) => ($(impl IsMinusOne for $t {
53+
fn is_minus_one(&self) -> bool {
54+
*self == -1
55+
}
56+
})*)
57+
}
58+
59+
impl_is_minus_one! { i8 i16 i32 i64 isize }
60+
61+
/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
62+
/// and if so, returns the last error from the Windows socket interface. This
63+
/// function must be called before another call to the socket API is made.
64+
pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
65+
if t.is_minus_one() { Err(last_error()) } else { Ok(t) }
66+
}
67+
68+
/// A variant of `cvt` for `getaddrinfo` which return 0 for a success.
69+
pub fn cvt_gai(err: c_int) -> io::Result<()> {
70+
if err == 0 { Ok(()) } else { Err(last_error()) }
71+
}
72+
73+
/// Just to provide the same interface as sys/pal/unix/net.rs
74+
pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
75+
where
76+
T: IsMinusOne,
77+
F: FnMut() -> T,
78+
{
79+
cvt(f())
80+
}

0 commit comments

Comments
 (0)