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