@@ -47,41 +47,6 @@ use crate::{Domain, Protocol, SockAddr, Type};
47
47
/// can lead to a data race when two threads are changing options in parallel.
48
48
///
49
49
/// # 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
- ///
85
50
/// ```no_run
86
51
/// # fn main() -> std::io::Result<()> {
87
52
/// use std::net::{SocketAddr, TcpListener};
@@ -107,29 +72,26 @@ pub struct Socket {
107
72
}
108
73
109
74
impl Socket {
110
- /// Creates a new socket ready to be configured .
75
+ /// Creates a new socket and sets common flags .
111
76
///
112
77
/// 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.
122
79
///
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.
125
83
///
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.
132
85
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 > {
133
95
let protocol = protocol. map ( |p| p. 0 ) . unwrap_or ( 0 ) ;
134
96
sys:: socket ( domain. 0 , ty. 0 , protocol) . map ( |inner| Socket { inner } )
135
97
}
@@ -138,17 +100,37 @@ impl Socket {
138
100
///
139
101
/// This function corresponds to `socketpair(2)`.
140
102
///
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.
142
105
///
143
- /// Much like [`Socket::new`] this doesn't set any flags, which might be
144
- /// advisable.
106
+ /// # Notes
145
107
///
146
108
/// This function is only available on Unix.
147
109
#[ cfg( all( feature = "all" , unix) ) ]
148
110
pub fn pair (
149
111
domain : Domain ,
150
112
ty : Type ,
151
113
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 > ,
152
134
) -> io:: Result < ( Socket , Socket ) > {
153
135
let protocol = protocol. map ( |p| p. 0 ) . unwrap_or ( 0 ) ;
154
136
sys:: socketpair ( domain. 0 , ty. 0 , protocol)
@@ -195,19 +177,43 @@ impl Socket {
195
177
196
178
/// Accept a new incoming connection from this listener.
197
179
///
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.
206
182
///
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.
210
185
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 ) > {
211
217
sys:: accept ( self . inner ) . map ( |( inner, addr) | ( Socket { inner } , addr) )
212
218
}
213
219
@@ -918,6 +924,52 @@ impl Socket {
918
924
}
919
925
}
920
926
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
+
921
973
impl Read for Socket {
922
974
fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
923
975
self . recv ( buf)
0 commit comments