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 /// let listener = socket.listen(1024)?;
72 /// # drop(listener);
73 ///
74 /// Ok(())
75 /// }
76 /// ```
77 ///
78 /// Setting socket options not explicitly provided by `TcpSocket` may be done by
79 /// accessing the `RawFd`/`RawSocket` using [`AsRawFd`]/[`AsRawSocket`] and
80 /// setting the option with a crate like [`socket2`].
81 ///
82 /// [`RawFd`]: https://doc.rust-lang.org/std/os/fd/type.RawFd.html
83 /// [`RawSocket`]: https://doc.rust-lang.org/std/os/windows/io/type.RawSocket.html
84 /// [`AsRawFd`]: https://doc.rust-lang.org/std/os/fd/trait.AsRawFd.html
85 /// [`AsRawSocket`]: https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html
86 /// [`socket2`]: https://docs.rs/socket2/
87 #[cfg_attr(docsrs, doc(alias = "connect_std"))]
88 pub struct TcpSocket {
89 inner: socket2::Socket,
90 }
91}
92
93impl TcpSocket {
94 /// Creates a new socket configured for IPv4.
95 ///
96 /// Calls `socket(2)` with `AF_INET` and `SOCK_STREAM`.
97 ///
98 /// # Returns
99 ///
100 /// On success, the newly created `TcpSocket` is returned. If an error is
101 /// encountered, it is returned instead.
102 ///
103 /// # Examples
104 ///
105 /// Create a new IPv4 socket and start listening.
106 ///
107 /// ```no_run
108 /// use tokio::net::TcpSocket;
109 ///
110 /// use std::io;
111 ///
112 /// #[tokio::main]
113 /// async fn main() -> io::Result<()> {
114 /// let addr = "127.0.0.1:8080".parse().unwrap();
115 /// let socket = TcpSocket::new_v4()?;
116 /// socket.bind(addr)?;
117 ///
118 /// let listener = socket.listen(128)?;
119 /// # drop(listener);
120 /// Ok(())
121 /// }
122 /// ```
123 pub fn new_v4() -> io::Result<TcpSocket> {
124 TcpSocket::new(socket2::Domain::IPV4)
125 }
126
127 /// Creates a new socket configured for IPv6.
128 ///
129 /// Calls `socket(2)` with `AF_INET6` and `SOCK_STREAM`.
130 ///
131 /// # Returns
132 ///
133 /// On success, the newly created `TcpSocket` is returned. If an error is
134 /// encountered, it is returned instead.
135 ///
136 /// # Examples
137 ///
138 /// Create a new IPv6 socket and start listening.
139 ///
140 /// ```no_run
141 /// use tokio::net::TcpSocket;
142 ///
143 /// use std::io;
144 ///
145 /// #[tokio::main]
146 /// async fn main() -> io::Result<()> {
147 /// let addr = "[::1]:8080".parse().unwrap();
148 /// let socket = TcpSocket::new_v6()?;
149 /// socket.bind(addr)?;
150 ///
151 /// let listener = socket.listen(128)?;
152 /// # drop(listener);
153 /// Ok(())
154 /// }
155 /// ```
156 pub fn new_v6() -> io::Result<TcpSocket> {
157 TcpSocket::new(socket2::Domain::IPV6)
158 }
159
160 fn new(domain: socket2::Domain) -> io::Result<TcpSocket> {
161 let ty = socket2::Type::STREAM;
162 #[cfg(any(
163 target_os = "android",
164 target_os = "dragonfly",
165 target_os = "freebsd",
166 target_os = "fuchsia",
167 target_os = "illumos",
168 target_os = "linux",
169 target_os = "netbsd",
170 target_os = "openbsd"
171 ))]
172 let ty = ty.nonblocking();
173 let inner = socket2::Socket::new(domain, ty, Some(socket2::Protocol::TCP))?;
174 #[cfg(not(any(
175 target_os = "android",
176 target_os = "dragonfly",
177 target_os = "freebsd",
178 target_os = "fuchsia",
179 target_os = "illumos",
180 target_os = "linux",
181 target_os = "netbsd",
182 target_os = "openbsd"
183 )))]
184 inner.set_nonblocking(true)?;
185 Ok(TcpSocket { inner })
186 }
187
188 /// Sets value for the `SO_KEEPALIVE` option on this socket.
189 pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
190 self.inner.set_keepalive(keepalive)
191 }
192
193 /// Gets the value of the `SO_KEEPALIVE` option on this socket.
194 pub fn keepalive(&self) -> io::Result<bool> {
195 self.inner.keepalive()
196 }
197
198 /// Allows the socket to bind to an in-use address.
199 ///
200 /// Behavior is platform specific. Refer to the target platform's
201 /// documentation for more details.
202 ///
203 /// # Examples
204 ///
205 /// ```no_run
206 /// use tokio::net::TcpSocket;
207 ///
208 /// use std::io;
209 ///
210 /// #[tokio::main]
211 /// async fn main() -> io::Result<()> {
212 /// let addr = "127.0.0.1:8080".parse().unwrap();
213 ///
214 /// let socket = TcpSocket::new_v4()?;
215 /// socket.set_reuseaddr(true)?;
216 /// socket.bind(addr)?;
217 ///
218 /// let listener = socket.listen(1024)?;
219 /// # drop(listener);
220 ///
221 /// Ok(())
222 /// }
223 /// ```
224 pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> {
225 self.inner.set_reuse_address(reuseaddr)
226 }
227
228 /// Retrieves the value set for `SO_REUSEADDR` on this socket.
229 ///
230 /// # Examples
231 ///
232 /// ```no_run
233 /// use tokio::net::TcpSocket;
234 ///
235 /// use std::io;
236 ///
237 /// #[tokio::main]
238 /// async fn main() -> io::Result<()> {
239 /// let addr = "127.0.0.1:8080".parse().unwrap();
240 ///
241 /// let socket = TcpSocket::new_v4()?;
242 /// socket.set_reuseaddr(true)?;
243 /// assert!(socket.reuseaddr().unwrap());
244 /// socket.bind(addr)?;
245 ///
246 /// let listener = socket.listen(1024)?;
247 /// Ok(())
248 /// }
249 /// ```
250 pub fn reuseaddr(&self) -> io::Result<bool> {
251 self.inner.reuse_address()
252 }
253
254 /// Allows the socket to bind to an in-use port. Only available for unix systems
255 /// (excluding Solaris & Illumos).
256 ///
257 /// Behavior is platform specific. Refer to the target platform's
258 /// documentation for more details.
259 ///
260 /// # Examples
261 ///
262 /// ```no_run
263 /// use tokio::net::TcpSocket;
264 ///
265 /// use std::io;
266 ///
267 /// #[tokio::main]
268 /// async fn main() -> io::Result<()> {
269 /// let addr = "127.0.0.1:8080".parse().unwrap();
270 ///
271 /// let socket = TcpSocket::new_v4()?;
272 /// socket.set_reuseport(true)?;
273 /// socket.bind(addr)?;
274 ///
275 /// let listener = socket.listen(1024)?;
276 /// Ok(())
277 /// }
278 /// ```
279 #[cfg(all(
280 unix,
281 not(target_os = "solaris"),
282 not(target_os = "illumos"),
283 not(target_os = "cygwin"),
284 ))]
285 #[cfg_attr(
286 docsrs,
287 doc(cfg(all(
288 unix,
289 not(target_os = "solaris"),
290 not(target_os = "illumos"),
291 not(target_os = "cygwin"),
292 )))
293 )]
294 pub fn set_reuseport(&self, reuseport: bool) -> io::Result<()> {
295 self.inner.set_reuse_port(reuseport)
296 }
297
298 /// Allows the socket to bind to an in-use port. Only available for unix systems
299 /// (excluding Solaris & Illumos).
300 ///
301 /// Behavior is platform specific. Refer to the target platform's
302 /// documentation for more details.
303 ///
304 /// # Examples
305 ///
306 /// ```no_run
307 /// use tokio::net::TcpSocket;
308 ///
309 /// use std::io;
310 ///
311 /// #[tokio::main]
312 /// async fn main() -> io::Result<()> {
313 /// let addr = "127.0.0.1:8080".parse().unwrap();
314 ///
315 /// let socket = TcpSocket::new_v4()?;
316 /// socket.set_reuseport(true)?;
317 /// assert!(socket.reuseport().unwrap());
318 /// socket.bind(addr)?;
319 ///
320 /// let listener = socket.listen(1024)?;
321 /// Ok(())
322 /// }
323 /// ```
324 #[cfg(all(
325 unix,
326 not(target_os = "solaris"),
327 not(target_os = "illumos"),
328 not(target_os = "cygwin"),
329 ))]
330 #[cfg_attr(
331 docsrs,
332 doc(cfg(all(
333 unix,
334 not(target_os = "solaris"),
335 not(target_os = "illumos"),
336 not(target_os = "cygwin"),
337 )))
338 )]
339 pub fn reuseport(&self) -> io::Result<bool> {
340 self.inner.reuse_port()
341 }
342
343 /// Sets the size of the TCP send buffer on this socket.
344 ///
345 /// On most operating systems, this sets the `SO_SNDBUF` socket option.
346 pub fn set_send_buffer_size(&self, size: u32) -> io::Result<()> {
347 self.inner.set_send_buffer_size(size as usize)
348 }
349
350 /// Returns the size of the TCP send buffer for this socket.
351 ///
352 /// On most operating systems, this is the value of the `SO_SNDBUF` socket
353 /// option.
354 ///
355 /// Note that if [`set_send_buffer_size`] has been called on this socket
356 /// previously, the value returned by this function may not be the same as
357 /// the argument provided to `set_send_buffer_size`. This is for the
358 /// following reasons:
359 ///
360 /// * Most operating systems have minimum and maximum allowed sizes for the
361 /// send buffer, and will clamp the provided value if it is below the
362 /// minimum or above the maximum. The minimum and maximum buffer sizes are
363 /// OS-dependent.
364 /// * Linux will double the buffer size to account for internal bookkeeping
365 /// data, and returns the doubled value from `getsockopt(2)`. As per `man
366 /// 7 socket`:
367 /// > Sets or gets the maximum socket send buffer in bytes. The
368 /// > kernel doubles this value (to allow space for bookkeeping
369 /// > overhead) when it is set using `setsockopt(2)`, and this doubled
370 /// > value is returned by `getsockopt(2)`.
371 ///
372 /// [`set_send_buffer_size`]: #method.set_send_buffer_size
373 pub fn send_buffer_size(&self) -> io::Result<u32> {
374 self.inner.send_buffer_size().map(|n| n as u32)
375 }
376
377 /// Sets the size of the TCP receive buffer on this socket.
378 ///
379 /// On most operating systems, this sets the `SO_RCVBUF` socket option.
380 pub fn set_recv_buffer_size(&self, size: u32) -> io::Result<()> {
381 self.inner.set_recv_buffer_size(size as usize)
382 }
383
384 /// Returns the size of the TCP receive buffer for this socket.
385 ///
386 /// On most operating systems, this is the value of the `SO_RCVBUF` socket
387 /// option.
388 ///
389 /// Note that if [`set_recv_buffer_size`] has been called on this socket
390 /// previously, the value returned by this function may not be the same as
391 /// the argument provided to `set_recv_buffer_size`. This is for the
392 /// following reasons:
393 ///
394 /// * Most operating systems have minimum and maximum allowed sizes for the
395 /// receive buffer, and will clamp the provided value if it is below the
396 /// minimum or above the maximum. The minimum and maximum buffer sizes are
397 /// OS-dependent.
398 /// * Linux will double the buffer size to account for internal bookkeeping
399 /// data, and returns the doubled value from `getsockopt(2)`. As per `man
400 /// 7 socket`:
401 /// > Sets or gets the maximum socket send buffer in bytes. The
402 /// > kernel doubles this value (to allow space for bookkeeping
403 /// > overhead) when it is set using `setsockopt(2)`, and this doubled
404 /// > value is returned by `getsockopt(2)`.
405 ///
406 /// [`set_recv_buffer_size`]: #method.set_recv_buffer_size
407 pub fn recv_buffer_size(&self) -> io::Result<u32> {
408 self.inner.recv_buffer_size().map(|n| n as u32)
409 }
410
411 /// Sets the linger duration of this socket by setting the `SO_LINGER` option.
412 ///
413 /// This option controls the action taken when a stream has unsent messages and the stream is
414 /// closed. If `SO_LINGER` is set, the system shall block the process until it can transmit the
415 /// data or until the time expires.
416 ///
417 /// If `SO_LINGER` is not specified, and the socket is closed, the system handles the call in a
418 /// way that allows the process to continue as quickly as possible.
419 pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
420 self.inner.set_linger(dur)
421 }
422
423 /// Reads the linger duration for this socket by getting the `SO_LINGER`
424 /// option.
425 ///
426 /// For more information about this option, see [`set_linger`].
427 ///
428 /// [`set_linger`]: TcpSocket::set_linger
429 pub fn linger(&self) -> io::Result<Option<Duration>> {
430 self.inner.linger()
431 }
432
433 /// Sets the value of the `TCP_NODELAY` option on this socket.
434 ///
435 /// If set, this option disables the Nagle algorithm. This means that segments are always
436 /// sent as soon as possible, even if there is only a small amount of data. When not set,
437 /// data is buffered until there is a sufficient amount to send out, thereby avoiding
438 /// the frequent sending of small packets.
439 ///
440 /// # Examples
441 ///
442 /// ```no_run
443 /// use tokio::net::TcpSocket;
444 ///
445 /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
446 /// let socket = TcpSocket::new_v4()?;
447 ///
448 /// socket.set_nodelay(true)?;
449 /// # Ok(())
450 /// # }
451 /// ```
452 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
453 self.inner.set_nodelay(nodelay)
454 }
455
456 /// Gets the value of the `TCP_NODELAY` option on this socket.
457 ///
458 /// For more information about this option, see [`set_nodelay`].
459 ///
460 /// [`set_nodelay`]: TcpSocket::set_nodelay
461 ///
462 /// # Examples
463 ///
464 /// ```no_run
465 /// use tokio::net::TcpSocket;
466 ///
467 /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
468 /// let socket = TcpSocket::new_v4()?;
469 ///
470 /// println!("{:?}", socket.nodelay()?);
471 /// # Ok(())
472 /// # }
473 /// ```
474 pub fn nodelay(&self) -> io::Result<bool> {
475 self.inner.nodelay()
476 }
477
478 /// Gets the value of the `IP_TOS` option for this socket.
479 ///
480 /// For more information about this option, see [`set_tos`].
481 ///
482 /// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
483 /// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
484 ///
485 /// [`set_tos`]: Self::set_tos
486 // https://docs.rs/socket2/0.5.3/src/socket2/socket.rs.html#1464
487 #[cfg(not(any(
488 target_os = "fuchsia",
489 target_os = "redox",
490 target_os = "solaris",
491 target_os = "illumos",
492 target_os = "haiku"
493 )))]
494 #[cfg_attr(
495 docsrs,
496 doc(cfg(not(any(
497 target_os = "fuchsia",
498 target_os = "redox",
499 target_os = "solaris",
500 target_os = "illumos",
501 target_os = "haiku"
502 ))))
503 )]
504 pub fn tos(&self) -> io::Result<u32> {
505 self.inner.tos()
506 }
507
508 /// Sets the value for the `IP_TOS` option on this socket.
509 ///
510 /// This value sets the type-of-service field that is used in every packet
511 /// sent from this socket.
512 ///
513 /// **NOTE:** On Windows, `IP_TOS` is only supported on [Windows 8+ or
514 /// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options)
515 // https://docs.rs/socket2/0.5.3/src/socket2/socket.rs.html#1446
516 #[cfg(not(any(
517 target_os = "fuchsia",
518 target_os = "redox",
519 target_os = "solaris",
520 target_os = "illumos",
521 target_os = "haiku"
522 )))]
523 #[cfg_attr(
524 docsrs,
525 doc(cfg(not(any(
526 target_os = "fuchsia",
527 target_os = "redox",
528 target_os = "solaris",
529 target_os = "illumos",
530 target_os = "haiku"
531 ))))
532 )]
533 pub fn set_tos(&self, tos: u32) -> io::Result<()> {
534 self.inner.set_tos(tos)
535 }
536
537 /// Gets the value for the `SO_BINDTODEVICE` option on this socket
538 ///
539 /// This value gets the socket binded device's interface name.
540 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
541 #[cfg_attr(
542 docsrs,
543 doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",)))
544 )]
545 pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
546 self.inner.device()
547 }
548
549 /// Sets the value for the `SO_BINDTODEVICE` option on this socket
550 ///
551 /// If a socket is bound to an interface, only packets received from that
552 /// particular interface are processed by the socket. Note that this only
553 /// works for some socket types, particularly `AF_INET` sockets.
554 ///
555 /// If `interface` is `None` or an empty string it removes the binding.
556 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
557 #[cfg_attr(
558 docsrs,
559 doc(cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))))
560 )]
561 pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
562 self.inner.bind_device(interface)
563 }
564
565 /// Gets the local address of this socket.
566 ///
567 /// Will fail on windows if called before `bind`.
568 ///
569 /// # Examples
570 ///
571 /// ```no_run
572 /// use tokio::net::TcpSocket;
573 ///
574 /// use std::io;
575 ///
576 /// #[tokio::main]
577 /// async fn main() -> io::Result<()> {
578 /// let addr = "127.0.0.1:8080".parse().unwrap();
579 ///
580 /// let socket = TcpSocket::new_v4()?;
581 /// socket.bind(addr)?;
582 /// assert_eq!(socket.local_addr().unwrap().to_string(), "127.0.0.1:8080");
583 /// let listener = socket.listen(1024)?;
584 /// Ok(())
585 /// }
586 /// ```
587 pub fn local_addr(&self) -> io::Result<SocketAddr> {
588 self.inner.local_addr().and_then(convert_address)
589 }
590
591 /// Returns the value of the `SO_ERROR` option.
592 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
593 self.inner.take_error()
594 }
595
596 /// Binds the socket to the given address.
597 ///
598 /// This calls the `bind(2)` operating-system function. Behavior is
599 /// platform specific. Refer to the target platform's documentation for more
600 /// details.
601 ///
602 /// # Examples
603 ///
604 /// Bind a socket before listening.
605 ///
606 /// ```no_run
607 /// use tokio::net::TcpSocket;
608 ///
609 /// use std::io;
610 ///
611 /// #[tokio::main]
612 /// async fn main() -> io::Result<()> {
613 /// let addr = "127.0.0.1:8080".parse().unwrap();
614 ///
615 /// let socket = TcpSocket::new_v4()?;
616 /// socket.bind(addr)?;
617 ///
618 /// let listener = socket.listen(1024)?;
619 /// # drop(listener);
620 ///
621 /// Ok(())
622 /// }
623 /// ```
624 pub fn bind(&self, addr: SocketAddr) -> io::Result<()> {
625 self.inner.bind(&addr.into())
626 }
627
628 /// Establishes a TCP connection with a peer at the specified socket address.
629 ///
630 /// The `TcpSocket` is consumed. Once the connection is established, a
631 /// connected [`TcpStream`] is returned. If the connection fails, the
632 /// encountered error is returned.
633 ///
634 /// [`TcpStream`]: TcpStream
635 ///
636 /// This calls the `connect(2)` operating-system function. Behavior is
637 /// platform specific. Refer to the target platform's documentation for more
638 /// details.
639 ///
640 /// # Examples
641 ///
642 /// Connecting to a peer.
643 ///
644 /// ```no_run
645 /// use tokio::net::TcpSocket;
646 ///
647 /// use std::io;
648 ///
649 /// #[tokio::main]
650 /// async fn main() -> io::Result<()> {
651 /// let addr = "127.0.0.1:8080".parse().unwrap();
652 ///
653 /// let socket = TcpSocket::new_v4()?;
654 /// let stream = socket.connect(addr).await?;
655 /// # drop(stream);
656 ///
657 /// Ok(())
658 /// }
659 /// ```
660 pub async fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
661 if let Err(err) = self.inner.connect(&addr.into()) {
662 #[cfg(unix)]
663 if err.raw_os_error() != Some(libc::EINPROGRESS) {
664 return Err(err);
665 }
666 #[cfg(windows)]
667 if err.kind() != io::ErrorKind::WouldBlock {
668 return Err(err);
669 }
670 }
671 #[cfg(unix)]
672 let mio = {
673 use std::os::unix::io::{FromRawFd, IntoRawFd};
674
675 let raw_fd = self.inner.into_raw_fd();
676 unsafe { mio::net::TcpStream::from_raw_fd(raw_fd) }
677 };
678
679 #[cfg(windows)]
680 let mio = {
681 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
682
683 let raw_socket = self.inner.into_raw_socket();
684 unsafe { mio::net::TcpStream::from_raw_socket(raw_socket) }
685 };
686
687 TcpStream::connect_mio(mio).await
688 }
689
690 /// Converts the socket into a `TcpListener`.
691 ///
692 /// `backlog` defines the maximum number of pending connections are queued
693 /// by the operating system at any given time. Connection are removed from
694 /// the queue with [`TcpListener::accept`]. When the queue is full, the
695 /// operating-system will start rejecting connections.
696 ///
697 /// [`TcpListener::accept`]: TcpListener::accept
698 ///
699 /// This calls the `listen(2)` operating-system function, marking the socket
700 /// as a passive socket. Behavior is platform specific. Refer to the target
701 /// platform's documentation for more details.
702 ///
703 /// # Examples
704 ///
705 /// Create a `TcpListener`.
706 ///
707 /// ```no_run
708 /// use tokio::net::TcpSocket;
709 ///
710 /// use std::io;
711 ///
712 /// #[tokio::main]
713 /// async fn main() -> io::Result<()> {
714 /// let addr = "127.0.0.1:8080".parse().unwrap();
715 ///
716 /// let socket = TcpSocket::new_v4()?;
717 /// socket.bind(addr)?;
718 ///
719 /// let listener = socket.listen(1024)?;
720 /// # drop(listener);
721 ///
722 /// Ok(())
723 /// }
724 /// ```
725 pub fn listen(self, backlog: u32) -> io::Result<TcpListener> {
726 self.inner.listen(backlog as i32)?;
727 #[cfg(unix)]
728 let mio = {
729 use std::os::unix::io::{FromRawFd, IntoRawFd};
730
731 let raw_fd = self.inner.into_raw_fd();
732 unsafe { mio::net::TcpListener::from_raw_fd(raw_fd) }
733 };
734
735 #[cfg(windows)]
736 let mio = {
737 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
738
739 let raw_socket = self.inner.into_raw_socket();
740 unsafe { mio::net::TcpListener::from_raw_socket(raw_socket) }
741 };
742
743 TcpListener::new(mio)
744 }
745
746 /// Converts a [`std::net::TcpStream`] into a `TcpSocket`. The provided
747 /// socket must not have been connected prior to calling this function. This
748 /// function is typically used together with crates such as [`socket2`] to
749 /// configure socket options that are not available on `TcpSocket`.
750 ///
751 /// [`std::net::TcpStream`]: struct@std::net::TcpStream
752 /// [`socket2`]: https://docs.rs/socket2/
753 ///
754 /// # Notes
755 ///
756 /// The caller is responsible for ensuring that the socket is in
757 /// non-blocking mode. Otherwise all I/O operations on the socket
758 /// will block the thread, which will cause unexpected behavior.
759 /// Non-blocking mode can be set using [`set_nonblocking`].
760 ///
761 /// [`set_nonblocking`]: std::net::TcpStream::set_nonblocking
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// use tokio::net::TcpSocket;
767 /// use socket2::{Domain, Socket, Type};
768 ///
769 /// #[tokio::main]
770 /// async fn main() -> std::io::Result<()> {
771 /// # if cfg!(miri) { return Ok(()); } // No `socket` in miri.
772 /// let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
773 /// socket2_socket.set_nonblocking(true)?;
774 ///
775 /// let socket = TcpSocket::from_std_stream(socket2_socket.into());
776 ///
777 /// Ok(())
778 /// }
779 /// ```
780 pub fn from_std_stream(std_stream: std::net::TcpStream) -> TcpSocket {
781 #[cfg(unix)]
782 {
783 use std::os::unix::io::{FromRawFd, IntoRawFd};
784
785 let raw_fd = std_stream.into_raw_fd();
786 unsafe { TcpSocket::from_raw_fd(raw_fd) }
787 }
788
789 #[cfg(windows)]
790 {
791 use std::os::windows::io::{FromRawSocket, IntoRawSocket};
792
793 let raw_socket = std_stream.into_raw_socket();
794 unsafe { TcpSocket::from_raw_socket(raw_socket) }
795 }
796 }
797}
798
799fn convert_address(address: socket2::SockAddr) -> io::Result<SocketAddr> {
800 match address.as_socket() {
801 Some(address) => Ok(address),
802 None => Err(io::Error::new(
803 io::ErrorKind::InvalidInput,
804 "invalid address family (not IPv4 or IPv6)",
805 )),
806 }
807}
808
809impl fmt::Debug for TcpSocket {
810 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
811 self.inner.fmt(fmt)
812 }
813}
814
815// These trait implementations can't be build on Windows, so we completely
816// ignore them, even when building documentation.
817#[cfg(unix)]
818cfg_unix! {
819 impl AsRawFd for TcpSocket {
820 fn as_raw_fd(&self) -> RawFd {
821 self.inner.as_raw_fd()
822 }
823 }
824
825 impl AsFd for TcpSocket {
826 fn as_fd(&self) -> BorrowedFd<'_> {
827 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
828 }
829 }
830
831 impl FromRawFd for TcpSocket {
832 /// Converts a `RawFd` to a `TcpSocket`.
833 ///
834 /// # Notes
835 ///
836 /// The caller is responsible for ensuring that the socket is in
837 /// non-blocking mode.
838 unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
839 let inner = socket2::Socket::from_raw_fd(fd);
840 TcpSocket { inner }
841 }
842 }
843
844 impl IntoRawFd for TcpSocket {
845 fn into_raw_fd(self) -> RawFd {
846 self.inner.into_raw_fd()
847 }
848 }
849}
850
851cfg_windows! {
852 impl IntoRawSocket for TcpSocket {
853 fn into_raw_socket(self) -> RawSocket {
854 self.inner.into_raw_socket()
855 }
856 }
857
858 impl AsRawSocket for TcpSocket {
859 fn as_raw_socket(&self) -> RawSocket {
860 self.inner.as_raw_socket()
861 }
862 }
863
864 impl AsSocket for TcpSocket {
865 fn as_socket(&self) -> BorrowedSocket<'_> {
866 unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
867 }
868 }
869
870 impl FromRawSocket for TcpSocket {
871 /// Converts a `RawSocket` to a `TcpStream`.
872 ///
873 /// # Notes
874 ///
875 /// The caller is responsible for ensuring that the socket is in
876 /// non-blocking mode.
877 unsafe fn from_raw_socket(socket: RawSocket) -> TcpSocket {
878 let inner = socket2::Socket::from_raw_socket(socket);
879 TcpSocket { inner }
880 }
881 }
882}