From 28eb241e0697ed0f6950c10ff0ab3117c6511a3a Mon Sep 17 00:00:00 2001 From: Atul Jatia Date: Sat, 5 Jun 2021 13:03:17 +0530 Subject: [PATCH 1/5] convert std TcpStream into TcpSocket --- tokio/src/net/tcp/socket.rs | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 4bcbe3f08ae..506ce8f4bb6 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -482,6 +482,48 @@ impl TcpSocket { let mio = self.inner.listen(backlog)?; TcpListener::new(mio) } + + /// Converts a TcpStream into a TcpSocket + /// This converts the TcpStream into + /// the platform specific raw_fd(unix) / raw_socket(windows) + /// and then converts them into the TcpSocket + /// as TcpSocket implements the FromRawFd(unix) and + /// FromRawSocket(windows) traits. + + /// # Examples + /// ``` + /// use tokio::net::TcpSocket; + /// + /// use std::net::TcpStream; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// + /// let stream = TcpStream::connect("127.0.0.1:8080")?; + /// + /// let socket = TcpSocket::from_std_stream(stream)?; + /// # drop(socket); + /// + /// Ok(()) + /// } + /// ``` + pub fn from_std_stream(std_stream: std::net::TcpStream) -> io::Result { + #[cfg(unix)] + { + use std::os::unix::io::{FromRawFd, IntoRawFd}; + + let raw_fd = std_stream.into_raw_fd(); + unsafe { Ok(TcpSocket::from_raw_fd(raw_fd)) } + } + + #[cfg(windows)] + { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + + let raw_socket = std_stream.into_raw_socket(); + unsafe { Ok(TcpSocket::from_raw_socket(raw_socket)) } + } + } } impl fmt::Debug for TcpSocket { From bab7c2ca3ee8bbcbd8e8c721dbd0cb0dacf81d98 Mon Sep 17 00:00:00 2001 From: Atul Jatia Date: Sat, 5 Jun 2021 13:03:17 +0530 Subject: [PATCH 2/5] convert std TcpStream into TcpSocket This converts the TcpStream into the platform specific raw_fd(unix) / raw_socket(windows) and then converts them into the TcpSocket as TcpSocket implements the FromRawFd(unix) and FromRawSocket(windows) traits. Fixes: #3734 --- tokio/src/net/tcp/socket.rs | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 4bcbe3f08ae..506ce8f4bb6 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -482,6 +482,48 @@ impl TcpSocket { let mio = self.inner.listen(backlog)?; TcpListener::new(mio) } + + /// Converts a TcpStream into a TcpSocket + /// This converts the TcpStream into + /// the platform specific raw_fd(unix) / raw_socket(windows) + /// and then converts them into the TcpSocket + /// as TcpSocket implements the FromRawFd(unix) and + /// FromRawSocket(windows) traits. + + /// # Examples + /// ``` + /// use tokio::net::TcpSocket; + /// + /// use std::net::TcpStream; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// + /// let stream = TcpStream::connect("127.0.0.1:8080")?; + /// + /// let socket = TcpSocket::from_std_stream(stream)?; + /// # drop(socket); + /// + /// Ok(()) + /// } + /// ``` + pub fn from_std_stream(std_stream: std::net::TcpStream) -> io::Result { + #[cfg(unix)] + { + use std::os::unix::io::{FromRawFd, IntoRawFd}; + + let raw_fd = std_stream.into_raw_fd(); + unsafe { Ok(TcpSocket::from_raw_fd(raw_fd)) } + } + + #[cfg(windows)] + { + use std::os::windows::io::{FromRawSocket, IntoRawSocket}; + + let raw_socket = std_stream.into_raw_socket(); + unsafe { Ok(TcpSocket::from_raw_socket(raw_socket)) } + } + } } impl fmt::Debug for TcpSocket { From 309036d277c5802fdf6f90e3bab8d3efc2e7d061 Mon Sep 17 00:00:00 2001 From: Atul Jatia Date: Tue, 8 Jun 2021 23:37:44 +0530 Subject: [PATCH 3/5] Review changes --- tokio/src/net/tcp/socket.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 506ce8f4bb6..44dd8607b81 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -483,37 +483,36 @@ impl TcpSocket { TcpListener::new(mio) } - /// Converts a TcpStream into a TcpSocket - /// This converts the TcpStream into - /// the platform specific raw_fd(unix) / raw_socket(windows) - /// and then converts them into the TcpSocket - /// as TcpSocket implements the FromRawFd(unix) and - /// FromRawSocket(windows) traits. - + /// Converts a `socket2::Socket` into a `TcpSocket`. The socket2 socket + /// needs to be in a disconnected state when passed as an argument. + /// /// # Examples + /// /// ``` /// use tokio::net::TcpSocket; - /// + /// use socket2::{Domain, Socket, Type}; /// use std::net::TcpStream; /// /// #[tokio::main] /// async fn main() -> io::Result<()> { /// - /// let stream = TcpStream::connect("127.0.0.1:8080")?; - /// + /// let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; + /// + /// let stream = TcpStream::from(socket2_socket); + /// /// let socket = TcpSocket::from_std_stream(stream)?; /// # drop(socket); /// /// Ok(()) /// } /// ``` - pub fn from_std_stream(std_stream: std::net::TcpStream) -> io::Result { + pub fn from_std_stream(std_stream: std::net::TcpStream) -> TcpSocket { #[cfg(unix)] { use std::os::unix::io::{FromRawFd, IntoRawFd}; let raw_fd = std_stream.into_raw_fd(); - unsafe { Ok(TcpSocket::from_raw_fd(raw_fd)) } + unsafe { TcpSocket::from_raw_fd(raw_fd) } } #[cfg(windows)] @@ -521,7 +520,7 @@ impl TcpSocket { use std::os::windows::io::{FromRawSocket, IntoRawSocket}; let raw_socket = std_stream.into_raw_socket(); - unsafe { Ok(TcpSocket::from_raw_socket(raw_socket)) } + unsafe { TcpSocket::from_raw_socket(raw_socket) } } } } From 629876ac04a7fb0ba652d350e96753be0c0d80be Mon Sep 17 00:00:00 2001 From: Atul Jatia Date: Thu, 10 Jun 2021 21:02:59 +0530 Subject: [PATCH 4/5] Review changes --- tokio/src/net/tcp/socket.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 44dd8607b81..564bb94fc71 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -483,25 +483,27 @@ impl TcpSocket { TcpListener::new(mio) } - /// Converts a `socket2::Socket` into a `TcpSocket`. The socket2 socket - /// needs to be in a disconnected state when passed as an argument. - /// + /// Converts a [`std::net::TcpStream`] into a `TcpSocket`. The provided + /// socket must not have been connected prior to calling this function. This + /// function is typically used together with crates such as [`socket2`] to + /// configure socket options that are not available on `TcpSocket`. + /// + /// [`std::net::TcpStream`]: struct@std::net::TcpStream + /// [`socket2`]: https://docs.rs/socket2/ + /// /// # Examples - /// + /// /// ``` /// use tokio::net::TcpSocket; /// use socket2::{Domain, Socket, Type}; /// use std::net::TcpStream; /// /// #[tokio::main] - /// async fn main() -> io::Result<()> { - /// + /// async fn main() -> std::io::Result<()> { + /// /// let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; - /// - /// let stream = TcpStream::from(socket2_socket); - /// - /// let socket = TcpSocket::from_std_stream(stream)?; - /// # drop(socket); + /// + /// let socket = TcpSocket::from_std_stream(socket2_socket.into())?; /// /// Ok(()) /// } From 8057f89d7642d32ca1ec5dbeb48096216e277833 Mon Sep 17 00:00:00 2001 From: Atul Jatia Date: Thu, 10 Jun 2021 23:59:17 +0530 Subject: [PATCH 5/5] Fixed documentation tests --- tokio/Cargo.toml | 1 + tokio/src/net/tcp/socket.rs | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tokio/Cargo.toml b/tokio/Cargo.toml index 7e82c7850db..07134570459 100644 --- a/tokio/Cargo.toml +++ b/tokio/Cargo.toml @@ -123,6 +123,7 @@ proptest = "1" rand = "0.8.0" tempfile = "3.1.0" async-stream = "0.3" +socket2 = "0.4" [target.'cfg(loom)'.dev-dependencies] loom = { version = "0.5", features = ["futures", "checkpoint"] } diff --git a/tokio/src/net/tcp/socket.rs b/tokio/src/net/tcp/socket.rs index 564bb94fc71..02cb6377e1d 100644 --- a/tokio/src/net/tcp/socket.rs +++ b/tokio/src/net/tcp/socket.rs @@ -496,14 +496,13 @@ impl TcpSocket { /// ``` /// use tokio::net::TcpSocket; /// use socket2::{Domain, Socket, Type}; - /// use std::net::TcpStream; /// /// #[tokio::main] /// async fn main() -> std::io::Result<()> { /// /// let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; /// - /// let socket = TcpSocket::from_std_stream(socket2_socket.into())?; + /// let socket = TcpSocket::from_std_stream(socket2_socket.into()); /// /// Ok(()) /// }