@@ -83,7 +83,9 @@ use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, OwnedSocket, R
8383use futures_io:: { AsyncRead , AsyncWrite } ;
8484use futures_lite:: stream:: { self , Stream } ;
8585use futures_lite:: { future, pin, ready} ;
86- use socket2:: { Domain , Protocol , SockAddr , Socket , Type } ;
86+
87+ use rustix:: io as rio;
88+ use rustix:: net as rn;
8789
8890use crate :: reactor:: { Reactor , Registration , Source } ;
8991
@@ -656,23 +658,7 @@ impl<T: AsFd> Async<T> {
656658 pub fn new ( io : T ) -> io:: Result < Async < T > > {
657659 // Put the file descriptor in non-blocking mode.
658660 let fd = io. as_fd ( ) ;
659- cfg_if:: cfg_if! {
660- // ioctl(FIONBIO) sets the flag atomically, but we use this only on Linux
661- // for now, as with the standard library, because it seems to behave
662- // differently depending on the platform.
663- // https://github.com/rust-lang/rust/commit/efeb42be2837842d1beb47b51bb693c7474aba3d
664- // https://github.com/libuv/libuv/blob/e9d91fccfc3e5ff772d5da90e1c4a24061198ca0/src/unix/poll.c#L78-L80
665- // https://github.com/tokio-rs/mio/commit/0db49f6d5caf54b12176821363d154384357e70a
666- if #[ cfg( target_os = "linux" ) ] {
667- rustix:: io:: ioctl_fionbio( fd, true ) ?;
668- } else {
669- let previous = rustix:: fs:: fcntl_getfl( fd) ?;
670- let new = previous | rustix:: fs:: OFlags :: NONBLOCK ;
671- if new != previous {
672- rustix:: fs:: fcntl_setfl( fd, new) ?;
673- }
674- }
675- }
661+ set_nonblocking ( fd) ?;
676662
677663 // SAFETY: It is impossible to drop the I/O source while it is registered through
678664 // this type.
@@ -1487,10 +1473,15 @@ impl Async<TcpStream> {
14871473 /// # std::io::Result::Ok(()) });
14881474 /// ```
14891475 pub async fn connect < A : Into < SocketAddr > > ( addr : A ) -> io:: Result < Async < TcpStream > > {
1490- // Begin async connect .
1476+ // Figure out how to handle this address .
14911477 let addr = addr. into ( ) ;
1492- let domain = Domain :: for_address ( addr) ;
1493- let socket = connect ( addr. into ( ) , domain, Some ( Protocol :: TCP ) ) ?;
1478+ let ( domain, sock_addr) = match addr {
1479+ SocketAddr :: V4 ( v4) => ( rn:: AddressFamily :: INET , rn:: SocketAddrAny :: V4 ( v4) ) ,
1480+ SocketAddr :: V6 ( v6) => ( rn:: AddressFamily :: INET6 , rn:: SocketAddrAny :: V6 ( v6) ) ,
1481+ } ;
1482+
1483+ // Begin async connect.
1484+ let socket = connect ( sock_addr, domain, Some ( rn:: ipproto:: TCP ) ) ?;
14941485 let stream = Async :: new ( TcpStream :: from ( socket) ) ?;
14951486
14961487 // The stream becomes writable when connected.
@@ -1819,7 +1810,11 @@ impl Async<UnixStream> {
18191810 /// ```
18201811 pub async fn connect < P : AsRef < Path > > ( path : P ) -> io:: Result < Async < UnixStream > > {
18211812 // Begin async connect.
1822- let socket = connect ( SockAddr :: unix ( path) ?, Domain :: UNIX , None ) ?;
1813+ let socket = connect (
1814+ rn:: SocketAddrUnix :: new ( path. as_ref ( ) ) ?. into ( ) ,
1815+ rn:: AddressFamily :: UNIX ,
1816+ None ,
1817+ ) ?;
18231818 let stream = Async :: new ( UnixStream :: from ( socket) ) ?;
18241819
18251820 // The stream becomes writable when connected.
@@ -2029,8 +2024,14 @@ async fn optimistic(fut: impl Future<Output = io::Result<()>>) -> io::Result<()>
20292024 . await
20302025}
20312026
2032- fn connect ( addr : SockAddr , domain : Domain , protocol : Option < Protocol > ) -> io:: Result < Socket > {
2033- let sock_type = Type :: STREAM ;
2027+ fn connect (
2028+ addr : rn:: SocketAddrAny ,
2029+ domain : rn:: AddressFamily ,
2030+ protocol : Option < rn:: Protocol > ,
2031+ ) -> io:: Result < rustix:: fd:: OwnedFd > {
2032+ #[ cfg( windows) ]
2033+ use rustix:: fd:: AsFd ;
2034+
20342035 #[ cfg( any(
20352036 target_os = "android" ,
20362037 target_os = "dragonfly" ,
@@ -2041,10 +2042,13 @@ fn connect(addr: SockAddr, domain: Domain, protocol: Option<Protocol>) -> io::Re
20412042 target_os = "netbsd" ,
20422043 target_os = "openbsd"
20432044 ) ) ]
2044- // If we can, set nonblocking at socket creation for unix
2045- let sock_type = sock_type. nonblocking ( ) ;
2046- // This automatically handles cloexec on unix, no_inherit on windows and nosigpipe on macos
2047- let socket = Socket :: new ( domain, sock_type, protocol) ?;
2045+ let socket = rn:: socket_with (
2046+ domain,
2047+ rn:: SocketType :: STREAM ,
2048+ rn:: SocketFlags :: CLOEXEC | rn:: SocketFlags :: NONBLOCK ,
2049+ protocol,
2050+ ) ?;
2051+
20482052 #[ cfg( not( any(
20492053 target_os = "android" ,
20502054 target_os = "dragonfly" ,
@@ -2055,14 +2059,100 @@ fn connect(addr: SockAddr, domain: Domain, protocol: Option<Protocol>) -> io::Re
20552059 target_os = "netbsd" ,
20562060 target_os = "openbsd"
20572061 ) ) ) ]
2058- // If the current platform doesn't support nonblocking at creation, enable it after creation
2059- socket. set_nonblocking ( true ) ?;
2060- match socket. connect ( & addr) {
2062+ let socket = {
2063+ #[ cfg( not( any(
2064+ target_os = "macos" ,
2065+ target_os = "ios" ,
2066+ target_os = "tvos" ,
2067+ target_os = "watchos" ,
2068+ target_os = "espidf" ,
2069+ windows,
2070+ ) ) ) ]
2071+ let flags = rn:: SocketFlags :: CLOEXEC ;
2072+ #[ cfg( any(
2073+ target_os = "macos" ,
2074+ target_os = "ios" ,
2075+ target_os = "tvos" ,
2076+ target_os = "watchos" ,
2077+ target_os = "espidf" ,
2078+ windows,
2079+ ) ) ]
2080+ let flags = rn:: SocketFlags :: empty ( ) ;
2081+
2082+ // Create the socket.
2083+ let socket = rn:: socket_with ( domain, rn:: SocketType :: STREAM , flags, protocol) ?;
2084+
2085+ // Set cloexec if necessary.
2086+ #[ cfg( any(
2087+ target_os = "macos" ,
2088+ target_os = "ios" ,
2089+ target_os = "tvos" ,
2090+ target_os = "watchos" ,
2091+ ) ) ]
2092+ rio:: fcntl_setfd ( & socket, rio:: fcntl_getfd ( & socket) ? | rio:: FdFlags :: CLOEXEC ) ?;
2093+
2094+ // Set non-blocking mode.
2095+ set_nonblocking ( socket. as_fd ( ) ) ?;
2096+
2097+ socket
2098+ } ;
2099+
2100+ // Set nosigpipe if necessary.
2101+ #[ cfg( any(
2102+ target_os = "macos" ,
2103+ target_os = "ios" ,
2104+ target_os = "tvos" ,
2105+ target_os = "watchos" ,
2106+ target_os = "freebsd"
2107+ ) ) ]
2108+ rn:: sockopt:: set_socket_nosigpipe ( & socket, true ) ?;
2109+
2110+ // Set the handle information to HANDLE_FLAG_INHERIT.
2111+ #[ cfg( windows) ]
2112+ unsafe {
2113+ if windows_sys:: Win32 :: Foundation :: SetHandleInformation (
2114+ socket. as_raw_socket ( ) as _ ,
2115+ windows_sys:: Win32 :: Foundation :: HANDLE_FLAG_INHERIT ,
2116+ windows_sys:: Win32 :: Foundation :: HANDLE_FLAG_INHERIT ,
2117+ ) == 0
2118+ {
2119+ return Err ( io:: Error :: last_os_error ( ) ) ;
2120+ }
2121+ }
2122+
2123+ #[ allow( unreachable_patterns) ]
2124+ match rn:: connect_any ( & socket, & addr) {
20612125 Ok ( _) => { }
20622126 #[ cfg( unix) ]
2063- Err ( err ) if err . raw_os_error ( ) == Some ( rustix :: io :: Errno :: INPROGRESS . raw_os_error ( ) ) => { }
2064- Err ( err ) if err . kind ( ) == io :: ErrorKind :: WouldBlock => { }
2065- Err ( err) => return Err ( err) ,
2127+ Err ( rio :: Errno :: INPROGRESS ) => { }
2128+ Err ( rio :: Errno :: AGAIN ) | Err ( rio :: Errno :: WOULDBLOCK ) => { }
2129+ Err ( err) => return Err ( err. into ( ) ) ,
20662130 }
20672131 Ok ( socket)
20682132}
2133+
2134+ #[ inline]
2135+ fn set_nonblocking (
2136+ #[ cfg( unix) ] fd : BorrowedFd < ' _ > ,
2137+ #[ cfg( windows) ] fd : BorrowedSocket < ' _ > ,
2138+ ) -> io:: Result < ( ) > {
2139+ cfg_if:: cfg_if! {
2140+ // ioctl(FIONBIO) sets the flag atomically, but we use this only on Linux
2141+ // for now, as with the standard library, because it seems to behave
2142+ // differently depending on the platform.
2143+ // https://github.com/rust-lang/rust/commit/efeb42be2837842d1beb47b51bb693c7474aba3d
2144+ // https://github.com/libuv/libuv/blob/e9d91fccfc3e5ff772d5da90e1c4a24061198ca0/src/unix/poll.c#L78-L80
2145+ // https://github.com/tokio-rs/mio/commit/0db49f6d5caf54b12176821363d154384357e70a
2146+ if #[ cfg( any( windows, target_os = "linux" ) ) ] {
2147+ rustix:: io:: ioctl_fionbio( fd, true ) ?;
2148+ } else {
2149+ let previous = rustix:: fs:: fcntl_getfl( fd) ?;
2150+ let new = previous | rustix:: fs:: OFlags :: NONBLOCK ;
2151+ if new != previous {
2152+ rustix:: fs:: fcntl_setfl( fd, new) ?;
2153+ }
2154+ }
2155+ }
2156+
2157+ Ok ( ( ) )
2158+ }
0 commit comments