rust-lang / socket2

Advanced configuration options for sockets.

Home Page:https://docs.rs/socket2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why cannot find WASStartup and WSACleanup in source code?

takkuumi opened this issue · comments

Question 1: I found that the WINDOWS system handles the network offline (unplug the peer network cable), and it takes about 8 seconds for the program to detect it.
Problem 2: During the brute force test, connections are constantly established and closed (shutdown). Socket2 does not call the WSACleanup function, so the connection fails.

Question 1: I found that the WINDOWS system handles the network offline (unplug the peer network cable), and it takes about 8 seconds for the program to detect it.

This is outside of the scope of socket2. Socket2 doesn't do anything to change this.

Problem 2: During the brute force test, connections are constantly established and closed (shutdown). Socket2 does not call the WSACleanup function, so the connection fails.

We use the standard library for WSAStartup, see

socket2/src/sys/windows.rs

Lines 218 to 227 in 1f70523

fn init() {
static INIT: Once = Once::new();
INIT.call_once(|| {
// Initialize winsock through the standard library by just creating a
// dummy socket. Whether this is successful or not we drop the result as
// libstd will be sure to have initialized winsock.
let _ = net::UdpSocket::bind("127.0.0.1:34254");
});
}
. In rust standard library: https://github.com/rust-lang/rust/blob/078eb1120a3f576598b976d9470701363f48fccc/library/std/src/sys/windows/net.rs#L36-L59

Is there a reason why WSAStartup isn't called directly? Being tied to the standard library's startup/shutdown seems less versatile and more hacky.

Is there a reason why WSAStartup isn't called directly? Being tied to the standard library's startup/shutdown seems less versatile and more hacky.

It's not really possible as standard library always calls the WSAStartup whenever a std::net type is used. Furthermore it will panic if the call to WSAStartup fails. So if socket2 would call WSAStartup itself any usage of a type in std::net would cause a panic.

WSAStartup can be successfully called multiple times. The std only panics if the call fails. Trivial example:

fn main() {
    init();
    init();
    init();
    println!("Succesfully initialized");
    unsafe {
        assert_eq!(WSACleanup(), 0);
        assert_eq!(WSACleanup(), 0);
        assert_eq!(WSACleanup(), 0);
    }
    println!("Successfully shutdown");
}

fn init() {
    unsafe {
        let mut data: WSADATA = std::mem::zeroed();
        let ret = WSAStartup(0x202, &mut data);
        assert_eq!(ret, 0);
    }
}

#[link(name="Ws2_32")]
extern "system" {
    fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32;
    fn WSACleanup() -> i32;
}
#[repr(C)]
#[allow(non_snake_case)]
pub struct WSADATA {
    pub wVersion: u16,
    pub wHighVersion: u16,
    pub iMaxSockets: u16,
    pub iMaxUdpDg: u16,
    pub lpVendorInfo: *const u8,
    pub szDescription: [u8; 257],
    pub szSystemStatus: [u8; 129],
}

WSAStartup can be successfully called multiple times. The std only panics if the call fails. Trivial example:

That certainly didn't use the be case. What Windows version are you using?

Some more background: tokio-rs/mio#1046, tokio-rs/mio#1029

I've not yet investigated those threads but it's documented behaviour so I'm surprised it didn't work.

An application can call WSAStartup more than once if it needs to obtain the WSADATA structure information more than once. On each such call, the application can specify any version number supported by the Winsock DLL...
An application must call the WSACleanup function for every successful time the WSAStartup function is called.

I've not yet investigated those threads but it's documented behaviour so I'm surprised it didn't work.

An application can call WSAStartup more than once if it needs to obtain the WSADATA structure information more than once. On each such call, the application can specify any version number supported by the Winsock DLL...
An application must call the WSACleanup function for every successful time the WSAStartup function is called.

This might have changed in later versions, I don't know, don't really keep track of it.