diff --git a/tokio/src/net/tcp/listener.rs b/tokio/src/net/tcp/listener.rs index 1ff094964b9..5c093bb76cd 100644 --- a/tokio/src/net/tcp/listener.rs +++ b/tokio/src/net/tcp/listener.rs @@ -192,7 +192,6 @@ impl TcpListener { /// backing event loop. This allows configuration of options like /// `SO_REUSEPORT`, binding to multiple addresses, etc. /// - /// /// # Examples /// /// ```rust,no_run @@ -221,6 +220,48 @@ impl TcpListener { Ok(TcpListener { io }) } + /// Turn a [`tokio::net::TcpListener`] into a [`std::net::TcpListener`]. + /// + /// The returned [`std::net::TcpListener`] will have nonblocking mode set as + /// `true`. Use [`set_nonblocking`] to change the blocking mode if needed. + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::error::Error; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let tokio_listener = tokio::net::TcpListener::bind("127.0.0.1:0").await?; + /// let std_listener = tokio_listener.into_std()?; + /// std_listener.set_nonblocking(false)?; + /// Ok(()) + /// } + /// ``` + /// + /// [`tokio::net::TcpListener`]: TcpListener + /// [`std::net::TcpListener`]: std::net::TcpListener + /// [`set_nonblocking`]: fn@std::net::TcpListener::set_nonblocking + pub fn into_std(self) -> io::Result { + #[cfg(unix)] + { + use std::os::unix::io::{FromRawFd, IntoRawFd}; + self.io + .into_inner() + .map(|io| io.into_raw_fd()) + .map(|raw_fd| unsafe { std::net::TcpListener::from_raw_fd(raw_fd) }) + } + + #[cfg(windows)] + { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + self.io + .into_inner() + .map(|io| io.into_raw_socket()) + .map(|raw_socket| unsafe { std::net::TcpListener::from_raw_socket(raw_socket) }) + } + } + pub(crate) fn new(listener: mio::net::TcpListener) -> io::Result { let io = PollEvented::new(listener)?; Ok(TcpListener { io }) diff --git a/tokio/src/net/tcp/stream.rs b/tokio/src/net/tcp/stream.rs index 91e357f4445..e231e5d83c4 100644 --- a/tokio/src/net/tcp/stream.rs +++ b/tokio/src/net/tcp/stream.rs @@ -8,11 +8,6 @@ use std::convert::TryFrom; use std::fmt; use std::io; use std::net::{Shutdown, SocketAddr}; -#[cfg(windows)] -use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket}; - -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; @@ -199,7 +194,7 @@ impl TcpStream { /// Turn a [`tokio::net::TcpStream`] into a [`std::net::TcpStream`]. /// - /// The returned [`std::net::TcpStream`] will have `nonblocking mode` set as `true`. + /// The returned [`std::net::TcpStream`] will have nonblocking mode set as `true`. /// Use [`set_nonblocking`] to change the blocking mode if needed. /// /// # Examples @@ -234,6 +229,7 @@ impl TcpStream { pub fn into_std(self) -> io::Result { #[cfg(unix)] { + use std::os::unix::io::{FromRawFd, IntoRawFd}; self.io .into_inner() .map(|io| io.into_raw_fd()) @@ -242,6 +238,7 @@ impl TcpStream { #[cfg(windows)] { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; self.io .into_inner() .map(|io| io.into_raw_socket()) @@ -932,11 +929,13 @@ impl TcpStream { fn to_mio(&self) -> mio::net::TcpSocket { #[cfg(windows)] { + use std::os::windows::io::{AsRawSocket, FromRawSocket}; unsafe { mio::net::TcpSocket::from_raw_socket(self.as_raw_socket()) } } #[cfg(unix)] { + use std::os::unix::io::{AsRawFd, FromRawFd}; unsafe { mio::net::TcpSocket::from_raw_fd(self.as_raw_fd()) } } } diff --git a/tokio/src/net/udp.rs b/tokio/src/net/udp.rs index 86b4fe9ce0d..2b0394112be 100644 --- a/tokio/src/net/udp.rs +++ b/tokio/src/net/udp.rs @@ -209,6 +209,48 @@ impl UdpSocket { UdpSocket::new(io) } + /// Turn a [`tokio::net::UdpSocket`] into a [`std::net::UdpSocket`]. + /// + /// The returned [`std::net::UdpSocket`] will have nonblocking mode set as + /// `true`. Use [`set_nonblocking`] to change the blocking mode if needed. + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::error::Error; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let tokio_socket = tokio::net::UdpSocket::bind("127.0.0.1:0").await?; + /// let std_socket = tokio_socket.into_std()?; + /// std_socket.set_nonblocking(false)?; + /// Ok(()) + /// } + /// ``` + /// + /// [`tokio::net::UdpSocket`]: UdpSocket + /// [`std::net::UdpSocket`]: std::net::UdpSocket + /// [`set_nonblocking`]: fn@std::net::UdpSocket::set_nonblocking + pub fn into_std(self) -> io::Result { + #[cfg(unix)] + { + use std::os::unix::io::{FromRawFd, IntoRawFd}; + self.io + .into_inner() + .map(|io| io.into_raw_fd()) + .map(|raw_fd| unsafe { std::net::UdpSocket::from_raw_fd(raw_fd) }) + } + + #[cfg(windows)] + { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + self.io + .into_inner() + .map(|io| io.into_raw_socket()) + .map(|raw_socket| unsafe { std::net::UdpSocket::from_raw_socket(raw_socket) }) + } + } + /// Returns the local address that this socket is bound to. /// /// # Example diff --git a/tokio/src/net/unix/datagram/socket.rs b/tokio/src/net/unix/datagram/socket.rs index 126a243279c..6bc5615917c 100644 --- a/tokio/src/net/unix/datagram/socket.rs +++ b/tokio/src/net/unix/datagram/socket.rs @@ -5,7 +5,7 @@ use std::convert::TryFrom; use std::fmt; use std::io; use std::net::Shutdown; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; use std::task::{Context, Poll}; @@ -376,6 +376,36 @@ impl UnixDatagram { Ok(UnixDatagram { io }) } + /// Turn a [`tokio::net::UnixDatagram`] into a [`std::os::unix::net::UnixDatagram`]. + /// + /// The returned [`std::os::unix::net::UnixDatagram`] will have nonblocking + /// mode set as `true`. Use [`set_nonblocking`] to change the blocking mode + /// if needed. + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::error::Error; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let tokio_socket = tokio::net::UnixDatagram::bind("127.0.0.1:0")?; + /// let std_socket = tokio_socket.into_std()?; + /// std_socket.set_nonblocking(false)?; + /// Ok(()) + /// } + /// ``` + /// + /// [`tokio::net::UnixDatagram`]: UnixDatagram + /// [`std::os::unix::net::UnixDatagram`]: std::os::unix::net::UnixDatagram + /// [`set_nonblocking`]: fn@std::os::unix::net::UnixDatagram::set_nonblocking + pub fn into_std(self) -> io::Result { + self.io + .into_inner() + .map(|io| io.into_raw_fd()) + .map(|raw_fd| unsafe { std::os::unix::net::UnixDatagram::from_raw_fd(raw_fd) }) + } + fn new(socket: mio::net::UnixDatagram) -> io::Result { let io = PollEvented::new(socket)?; Ok(UnixDatagram { io }) diff --git a/tokio/src/net/unix/listener.rs b/tokio/src/net/unix/listener.rs index d1c063e729f..b5b05a6935d 100644 --- a/tokio/src/net/unix/listener.rs +++ b/tokio/src/net/unix/listener.rs @@ -4,7 +4,7 @@ use crate::net::unix::{SocketAddr, UnixStream}; use std::convert::TryFrom; use std::fmt; use std::io; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; use std::task::{Context, Poll}; @@ -88,6 +88,35 @@ impl UnixListener { Ok(UnixListener { io }) } + /// Turn a [`tokio::net::UnixListener`] into a [`std::os::unix::net::UnixListener`]. + /// + /// The returned [`std::os::unix::net::UnixListener`] will have nonblocking mode + /// set as `true`. Use [`set_nonblocking`] to change the blocking mode if needed. + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::error::Error; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let tokio_listener = tokio::net::UnixListener::bind("127.0.0.1:0")?; + /// let std_listener = tokio_listener.into_std()?; + /// std_listener.set_nonblocking(false)?; + /// Ok(()) + /// } + /// ``` + /// + /// [`tokio::net::UnixListener`]: UnixListener + /// [`std::os::unix::net::UnixListener`]: std::os::unix::net::UnixListener + /// [`set_nonblocking`]: fn@std::os::unix::net::UnixListener::set_nonblocking + pub fn into_std(self) -> io::Result { + self.io + .into_inner() + .map(|io| io.into_raw_fd()) + .map(|raw_fd| unsafe { net::UnixListener::from_raw_fd(raw_fd) }) + } + /// Returns the local socket address of this listener. pub fn local_addr(&self) -> io::Result { self.io.local_addr().map(SocketAddr) diff --git a/tokio/src/net/unix/stream.rs b/tokio/src/net/unix/stream.rs index a3e3487e243..d797aae0700 100644 --- a/tokio/src/net/unix/stream.rs +++ b/tokio/src/net/unix/stream.rs @@ -9,7 +9,7 @@ use std::convert::TryFrom; use std::fmt; use std::io::{self, Read, Write}; use std::net::Shutdown; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::os::unix::net; use std::path::Path; use std::pin::Pin; @@ -508,6 +508,51 @@ impl UnixStream { Ok(UnixStream { io }) } + /// Turn a [`tokio::net::UnixStream`] into a [`std::os::unix::net::UnixStream`]. + /// + /// The returned [`std::os::unix::net::UnixStream`] will have nonblocking + /// mode set as `true`. Use [`set_nonblocking`] to change the blocking + /// mode if needed. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::io::Read; + /// use tokio::net::UnixListener; + /// # use tokio::net::UnixStream; + /// # use tokio::io::AsyncWriteExt; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// + /// let mut data = [0u8; 12]; + /// let listener = UnixListener::bind(&bind_path)?; + /// # let handle = tokio::spawn(async { + /// # let mut stream = UnixStream::connect(bind_path).await.unwrap(); + /// # stream.write(b"Hello world!").await.unwrap(); + /// # }); + /// let (tokio_unix_stream, _) = listener.accept().await?; + /// let mut std_unix_stream = tokio_unix_stream.into_std()?; + /// # handle.await.expect("The task being joined has panicked"); + /// std_unix_stream.set_nonblocking(false)?; + /// std_unix_stream.read_exact(&mut data)?; + /// # assert_eq!(b"Hello world!", &data); + /// Ok(()) + /// } + /// ``` + /// [`tokio::net::UnixStream`]: UnixStream + /// [`std::os::unix::net::UnixStream`]: std::os::unix::net::UnixStream + /// [`set_nonblocking`]: fn@std::os::unix::net::UnixStream::set_nonblocking + pub fn into_std(self) -> io::Result { + self.io + .into_inner() + .map(|io| io.into_raw_fd()) + .map(|raw_fd| unsafe { std::os::unix::net::UnixStream::from_raw_fd(raw_fd) }) + } + /// Creates an unnamed pair of connected sockets. /// /// This function will create a pair of interconnected Unix sockets for