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}