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}