tokio/net/tcp/
socket.rs

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