Skip to content

Commit fdc4fd4

Browse files
committed
Add Socket::new_raw
And change Socket::new to set all commonly used flags.
1 parent ed494d5 commit fdc4fd4

File tree

2 files changed

+58
-36
lines changed

2 files changed

+58
-36
lines changed

src/socket.rs

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,40 +43,6 @@ use crate::{Domain, Protocol, SockAddr, Type};
4343
///
4444
/// # Examples
4545
///
46-
/// Creating a new socket setting all advisable flags.
47-
///
48-
#[cfg_attr(feature = "all", doc = "```")] // Protocol::cloexec requires the `all` feature.
49-
#[cfg_attr(not(feature = "all"), doc = "```ignore")]
50-
/// # fn main() -> std::io::Result<()> {
51-
/// use socket2::{Protocol, Domain, Type, Socket};
52-
///
53-
/// let domain = Domain::IPV4;
54-
/// let ty = Type::STREAM;
55-
/// let protocol = Protocol::TCP;
56-
///
57-
/// // On platforms that support it set `SOCK_CLOEXEC`.
58-
/// #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
59-
/// let ty = ty.cloexec();
60-
///
61-
/// // On windows set `WSA_FLAG_NO_HANDLE_INHERIT`.
62-
/// #[cfg(windows)]
63-
/// let ty = ty.no_inherit();
64-
///
65-
/// let socket = Socket::new(domain, ty, Some(protocol))?;
66-
///
67-
/// // On platforms that don't support `SOCK_CLOEXEC`, use `FD_CLOEXEC`.
68-
/// #[cfg(all(not(windows), not(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "openbsd"))))]
69-
/// socket.set_cloexec()?;
70-
///
71-
/// // On macOS and iOS set `NOSIGPIPE`.
72-
/// #[cfg(target_vendor = "apple")]
73-
/// socket.set_nosigpipe()?;
74-
///
75-
/// # drop(socket);
76-
/// # Ok(())
77-
/// # }
78-
/// ```
79-
///
8046
/// ```no_run
8147
/// # fn main() -> std::io::Result<()> {
8248
/// use std::net::{SocketAddr, TcpListener};
@@ -102,6 +68,55 @@ pub struct Socket {
10268
}
10369

10470
impl Socket {
71+
/// Creates a new socket ready to be configured.
72+
///
73+
/// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
74+
/// Windows and creates a new socket. Unlike `Socket::new_raw` this sets the
75+
/// most commonly used flags in the fastest possible way.
76+
///
77+
/// On Unix this sets the `CLOEXEC` flag. Furthermore on macOS and iOS
78+
/// `NOSIGPIPE` is set.
79+
///
80+
/// On Windows the `HANDLE_FLAG_INHERIT` is set to zero.
81+
pub fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
82+
// On platforms that support it set `SOCK_CLOEXEC`.
83+
#[cfg(any(
84+
target_os = "android",
85+
target_os = "dragonfly",
86+
target_os = "freebsd",
87+
target_os = "linux",
88+
target_os = "netbsd",
89+
target_os = "openbsd"
90+
))]
91+
let ty = ty.cloexec();
92+
93+
// On windows set `WSA_FLAG_NO_HANDLE_INHERIT`.
94+
#[cfg(windows)]
95+
let ty = ty.no_inherit();
96+
97+
let socket = Socket::new_raw(domain, ty, protocol)?;
98+
99+
// On platforms that don't support `SOCK_CLOEXEC`, use `FD_CLOEXEC`.
100+
#[cfg(all(
101+
not(windows),
102+
not(any(
103+
target_os = "android",
104+
target_os = "dragonfly",
105+
target_os = "freebsd",
106+
target_os = "linux",
107+
target_os = "netbsd",
108+
target_os = "openbsd"
109+
))
110+
))]
111+
socket.set_cloexec()?;
112+
113+
// On macOS and iOS set `NOSIGPIPE`.
114+
#[cfg(target_vendor = "apple")]
115+
socket._set_nosigpipe()?;
116+
117+
Ok(socket)
118+
}
119+
105120
/// Creates a new socket ready to be configured.
106121
///
107122
/// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
@@ -124,7 +139,7 @@ impl Socket {
124139
///
125140
/// See the `Socket` documentation for a full example of setting all the
126141
/// above mentioned flags.
127-
pub fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
142+
pub fn new_raw(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
128143
let protocol = protocol.map(|p| p.0).unwrap_or(0);
129144
sys::socket(domain.0, ty.0, protocol).map(|inner| Socket { inner })
130145
}

src/sys/unix.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,13 @@ impl crate::Socket {
432432
/// Only supported on Apple platforms (`target_vendor = "apple"`).
433433
#[cfg(all(feature = "all", target_vendor = "apple"))]
434434
pub fn set_nosigpipe(&self) -> io::Result<()> {
435+
self._set_nosigpipe()
436+
}
437+
438+
// Because `set_nosigpipe` is behind the `all` feature flag we need a
439+
// private version for `Socket::new`, which is always enabled.
440+
#[cfg(target_vendor = "apple")]
441+
pub(crate) fn _set_nosigpipe(&self) -> io::Result<()> {
435442
unsafe { setsockopt(self.inner, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32) }
436443
}
437444
}
@@ -479,7 +486,7 @@ unsafe fn getsockopt<T>(fd: SysSocket, opt: c_int, val: c_int) -> io::Result<T>
479486
}
480487

481488
/// Caller must ensure `T` is the correct type for `opt` and `val`.
482-
#[cfg(all(feature = "all", target_vendor = "apple"))]
489+
#[cfg(target_vendor = "apple")]
483490
unsafe fn setsockopt<T>(fd: SysSocket, opt: c_int, val: c_int, payload: T) -> io::Result<()>
484491
where
485492
T: Copy,

0 commit comments

Comments
 (0)