From 1af7bb08032fbdfe35f020d987139c1bbb8c77cb Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sun, 12 Mar 2023 18:19:44 +0100 Subject: [PATCH] Build enough for Tokio/hyper to make use of incoming connections --- Cargo.lock | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 ++ rust/src/lib.rs | 64 ++++++++++++++- 3 files changed, 274 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 985e78b..a1820ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cc" version = "1.0.79" @@ -69,18 +75,113 @@ dependencies = [ "libc", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "hermit-abi" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "io-lifetimes" version = "1.0.6" @@ -103,6 +204,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + [[package]] name = "libc" version = "0.2.140" @@ -114,9 +221,11 @@ name = "libtailscale" version = "0.1.0" dependencies = [ "env_logger", + "hyper", "log", "nix", "thiserror", + "tokio", ] [[package]] @@ -149,6 +258,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys", +] + [[package]] name = "nix" version = "0.26.2" @@ -163,6 +284,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "pin-utils" version = "0.1.0" @@ -218,6 +351,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -264,12 +407,74 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio" +version = "1.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +dependencies = [ + "autocfg", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 3ed8f51..b887186 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,9 +24,15 @@ include = [ path = "rust/src/lib.rs" [dependencies] +hyper = { version = "0.14.25", optional = true, features = ["server"] } log = { version = "0.4.17", default-features = false } nix = "0.26.2" thiserror = "1.0.39" +tokio = { version = "1.26.0", optional = true, features = ["rt", "net"] } [dev-dependencies] env_logger = "0.10.0" + +[features] +default = [] +tokio = ["dep:tokio", "dep:hyper"] diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 17ba4e9..e57c0f9 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -50,7 +50,6 @@ //! } //! ``` #[deny(missing_docs)] - #[allow(non_camel_case_types, dead_code)] mod sys; @@ -64,6 +63,17 @@ use std::{ path::PathBuf, thread, }; +#[cfg(feature = "tokio")] +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + +#[cfg(feature = "tokio")] +use hyper::server::accept::Accept; +#[cfg(feature = "tokio")] +use tokio::{net, task}; /// Possible errors #[derive(Debug, thiserror::Error)] @@ -186,6 +196,15 @@ impl Server { }) } } + + #[cfg(feature = "tokio")] + pub fn listen_async(&self, network: Network, address: &str) -> Result { + let ls = self.listen(network, address)?; + Ok(AsyncListener { + listener: ls, + fut: None, + }) + } } impl Drop for Server { @@ -443,3 +462,46 @@ impl Iterator for &Listener { Some(self.accept()) } } + +#[cfg(feature = "tokio")] +pub struct AsyncListener { + listener: Listener, + fut: Option>>, +} + +#[cfg(feature = "tokio")] +impl Accept for AsyncListener { + type Conn = net::TcpStream; + type Error = Error; + + fn poll_accept( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + if self.fut.is_none() { + let ts = self.listener.handle; + self.fut = Some(task::spawn_blocking(move || unsafe { + let mut conn = 0; + + let res = err(ts, sys::tailscale_accept(ts, &mut conn as *mut _)); + res.map(|_| { + let stream = TcpStream::from_raw_fd(conn); + let _ = stream.set_nonblocking(true); + net::TcpStream::from_std(stream).unwrap() + }) + })); + } + + let mut fut = self.fut.take().unwrap(); + let fut_pl = Pin::new(&mut fut); + let stream = match fut_pl.poll(cx) { + Poll::Ready(t) => t, + Poll::Pending => { + self.fut = Some(fut); + return Poll::Pending; + } + }; + + Poll::Ready(Some(stream.unwrap())) + } +}