Skip to main content

tokio/net/tcp/
socket.rs

1use crate::net::{TcpListener, TcpStream};
2
3use std::fmt;
4use std::io;
5use std::net::SocketAddr;
6
7#[cfg(not(windows))]
8use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
9use std::time::Duration;
10
11cfg_windows! {
12    use crate::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket, AsSocket, BorrowedSocket};
13}
14
15cfg_net! {
16    /// A TCP socket that has not yet been converted to a `TcpStream` or
17    /// `TcpListener`.
18    ///
19    /// `TcpSocket` wraps an operating system socket and enables the caller to
20    /// configure the socket before establishing a TCP connection or accepting
21    /// inbound connections. The caller is able to set socket option and explicitly
22    /// bind the socket with a socket address.
23    ///
24    /// The underlying socket is closed when the `TcpSocket` value is dropped.
25    ///
26    /// `TcpSocket` should only be used directly if the default configuration used
27    /// by `TcpStream::connect` and `TcpListener::bind` does not meet the required
28    /// use case.
29    ///
30    /// Calling `TcpStream::connect("127.0.0.1:8080")` is equivalent to:
31    ///
32    /// ```no_run
33    /// use tokio::net::TcpSocket;
34    ///
35    /// use std::io;
36    ///
37    /// #[tokio::main]
38    /// async fn main() -> io::Result<()> {
39    ///     let addr = "127.0.0.1:8080".parse().unwrap();
40    ///
41    ///     let socket = TcpSocket::new_v4()?;
42    ///     let stream = socket.connect(addr).await?;
43    /// # drop(stream);
44    ///
45    ///     Ok(())
46    /// }
47    /// ```
48    ///
49    /// Calling `TcpListener::bind("127.0.0.1:8080")` is equivalent to:
50    ///
51    /// ```no_run
52    /// use tokio::net::TcpSocket;
53    ///
54    /// use std::io;
55    ///
56    /// #[tokio::main]
57    /// async fn main() -> io::Result<()> {
58    ///     let addr = "127.0.0.1:8080".parse().unwrap();
59    ///
60    ///     let socket = TcpSocket::new_v4()?;
61    ///     // On platforms with Berkeley-derived sockets, this allows to quickly
62    ///     // rebind a socket, without needing to wait for the OS to clean up the
63    ///     // previous one.
64    ///     //
65    ///     // On Windows, this allows rebinding sockets which are actively in use,
66    ///     // which allows "socket hijacking", so we explicitly don't set it here.
67    ///     // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
68    ///     socket.set_reuseaddr(true)?;
69    ///     socket.bind(addr)?;
70    ///
71    ///     // Note: the actual backlog used by `TcpListener::bind` is platform-dependent,
72    ///     // as Tokio relies on Mio's default backlog value configuration. The `1024` here is only
73    ///     // illustrative and does not reflect the real value used.
74    ///     let listener = socket.listen(1024)?;
75    /// # drop(listener);
76    ///
77    ///     Ok(())
78    /// }
79    /// ```
80    ///
81    /// Setting socket options not explicitly provided by `TcpSocket` may be done by
82    /// accessing the `RawFd`/`RawSocket` using [`AsRawFd`]/[`AsRawSocket`] and
83    /// setting the option with a crate like [`socket2`].
84    ///
85    /// [`RawFd`]: https://doc.rust-lang.org/std/os/fd/type.RawFd.html
86    /// [`RawSocket`]: https://doc.rust-lang.org/std/os/windows/io/type.RawSocket.html
87    /// [`AsRawFd`]: https://doc.rust-lang.org/std/os/fd/trait.AsRawFd.html
88    /// [`AsRawSocket`]: https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html
89    /// [`socket2`]: https://docs.rs/socket2/
90    #[cfg_attr(docsrs, doc(alias = "connect_std"))]
91    pub struct TcpSocket {
92        inner: socket2::Socket,
93    }
94}
95
96impl TcpSocket {
97    /// Creates a new socket configured for IPv4.
98    ///
99    /// Calls `socket(2)` with `AF_INET` and `SOCK_STREAM`.
100    ///
101    /// # Returns
102    ///
103    /// On success, the newly created `TcpSocket` is returned. If an error is
104    /// encountered, it is returned instead.
105    ///
106    /// # Examples
107    ///
108    /// Create a new IPv4 socket and start listening.
109    ///
110    /// ```no_run
111    /// use tokio::net::TcpSocket;
112    ///
113    /// use std::io;
114    ///
115    /// #[tokio::main]
116    /// async fn main() -> io::Result<()> {
117    ///     let addr = "127.0.0.1:8080".parse().unwrap();
118    ///     let socket = TcpSocket::new_v4()?;
119    ///     socket.bind(addr)?;
120    ///
121    ///     let listener = socket.listen(128)?;
122    /// # drop(listener);
123    ///     Ok(())
124    /// }
125    /// ```
126    pub fn new_v4() -> io::Result<TcpSocket> {
127        TcpSocket::new(socket2::Domain::IPV4)
128    }
129
130    /// Creates a new socket configured for IPv6.
131    ///
132    /// Calls `socket(2)` with `AF_INET6` and `SOCK_STREAM`.
133    ///
134    /// # Returns
135    ///
136    /// On success, the newly created `TcpSocket` is returned. If an error is
137    /// encountered, it is returned instead.
138    ///
139    /// # Examples
140    ///
141    /// Create a new IPv6 socket and start listening.
142    ///
143    /// ```no_run
144    /// use tokio::net::TcpSocket;
145    ///
146    /// use std::io;
147    ///
148    /// #[tokio::main]
149    /// async fn main() -> io::Result<()> {
150    ///     let addr = "[::1]:8080".parse().unwrap();
151    ///     let socket = TcpSocket::new_v6()?;
152    ///     socket.bind(addr)?;
153    ///
154    ///     let listener = socket.listen(128)?;
155    /// # drop(listener);
156    ///     Ok(())
157    /// }
158    /// ```
159    pub fn new_v6() -> io::Result<TcpSocket> {
160        TcpSocket::new(socket2::Domain::IPV6)
161    }
162
163    fn new(domain: socket2::Domain) -> io::Result<TcpSocket> {
164        let ty = socket2::Type::STREAM;
165        #[cfg(any(
166            target_os = "android",
167            target_os = "dragonfly",
168            target_os = "freebsd",
169            target_os = "fuchsia",
170            target_os = "illumos",
171            target_os = "linux",
172            target_os = "netbsd",
173            target_os = "openbsd",
174            target_os = "wasi",
175        ))]
176        let ty = ty.nonblocking();
177        let inner = socket2::Socket::new(domain, ty, Some(socket2::Protocol::TCP))?;
178        #[cfg(not(any(
179            target_os = "android",
180            target_os = "dragonfly",
181            target_os = "freebsd",
182            target_os = "fuchsia",
183            target_os = "illumos",
184            target_os = "linux",
185            target_os = "netbsd",
186            target_os = "openbsd",
187            target_os = "wasi",
188        )))]
189        inner.set_nonblocking(true)?;
190        Ok(TcpSocket { inner })
191    }
192
193    /// Sets value for the `SO_KEEPALIVE` option on this socket.
194    pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
195        self.inner.set_keepalive(keepalive)
196    }
197
198    /// Gets the value of the `SO_KEEPALIVE` option on this socket.
199    pub fn keepalive(&self) -> io::Result<bool> {
200        self.inner.keepalive()
201    }
202
203    /// Allows the socket to bind to an in-use address.
204    ///
205    /// Behavior is platform specific. Refer to the target platform's
206    /// documentation for more details.
207    ///
208    /// # Examples
209    ///
210    /// ```no_run
211    /// use tokio::net::TcpSocket;
212    ///
213    /// use std::io;
214    ///
215    /// #[tokio::main]
216    /// async fn main() -> io::Result<()> {
217    ///     let addr = "127.0.0.1:8080".parse().unwrap();
218    ///
219    ///     let socket = TcpSocket::new_v4()?;
220    ///     socket.set_reuseaddr(true)?;
221    ///     socket.bind(addr)?;
222    ///
223    ///     let listener = socket.listen(1024)?;
224    /// # drop(listener);
225    ///
226    ///     Ok(())
227    /// }
228    /// ```
229    pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> {
230        self.inner.set_reuse_address(reuseaddr)
231    }
232
233    /// Retrieves the value set for `SO_REUSEADDR` on this socket.
234    ///
235    /// # Examples
236    ///
237    /// ```no_run
238    /// use tokio::net::TcpSocket;
239    ///
240    /// use std::io;
241    ///
242    /// #[tokio::main]
243    /// async fn main() -> io::Result<()> {
244    ///     let addr = "127.0.0.1:8080".parse().unwrap();
245    ///
246    ///     let socket = TcpSocket::new_v4()?;
247    ///     socket.set_reuseaddr(true)?;
248    ///     assert!(socket.reuseaddr().unwrap());
249    ///     socket.bind(addr)?;
250    ///
251    ///     let listener = socket.listen(1024)?;
252    ///     Ok(())
253    /// }
254    /// ```
255    pub fn reuseaddr(&self) -> io::Result<bool> {
256        self.inner.reuse_address()
257    }
258
259    /// Allows the socket to bind to an in-use port. Only available for unix systems
260    /// (excluding Solaris, Illumos, and Cygwin).
261    ///
262    /// Behavior is platform specific. Refer to the target platform's
263    /// documentation for more details.
264    ///
265    /// # Examples
266    ///
267    /// ```no_run
268    /// use tokio::net::TcpSocket;
269    ///
270    /// use std::io;
271    ///
272    /// #[tokio::main]
273    /// async fn main() -> io::Result<()> {
274    ///     let addr = "127.0.0.1:8080".parse().unwrap();
275    ///
276    ///     let socket = TcpSocket::new_v4()?;
277    ///     socket.set_reuseport(true)?;
278    ///     socket.bind(addr)?;
279    ///
280    ///     let listener = socket.listen(1024)?;
281    ///     Ok(())
282    /// }
283    /// ```
284    #[cfg(all(
285        unix,
286        not(target_os = "solaris"),
287        not(target_os = "illumos"),
288        not(target_os = "cygwin"),
289        not(target_os = "nuttx"),
290    ))]
291    #[cfg_attr(
292        docsrs,
293        doc(cfg(all(
294            unix,
295            not(target_os = "solaris"),
296            not(target_os = "illumos"),
297            not(target_os = "cygwin"),
298            not(target_os = "nuttx"),
299        )))
300    )]
301    pub fn set_reuseport(&self, reuseport: bool) -> io::Result<()> {
302        self.inner.set_reuse_port(reuseport)
303    }
304
305    /// Allows the socket to bind to an in-use port. Only available for unix systems
306    /// (excluding Solaris, Illumos, and Cygwin).
307    ///
308    /// Behavior is platform specific. Refer to the target platform's
309    /// documentation for more details.
310    ///
311    /// # Examples
312    ///
313    /// ```no_run
314    /// use tokio::net::TcpSocket;
315    ///
316    /// use std::io;
317    ///
318    /// #[tokio::main]
319    /// async fn main() -> io::Result<()> {
320    ///     let addr = "127.0.0.1:8080".parse().unwrap();
321    ///
322    ///     let socket = TcpSocket::new_v4()?;
323    ///     socket.set_reuseport(true)?;
324    ///     assert!(socket.reuseport().unwrap());
325    ///     socket.bind(addr)?;
326    ///
327    ///     let listener = socket.listen(1024)?;
328    ///     Ok(())
329    /// }
330    /// ```
331    #[cfg(all(
332        unix,
333        not(target_os = "solaris"),
334        not(target_os = "illumos"),
335        not(target_os = "cygwin"),
336        not(target_os = "nuttx"),
337    ))]
338    #[cfg_attr(
339        docsrs,
340        doc(cfg(all(
341            unix,
342            not(target_os = "solaris"),
343            not(target_os = "illumos"),
344            not(target_os = "cygwin"),
345            not(target_os = "nuttx"),
346        )))
347    )]
348    pub fn reuseport(&self) -> io::Result<bool> {
349        self.inner.reuse_port()
350    }
351
352    /// Sets the size of the TCP send buffer on this socket.
353    ///
354    /// On most operating systems, this sets the `SO_SNDBUF` socket option.
355    pub fn set_send_buffer_size(&self, size: u32) -> io::Result<()> {
356        self.inner.set_send_buffer_size(size as usize)
357    }
358
359    /// Returns the size of the TCP send buffer for this socket.
360    ///
361    /// On most operating systems, this is the value of the `SO_SNDBUF` socket
362    /// option.
363    ///
364    /// Note that if [`set_send_buffer_size`] has been called on this socket
365    /// previously, the value returned by this function may not be the same as
366    /// the argument provided to `set_send_buffer_size`. This is for the
367    /// following reasons:
368    ///
369    /// * Most operating systems have minimum and maximum allowed sizes for the
370    ///   send buffer, and will clamp the provided value if it is below the
371    ///   minimum or above the maximum. The minimum and maximum buffer sizes are
372    ///   OS-dependent.
373    /// * Linux will double the buffer size to account for internal bookkeeping
374    ///   data, and returns the doubled value from `getsockopt(2)`. As per `man
375    ///   7 socket`:
376    ///   > Sets or gets the maximum socket send buffer in bytes. The
377    ///   > kernel doubles this value (to allow space for bookkeeping
378    ///   > overhead) when it is set using `setsockopt(2)`, and this doubled
379    ///   > value is returned by `getsockopt(2)`.
380    ///
381    /// [`set_send_buffer_size`]: #method.set_send_buffer_size
382    pub fn send_buffer_size(&self) -> io::Result<u32> {
383        self.inner.send_buffer_size().map(|n| n as u32)
384    }
385
386    /// Sets the size of the TCP receive buffer on this socket.
387    ///
388    /// On most operating systems, this sets the `SO_RCVBUF` socket option.
389    pub fn set_recv_buffer_size(&self, size: u32) -> io::Result<()> {
390        self.inner.set_recv_buffer_size(size as usize)
391    }
392
393    /// Returns the size of the TCP receive buffer for this socket.
394    ///
395    /// On most operating systems, this is the value of the `SO_RCVBUF` socket
396    /// option.
397    ///
398    /// Note that if [`set_recv_buffer_size`] has been called on this socket
399    /// previously, the value returned by this function may not be the same as
400    /// the argument provided to `set_recv_buffer_size`. This is for the
401    /// following reasons:
402    ///
403    /// * Most operating systems have minimum and maximum allowed sizes for the
404    ///   receive buffer, and will clamp the provided value if it is below the
405    ///   minimum or above the maximum. The minimum and maximum buffer sizes are
406    ///   OS-dependent.
407    /// * Linux will double the buffer size to account for internal bookkeeping
408    ///   data, and returns the doubled value from `getsockopt(2)`. As per `man
409    ///   7 socket`:
410    ///   > Sets or gets the maximum socket send buffer in bytes. The
411    ///   > kernel doubles this value (to allow space for bookkeeping
412    ///   > overhead) when it is set using `setsockopt(2)`, and this doubled
413    ///   > value is returned by `getsockopt(2)`.
414    ///
415    /// [`set_recv_buffer_size`]: #method.set_recv_buffer_size
416    pub fn recv_buffer_size(&self) -> io::Result<u32> {
417        self.inner.recv_buffer_size().map(|n| n as u32)
418    }
419
420    /// Sets the linger duration of this socket by setting the `SO_LINGER` option.
421    ///
422    /// This option controls the action taken when a stream has unsent messages and the stream is
423    /// closed. If `SO_LINGER` is set, the system shall block the process until it can transmit the
424    /// data or until the time expires.
425    ///
426    /// If `SO_LINGER` is not specified, and the socket is closed, the system handles the call in a
427    /// way that allows the process to continue as quickly as possible.
428    ///
429    /// This option is deprecated because setting `SO_LINGER` on a socket used with Tokio is always
430    /// incorrect as it leads to blocking the thread when the socket is closed. For more details,
431    /// please see:
432    ///
433    /// > Volumes of communications have been devoted to the intricacies of `SO_LINGER` versus
434    /// > non-blocking (`O_NONBLOCK`) sockets. From what I can tell, the final word is: don't do
435    /// > it. Rely on the `shutdown()`-followed-by-`read()`-eof technique instead.
436    /// >
437    /// > From [The ultimate `SO_LINGER` page, or: why is my tcp not reliable](https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable)
438    ///
439    /// Although this method is deprecated, it will not be removed from Tokio.
440    ///
441    /// Note that the special case of setting `SO_LINGER` to zero does not lead to blocking. Tokio
442    /// provides [`set_zero_linger`](Self::set_zero_linger) for this purpose.
443    #[deprecated = "`SO_LINGER` causes the socket to block the thread on drop"]
444    pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
445        self.inner.set_linger(dur)
446    }
447
448    /// Sets a linger duration of zero on this socket by setting the `SO_LINGER` option.
449    ///
450    /// This causes the connection to be forcefully aborted ("abortive close") when the socket is
451    /// dropped or closed. Instead of the normal TCP shutdown handshake (`FIN`/`ACK`), a TCP `RST`
452    /// (reset) segment is sent to the peer, and the socket immediately discards any unsent data
453    /// residing in the socket send buffer. This prevents the socket from entering the `TIME_WAIT`
454    /// state after closing it.
455    ///
456    /// This is a destructive action. Any data currently buffered by the OS but not yet transmitted
457    /// will be lost. The peer will likely receive a "Connection Reset" error rather than a clean
458    /// end-of-stream.
459    ///
460    /// See the documentation for [`set_linger`](Self::set_linger) for additional details on how
461    /// `SO_LINGER` works.
462    pub fn set_zero_linger(&self) -> io::Result<()> {
463        self.inner.set_linger(Some(Duration::ZERO))
464    }
465
466    /// Reads the linger duration for this socket by getting the `SO_LINGER`
467    /// option.
468    ///
469    /// For more information about this option, see [`set_zero_linger`] and [`set_linger`].
470    ///
471    /// [`set_linger`]: TcpSocket::set_linger
472    /// [`set_zero_linger`]: TcpSocket::set_zero_linger
473    pub fn linger(&self) -> io::Result<Option<Duration>> {
474        self.inner.linger()
475    }
476
477    /// Sets the value of the `TCP_NODELAY` option on this socket.
478    ///
479    /// If set, this option disables the Nagle algorithm. This means that segments are always
480    /// sent as soon as possible, even if there is only a small amount of data. When not set,
481    /// data is buffered until there is a sufficient amount to send out, thereby avoiding
482    /// the frequent sending of small packets.
483    ///
484    /// # Examples
485    ///
486    /// ```no_run
487    /// use tokio::net::TcpSocket;
488    ///
489    /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
490    /// let socket = TcpSocket::new_v4()?;
491    ///
492    /// socket.set_nodelay(true)?;
493    /// # Ok(())
494    /// # }
495    /// ```
496    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
497        self.inner.set_tcp_nodelay(nodelay)
498    }
499
500    /// Gets the value of the `TCP_NODELAY` option on this socket.
501    ///
502    /// For more information about this option, see [`set_nodelay`].
503    ///
504    /// [`set_nodelay`]: TcpSocket::set_nodelay
505    ///
506    /// # Examples
507    ///
508    /// ```no_run
509    /// use tokio::net::TcpSocket;
510    ///
511    /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
512    /// let socket = TcpSocket::new_v4()?;
513    ///
514    /// println!("{:?}", socket.nodelay()?);
515    /// # Ok(())
516    /// # }
517    /// ```
518    pub fn nodelay(&self) -> io::Result<bool> {
519        self.inner.tcp_nodelay()
520    }
521
522    /// Gets the value of the `IPV6_TCLASS` option for this socket.
523    ///
524    /// For more information about this option, see [`set_tclass_v6`].
525    ///
526    /// [`set_tclass_v6`]: Self::set_tclass_v6
527    // https://docs.rs/socket2/0.6.1/src/socket2/sys/unix.rs.html#2541
528    #[cfg(any(
529        target_os = "android",
530        target_os = "dragonfly",
531        target_os = "freebsd",
532        target_os = "fuchsia",
533        target_os = "linux",
534        target_os = "macos",
535        target_os = "netbsd",
536        target_os = "openbsd",
537        target_os = "cygwin",
538    ))]
539    #[cfg_attr(
540        docsrs,
541        doc(cfg(any(
542            target_os = "android",
543            target_os = "dragonfly",
544            target_os = "freebsd",
545            target_os = "fuchsia",
546            target_os = "linux",
547            target_os = "macos",
548            target_os = "netbsd",
549            target_os = "openbsd",
550            target_os = "cygwin",
551        )))
552    )]
553    pub fn tclass_v6(&self) -> io::Result<u32> {
554        self.inner.tclass_v6()
555    }
556
557    /// Sets the value for the `IPV6_TCLASS` option on this socket.
558    ///
559    /// Specifies the traffic class field that is used in every packet
560    /// sent from this socket.
561    ///
562    /// # Note
563    ///
564    /// This may not have any effect on IPv4 sockets.
565    // https://docs.rs/socket2/0.6.1/src/socket2/sys/unix.rs.html#2566
566    #[cfg(any(
567        target_os = "android",
568        target_os = "dragonfly",
569        target_os = "freebsd",
570        target_os = "fuchsia",
571        target_os = "linux",
572        target_os = "macos",
573        target_os = "netbsd",
574        target_os = "openbsd",
575        target_os = "cygwin",
576    ))]
577    #[cfg_attr(
578        docsrs,
579        doc(cfg(any(
580            target_os = "android",
581            target_os = "dragonfly",
582            target_os = "freebsd",
583            target_os = "fuchsia",
584            target_os = "linux",
585            target_os = "macos",
586            target_os = "netbsd",
587            target_os = "openbsd",
588            target_os = "cygwin",
589        )))
590    )]
591    pub fn set_tclass_v6(&self, tclass: u32) -> io::Result<()> {
592        self.inner.set_tclass_v6(tclass)
593    }
594
595    /// Gets the value of the `IP_TOS` option for this socket.
596    ///
597    /// For more information about this option, see [`set_tos_v4`].
598    ///
599    /// [`set_tos_v4`]: Self::set_tos_v4
600    // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1585
601    #[cfg(not(any(
602        target_os = "fuchsia",
603        target_os = "redox",
604        target_os = "solaris",
605        target_os = "illumos",
606        target_os = "haiku",
607        target_os = "wasi",
608    )))]
609    #[cfg_attr(
610        docsrs,
611        doc(cfg(not(any(
612            target_os = "fuchsia",
613            target_os = "redox",
614            target_os = "solaris",
615            target_os = "illumos",
616            target_os = "haiku",
617            target_os = "wasi",
618        ))))
619    )]
620    pub fn tos_v4(&self) -> io::Result<u32> {
621        self.inner.tos_v4()
622    }
623
624    /// Deprecated. Use [`tos_v4()`] instead.
625    ///
626    /// [`tos_v4()`]: Self::tos_v4
627    #[deprecated(
628        note = "`tos` related methods have been renamed `tos_v4` since they are IPv4-specific."
629    )]
630    #[doc(hidden)]
631    #[cfg(not(any(
632        target_os = "fuchsia",
633        target_os = "redox",
634        target_os = "solaris",
635        target_os = "illumos",
636        target_os = "haiku",
637        target_os = "wasi",
638    )))]
639    #[cfg_attr(
640        docsrs,
641        doc(cfg(not(any(
642            target_os = "fuchsia",
643            target_os = "redox",
644            target_os = "solaris",
645            target_os = "illumos",
646            target_os = "haiku",
647            target_os = "wasi",
648        ))))
649    )]
650    pub fn tos(&self) -> io::Result<u32> {
651        self.tos_v4()
652    }
653
654    /// Sets the value for the `IP_TOS` option on this socket.
655    ///
656    /// This value sets the type-of-service field that is used in every packet
657    /// sent from this socket.
658    ///
659    /// # Note
660    ///
661    /// - This may not have any effect on IPv6 sockets.
662    /// - On Windows, `IP_TOS` is only supported on [Windows 8+ or
663    ///   Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
664    // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1566
665    #[cfg(not(any(
666        target_os = "fuchsia",
667        target_os = "redox",
668        target_os = "solaris",
669        target_os = "illumos",
670        target_os = "haiku",
671        target_os = "wasi",
672    )))]
673    #[cfg_attr(
674        docsrs,
675        doc(cfg(not(any(
676            target_os = "fuchsia",
677            target_os = "redox",
678            target_os = "solaris",
679            target_os = "illumos",
680            target_os = "haiku",
681            target_os = "wasi",
682        ))))
683    )]
684    pub fn set_tos_v4(&self, tos: u32) -> io::Result<()> {
685        self.inner.set_tos_v4(tos)
686    }
687
688    /// Deprecated. Use [`set_tos_v4()`] instead.
689    ///
690    /// [`set_tos_v4()`]: Self::set_tos_v4
691    #[deprecated(
692        note = "`tos` related methods have been renamed `tos_v4` since they are IPv4-specific."
693    )]
694    #[doc(hidden)]
695    #[cfg(not(any(
696        target_os = "fuchsia",
697        target_os = "redox",
698        target_os = "solaris",
699        target_os = "illumos",
700        target_os = "haiku",
701        target_os = "wasi",
702    )))]
703    #[cfg_attr(
704        docsrs,
705        doc(cfg(not(any(
706            target_os = "fuchsia",
707            target_os = "redox",
708            target_os = "solaris",
709            target_os = "illumos",
710            target_os = "haiku",
711            target_os = "wasi",
712        ))))
713    )]
714    pub fn set_tos(&self, tos: u32) -> io::Result<()> {
715        self.set_tos_v4(tos)
716    }
717
718    /// Gets the value for the `SO_BINDTODEVICE` option on this socket
719    ///
720    /// This value gets the socket binded device's interface name.
721    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
722    #[cfg_attr(
723        docsrs,
724        doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",)))
725    )]
726    pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
727        self.inner.device()
728    }
729
730    /// Sets the value for the `SO_BINDTODEVICE` option on this socket
731    ///
732    /// If a socket is bound to an interface, only packets received from that
733    /// particular interface are processed by the socket. Note that this only
734    /// works for some socket types, particularly `AF_INET` sockets.
735    ///
736    /// If `interface` is `None` or an empty string it removes the binding.
737    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
738    #[cfg_attr(
739        docsrs,
740        doc(cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))))
741    )]
742    pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
743        self.inner.bind_device(interface)
744    }
745
746    /// Gets the local address of this socket.
747    ///
748    /// Will fail on windows if called before `bind`.
749    ///
750    /// # Examples
751    ///
752    /// ```no_run
753    /// use tokio::net::TcpSocket;
754    ///
755    /// use std::io;
756    ///
757    /// #[tokio::main]
758    /// async fn main() -> io::Result<()> {
759    ///     let addr = "127.0.0.1:8080".parse().unwrap();
760    ///
761    ///     let socket = TcpSocket::new_v4()?;
762    ///     socket.bind(addr)?;
763    ///     assert_eq!(socket.local_addr().unwrap().to_string(), "127.0.0.1:8080");
764    ///     let listener = socket.listen(1024)?;
765    ///     Ok(())
766    /// }
767    /// ```
768    pub fn local_addr(&self) -> io::Result<SocketAddr> {
769        self.inner.local_addr().and_then(convert_address)
770    }
771
772    /// Returns the value of the `SO_ERROR` option.
773    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
774        self.inner.take_error()
775    }
776
777    /// Binds the socket to the given address.
778    ///
779    /// This calls the `bind(2)` operating-system function. Behavior is
780    /// platform specific. Refer to the target platform's documentation for more
781    /// details.
782    ///
783    /// # Examples
784    ///
785    /// Bind a socket before listening.
786    ///
787    /// ```no_run
788    /// use tokio::net::TcpSocket;
789    ///
790    /// use std::io;
791    ///
792    /// #[tokio::main]
793    /// async fn main() -> io::Result<()> {
794    ///     let addr = "127.0.0.1:8080".parse().unwrap();
795    ///
796    ///     let socket = TcpSocket::new_v4()?;
797    ///     socket.bind(addr)?;
798    ///
799    ///     let listener = socket.listen(1024)?;
800    /// # drop(listener);
801    ///
802    ///     Ok(())
803    /// }
804    /// ```
805    pub fn bind(&self, addr: SocketAddr) -> io::Result<()> {
806        self.inner.bind(&addr.into())
807    }
808
809    /// Establishes a TCP connection with a peer at the specified socket address.
810    ///
811    /// The `TcpSocket` is consumed. Once the connection is established, a
812    /// connected [`TcpStream`] is returned. If the connection fails, the
813    /// encountered error is returned.
814    ///
815    /// [`TcpStream`]: TcpStream
816    ///
817    /// This calls the `connect(2)` operating-system function. Behavior is
818    /// platform specific. Refer to the target platform's documentation for more
819    /// details.
820    ///
821    /// # Examples
822    ///
823    /// Connecting to a peer.
824    ///
825    /// ```no_run
826    /// use tokio::net::TcpSocket;
827    ///
828    /// use std::io;
829    ///
830    /// #[tokio::main]
831    /// async fn main() -> io::Result<()> {
832    ///     let addr = "127.0.0.1:8080".parse().unwrap();
833    ///
834    ///     let socket = TcpSocket::new_v4()?;
835    ///     let stream = socket.connect(addr).await?;
836    /// # drop(stream);
837    ///
838    ///     Ok(())
839    /// }
840    /// ```
841    pub async fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
842        if let Err(err) = self.inner.connect(&addr.into()) {
843            #[cfg(not(windows))]
844            if err.raw_os_error() != Some(libc::EINPROGRESS) {
845                return Err(err);
846            }
847            #[cfg(windows)]
848            if err.kind() != io::ErrorKind::WouldBlock {
849                return Err(err);
850            }
851        }
852        #[cfg(not(windows))]
853        let mio = {
854            use std::os::fd::{FromRawFd, IntoRawFd};
855
856            let raw_fd = self.inner.into_raw_fd();
857            unsafe { mio::net::TcpStream::from_raw_fd(raw_fd) }
858        };
859
860        #[cfg(windows)]
861        let mio = {
862            use std::os::windows::io::{FromRawSocket, IntoRawSocket};
863
864            let raw_socket = self.inner.into_raw_socket();
865            unsafe { mio::net::TcpStream::from_raw_socket(raw_socket) }
866        };
867
868        TcpStream::connect_mio(mio).await
869    }
870
871    /// Converts the socket into a `TcpListener`.
872    ///
873    /// `backlog` defines the maximum number of pending connections are queued
874    /// by the operating system at any given time. Connection are removed from
875    /// the queue with [`TcpListener::accept`]. When the queue is full, the
876    /// operating-system will start rejecting connections.
877    ///
878    /// [`TcpListener::accept`]: TcpListener::accept
879    ///
880    /// This calls the `listen(2)` operating-system function, marking the socket
881    /// as a passive socket. Behavior is platform specific. Refer to the target
882    /// platform's documentation for more details.
883    ///
884    /// # Examples
885    ///
886    /// Create a `TcpListener`.
887    ///
888    /// ```no_run
889    /// use tokio::net::TcpSocket;
890    ///
891    /// use std::io;
892    ///
893    /// #[tokio::main]
894    /// async fn main() -> io::Result<()> {
895    ///     let addr = "127.0.0.1:8080".parse().unwrap();
896    ///
897    ///     let socket = TcpSocket::new_v4()?;
898    ///     socket.bind(addr)?;
899    ///
900    ///     let listener = socket.listen(1024)?;
901    /// # drop(listener);
902    ///
903    ///     Ok(())
904    /// }
905    /// ```
906    pub fn listen(self, backlog: u32) -> io::Result<TcpListener> {
907        self.inner.listen(backlog as i32)?;
908        #[cfg(not(windows))]
909        let mio = {
910            use std::os::fd::{FromRawFd, IntoRawFd};
911
912            let raw_fd = self.inner.into_raw_fd();
913            unsafe { mio::net::TcpListener::from_raw_fd(raw_fd) }
914        };
915
916        #[cfg(windows)]
917        let mio = {
918            use std::os::windows::io::{FromRawSocket, IntoRawSocket};
919
920            let raw_socket = self.inner.into_raw_socket();
921            unsafe { mio::net::TcpListener::from_raw_socket(raw_socket) }
922        };
923
924        TcpListener::new(mio)
925    }
926
927    /// Converts a [`std::net::TcpStream`] into a `TcpSocket`. The provided
928    /// socket must not have been connected prior to calling this function. This
929    /// function is typically used together with crates such as [`socket2`] to
930    /// configure socket options that are not available on `TcpSocket`.
931    ///
932    /// [`std::net::TcpStream`]: struct@std::net::TcpStream
933    /// [`socket2`]: https://docs.rs/socket2/
934    ///
935    /// # Notes
936    ///
937    /// The caller is responsible for ensuring that the socket is in
938    /// non-blocking mode. Otherwise all I/O operations on the socket
939    /// will block the thread, which will cause unexpected behavior.
940    /// Non-blocking mode can be set using [`set_nonblocking`].
941    ///
942    /// [`set_nonblocking`]: std::net::TcpStream::set_nonblocking
943    ///
944    /// # Examples
945    ///
946    /// ```
947    /// use tokio::net::TcpSocket;
948    /// use socket2::{Domain, Socket, Type};
949    ///
950    /// #[tokio::main]
951    /// async fn main() -> std::io::Result<()> {
952    ///     let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
953    ///     socket2_socket.set_nonblocking(true)?;
954    ///
955    ///     let socket = TcpSocket::from_std_stream(socket2_socket.into());
956    ///
957    ///     Ok(())
958    /// }
959    /// ```
960    pub fn from_std_stream(std_stream: std::net::TcpStream) -> TcpSocket {
961        #[cfg(not(windows))]
962        {
963            use std::os::fd::{FromRawFd, IntoRawFd};
964
965            let raw_fd = std_stream.into_raw_fd();
966            unsafe { TcpSocket::from_raw_fd(raw_fd) }
967        }
968
969        #[cfg(windows)]
970        {
971            use std::os::windows::io::{FromRawSocket, IntoRawSocket};
972
973            let raw_socket = std_stream.into_raw_socket();
974            unsafe { TcpSocket::from_raw_socket(raw_socket) }
975        }
976    }
977}
978
979fn convert_address(address: socket2::SockAddr) -> io::Result<SocketAddr> {
980    match address.as_socket() {
981        Some(address) => Ok(address),
982        None => Err(io::Error::new(
983            io::ErrorKind::InvalidInput,
984            "invalid address family (not IPv4 or IPv6)",
985        )),
986    }
987}
988
989impl fmt::Debug for TcpSocket {
990    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
991        self.inner.fmt(fmt)
992    }
993}
994
995// These trait implementations can't be build on Windows, so we completely
996// ignore them, even when building documentation.
997#[cfg(any(unix, target_os = "wasi"))]
998cfg_unix_or_wasi! {
999    impl AsRawFd for TcpSocket {
1000        fn as_raw_fd(&self) -> RawFd {
1001            self.inner.as_raw_fd()
1002        }
1003    }
1004
1005    impl AsFd for TcpSocket {
1006        fn as_fd(&self) -> BorrowedFd<'_> {
1007            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
1008        }
1009    }
1010
1011    impl FromRawFd for TcpSocket {
1012        /// Converts a `RawFd` to a `TcpSocket`.
1013        ///
1014        /// # Notes
1015        ///
1016        /// The caller is responsible for ensuring that the socket is in
1017        /// non-blocking mode.
1018        unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
1019            // Safety: exactly the same safety requirements as the
1020            // `FromRawFd::from_raw_fd` trait method.
1021            let inner = unsafe { socket2::Socket::from_raw_fd(fd) };
1022            TcpSocket { inner }
1023        }
1024    }
1025
1026    impl IntoRawFd for TcpSocket {
1027        fn into_raw_fd(self) -> RawFd {
1028            self.inner.into_raw_fd()
1029        }
1030    }
1031}
1032
1033cfg_windows! {
1034    impl IntoRawSocket for TcpSocket {
1035        fn into_raw_socket(self) -> RawSocket {
1036            self.inner.into_raw_socket()
1037        }
1038    }
1039
1040    impl AsRawSocket for TcpSocket {
1041        fn as_raw_socket(&self) -> RawSocket {
1042            self.inner.as_raw_socket()
1043        }
1044    }
1045
1046    impl AsSocket for TcpSocket {
1047        fn as_socket(&self) -> BorrowedSocket<'_> {
1048            unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
1049        }
1050    }
1051
1052    impl FromRawSocket for TcpSocket {
1053        /// Converts a `RawSocket` to a `TcpStream`.
1054        ///
1055        /// # Notes
1056        ///
1057        /// The caller is responsible for ensuring that the socket is in
1058        /// non-blocking mode.
1059        unsafe fn from_raw_socket(socket: RawSocket) -> TcpSocket {
1060            let inner = unsafe { socket2::Socket::from_raw_socket(socket) };
1061            TcpSocket { inner }
1062        }
1063    }
1064}