1 // Copyright 2015 The Rust Project Developers.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 use std::fmt;
10 use std::io::{self, Read, Write};
11 #[cfg(not(target_os = "redox"))]
12 use std::io::{IoSlice, IoSliceMut};
13 use std::mem::MaybeUninit;
14 use std::net::{self, Ipv4Addr, Ipv6Addr, Shutdown};
15 #[cfg(unix)]
16 use std::os::unix::io::{FromRawFd, IntoRawFd};
17 #[cfg(windows)]
18 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
19 use std::time::Duration;
20
21 use crate::sys::{self, c_int, getsockopt, setsockopt, Bool};
22 use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
23 #[cfg(not(target_os = "redox"))]
24 use crate::{MaybeUninitSlice, RecvFlags};
25
26 /// Owned wrapper around a system socket.
27 ///
28 /// This type simply wraps an instance of a file descriptor (`c_int`) on Unix
29 /// and an instance of `SOCKET` on Windows. This is the main type exported by
30 /// this crate and is intended to mirror the raw semantics of sockets on
31 /// platforms as closely as possible. Almost all methods correspond to
32 /// precisely one libc or OS API call which is essentially just a "Rustic
33 /// translation" of what's below.
34 ///
35 /// This type can be freely converted into the network primitives provided by
36 /// the standard library, such as [`TcpStream`] or [`UdpSocket`], using the
37 /// [`Into`] trait, see the example below.
38 ///
39 /// [`TcpStream`]: std::net::TcpStream
40 /// [`UdpSocket`]: std::net::UdpSocket
41 ///
42 /// # Notes
43 ///
44 /// Some methods that set options on `Socket` require two system calls to set
45 /// there options without overwriting previously set options. We do this by
46 /// first getting the current settings, applying the desired changes and than
47 /// updating the settings. This means that the operation is **not** atomic. This
48 /// can lead to a data race when two threads are changing options in parallel.
49 ///
50 /// # Examples
51 /// ```no_run
52 /// # fn main() -> std::io::Result<()> {
53 /// use std::net::{SocketAddr, TcpListener};
54 /// use socket2::{Socket, Domain, Type};
55 ///
56 /// // create a TCP listener bound to two addresses
57 /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
58 ///
59 /// let address: SocketAddr = "[::1]:12345".parse().unwrap();
60 /// let address = address.into();
61 /// socket.bind(&address)?;
62 /// socket.bind(&address)?;
63 /// socket.listen(128)?;
64 ///
65 /// let listener: TcpListener = socket.into();
66 /// // ...
67 /// # drop(listener);
68 /// # Ok(()) }
69 /// ```
70 pub struct Socket {
71 inner: Inner,
72 }
73
74 /// Store a `TcpStream` internally to take advantage of its niche optimizations on Unix platforms.
75 pub(crate) type Inner = std::net::TcpStream;
76
77 impl Socket {
78 /// # Safety
79 ///
80 /// The caller must ensure `raw` is a valid file descriptor/socket. NOTE:
81 /// this should really be marked `unsafe`, but this being an internal
82 /// function, often passed as mapping function, it's makes it very
83 /// inconvenient to mark it as `unsafe`.
from_raw(raw: sys::Socket) -> Socket84 pub(crate) fn from_raw(raw: sys::Socket) -> Socket {
85 Socket {
86 inner: unsafe {
87 // SAFETY: the caller must ensure that `raw` is a valid file
88 // descriptor, but when it isn't it could return I/O errors, or
89 // potentially close a fd it doesn't own. All of that isn't
90 // memory unsafe, so it's not desired but never memory unsafe or
91 // causes UB.
92 //
93 // However there is one exception. We use `TcpStream` to
94 // represent the `Socket` internally (see `Inner` type),
95 // `TcpStream` has a layout optimisation that doesn't allow for
96 // negative file descriptors (as those are always invalid).
97 // Violating this assumption (fd never negative) causes UB,
98 // something we don't want. So check for that we have this
99 // `assert!`.
100 #[cfg(unix)]
101 assert!(raw >= 0, "tried to create a `Socket` with an invalid fd");
102 sys::socket_from_raw(raw)
103 },
104 }
105 }
106
as_raw(&self) -> sys::Socket107 pub(crate) fn as_raw(&self) -> sys::Socket {
108 sys::socket_as_raw(&self.inner)
109 }
110
into_raw(self) -> sys::Socket111 pub(crate) fn into_raw(self) -> sys::Socket {
112 sys::socket_into_raw(self.inner)
113 }
114
115 /// Creates a new socket and sets common flags.
116 ///
117 /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
118 /// Windows.
119 ///
120 /// On Unix-like systems, the close-on-exec flag is set on the new socket.
121 /// Additionally, on Apple platforms `SOCK_NOSIGPIPE` is set. On Windows,
122 /// the socket is made non-inheritable.
123 ///
124 /// [`Socket::new_raw`] can be used if you don't want these flags to be set.
new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket>125 pub fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
126 let ty = set_common_type(ty);
127 Socket::new_raw(domain, ty, protocol).and_then(set_common_flags)
128 }
129
130 /// Creates a new socket ready to be configured.
131 ///
132 /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on
133 /// Windows and simply creates a new socket, no other configuration is done.
new_raw(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket>134 pub fn new_raw(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
135 let protocol = protocol.map(|p| p.0).unwrap_or(0);
136 sys::socket(domain.0, ty.0, protocol).map(Socket::from_raw)
137 }
138
139 /// Creates a pair of sockets which are connected to each other.
140 ///
141 /// This function corresponds to `socketpair(2)`.
142 ///
143 /// This function sets the same flags as in done for [`Socket::new`],
144 /// [`Socket::pair_raw`] can be used if you don't want to set those flags.
145 #[cfg(any(doc, all(feature = "all", unix)))]
146 #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))]
pair( domain: Domain, ty: Type, protocol: Option<Protocol>, ) -> io::Result<(Socket, Socket)>147 pub fn pair(
148 domain: Domain,
149 ty: Type,
150 protocol: Option<Protocol>,
151 ) -> io::Result<(Socket, Socket)> {
152 let ty = set_common_type(ty);
153 let (a, b) = Socket::pair_raw(domain, ty, protocol)?;
154 let a = set_common_flags(a)?;
155 let b = set_common_flags(b)?;
156 Ok((a, b))
157 }
158
159 /// Creates a pair of sockets which are connected to each other.
160 ///
161 /// This function corresponds to `socketpair(2)`.
162 #[cfg(any(doc, all(feature = "all", unix)))]
163 #[cfg_attr(docsrs, doc(cfg(all(feature = "all", unix))))]
pair_raw( domain: Domain, ty: Type, protocol: Option<Protocol>, ) -> io::Result<(Socket, Socket)>164 pub fn pair_raw(
165 domain: Domain,
166 ty: Type,
167 protocol: Option<Protocol>,
168 ) -> io::Result<(Socket, Socket)> {
169 let protocol = protocol.map(|p| p.0).unwrap_or(0);
170 sys::socketpair(domain.0, ty.0, protocol)
171 .map(|[a, b]| (Socket::from_raw(a), Socket::from_raw(b)))
172 }
173
174 /// Binds this socket to the specified address.
175 ///
176 /// This function directly corresponds to the `bind(2)` function on Windows
177 /// and Unix.
bind(&self, address: &SockAddr) -> io::Result<()>178 pub fn bind(&self, address: &SockAddr) -> io::Result<()> {
179 sys::bind(self.as_raw(), address)
180 }
181
182 /// Initiate a connection on this socket to the specified address.
183 ///
184 /// This function directly corresponds to the `connect(2)` function on
185 /// Windows and Unix.
186 ///
187 /// An error will be returned if `listen` or `connect` has already been
188 /// called on this builder.
189 ///
190 /// # Notes
191 ///
192 /// When using a non-blocking connect (by setting the socket into
193 /// non-blocking mode before calling this function), socket option can't be
194 /// set *while connecting*. This will cause errors on Windows. Socket
195 /// options can be safely set before and after connecting the socket.
connect(&self, address: &SockAddr) -> io::Result<()>196 pub fn connect(&self, address: &SockAddr) -> io::Result<()> {
197 sys::connect(self.as_raw(), address)
198 }
199
200 /// Initiate a connection on this socket to the specified address, only
201 /// only waiting for a certain period of time for the connection to be
202 /// established.
203 ///
204 /// Unlike many other methods on `Socket`, this does *not* correspond to a
205 /// single C function. It sets the socket to nonblocking mode, connects via
206 /// connect(2), and then waits for the connection to complete with poll(2)
207 /// on Unix and select on Windows. When the connection is complete, the
208 /// socket is set back to blocking mode. On Unix, this will loop over
209 /// `EINTR` errors.
210 ///
211 /// # Warnings
212 ///
213 /// The non-blocking state of the socket is overridden by this function -
214 /// it will be returned in blocking mode on success, and in an indeterminate
215 /// state on failure.
216 ///
217 /// If the connection request times out, it may still be processing in the
218 /// background - a second call to `connect` or `connect_timeout` may fail.
connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()>219 pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
220 self.set_nonblocking(true)?;
221 let res = self.connect(addr);
222 self.set_nonblocking(false)?;
223
224 match res {
225 Ok(()) => return Ok(()),
226 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
227 #[cfg(unix)]
228 Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
229 Err(e) => return Err(e),
230 }
231
232 sys::poll_connect(self, timeout)
233 }
234
235 /// Mark a socket as ready to accept incoming connection requests using
236 /// [`Socket::accept()`].
237 ///
238 /// This function directly corresponds to the `listen(2)` function on
239 /// Windows and Unix.
240 ///
241 /// An error will be returned if `listen` or `connect` has already been
242 /// called on this builder.
listen(&self, backlog: c_int) -> io::Result<()>243 pub fn listen(&self, backlog: c_int) -> io::Result<()> {
244 sys::listen(self.as_raw(), backlog)
245 }
246
247 /// Accept a new incoming connection from this listener.
248 ///
249 /// This function uses `accept4(2)` on platforms that support it and
250 /// `accept(2)` platforms that do not.
251 ///
252 /// This function sets the same flags as in done for [`Socket::new`],
253 /// [`Socket::accept_raw`] can be used if you don't want to set those flags.
accept(&self) -> io::Result<(Socket, SockAddr)>254 pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
255 // Use `accept4` on platforms that support it.
256 #[cfg(any(
257 target_os = "android",
258 target_os = "dragonfly",
259 target_os = "freebsd",
260 target_os = "fuchsia",
261 target_os = "illumos",
262 target_os = "linux",
263 target_os = "netbsd",
264 target_os = "openbsd",
265 ))]
266 return self._accept4(libc::SOCK_CLOEXEC);
267
268 // Fall back to `accept` on platforms that do not support `accept4`.
269 #[cfg(not(any(
270 target_os = "android",
271 target_os = "dragonfly",
272 target_os = "freebsd",
273 target_os = "fuchsia",
274 target_os = "illumos",
275 target_os = "linux",
276 target_os = "netbsd",
277 target_os = "openbsd",
278 )))]
279 {
280 let (socket, addr) = self.accept_raw()?;
281 let socket = set_common_flags(socket)?;
282 // `set_common_flags` does not disable inheritance on Windows because `Socket::new`
283 // unlike `accept` is able to create the socket with inheritance disabled.
284 #[cfg(windows)]
285 socket._set_no_inherit(true)?;
286 Ok((socket, addr))
287 }
288 }
289
290 /// Accept a new incoming connection from this listener.
291 ///
292 /// This function directly corresponds to the `accept(2)` function on
293 /// Windows and Unix.
accept_raw(&self) -> io::Result<(Socket, SockAddr)>294 pub fn accept_raw(&self) -> io::Result<(Socket, SockAddr)> {
295 sys::accept(self.as_raw()).map(|(inner, addr)| (Socket::from_raw(inner), addr))
296 }
297
298 /// Returns the socket address of the local half of this socket.
299 ///
300 /// # Notes
301 ///
302 /// Depending on the OS this may return an error if the socket is not
303 /// [bound].
304 ///
305 /// [bound]: Socket::bind
local_addr(&self) -> io::Result<SockAddr>306 pub fn local_addr(&self) -> io::Result<SockAddr> {
307 sys::getsockname(self.as_raw())
308 }
309
310 /// Returns the socket address of the remote peer of this socket.
311 ///
312 /// # Notes
313 ///
314 /// This returns an error if the socket is not [`connect`ed].
315 ///
316 /// [`connect`ed]: Socket::connect
peer_addr(&self) -> io::Result<SockAddr>317 pub fn peer_addr(&self) -> io::Result<SockAddr> {
318 sys::getpeername(self.as_raw())
319 }
320
321 /// Returns the [`Type`] of this socket by checking the `SO_TYPE` option on
322 /// this socket.
323 pub fn r#type(&self) -> io::Result<Type> {
324 unsafe { getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_TYPE).map(Type) }
325 }
326
327 /// Creates a new independently owned handle to the underlying socket.
328 ///
329 /// # Notes
330 ///
331 /// On Unix this uses `F_DUPFD_CLOEXEC` and thus sets the `FD_CLOEXEC` on
332 /// the returned socket.
333 ///
334 /// On Windows this uses `WSA_FLAG_NO_HANDLE_INHERIT` setting inheriting to
335 /// false.
336 ///
337 /// On Windows this can **not** be used function cannot be used on a
338 /// QOS-enabled socket, see
339 /// <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaduplicatesocketw>.
try_clone(&self) -> io::Result<Socket>340 pub fn try_clone(&self) -> io::Result<Socket> {
341 sys::try_clone(self.as_raw()).map(Socket::from_raw)
342 }
343
344 /// Moves this TCP stream into or out of nonblocking mode.
345 ///
346 /// # Notes
347 ///
348 /// On Unix this corresponds to calling `fcntl` (un)setting `O_NONBLOCK`.
349 ///
350 /// On Windows this corresponds to calling `ioctlsocket` (un)setting
351 /// `FIONBIO`.
set_nonblocking(&self, nonblocking: bool) -> io::Result<()>352 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
353 sys::set_nonblocking(self.as_raw(), nonblocking)
354 }
355
356 /// Shuts down the read, write, or both halves of this connection.
357 ///
358 /// This function will cause all pending and future I/O on the specified
359 /// portions to return immediately with an appropriate value.
shutdown(&self, how: Shutdown) -> io::Result<()>360 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
361 sys::shutdown(self.as_raw(), how)
362 }
363
364 /// Receives data on the socket from the remote address to which it is
365 /// connected.
366 ///
367 /// The [`connect`] method will connect this socket to a remote address.
368 /// This method might fail if the socket is not connected.
369 ///
370 /// [`connect`]: Socket::connect
371 ///
372 /// # Safety
373 ///
374 /// Normally casting a `&mut [u8]` to `&mut [MaybeUninit<u8>]` would be
375 /// unsound, as that allows us to write uninitialised bytes to the buffer.
376 /// However this implementation promises to not write uninitialised bytes to
377 /// the `buf`fer and passes it directly to `recv(2)` system call. This
378 /// promise ensures that this function can be called using a `buf`fer of
379 /// type `&mut [u8]`.
380 ///
381 /// Note that the [`io::Read::read`] implementation calls this function with
382 /// a `buf`fer of type `&mut [u8]`, allowing initialised buffers to be used
383 /// without using `unsafe`.
recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize>384 pub fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
385 self.recv_with_flags(buf, 0)
386 }
387
388 /// Receives out-of-band (OOB) data on the socket from the remote address to
389 /// which it is connected by setting the `MSG_OOB` flag for this call.
390 ///
391 /// For more information, see [`recv`], [`out_of_band_inline`].
392 ///
393 /// [`recv`]: Socket::recv
394 /// [`out_of_band_inline`]: Socket::out_of_band_inline
recv_out_of_band(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize>395 pub fn recv_out_of_band(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
396 self.recv_with_flags(buf, sys::MSG_OOB)
397 }
398
399 /// Identical to [`recv`] but allows for specification of arbitrary flags to
400 /// the underlying `recv` call.
401 ///
402 /// [`recv`]: Socket::recv
recv_with_flags( &self, buf: &mut [MaybeUninit<u8>], flags: sys::c_int, ) -> io::Result<usize>403 pub fn recv_with_flags(
404 &self,
405 buf: &mut [MaybeUninit<u8>],
406 flags: sys::c_int,
407 ) -> io::Result<usize> {
408 sys::recv(self.as_raw(), buf, flags)
409 }
410
411 /// Receives data on the socket from the remote address to which it is
412 /// connected. Unlike [`recv`] this allows passing multiple buffers.
413 ///
414 /// The [`connect`] method will connect this socket to a remote address.
415 /// This method might fail if the socket is not connected.
416 ///
417 /// In addition to the number of bytes read, this function returns the flags
418 /// for the received message. See [`RecvFlags`] for more information about
419 /// the returned flags.
420 ///
421 /// [`recv`]: Socket::recv
422 /// [`connect`]: Socket::connect
423 ///
424 /// # Safety
425 ///
426 /// Normally casting a `IoSliceMut` to `MaybeUninitSlice` would be unsound,
427 /// as that allows us to write uninitialised bytes to the buffer. However
428 /// this implementation promises to not write uninitialised bytes to the
429 /// `bufs` and passes it directly to `recvmsg(2)` system call. This promise
430 /// ensures that this function can be called using `bufs` of type `&mut
431 /// [IoSliceMut]`.
432 ///
433 /// Note that the [`io::Read::read_vectored`] implementation calls this
434 /// function with `buf`s of type `&mut [IoSliceMut]`, allowing initialised
435 /// buffers to be used without using `unsafe`.
436 #[cfg(not(target_os = "redox"))]
437 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
recv_vectored( &self, bufs: &mut [MaybeUninitSlice<'_>], ) -> io::Result<(usize, RecvFlags)>438 pub fn recv_vectored(
439 &self,
440 bufs: &mut [MaybeUninitSlice<'_>],
441 ) -> io::Result<(usize, RecvFlags)> {
442 self.recv_vectored_with_flags(bufs, 0)
443 }
444
445 /// Identical to [`recv_vectored`] but allows for specification of arbitrary
446 /// flags to the underlying `recvmsg`/`WSARecv` call.
447 ///
448 /// [`recv_vectored`]: Socket::recv_vectored
449 ///
450 /// # Safety
451 ///
452 /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
453 /// as [`recv_vectored`].
454 ///
455 /// [`recv_vectored`]: Socket::recv_vectored
456 #[cfg(not(target_os = "redox"))]
457 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
recv_vectored_with_flags( &self, bufs: &mut [MaybeUninitSlice<'_>], flags: c_int, ) -> io::Result<(usize, RecvFlags)>458 pub fn recv_vectored_with_flags(
459 &self,
460 bufs: &mut [MaybeUninitSlice<'_>],
461 flags: c_int,
462 ) -> io::Result<(usize, RecvFlags)> {
463 sys::recv_vectored(self.as_raw(), bufs, flags)
464 }
465
466 /// Receives data on the socket from the remote adress to which it is
467 /// connected, without removing that data from the queue. On success,
468 /// returns the number of bytes peeked.
469 ///
470 /// Successive calls return the same data. This is accomplished by passing
471 /// `MSG_PEEK` as a flag to the underlying `recv` system call.
472 ///
473 /// # Safety
474 ///
475 /// `peek` makes the same safety guarantees regarding the `buf`fer as
476 /// [`recv`].
477 ///
478 /// [`recv`]: Socket::recv
peek(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize>479 pub fn peek(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
480 self.recv_with_flags(buf, sys::MSG_PEEK)
481 }
482
483 /// Receives data from the socket. On success, returns the number of bytes
484 /// read and the address from whence the data came.
485 ///
486 /// # Safety
487 ///
488 /// `recv_from` makes the same safety guarantees regarding the `buf`fer as
489 /// [`recv`].
490 ///
491 /// [`recv`]: Socket::recv
recv_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)>492 pub fn recv_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
493 self.recv_from_with_flags(buf, 0)
494 }
495
496 /// Identical to [`recv_from`] but allows for specification of arbitrary
497 /// flags to the underlying `recvfrom` call.
498 ///
499 /// [`recv_from`]: Socket::recv_from
recv_from_with_flags( &self, buf: &mut [MaybeUninit<u8>], flags: c_int, ) -> io::Result<(usize, SockAddr)>500 pub fn recv_from_with_flags(
501 &self,
502 buf: &mut [MaybeUninit<u8>],
503 flags: c_int,
504 ) -> io::Result<(usize, SockAddr)> {
505 sys::recv_from(self.as_raw(), buf, flags)
506 }
507
508 /// Receives data from the socket. Returns the amount of bytes read, the
509 /// [`RecvFlags`] and the remote address from the data is coming. Unlike
510 /// [`recv_from`] this allows passing multiple buffers.
511 ///
512 /// [`recv_from`]: Socket::recv_from
513 ///
514 /// # Safety
515 ///
516 /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
517 /// as [`recv_vectored`].
518 ///
519 /// [`recv_vectored`]: Socket::recv_vectored
520 #[cfg(not(target_os = "redox"))]
521 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
recv_from_vectored( &self, bufs: &mut [MaybeUninitSlice<'_>], ) -> io::Result<(usize, RecvFlags, SockAddr)>522 pub fn recv_from_vectored(
523 &self,
524 bufs: &mut [MaybeUninitSlice<'_>],
525 ) -> io::Result<(usize, RecvFlags, SockAddr)> {
526 self.recv_from_vectored_with_flags(bufs, 0)
527 }
528
529 /// Identical to [`recv_from_vectored`] but allows for specification of
530 /// arbitrary flags to the underlying `recvmsg`/`WSARecvFrom` call.
531 ///
532 /// [`recv_from_vectored`]: Socket::recv_from_vectored
533 ///
534 /// # Safety
535 ///
536 /// `recv_from_vectored` makes the same safety guarantees regarding `bufs`
537 /// as [`recv_vectored`].
538 ///
539 /// [`recv_vectored`]: Socket::recv_vectored
540 #[cfg(not(target_os = "redox"))]
541 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
recv_from_vectored_with_flags( &self, bufs: &mut [MaybeUninitSlice<'_>], flags: c_int, ) -> io::Result<(usize, RecvFlags, SockAddr)>542 pub fn recv_from_vectored_with_flags(
543 &self,
544 bufs: &mut [MaybeUninitSlice<'_>],
545 flags: c_int,
546 ) -> io::Result<(usize, RecvFlags, SockAddr)> {
547 sys::recv_from_vectored(self.as_raw(), bufs, flags)
548 }
549
550 /// Receives data from the socket, without removing it from the queue.
551 ///
552 /// Successive calls return the same data. This is accomplished by passing
553 /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
554 ///
555 /// On success, returns the number of bytes peeked and the address from
556 /// whence the data came.
557 ///
558 /// # Safety
559 ///
560 /// `peek_from` makes the same safety guarantees regarding the `buf`fer as
561 /// [`recv`].
562 ///
563 /// [`recv`]: Socket::recv
peek_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)>564 pub fn peek_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
565 self.recv_from_with_flags(buf, sys::MSG_PEEK)
566 }
567
568 /// Sends data on the socket to a connected peer.
569 ///
570 /// This is typically used on TCP sockets or datagram sockets which have
571 /// been connected.
572 ///
573 /// On success returns the number of bytes that were sent.
send(&self, buf: &[u8]) -> io::Result<usize>574 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
575 self.send_with_flags(buf, 0)
576 }
577
578 /// Identical to [`send`] but allows for specification of arbitrary flags to the underlying
579 /// `send` call.
580 ///
581 /// [`send`]: #method.send
send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize>582 pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
583 sys::send(self.as_raw(), buf, flags)
584 }
585
586 /// Send data to the connected peer. Returns the amount of bytes written.
587 #[cfg(not(target_os = "redox"))]
588 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize>589 pub fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
590 self.send_vectored_with_flags(bufs, 0)
591 }
592
593 /// Identical to [`send_vectored`] but allows for specification of arbitrary
594 /// flags to the underlying `sendmsg`/`WSASend` call.
595 ///
596 /// [`send_vectored`]: Socket::send_vectored
597 #[cfg(not(target_os = "redox"))]
598 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
send_vectored_with_flags( &self, bufs: &[IoSlice<'_>], flags: c_int, ) -> io::Result<usize>599 pub fn send_vectored_with_flags(
600 &self,
601 bufs: &[IoSlice<'_>],
602 flags: c_int,
603 ) -> io::Result<usize> {
604 sys::send_vectored(self.as_raw(), bufs, flags)
605 }
606
607 /// Sends out-of-band (OOB) data on the socket to connected peer
608 /// by setting the `MSG_OOB` flag for this call.
609 ///
610 /// For more information, see [`send`], [`out_of_band_inline`].
611 ///
612 /// [`send`]: #method.send
613 /// [`out_of_band_inline`]: #method.out_of_band_inline
send_out_of_band(&self, buf: &[u8]) -> io::Result<usize>614 pub fn send_out_of_band(&self, buf: &[u8]) -> io::Result<usize> {
615 self.send_with_flags(buf, sys::MSG_OOB)
616 }
617
618 /// Sends data on the socket to the given address. On success, returns the
619 /// number of bytes written.
620 ///
621 /// This is typically used on UDP or datagram-oriented sockets.
send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize>622 pub fn send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize> {
623 self.send_to_with_flags(buf, addr, 0)
624 }
625
626 /// Identical to [`send_to`] but allows for specification of arbitrary flags
627 /// to the underlying `sendto` call.
628 ///
629 /// [`send_to`]: Socket::send_to
send_to_with_flags( &self, buf: &[u8], addr: &SockAddr, flags: c_int, ) -> io::Result<usize>630 pub fn send_to_with_flags(
631 &self,
632 buf: &[u8],
633 addr: &SockAddr,
634 flags: c_int,
635 ) -> io::Result<usize> {
636 sys::send_to(self.as_raw(), buf, addr, flags)
637 }
638
639 /// Send data to a peer listening on `addr`. Returns the amount of bytes
640 /// written.
641 #[cfg(not(target_os = "redox"))]
642 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
send_to_vectored(&self, bufs: &[IoSlice<'_>], addr: &SockAddr) -> io::Result<usize>643 pub fn send_to_vectored(&self, bufs: &[IoSlice<'_>], addr: &SockAddr) -> io::Result<usize> {
644 self.send_to_vectored_with_flags(bufs, addr, 0)
645 }
646
647 /// Identical to [`send_to_vectored`] but allows for specification of
648 /// arbitrary flags to the underlying `sendmsg`/`WSASendTo` call.
649 ///
650 /// [`send_to_vectored`]: Socket::send_to_vectored
651 #[cfg(not(target_os = "redox"))]
652 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
send_to_vectored_with_flags( &self, bufs: &[IoSlice<'_>], addr: &SockAddr, flags: c_int, ) -> io::Result<usize>653 pub fn send_to_vectored_with_flags(
654 &self,
655 bufs: &[IoSlice<'_>],
656 addr: &SockAddr,
657 flags: c_int,
658 ) -> io::Result<usize> {
659 sys::send_to_vectored(self.as_raw(), bufs, addr, flags)
660 }
661 }
662
663 /// Set `SOCK_CLOEXEC` and `NO_HANDLE_INHERIT` on the `ty`pe on platforms that
664 /// support it.
665 #[inline(always)]
set_common_type(ty: Type) -> Type666 fn set_common_type(ty: Type) -> Type {
667 // On platforms that support it set `SOCK_CLOEXEC`.
668 #[cfg(any(
669 target_os = "android",
670 target_os = "dragonfly",
671 target_os = "freebsd",
672 target_os = "fuchsia",
673 target_os = "illumos",
674 target_os = "linux",
675 target_os = "netbsd",
676 target_os = "openbsd",
677 ))]
678 let ty = ty._cloexec();
679
680 // On windows set `NO_HANDLE_INHERIT`.
681 #[cfg(windows)]
682 let ty = ty._no_inherit();
683
684 ty
685 }
686
687 /// Set `FD_CLOEXEC` and `NOSIGPIPE` on the `socket` for platforms that need it.
688 #[inline(always)]
689 #[allow(clippy::unnecessary_wraps)]
set_common_flags(socket: Socket) -> io::Result<Socket>690 fn set_common_flags(socket: Socket) -> io::Result<Socket> {
691 // On platforms that don't have `SOCK_CLOEXEC` use `FD_CLOEXEC`.
692 #[cfg(all(
693 unix,
694 not(any(
695 target_os = "android",
696 target_os = "dragonfly",
697 target_os = "freebsd",
698 target_os = "fuchsia",
699 target_os = "illumos",
700 target_os = "linux",
701 target_os = "netbsd",
702 target_os = "openbsd",
703 ))
704 ))]
705 socket._set_cloexec(true)?;
706
707 // On Apple platforms set `NOSIGPIPE`.
708 #[cfg(target_vendor = "apple")]
709 socket._set_nosigpipe(true)?;
710
711 Ok(socket)
712 }
713
714 /// Socket options get/set using `SOL_SOCKET`.
715 ///
716 /// Additional documentation can be found in documentation of the OS.
717 /// * Linux: <https://man7.org/linux/man-pages/man7/socket.7.html>
718 /// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options>
719 impl Socket {
720 /// Get the value of the `SO_BROADCAST` option for this socket.
721 ///
722 /// For more information about this option, see [`set_broadcast`].
723 ///
724 /// [`set_broadcast`]: Socket::set_broadcast
broadcast(&self) -> io::Result<bool>725 pub fn broadcast(&self) -> io::Result<bool> {
726 unsafe {
727 getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_BROADCAST)
728 .map(|broadcast| broadcast != 0)
729 }
730 }
731
732 /// Set the value of the `SO_BROADCAST` option for this socket.
733 ///
734 /// When enabled, this socket is allowed to send packets to a broadcast
735 /// address.
set_broadcast(&self, broadcast: bool) -> io::Result<()>736 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
737 unsafe {
738 setsockopt(
739 self.as_raw(),
740 sys::SOL_SOCKET,
741 sys::SO_BROADCAST,
742 broadcast as c_int,
743 )
744 }
745 }
746
747 /// Get the value of the `SO_ERROR` option on this socket.
748 ///
749 /// This will retrieve the stored error in the underlying socket, clearing
750 /// the field in the process. This can be useful for checking errors between
751 /// calls.
take_error(&self) -> io::Result<Option<io::Error>>752 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
753 match unsafe { getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_ERROR) } {
754 Ok(0) => Ok(None),
755 Ok(errno) => Ok(Some(io::Error::from_raw_os_error(errno))),
756 Err(err) => Err(err),
757 }
758 }
759
760 /// Get the value of the `SO_KEEPALIVE` option on this socket.
761 ///
762 /// For more information about this option, see [`set_keepalive`].
763 ///
764 /// [`set_keepalive`]: Socket::set_keepalive
keepalive(&self) -> io::Result<bool>765 pub fn keepalive(&self) -> io::Result<bool> {
766 unsafe {
767 getsockopt::<Bool>(self.as_raw(), sys::SOL_SOCKET, sys::SO_KEEPALIVE)
768 .map(|keepalive| keepalive != 0)
769 }
770 }
771
772 /// Set value for the `SO_KEEPALIVE` option on this socket.
773 ///
774 /// Enable sending of keep-alive messages on connection-oriented sockets.
set_keepalive(&self, keepalive: bool) -> io::Result<()>775 pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
776 unsafe {
777 setsockopt(
778 self.as_raw(),
779 sys::SOL_SOCKET,
780 sys::SO_KEEPALIVE,
781 keepalive as c_int,
782 )
783 }
784 }
785
786 /// Get the value of the `SO_LINGER` option on this socket.
787 ///
788 /// For more information about this option, see [`set_linger`].
789 ///
790 /// [`set_linger`]: Socket::set_linger
linger(&self) -> io::Result<Option<Duration>>791 pub fn linger(&self) -> io::Result<Option<Duration>> {
792 unsafe {
793 getsockopt::<sys::linger>(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER)
794 .map(from_linger)
795 }
796 }
797
798 /// Set value for the `SO_LINGER` option on this socket.
799 ///
800 /// If `linger` is not `None`, a close(2) or shutdown(2) will not return
801 /// until all queued messages for the socket have been successfully sent or
802 /// the linger timeout has been reached. Otherwise, the call returns
803 /// immediately and the closing is done in the background. When the socket
804 /// is closed as part of exit(2), it always lingers in the background.
805 ///
806 /// # Notes
807 ///
808 /// On most OSs the duration only has a precision of seconds and will be
809 /// silently truncated.
810 ///
811 /// On Apple platforms (e.g. macOS, iOS, etc) this uses `SO_LINGER_SEC`.
set_linger(&self, linger: Option<Duration>) -> io::Result<()>812 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
813 let linger = into_linger(linger);
814 unsafe { setsockopt(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER, linger) }
815 }
816
817 /// Get value for the `SO_OOBINLINE` option on this socket.
818 ///
819 /// For more information about this option, see [`set_out_of_band_inline`].
820 ///
821 /// [`set_out_of_band_inline`]: Socket::set_out_of_band_inline
822 #[cfg(not(target_os = "redox"))]
823 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
out_of_band_inline(&self) -> io::Result<bool>824 pub fn out_of_band_inline(&self) -> io::Result<bool> {
825 unsafe {
826 getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_OOBINLINE)
827 .map(|oob_inline| oob_inline != 0)
828 }
829 }
830
831 /// Set value for the `SO_OOBINLINE` option on this socket.
832 ///
833 /// If this option is enabled, out-of-band data is directly placed into the
834 /// receive data stream. Otherwise, out-of-band data is passed only when the
835 /// `MSG_OOB` flag is set during receiving. As per RFC6093, TCP sockets
836 /// using the Urgent mechanism are encouraged to set this flag.
837 #[cfg(not(target_os = "redox"))]
838 #[cfg_attr(docsrs, doc(cfg(not(target_os = "redox"))))]
set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()>839 pub fn set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()> {
840 unsafe {
841 setsockopt(
842 self.as_raw(),
843 sys::SOL_SOCKET,
844 sys::SO_OOBINLINE,
845 oob_inline as c_int,
846 )
847 }
848 }
849
850 /// Get value for the `SO_RCVBUF` option on this socket.
851 ///
852 /// For more information about this option, see [`set_recv_buffer_size`].
853 ///
854 /// [`set_recv_buffer_size`]: Socket::set_recv_buffer_size
recv_buffer_size(&self) -> io::Result<usize>855 pub fn recv_buffer_size(&self) -> io::Result<usize> {
856 unsafe {
857 getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVBUF)
858 .map(|size| size as usize)
859 }
860 }
861
862 /// Set value for the `SO_RCVBUF` option on this socket.
863 ///
864 /// Changes the size of the operating system's receive buffer associated
865 /// with the socket.
set_recv_buffer_size(&self, size: usize) -> io::Result<()>866 pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
867 unsafe {
868 setsockopt(
869 self.as_raw(),
870 sys::SOL_SOCKET,
871 sys::SO_RCVBUF,
872 size as c_int,
873 )
874 }
875 }
876
877 /// Get value for the `SO_RCVTIMEO` option on this socket.
878 ///
879 /// If the returned timeout is `None`, then `read` and `recv` calls will
880 /// block indefinitely.
read_timeout(&self) -> io::Result<Option<Duration>>881 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
882 sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO)
883 }
884
885 /// Set value for the `SO_RCVTIMEO` option on this socket.
886 ///
887 /// If `timeout` is `None`, then `read` and `recv` calls will block
888 /// indefinitely.
set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()>889 pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
890 sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO, duration)
891 }
892
893 /// Get the value of the `SO_REUSEADDR` option on this socket.
894 ///
895 /// For more information about this option, see [`set_reuse_address`].
896 ///
897 /// [`set_reuse_address`]: Socket::set_reuse_address
reuse_address(&self) -> io::Result<bool>898 pub fn reuse_address(&self) -> io::Result<bool> {
899 unsafe {
900 getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_REUSEADDR)
901 .map(|reuse| reuse != 0)
902 }
903 }
904
905 /// Set value for the `SO_REUSEADDR` option on this socket.
906 ///
907 /// This indicates that futher calls to `bind` may allow reuse of local
908 /// addresses. For IPv4 sockets this means that a socket may bind even when
909 /// there's a socket already listening on this port.
set_reuse_address(&self, reuse: bool) -> io::Result<()>910 pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
911 unsafe {
912 setsockopt(
913 self.as_raw(),
914 sys::SOL_SOCKET,
915 sys::SO_REUSEADDR,
916 reuse as c_int,
917 )
918 }
919 }
920
921 /// Get the value of the `SO_SNDBUF` option on this socket.
922 ///
923 /// For more information about this option, see [`set_send_buffer_size`].
924 ///
925 /// [`set_send_buffer_size`]: Socket::set_send_buffer_size
send_buffer_size(&self) -> io::Result<usize>926 pub fn send_buffer_size(&self) -> io::Result<usize> {
927 unsafe {
928 getsockopt::<c_int>(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDBUF)
929 .map(|size| size as usize)
930 }
931 }
932
933 /// Set value for the `SO_SNDBUF` option on this socket.
934 ///
935 /// Changes the size of the operating system's send buffer associated with
936 /// the socket.
set_send_buffer_size(&self, size: usize) -> io::Result<()>937 pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
938 unsafe {
939 setsockopt(
940 self.as_raw(),
941 sys::SOL_SOCKET,
942 sys::SO_SNDBUF,
943 size as c_int,
944 )
945 }
946 }
947
948 /// Get value for the `SO_SNDTIMEO` option on this socket.
949 ///
950 /// If the returned timeout is `None`, then `write` and `send` calls will
951 /// block indefinitely.
write_timeout(&self) -> io::Result<Option<Duration>>952 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
953 sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO)
954 }
955
956 /// Set value for the `SO_SNDTIMEO` option on this socket.
957 ///
958 /// If `timeout` is `None`, then `write` and `send` calls will block
959 /// indefinitely.
set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()>960 pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
961 sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO, duration)
962 }
963 }
964
from_linger(linger: sys::linger) -> Option<Duration>965 fn from_linger(linger: sys::linger) -> Option<Duration> {
966 if linger.l_onoff == 0 {
967 None
968 } else {
969 Some(Duration::from_secs(linger.l_linger as u64))
970 }
971 }
972
into_linger(duration: Option<Duration>) -> sys::linger973 fn into_linger(duration: Option<Duration>) -> sys::linger {
974 match duration {
975 Some(duration) => sys::linger {
976 l_onoff: 1,
977 l_linger: duration.as_secs() as _,
978 },
979 None => sys::linger {
980 l_onoff: 0,
981 l_linger: 0,
982 },
983 }
984 }
985
986 /// Socket options for IPv4 sockets, get/set using `IPPROTO_IP`.
987 ///
988 /// Additional documentation can be found in documentation of the OS.
989 /// * Linux: <https://man7.org/linux/man-pages/man7/ip.7.html>
990 /// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
991 impl Socket {
992 /// Get the value of the `IP_TRANSPARENT` option on this socket.
993 ///
994 /// For more information about this option, see [`set_ip_transparent`].
995 ///
996 /// [`set_ip_transparent`]: Socket::set_ip_transparent
997 #[cfg(any(doc, all(feature = "all", target_os = "linux")))]
998 #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
ip_transparent(&self) -> io::Result<bool>999 pub fn ip_transparent(&self) -> io::Result<bool> {
1000 unsafe {
1001 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_TRANSPARENT)
1002 .map(|transparent| transparent != 0)
1003 }
1004 }
1005
1006 /// Set the value of the `IP_TRANSPARENT` option on this socket.
1007 ///
1008 /// Setting this boolean option enables transparent proxying
1009 /// on this socket. This socket option allows the calling
1010 /// application to bind to a nonlocal IP address and operate
1011 /// both as a client and a server with the foreign address as
1012 /// the local endpoint. NOTE: this requires that routing be
1013 /// set up in a way that packets going to the foreign address
1014 /// are routed through the TProxy box (i.e., the system
1015 /// hosting the application that employs the IP_TRANSPARENT
1016 /// socket option). Enabling this socket option requires
1017 /// superuser privileges (the CAP_NET_ADMIN capability).
1018 ///
1019 /// TProxy redirection with the iptables TPROXY target also
1020 /// requires that this option be set on the redirected socket.
1021 #[cfg(any(doc, all(feature = "all", target_os = "linux")))]
1022 #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "linux"))))]
set_ip_transparent(&self, transparent: bool) -> io::Result<()>1023 pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> {
1024 unsafe {
1025 setsockopt(
1026 self.as_raw(),
1027 sys::IPPROTO_IP,
1028 libc::IP_TRANSPARENT,
1029 transparent as c_int,
1030 )
1031 }
1032 }
1033
1034 /// Join a multicast group using `IP_ADD_MEMBERSHIP` option on this socket.
1035 ///
1036 /// This function specifies a new multicast group for this socket to join.
1037 /// The address must be a valid multicast address, and `interface` is the
1038 /// address of the local interface with which the system should join the
1039 /// multicast group. If it's [`Ipv4Addr::UNSPECIFIED`] (`INADDR_ANY`) then
1040 /// an appropriate interface is chosen by the system.
join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>1041 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1042 let mreq = sys::IpMreq {
1043 imr_multiaddr: sys::to_in_addr(multiaddr),
1044 imr_interface: sys::to_in_addr(interface),
1045 };
1046 unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_ADD_MEMBERSHIP, mreq) }
1047 }
1048
1049 /// Leave a multicast group using `IP_DROP_MEMBERSHIP` option on this socket.
1050 ///
1051 /// For more information about this option, see [`join_multicast_v4`].
1052 ///
1053 /// [`join_multicast_v4`]: Socket::join_multicast_v4
leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>1054 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1055 let mreq = sys::IpMreq {
1056 imr_multiaddr: sys::to_in_addr(multiaddr),
1057 imr_interface: sys::to_in_addr(interface),
1058 };
1059 unsafe {
1060 setsockopt(
1061 self.as_raw(),
1062 sys::IPPROTO_IP,
1063 sys::IP_DROP_MEMBERSHIP,
1064 mreq,
1065 )
1066 }
1067 }
1068
1069 /// Get the value of the `IP_MULTICAST_IF` option for this socket.
1070 ///
1071 /// For more information about this option, see [`set_multicast_if_v4`].
1072 ///
1073 /// [`set_multicast_if_v4`]: Socket::set_multicast_if_v4
multicast_if_v4(&self) -> io::Result<Ipv4Addr>1074 pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
1075 unsafe {
1076 getsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF).map(sys::from_in_addr)
1077 }
1078 }
1079
1080 /// Set the value of the `IP_MULTICAST_IF` option for this socket.
1081 ///
1082 /// Specifies the interface to use for routing multicast packets.
set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>1083 pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> {
1084 let interface = sys::to_in_addr(interface);
1085 unsafe {
1086 setsockopt(
1087 self.as_raw(),
1088 sys::IPPROTO_IP,
1089 sys::IP_MULTICAST_IF,
1090 interface,
1091 )
1092 }
1093 }
1094
1095 /// Get the value of the `IP_MULTICAST_LOOP` option for this socket.
1096 ///
1097 /// For more information about this option, see [`set_multicast_loop_v4`].
1098 ///
1099 /// [`set_multicast_loop_v4`]: Socket::set_multicast_loop_v4
multicast_loop_v4(&self) -> io::Result<bool>1100 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
1101 unsafe {
1102 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP)
1103 .map(|loop_v4| loop_v4 != 0)
1104 }
1105 }
1106
1107 /// Set the value of the `IP_MULTICAST_LOOP` option for this socket.
1108 ///
1109 /// If enabled, multicast packets will be looped back to the local socket.
1110 /// Note that this may not have any affect on IPv6 sockets.
set_multicast_loop_v4(&self, loop_v4: bool) -> io::Result<()>1111 pub fn set_multicast_loop_v4(&self, loop_v4: bool) -> io::Result<()> {
1112 unsafe {
1113 setsockopt(
1114 self.as_raw(),
1115 sys::IPPROTO_IP,
1116 sys::IP_MULTICAST_LOOP,
1117 loop_v4 as c_int,
1118 )
1119 }
1120 }
1121
1122 /// Get the value of the `IP_MULTICAST_TTL` option for this socket.
1123 ///
1124 /// For more information about this option, see [`set_multicast_ttl_v4`].
1125 ///
1126 /// [`set_multicast_ttl_v4`]: Socket::set_multicast_ttl_v4
multicast_ttl_v4(&self) -> io::Result<u32>1127 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
1128 unsafe {
1129 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_TTL)
1130 .map(|ttl| ttl as u32)
1131 }
1132 }
1133
1134 /// Set the value of the `IP_MULTICAST_TTL` option for this socket.
1135 ///
1136 /// Indicates the time-to-live value of outgoing multicast packets for
1137 /// this socket. The default value is 1 which means that multicast packets
1138 /// don't leave the local network unless explicitly requested.
1139 ///
1140 /// Note that this may not have any affect on IPv6 sockets.
set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>1141 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
1142 unsafe {
1143 setsockopt(
1144 self.as_raw(),
1145 sys::IPPROTO_IP,
1146 sys::IP_MULTICAST_TTL,
1147 ttl as c_int,
1148 )
1149 }
1150 }
1151
1152 /// Get the value of the `IP_TTL` option for this socket.
1153 ///
1154 /// For more information about this option, see [`set_ttl`].
1155 ///
1156 /// [`set_ttl`]: Socket::set_ttl
ttl(&self) -> io::Result<u32>1157 pub fn ttl(&self) -> io::Result<u32> {
1158 unsafe {
1159 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL).map(|ttl| ttl as u32)
1160 }
1161 }
1162
1163 /// Set the value of the `IP_TTL` option for this socket.
1164 ///
1165 /// This value sets the time-to-live field that is used in every packet sent
1166 /// from this socket.
set_ttl(&self, ttl: u32) -> io::Result<()>1167 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1168 unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL, ttl as c_int) }
1169 }
1170
1171 /// Set the value of the `IP_TOS` option for this socket.
1172 ///
1173 /// This value sets the type-of-service field that is used in every packet
1174 /// sent from this socket.
1175 ///
1176 /// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
1177 /// documents that not all versions of windows support `IP_TOS`.
1178 #[cfg(not(any(
1179 target_os = "fuschia",
1180 target_os = "redox",
1181 target_os = "solaris",
1182 target_os = "illumos",
1183 )))]
set_tos(&self, tos: u32) -> io::Result<()>1184 pub fn set_tos(&self, tos: u32) -> io::Result<()> {
1185 unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_TOS, tos as c_int) }
1186 }
1187
1188 /// Get the value of the `IP_TOS` option for this socket.
1189 ///
1190 /// For more information about this option, see [`set_tos`].
1191 ///
1192 /// NOTE: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options>
1193 /// documents that not all versions of windows support `IP_TOS`.
1194 /// [`set_tos`]: Socket::set_tos
1195 #[cfg(not(any(
1196 target_os = "fuschia",
1197 target_os = "redox",
1198 target_os = "solaris",
1199 target_os = "illumos",
1200 )))]
tos(&self) -> io::Result<u32>1201 pub fn tos(&self) -> io::Result<u32> {
1202 unsafe {
1203 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_TOS).map(|tos| tos as u32)
1204 }
1205 }
1206 }
1207
1208 /// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
1209 ///
1210 /// Additional documentation can be found in documentation of the OS.
1211 /// * Linux: <https://man7.org/linux/man-pages/man7/ipv6.7.html>
1212 /// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-options>
1213 impl Socket {
1214 /// Join a multicast group using `IPV6_ADD_MEMBERSHIP` option on this socket.
1215 ///
1216 /// Some OSs use `IPV6_JOIN_GROUP` for this option.
1217 ///
1218 /// This function specifies a new multicast group for this socket to join.
1219 /// The address must be a valid multicast address, and `interface` is the
1220 /// index of the interface to join/leave (or 0 to indicate any interface).
join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>1221 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1222 let mreq = sys::Ipv6Mreq {
1223 ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
1224 // NOTE: some OSs use `c_int`, others use `c_uint`.
1225 ipv6mr_interface: interface as _,
1226 };
1227 unsafe {
1228 setsockopt(
1229 self.as_raw(),
1230 sys::IPPROTO_IPV6,
1231 sys::IPV6_ADD_MEMBERSHIP,
1232 mreq,
1233 )
1234 }
1235 }
1236
1237 /// Leave a multicast group using `IPV6_DROP_MEMBERSHIP` option on this socket.
1238 ///
1239 /// Some OSs use `IPV6_LEAVE_GROUP` for this option.
1240 ///
1241 /// For more information about this option, see [`join_multicast_v6`].
1242 ///
1243 /// [`join_multicast_v6`]: Socket::join_multicast_v6
leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>1244 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1245 let mreq = sys::Ipv6Mreq {
1246 ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
1247 // NOTE: some OSs use `c_int`, others use `c_uint`.
1248 ipv6mr_interface: interface as _,
1249 };
1250 unsafe {
1251 setsockopt(
1252 self.as_raw(),
1253 sys::IPPROTO_IPV6,
1254 sys::IPV6_DROP_MEMBERSHIP,
1255 mreq,
1256 )
1257 }
1258 }
1259
1260 /// Get the value of the `IPV6_MULTICAST_HOPS` option for this socket
1261 ///
1262 /// For more information about this option, see [`set_multicast_hops_v6`].
1263 ///
1264 /// [`set_multicast_hops_v6`]: Socket::set_multicast_hops_v6
multicast_hops_v6(&self) -> io::Result<u32>1265 pub fn multicast_hops_v6(&self) -> io::Result<u32> {
1266 unsafe {
1267 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS)
1268 .map(|hops| hops as u32)
1269 }
1270 }
1271
1272 /// Set the value of the `IPV6_MULTICAST_HOPS` option for this socket
1273 ///
1274 /// Indicates the number of "routers" multicast packets will transit for
1275 /// this socket. The default value is 1 which means that multicast packets
1276 /// don't leave the local network unless explicitly requested.
set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>1277 pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1278 unsafe {
1279 setsockopt(
1280 self.as_raw(),
1281 sys::IPPROTO_IPV6,
1282 sys::IPV6_MULTICAST_HOPS,
1283 hops as c_int,
1284 )
1285 }
1286 }
1287
1288 /// Get the value of the `IPV6_MULTICAST_IF` option for this socket.
1289 ///
1290 /// For more information about this option, see [`set_multicast_if_v6`].
1291 ///
1292 /// [`set_multicast_if_v6`]: Socket::set_multicast_if_v6
multicast_if_v6(&self) -> io::Result<u32>1293 pub fn multicast_if_v6(&self) -> io::Result<u32> {
1294 unsafe {
1295 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF)
1296 .map(|interface| interface as u32)
1297 }
1298 }
1299
1300 /// Set the value of the `IPV6_MULTICAST_IF` option for this socket.
1301 ///
1302 /// Specifies the interface to use for routing multicast packets. Unlike
1303 /// ipv4, this is generally required in ipv6 contexts where network routing
1304 /// prefixes may overlap.
set_multicast_if_v6(&self, interface: u32) -> io::Result<()>1305 pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
1306 unsafe {
1307 setsockopt(
1308 self.as_raw(),
1309 sys::IPPROTO_IPV6,
1310 sys::IPV6_MULTICAST_IF,
1311 interface as c_int,
1312 )
1313 }
1314 }
1315
1316 /// Get the value of the `IPV6_MULTICAST_LOOP` option for this socket.
1317 ///
1318 /// For more information about this option, see [`set_multicast_loop_v6`].
1319 ///
1320 /// [`set_multicast_loop_v6`]: Socket::set_multicast_loop_v6
multicast_loop_v6(&self) -> io::Result<bool>1321 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
1322 unsafe {
1323 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP)
1324 .map(|loop_v6| loop_v6 != 0)
1325 }
1326 }
1327
1328 /// Set the value of the `IPV6_MULTICAST_LOOP` option for this socket.
1329 ///
1330 /// Controls whether this socket sees the multicast packets it sends itself.
1331 /// Note that this may not have any affect on IPv4 sockets.
set_multicast_loop_v6(&self, loop_v6: bool) -> io::Result<()>1332 pub fn set_multicast_loop_v6(&self, loop_v6: bool) -> io::Result<()> {
1333 unsafe {
1334 setsockopt(
1335 self.as_raw(),
1336 sys::IPPROTO_IPV6,
1337 sys::IPV6_MULTICAST_LOOP,
1338 loop_v6 as c_int,
1339 )
1340 }
1341 }
1342
1343 /// Get the value of the `IPV6_UNICAST_HOPS` option for this socket.
1344 ///
1345 /// Specifies the hop limit for ipv6 unicast packets
unicast_hops_v6(&self) -> io::Result<u32>1346 pub fn unicast_hops_v6(&self) -> io::Result<u32> {
1347 unsafe {
1348 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS)
1349 .map(|hops| hops as u32)
1350 }
1351 }
1352
1353 /// Set the value for the `IPV6_UNICAST_HOPS` option on this socket.
1354 ///
1355 /// Specifies the hop limit for ipv6 unicast packets
set_unicast_hops_v6(&self, hops: u32) -> io::Result<()>1356 pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1357 unsafe {
1358 setsockopt(
1359 self.as_raw(),
1360 sys::IPPROTO_IPV6,
1361 sys::IPV6_UNICAST_HOPS,
1362 hops as c_int,
1363 )
1364 }
1365 }
1366
1367 /// Get the value of the `IPV6_V6ONLY` option for this socket.
1368 ///
1369 /// For more information about this option, see [`set_only_v6`].
1370 ///
1371 /// [`set_only_v6`]: Socket::set_only_v6
only_v6(&self) -> io::Result<bool>1372 pub fn only_v6(&self) -> io::Result<bool> {
1373 unsafe {
1374 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_V6ONLY)
1375 .map(|only_v6| only_v6 != 0)
1376 }
1377 }
1378
1379 /// Set the value for the `IPV6_V6ONLY` option on this socket.
1380 ///
1381 /// If this is set to `true` then the socket is restricted to sending and
1382 /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
1383 /// can bind the same port at the same time.
1384 ///
1385 /// If this is set to `false` then the socket can be used to send and
1386 /// receive packets from an IPv4-mapped IPv6 address.
set_only_v6(&self, only_v6: bool) -> io::Result<()>1387 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1388 unsafe {
1389 setsockopt(
1390 self.as_raw(),
1391 sys::IPPROTO_IPV6,
1392 sys::IPV6_V6ONLY,
1393 only_v6 as c_int,
1394 )
1395 }
1396 }
1397 }
1398
1399 /// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.
1400 ///
1401 /// Additional documentation can be found in documentation of the OS.
1402 /// * Linux: <https://man7.org/linux/man-pages/man7/tcp.7.html>
1403 /// * Windows: <https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options>
1404 impl Socket {
1405 /// Get the value of the `TCP_KEEPIDLE` option on this socket.
1406 ///
1407 /// This returns the value of `TCP_KEEPALIVE` on macOS and iOS and `TCP_KEEPIDLE` on all other
1408 /// supported Unix operating systems.
1409 #[cfg(any(
1410 doc,
1411 all(
1412 feature = "all",
1413 not(any(windows, target_os = "haiku", target_os = "openbsd"))
1414 )
1415 ))]
1416 #[cfg_attr(
1417 docsrs,
1418 doc(cfg(all(
1419 feature = "all",
1420 not(any(windows, target_os = "haiku", target_os = "openbsd"))
1421 )))
1422 )]
keepalive_time(&self) -> io::Result<Duration>1423 pub fn keepalive_time(&self) -> io::Result<Duration> {
1424 sys::keepalive_time(self.as_raw())
1425 }
1426
1427 /// Get the value of the `TCP_KEEPINTVL` option on this socket.
1428 ///
1429 /// For more information about this option, see [`set_tcp_keepalive`].
1430 ///
1431 /// [`set_tcp_keepalive`]: Socket::set_tcp_keepalive
1432 #[cfg(all(
1433 feature = "all",
1434 any(
1435 doc,
1436 target_os = "android",
1437 target_os = "dragonfly",
1438 target_os = "freebsd",
1439 target_os = "fuchsia",
1440 target_os = "illumos",
1441 target_os = "linux",
1442 target_os = "netbsd",
1443 target_vendor = "apple",
1444 )
1445 ))]
1446 #[cfg_attr(
1447 docsrs,
1448 doc(cfg(all(
1449 feature = "all",
1450 any(
1451 target_os = "android",
1452 target_os = "dragonfly",
1453 target_os = "freebsd",
1454 target_os = "fuchsia",
1455 target_os = "illumos",
1456 target_os = "linux",
1457 target_os = "netbsd",
1458 target_vendor = "apple",
1459 )
1460 )))
1461 )]
keepalive_interval(&self) -> io::Result<Duration>1462 pub fn keepalive_interval(&self) -> io::Result<Duration> {
1463 unsafe {
1464 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPINTVL)
1465 .map(|secs| Duration::from_secs(secs as u64))
1466 }
1467 }
1468
1469 /// Get the value of the `TCP_KEEPCNT` option on this socket.
1470 ///
1471 /// For more information about this option, see [`set_tcp_keepalive`].
1472 ///
1473 /// [`set_tcp_keepalive`]: Socket::set_tcp_keepalive
1474 #[cfg(all(
1475 feature = "all",
1476 any(
1477 doc,
1478 target_os = "android",
1479 target_os = "dragonfly",
1480 target_os = "freebsd",
1481 target_os = "fuchsia",
1482 target_os = "illumos",
1483 target_os = "linux",
1484 target_os = "netbsd",
1485 target_vendor = "apple",
1486 )
1487 ))]
1488 #[cfg_attr(
1489 docsrs,
1490 doc(cfg(all(
1491 feature = "all",
1492 any(
1493 target_os = "android",
1494 target_os = "dragonfly",
1495 target_os = "freebsd",
1496 target_os = "fuchsia",
1497 target_os = "illumos",
1498 target_os = "linux",
1499 target_os = "netbsd",
1500 target_vendor = "apple",
1501 )
1502 )))
1503 )]
keepalive_retries(&self) -> io::Result<u32>1504 pub fn keepalive_retries(&self) -> io::Result<u32> {
1505 unsafe {
1506 getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPCNT)
1507 .map(|retries| retries as u32)
1508 }
1509 }
1510
1511 /// Set parameters configuring TCP keepalive probes for this socket.
1512 ///
1513 /// The supported parameters depend on the operating system, and are
1514 /// configured using the [`TcpKeepalive`] struct. At a minimum, all systems
1515 /// support configuring the [keepalive time]: the time after which the OS
1516 /// will start sending keepalive messages on an idle connection.
1517 ///
1518 /// [keepalive time]: TcpKeepalive::with_time
1519 ///
1520 /// # Notes
1521 ///
1522 /// * This will enable `SO_KEEPALIVE` on this socket, if it is not already
1523 /// enabled.
1524 /// * On some platforms, such as Windows, any keepalive parameters *not*
1525 /// configured by the `TcpKeepalive` struct passed to this function may be
1526 /// overwritten with their default values. Therefore, this function should
1527 /// either only be called once per socket, or the same parameters should
1528 /// be passed every time it is called.
1529 ///
1530 /// # Examples
1531 ///
1532 /// ```
1533 /// use std::time::Duration;
1534 ///
1535 /// use socket2::{Socket, TcpKeepalive, Domain, Type};
1536 ///
1537 /// # fn main() -> std::io::Result<()> {
1538 /// let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
1539 /// let keepalive = TcpKeepalive::new()
1540 /// .with_time(Duration::from_secs(4));
1541 /// // Depending on the target operating system, we may also be able to
1542 /// // configure the keepalive probe interval and/or the number of
1543 /// // retries here as well.
1544 ///
1545 /// socket.set_tcp_keepalive(&keepalive)?;
1546 /// # Ok(()) }
1547 /// ```
1548 ///
set_tcp_keepalive(&self, params: &TcpKeepalive) -> io::Result<()>1549 pub fn set_tcp_keepalive(&self, params: &TcpKeepalive) -> io::Result<()> {
1550 self.set_keepalive(true)?;
1551 sys::set_tcp_keepalive(self.as_raw(), params)
1552 }
1553
1554 /// Get the value of the `TCP_NODELAY` option on this socket.
1555 ///
1556 /// For more information about this option, see [`set_nodelay`].
1557 ///
1558 /// [`set_nodelay`]: Socket::set_nodelay
nodelay(&self) -> io::Result<bool>1559 pub fn nodelay(&self) -> io::Result<bool> {
1560 unsafe {
1561 getsockopt::<Bool>(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_NODELAY)
1562 .map(|nodelay| nodelay != 0)
1563 }
1564 }
1565
1566 /// Set the value of the `TCP_NODELAY` option on this socket.
1567 ///
1568 /// If set, this option disables the Nagle algorithm. This means that
1569 /// segments are always sent as soon as possible, even if there is only a
1570 /// small amount of data. When not set, data is buffered until there is a
1571 /// sufficient amount to send out, thereby avoiding the frequent sending of
1572 /// small packets.
set_nodelay(&self, nodelay: bool) -> io::Result<()>1573 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
1574 unsafe {
1575 setsockopt(
1576 self.as_raw(),
1577 sys::IPPROTO_TCP,
1578 sys::TCP_NODELAY,
1579 nodelay as c_int,
1580 )
1581 }
1582 }
1583 }
1584
1585 impl Read for Socket {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>1586 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1587 // Safety: the `recv` implementation promises not to write uninitialised
1588 // bytes to the `buf`fer, so this casting is safe.
1589 let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
1590 self.recv(buf)
1591 }
1592
1593 #[cfg(not(target_os = "redox"))]
read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>1594 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
1595 // Safety: both `IoSliceMut` and `MaybeUninitSlice` promise to have the
1596 // same layout, that of `iovec`/`WSABUF`. Furthermore `recv_vectored`
1597 // promises to not write unitialised bytes to the `bufs` and pass it
1598 // directly to the `recvmsg` system call, so this is safe.
1599 let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
1600 self.recv_vectored(bufs).map(|(n, _)| n)
1601 }
1602 }
1603
1604 impl<'a> Read for &'a Socket {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>1605 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1606 // Safety: see other `Read::read` impl.
1607 let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
1608 self.recv(buf)
1609 }
1610
1611 #[cfg(not(target_os = "redox"))]
read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>1612 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
1613 // Safety: see other `Read::read` impl.
1614 let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
1615 self.recv_vectored(bufs).map(|(n, _)| n)
1616 }
1617 }
1618
1619 impl Write for Socket {
write(&mut self, buf: &[u8]) -> io::Result<usize>1620 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1621 self.send(buf)
1622 }
1623
1624 #[cfg(not(target_os = "redox"))]
write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>1625 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1626 self.send_vectored(bufs)
1627 }
1628
flush(&mut self) -> io::Result<()>1629 fn flush(&mut self) -> io::Result<()> {
1630 Ok(())
1631 }
1632 }
1633
1634 impl<'a> Write for &'a Socket {
write(&mut self, buf: &[u8]) -> io::Result<usize>1635 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1636 self.send(buf)
1637 }
1638
1639 #[cfg(not(target_os = "redox"))]
write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>1640 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1641 self.send_vectored(bufs)
1642 }
1643
flush(&mut self) -> io::Result<()>1644 fn flush(&mut self) -> io::Result<()> {
1645 Ok(())
1646 }
1647 }
1648
1649 impl fmt::Debug for Socket {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1650 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1651 f.debug_struct("Socket")
1652 .field("raw", &self.as_raw())
1653 .field("local_addr", &self.local_addr().ok())
1654 .field("peer_addr", &self.peer_addr().ok())
1655 .finish()
1656 }
1657 }
1658
1659 from!(net::TcpStream, Socket);
1660 from!(net::TcpListener, Socket);
1661 from!(net::UdpSocket, Socket);
1662 from!(Socket, net::TcpStream);
1663 from!(Socket, net::TcpListener);
1664 from!(Socket, net::UdpSocket);
1665