@@ -47,41 +47,6 @@ use crate::{Domain, Protocol, SockAddr, Type};
4747/// can lead to a data race when two threads are changing options in parallel.
4848///
4949/// # Examples
50- ///
51- /// Creating a new socket setting all advisable flags.
52- ///
53- #[ cfg_attr( feature = "all" , doc = "```" ) ] // Protocol::cloexec requires the `all` feature.
54- #[ cfg_attr( not( feature = "all" ) , doc = "```ignore" ) ]
55- /// # fn main() -> std::io::Result<()> {
56- /// use socket2::{Protocol, Domain, Type, Socket};
57- ///
58- /// let domain = Domain::IPV4;
59- /// let ty = Type::STREAM;
60- /// let protocol = Protocol::TCP;
61- ///
62- /// // On platforms that support it set `SOCK_CLOEXEC`.
63- /// #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
64- /// let ty = ty.cloexec();
65- ///
66- /// // On windows set `WSA_FLAG_NO_HANDLE_INHERIT`.
67- /// #[cfg(windows)]
68- /// let ty = ty.no_inherit();
69- ///
70- /// let socket = Socket::new(domain, ty, Some(protocol))?;
71- ///
72- /// // On platforms that don't support `SOCK_CLOEXEC`, use `FD_CLOEXEC`.
73- /// #[cfg(all(not(windows), not(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "openbsd"))))]
74- /// socket.set_cloexec(true)?;
75- ///
76- /// // On macOS and iOS set `NOSIGPIPE`.
77- /// #[cfg(target_vendor = "apple")]
78- /// socket.set_nosigpipe(true)?;
79- ///
80- /// # drop(socket);
81- /// # Ok(())
82- /// # }
83- /// ```
84- ///
8550/// ```no_run
8651/// # fn main() -> std::io::Result<()> {
8752/// use std::net::{SocketAddr, TcpListener};
@@ -107,29 +72,26 @@ pub struct Socket {
10772}
10873
10974impl Socket {
110- /// Creates a new socket ready to be configured .
75+ /// Creates a new socket and sets common flags .
11176 ///
11277 /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
113- /// Windows and simply creates a new socket, no other configuration is done
114- /// and further functions must be invoked to configure this socket.
115- ///
116- /// # Notes
117- ///
118- /// The standard library sets the `CLOEXEC` flag on Unix on sockets, this
119- /// function does **not** do this, but its advisable. On supported platforms
120- /// [`Type::cloexec`] can be used for this, or by using
121- /// [`Socket::set_cloexec`].
78+ /// Windows.
12279 ///
123- /// Furthermore on macOS and iOS `NOSIGPIPE` is not set, this can be done
124- /// using [`Socket::set_nosigpipe`].
80+ /// On Unix-like systems, the close-on-exec flag is set on the new socket.
81+ /// Additionally, on Apple platforms `SOCK_NOSIGPIPE` is set. On Windows,
82+ /// the socket is made non-inheritable.
12583 ///
126- /// Similarly on Windows the `HANDLE_FLAG_INHERIT` is **not** set to zero,
127- /// but again in most cases its advisable to do so. This can be doing using
128- /// [`Socket::set_no_inherit`].
129- ///
130- /// See the `Socket` documentation for a full example of setting all the
131- /// above mentioned flags.
84+ /// [`Socket::new_raw`] can be used if you don't want these flags to be set.
13285 pub fn new ( domain : Domain , ty : Type , protocol : Option < Protocol > ) -> io:: Result < Socket > {
86+ let ty = set_common_type ( ty) ;
87+ Socket :: new_raw ( domain, ty, protocol) . and_then ( set_common_flags)
88+ }
89+
90+ /// Creates a new socket ready to be configured.
91+ ///
92+ /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
93+ /// Windows and simply creates a new socket, no other configuration is done.
94+ pub fn new_raw ( domain : Domain , ty : Type , protocol : Option < Protocol > ) -> io:: Result < Socket > {
13395 let protocol = protocol. map ( |p| p. 0 ) . unwrap_or ( 0 ) ;
13496 sys:: socket ( domain. 0 , ty. 0 , protocol) . map ( |inner| Socket { inner } )
13597 }
@@ -138,17 +100,37 @@ impl Socket {
138100 ///
139101 /// This function corresponds to `socketpair(2)`.
140102 ///
141- /// # Notes
103+ /// This function sets the same flags as in done for [`Socket::new`],
104+ /// [`Socket::pair_raw`] can be used if you don't want to set those flags.
142105 ///
143- /// Much like [`Socket::new`] this doesn't set any flags, which might be
144- /// advisable.
106+ /// # Notes
145107 ///
146108 /// This function is only available on Unix.
147109 #[ cfg( all( feature = "all" , unix) ) ]
148110 pub fn pair (
149111 domain : Domain ,
150112 ty : Type ,
151113 protocol : Option < Protocol > ,
114+ ) -> io:: Result < ( Socket , Socket ) > {
115+ let ty = set_common_type ( ty) ;
116+ let ( a, b) = Socket :: pair_raw ( domain, ty, protocol) ?;
117+ let a = set_common_flags ( a) ?;
118+ let b = set_common_flags ( b) ?;
119+ Ok ( ( a, b) )
120+ }
121+
122+ /// Creates a pair of sockets which are connected to each other.
123+ ///
124+ /// This function corresponds to `socketpair(2)`.
125+ ///
126+ /// # Notes
127+ ///
128+ /// This function is only available on Unix.
129+ #[ cfg( all( feature = "all" , unix) ) ]
130+ pub fn pair_raw (
131+ domain : Domain ,
132+ ty : Type ,
133+ protocol : Option < Protocol > ,
152134 ) -> io:: Result < ( Socket , Socket ) > {
153135 let protocol = protocol. map ( |p| p. 0 ) . unwrap_or ( 0 ) ;
154136 sys:: socketpair ( domain. 0 , ty. 0 , protocol)
@@ -195,19 +177,43 @@ impl Socket {
195177
196178 /// Accept a new incoming connection from this listener.
197179 ///
198- /// This function directly corresponds to the `accept(2)` function on
199- /// Windows and Unix.
200- ///
201- /// This function will block the calling thread until a new connection is
202- /// established. When established, the corresponding `Socket` and the
203- /// remote peer's address will be returned.
204- ///
205- /// # Notes
180+ /// This function uses `accept4(2)` on platforms that support it and
181+ /// `accept(2)` platforms that do not.
206182 ///
207- /// Like [`Socket::new`] this will not set any flags. If that is desirable,
208- /// e.g. setting `CLOEXEC`, [`Socket::accept4`] can be used on supported
209- /// OSes or [`Socket::set_cloexec`] can be called.
183+ /// This function sets the same flags as in done for [`Socket::new`],
184+ /// [`Socket::accept_raw`] can be used if you don't want to set those flags.
210185 pub fn accept ( & self ) -> io:: Result < ( Socket , SockAddr ) > {
186+ // Use `accept4` on platforms that support it.
187+ #[ cfg( any(
188+ target_os = "android" ,
189+ target_os = "dragonfly" ,
190+ target_os = "freebsd" ,
191+ target_os = "linux" ,
192+ target_os = "netbsd" ,
193+ target_os = "openbsd" ,
194+ ) ) ]
195+ return self . _accept4 ( libc:: SOCK_CLOEXEC ) ;
196+
197+ // Fall back to `accept` on platforms that do not support `accept4`.
198+ #[ cfg( not( any(
199+ target_os = "android" ,
200+ target_os = "dragonfly" ,
201+ target_os = "freebsd" ,
202+ target_os = "linux" ,
203+ target_os = "netbsd" ,
204+ target_os = "openbsd" ,
205+ ) ) ) ]
206+ {
207+ let ( socket, addr) = self . accept_raw ( ) ?;
208+ set_common_flags ( socket) . map ( |socket| ( socket, addr) )
209+ }
210+ }
211+
212+ /// Accept a new incoming connection from this listener.
213+ ///
214+ /// This function directly corresponds to the `accept(2)` function on
215+ /// Windows and Unix.
216+ pub fn accept_raw ( & self ) -> io:: Result < ( Socket , SockAddr ) > {
211217 sys:: accept ( self . inner ) . map ( |( inner, addr) | ( Socket { inner } , addr) )
212218 }
213219
@@ -918,6 +924,52 @@ impl Socket {
918924 }
919925}
920926
927+ /// Set `SOCK_CLOEXEC` and `NO_HANDLE_INHERIT` on the `ty`pe on platforms that
928+ /// support it.
929+ #[ inline( always) ]
930+ fn set_common_type ( ty : Type ) -> Type {
931+ // On platforms that support it set `SOCK_CLOEXEC`.
932+ #[ cfg( any(
933+ target_os = "android" ,
934+ target_os = "dragonfly" ,
935+ target_os = "freebsd" ,
936+ target_os = "linux" ,
937+ target_os = "netbsd" ,
938+ target_os = "openbsd" ,
939+ ) ) ]
940+ let ty = ty. _cloexec ( ) ;
941+
942+ // On windows set `NO_HANDLE_INHERIT`.
943+ #[ cfg( windows) ]
944+ let ty = ty. _no_inherit ( ) ;
945+
946+ ty
947+ }
948+
949+ /// Set `FD_CLOEXEC` and `NOSIGPIPE` on the `socket` for platforms that need it.
950+ #[ inline( always) ]
951+ fn set_common_flags ( socket : Socket ) -> io:: Result < Socket > {
952+ // On platforms that don't have `SOCK_CLOEXEC` use `FD_CLOEXEC`.
953+ #[ cfg( all(
954+ unix,
955+ not( any(
956+ target_os = "android" ,
957+ target_os = "dragonfly" ,
958+ target_os = "freebsd" ,
959+ target_os = "linux" ,
960+ target_os = "netbsd" ,
961+ target_os = "openbsd" ,
962+ ) )
963+ ) ) ]
964+ socket. _set_cloexec ( true ) ?;
965+
966+ // On Apple platforms set `NOSIGPIPE`.
967+ #[ cfg( target_vendor = "apple" ) ]
968+ socket. _set_nosigpipe ( true ) ?;
969+
970+ Ok ( socket)
971+ }
972+
921973impl Read for Socket {
922974 fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
923975 self . recv ( buf)
0 commit comments