@@ -83,7 +83,9 @@ use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, OwnedSocket, R
83
83
use futures_io:: { AsyncRead , AsyncWrite } ;
84
84
use futures_lite:: stream:: { self , Stream } ;
85
85
use 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;
87
89
88
90
use crate :: reactor:: { Reactor , Registration , Source } ;
89
91
@@ -656,23 +658,7 @@ impl<T: AsFd> Async<T> {
656
658
pub fn new ( io : T ) -> io:: Result < Async < T > > {
657
659
// Put the file descriptor in non-blocking mode.
658
660
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) ?;
676
662
677
663
// SAFETY: It is impossible to drop the I/O source while it is registered through
678
664
// this type.
@@ -1487,10 +1473,15 @@ impl Async<TcpStream> {
1487
1473
/// # std::io::Result::Ok(()) });
1488
1474
/// ```
1489
1475
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 .
1491
1477
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 ) ) ?;
1494
1485
let stream = Async :: new ( TcpStream :: from ( socket) ) ?;
1495
1486
1496
1487
// The stream becomes writable when connected.
@@ -1819,7 +1810,11 @@ impl Async<UnixStream> {
1819
1810
/// ```
1820
1811
pub async fn connect < P : AsRef < Path > > ( path : P ) -> io:: Result < Async < UnixStream > > {
1821
1812
// 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
+ ) ?;
1823
1818
let stream = Async :: new ( UnixStream :: from ( socket) ) ?;
1824
1819
1825
1820
// The stream becomes writable when connected.
@@ -2029,8 +2024,14 @@ async fn optimistic(fut: impl Future<Output = io::Result<()>>) -> io::Result<()>
2029
2024
. await
2030
2025
}
2031
2026
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
+
2034
2035
#[ cfg( any(
2035
2036
target_os = "android" ,
2036
2037
target_os = "dragonfly" ,
@@ -2041,10 +2042,13 @@ fn connect(addr: SockAddr, domain: Domain, protocol: Option<Protocol>) -> io::Re
2041
2042
target_os = "netbsd" ,
2042
2043
target_os = "openbsd"
2043
2044
) ) ]
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
+
2048
2052
#[ cfg( not( any(
2049
2053
target_os = "android" ,
2050
2054
target_os = "dragonfly" ,
@@ -2055,14 +2059,100 @@ fn connect(addr: SockAddr, domain: Domain, protocol: Option<Protocol>) -> io::Re
2055
2059
target_os = "netbsd" ,
2056
2060
target_os = "openbsd"
2057
2061
) ) ) ]
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) {
2061
2125
Ok ( _) => { }
2062
2126
#[ 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 ( ) ) ,
2066
2130
}
2067
2131
Ok ( socket)
2068
2132
}
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