From 32ad01e10c20761ce0f4ce0a0bef16a745019b1b Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Fri, 3 Mar 2023 17:02:31 -0500 Subject: [PATCH 1/5] first attempt at making it work in Rust Signed-off-by: Xe Iaso --- .envrc | 1 + .gitignore | 4 +- flake.lock | 43 ++++ flake.nix | 42 ++++ rust/Cargo.lock | 399 +++++++++++++++++++++++++++++++++++++ rust/Cargo.toml | 20 ++ rust/src/bin/echoclient.rs | 15 ++ rust/src/bin/echoserver.rs | 40 ++++ rust/src/lib.rs | 206 +++++++++++++++++++ rust/tsnet-sys/Cargo.toml | 11 + rust/tsnet-sys/build.rs | 37 ++++ rust/tsnet-sys/src/lib.rs | 18 ++ rust/tsnet-sys/wrapper.h | 1 + 13 files changed, 836 insertions(+), 1 deletion(-) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 rust/Cargo.lock create mode 100644 rust/Cargo.toml create mode 100644 rust/src/bin/echoclient.rs create mode 100644 rust/src/bin/echoserver.rs create mode 100644 rust/src/lib.rs create mode 100644 rust/tsnet-sys/Cargo.toml create mode 100644 rust/tsnet-sys/build.rs create mode 100644 rust/tsnet-sys/src/lib.rs create mode 100644 rust/tsnet-sys/wrapper.h diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 234dd96..85ff7b2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ libtailscale.h /ruby/ext/libtailscale/*.go /ruby/ext/libtailscale/go.mod /ruby/ext/libtailscale/go.sum -/ruby/LICENSE \ No newline at end of file +/ruby/LICENSE +.direnv +/rust/target diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..e841035 --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1677816901, + "narHash": "sha256-oqe8Q9LlWNGfVfUDkKfpWAk+I9RRDBvMSyYVIOZCfPM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0749042bfaa2f4efa70ac829c5387133cfc0a337", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "utils": { + "locked": { + "lastModified": 1676283394, + "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..a1388b7 --- /dev/null +++ b/flake.nix @@ -0,0 +1,42 @@ +{ + inputs = { + utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + }; + + outputs = { self, utils, nixpkgs }: + utils.lib.eachDefaultSystem (system: + let + pkgs = (import nixpkgs) { + inherit system; + }; + + in rec { + # For `nix develop`: + devShell = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + # go + go_1_20 + gopls + gotools + go-tools + + # Rust + rustc + cargo + rustfmt + rust-analyzer + rust-bindgen + clang + libllvm + + # Ruby + rubyPackages_3_1.rake + ruby_3_1 + ]; + + LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + }; + } + ); +} diff --git a/rust/Cargo.lock b/rust/Cargo.lock new file mode 100644 index 0000000..771bf26 --- /dev/null +++ b/rust/Cargo.lock @@ -0,0 +1,399 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bindgen" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5" +dependencies = [ + "bitflags", + "cexpr", + "cfg-if 0.1.10", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tsnet" +version = "0.1.0" +dependencies = [ + "bindgen", + "thiserror", + "tsnet-sys", +] + +[[package]] +name = "tsnet-sys" +version = "0.1.0" +dependencies = [ + "bindgen", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..7cdeac9 --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "tsnet" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +thiserror = "1" + +[dependencies.tsnet-sys] +path = "./tsnet-sys" + +[build-dependencies] +bindgen = "0.53.1" + +[workspace] +members = [ + "./tsnet-sys" +] diff --git a/rust/src/bin/echoclient.rs b/rust/src/bin/echoclient.rs new file mode 100644 index 0000000..97e3eee --- /dev/null +++ b/rust/src/bin/echoclient.rs @@ -0,0 +1,15 @@ +use tsnet::Server; +use std::{io::Write, env}; + +fn main() { + let target = env::args().skip(1).next().unwrap(); + let srv = Server::new() + .hostname("tsnet-rs-echoclient") + .ephemeral() + .authkey(env::var("TS_AUTHKEY").unwrap()) + .build() + .unwrap(); + + let mut conn = srv.dial("tcp", &target).unwrap(); + write!(conn, "This is a test of the Tailscale connection service.\n").unwrap(); +} diff --git a/rust/src/bin/echoserver.rs b/rust/src/bin/echoserver.rs new file mode 100644 index 0000000..c5e9570 --- /dev/null +++ b/rust/src/bin/echoserver.rs @@ -0,0 +1,40 @@ +use tsnet::Server; +use std::{io::{Write, Read}, env, thread, net::TcpStream}; + +fn main() { + let hostport = env::args().skip(1).next().unwrap(); + let srv = Server::new() + .hostname("tsnet-rs-echoserver") + .ephemeral() + .authkey(env::var("TS_AUTHKEY").unwrap()) + .build() + .unwrap(); + + let mut ln = srv.listen("tcp", &hostport).unwrap(); + loop { + let conn = ln.accept().unwrap(); + + thread::spawn(move ||{ + handle_client(conn); + }); + } +} + +fn handle_client(mut stream: TcpStream) { + // read 20 bytes at a time from stream echoing back to stream + loop { + let mut read = [0; 1028]; + match stream.read(&mut read) { + Ok(n) => { + if n == 0 { + // connection was closed + break; + } + stream.write(&read[0..n]).unwrap(); + } + Err(err) => { + panic!("{err}"); + } + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000..e078c06 --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,206 @@ +use std::ffi::{c_int, CString}; +use std::net::TcpStream; +use std::os::fd::FromRawFd; +use std::path::PathBuf; +use tsnet_sys as sys; + +pub struct Server { + srv: sys::tailscale, +} + +impl Drop for Server { + fn drop(&mut self) { + // TODO: drop all sockets + unsafe { sys::tailscale_close(self.srv) }; + } +} + +impl Server { + pub fn new() -> ServerBuilder { + ServerBuilder::default() + } + + /// internal function to grab error messages from tsnet. + fn errmsg(&self) -> Result { + let msg: [u8; 1024] = [0; 1024]; + if unsafe { sys::tailscale_errmsg(self.srv, msg.as_ptr() as *mut i8, msg.len() as u64) } + != 0 + { + return Err(Error::FetchingErrorFromTSNet); + } + + let result = String::from_utf8(msg.to_vec())?; + let result = result.trim_end_matches('\0'); + + Ok(result.to_string()) + } + + pub fn dial(&self, network: &str, addr: &str) -> Result { + let mut conn: sys::tailscale_conn = 0; + let network = CString::new(network)?; + let addr = CString::new(addr)?; + + if unsafe { sys::tailscale_dial(self.srv, network.as_ptr(), addr.as_ptr(), &mut conn) } != 0 + { + return Err(Error::TSNet(self.errmsg()?)); + } + + let conn = conn as c_int; + Ok(unsafe { TcpStream::from_raw_fd(conn) }) + } + + pub fn listen(&self, network: &str, addr: &str) -> Result { + let mut ln: sys::tailscale_listener = 0; + let network = CString::new(network)?; + let addr = CString::new(addr)?; + + if unsafe { sys::tailscale_listen(self.srv, network.as_ptr(), addr.as_ptr(), &mut ln) } != 0 + { + return Err(Error::TSNet(self.errmsg()?)); + } + + Ok(Listener { ln }) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("can't convert this from an OsString to a String, invalid unicode?")] + CantConvertToString, + + #[error("error fetching error from tsnet")] + FetchingErrorFromTSNet, + + #[error("[unexpected] string from tsnet has invalid UTF-8: {0}")] + TSNetSentBadUTF8(#[from] std::string::FromUtf8Error), + + #[error("tsnet: {0}")] + TSNet(String), + + #[error("your string has NULL in it: {0}")] + NullInString(#[from] std::ffi::NulError), +} + +pub type Result = std::result::Result; + +#[derive(Default)] +pub struct ServerBuilder { + dir: Option, + hostname: Option, + authkey: Option, + control_url: Option, + ephemeral: bool, +} + +impl ServerBuilder { + pub fn dir(mut self, dir: PathBuf) -> Self { + self.dir = Some(dir); + self + } + + pub fn hostname(mut self, hostname: &str) -> Self { + self.hostname = Some(hostname.to_owned()); + self + } + + pub fn authkey(mut self, authkey: String) -> Self { + self.authkey = Some(authkey); + self + } + + pub fn control_url(mut self, control_url: String) -> Self { + self.control_url = Some(control_url); + self + } + + pub fn ephemeral(mut self) -> Self { + self.ephemeral = true; + self + } + + pub fn build(self) -> Result { + let result = unsafe { + Server { + srv: sys::tailscale_new(), + } + }; + + if let Some(dir) = self.dir { + let dir = dir.into_os_string(); + let dir = dir.into_string().map_err(|_| Error::CantConvertToString)?; + let dir = CString::new(dir)?; + if unsafe { sys::tailscale_set_dir(result.srv, dir.as_ptr()) } != 0 { + return Err(Error::TSNet(result.errmsg()?)); + } + } + + if let Some(hostname) = self.hostname { + let hostname = CString::new(hostname)?; + if unsafe { sys::tailscale_set_hostname(result.srv, hostname.as_ptr()) } != 0 { + return Err(Error::TSNet(result.errmsg()?)); + } + } + + if let Some(authkey) = self.authkey { + let authkey = CString::new(authkey)?; + if unsafe { sys::tailscale_set_authkey(result.srv, authkey.as_ptr()) } != 0 { + return Err(Error::TSNet(result.errmsg()?)); + } + } + + if let Some(control_url) = self.control_url { + let control_url = CString::new(control_url)?; + if unsafe { sys::tailscale_set_control_url(result.srv, control_url.as_ptr()) } != 0 { + return Err(Error::TSNet(result.errmsg()?)); + } + } + + if unsafe { sys::tailscale_set_ephemeral(result.srv, if self.ephemeral { 1 } else { 0 }) } + != 0 + { + return Err(Error::TSNet(result.errmsg()?)); + } + if unsafe { sys::tailscale_start(result.srv) } != 0 { + return Err(Error::TSNet(result.errmsg()?)); + } + + Ok(result) + } +} + +pub struct Listener { + ln: sys::tailscale_listener, +} + +impl Listener { + pub fn accept(&mut self) -> Result { + let mut conn: sys::tailscale_conn = 0; + if unsafe { sys::tailscale_accept(self.ln, &mut conn) } != 0 { + return Err(Error::FetchingErrorFromTSNet); + } + + let conn = conn as c_int; + Ok(unsafe { TcpStream::from_raw_fd(conn) }) + } +} + +impl Drop for Listener { + fn drop(&mut self) { + unsafe { sys::tailscale_listener_close(self.ln) }; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[forbid(unsafe_code)] + fn make_server() { + Server::new() + .hostname("xn--g28h") // 😂 + .ephemeral() + .build() + .unwrap(); + } +} diff --git a/rust/tsnet-sys/Cargo.toml b/rust/tsnet-sys/Cargo.toml new file mode 100644 index 0000000..293419a --- /dev/null +++ b/rust/tsnet-sys/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tsnet-sys" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[build-dependencies] +bindgen = "0.53.1" diff --git a/rust/tsnet-sys/build.rs b/rust/tsnet-sys/build.rs new file mode 100644 index 0000000..df9ac84 --- /dev/null +++ b/rust/tsnet-sys/build.rs @@ -0,0 +1,37 @@ +extern crate bindgen; + +use std::env; +use std::path::PathBuf; + +fn main() { + // Tell cargo to look for shared libraries in the specified directory + println!("cargo:rustc-link-search=../"); + + // Tell cargo to tell rustc to link the system bzip2 + // shared library. + println!("cargo:rustc-link-lib=tailscale"); + + // Tell cargo to invalidate the built crate whenever the wrapper changes + println!("cargo:rerun-if-changed=wrapper.h"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header("wrapper.h") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/rust/tsnet-sys/src/lib.rs b/rust/tsnet-sys/src/lib.rs new file mode 100644 index 0000000..3f911f6 --- /dev/null +++ b/rust/tsnet-sys/src/lib.rs @@ -0,0 +1,18 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn open_and_close() { + let srv = unsafe { tailscale_new() }; + assert_eq!(unsafe { tailscale_start(srv) }, 0); + assert_eq!(unsafe { tailscale_close(srv) }, 0); + drop(srv); + } +} diff --git a/rust/tsnet-sys/wrapper.h b/rust/tsnet-sys/wrapper.h new file mode 100644 index 0000000..f9c45c9 --- /dev/null +++ b/rust/tsnet-sys/wrapper.h @@ -0,0 +1 @@ +#include "../../tailscale.h" From 57343641ac709ad3d8aa01dbef2a7f42b6dbd3fc Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sat, 4 Mar 2023 18:14:18 -0500 Subject: [PATCH 2/5] start working on tokio implementation Signed-off-by: Xe Iaso --- rust/Cargo.lock | 141 +++++++++++++++++++++++++++++++ rust/Cargo.toml | 9 ++ rust/src/bin/echoclient_async.rs | 20 +++++ rust/src/bin/echoserver.rs | 29 +++++-- rust/src/lib.rs | 21 +++++ 5 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 rust/src/bin/echoclient_async.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 771bf26..c7279d2 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -31,6 +31,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bindgen" version = "0.53.3" @@ -61,6 +67,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" @@ -194,6 +206,18 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[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 = "nom" version = "5.1.2" @@ -210,6 +234,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "proc-macro2" version = "1.0.51" @@ -263,6 +293,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "strsim" version = "0.8.0" @@ -318,12 +358,41 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio" +version = "1.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tsnet" version = "0.1.0" dependencies = [ "bindgen", "thiserror", + "tokio", "tsnet-sys", ] @@ -358,6 +427,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "which" version = "3.1.1" @@ -397,3 +472,69 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 7cdeac9..623f8f9 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -5,9 +5,18 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["tokio"] +tokio = ["dep:tokio"] + [dependencies] thiserror = "1" +[dependencies.tokio] +version = "1" +optional = true +features = ["net", "macros", "rt", "io-util"] + [dependencies.tsnet-sys] path = "./tsnet-sys" diff --git a/rust/src/bin/echoclient_async.rs b/rust/src/bin/echoclient_async.rs new file mode 100644 index 0000000..7a736a9 --- /dev/null +++ b/rust/src/bin/echoclient_async.rs @@ -0,0 +1,20 @@ +use tsnet::Server; +use std::{env}; +use tokio::io::AsyncWriteExt; +use tokio::runtime::Builder; + +fn main() { + let target = env::args().skip(1).next().expect("usage: echoclient_async "); + let srv = Server::new() + .hostname("tsnet-rs-echoclient-async") + .ephemeral() + .authkey(env::var("TS_AUTHKEY").expect("want TS_AUTHKEY in environment")) + .build() + .unwrap(); + + let rt = Builder::new_current_thread().enable_all().build().unwrap(); + rt.block_on(async { + let mut conn = srv.dial_async("tcp", &target).unwrap(); + conn.write_all(b"Hi from async connection land!\n").await.unwrap(); + }); +} diff --git a/rust/src/bin/echoserver.rs b/rust/src/bin/echoserver.rs index c5e9570..63266c8 100644 --- a/rust/src/bin/echoserver.rs +++ b/rust/src/bin/echoserver.rs @@ -1,5 +1,10 @@ +use std::{ + env, + io::{Read, Write}, + net::TcpStream, + thread, +}; use tsnet::Server; -use std::{io::{Write, Read}, env, thread, net::TcpStream}; fn main() { let hostport = env::args().skip(1).next().unwrap(); @@ -10,13 +15,21 @@ fn main() { .build() .unwrap(); - let mut ln = srv.listen("tcp", &hostport).unwrap(); - loop { - let conn = ln.accept().unwrap(); + let ln = srv.listen("tcp", &hostport).unwrap(); + for conn in ln { + match conn { + Ok(conn) => { + match conn.peer_addr() { + Ok(addr) => println!("remote IP: {addr}"), + Err(err) => eprintln!("can't read remote IP: {err}"), + } - thread::spawn(move ||{ - handle_client(conn); - }); + thread::spawn(move || { + handle_client(conn); + }); + } + Err(err) => panic!("{err}"), + } } } @@ -26,7 +39,7 @@ fn handle_client(mut stream: TcpStream) { let mut read = [0; 1028]; match stream.read(&mut read) { Ok(n) => { - if n == 0 { + if n == 0 { // connection was closed break; } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index e078c06..e292ad6 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -49,6 +49,13 @@ impl Server { Ok(unsafe { TcpStream::from_raw_fd(conn) }) } + #[cfg(feature = "tokio")] + pub fn dial_async(&self, network: &str, addr: &str) -> Result { + let conn = self.dial(network, addr)?; + conn.set_nonblocking(true)?; + Ok(tokio::net::TcpStream::from_std(conn)?) + } + pub fn listen(&self, network: &str, addr: &str) -> Result { let mut ln: sys::tailscale_listener = 0; let network = CString::new(network)?; @@ -77,6 +84,9 @@ pub enum Error { #[error("tsnet: {0}")] TSNet(String), + #[error("io error: {0}")] + IO(#[from] std::io::Error), + #[error("your string has NULL in it: {0}")] NullInString(#[from] std::ffi::NulError), } @@ -182,6 +192,10 @@ impl Listener { let conn = conn as c_int; Ok(unsafe { TcpStream::from_raw_fd(conn) }) } + + pub fn incoming(&mut self) -> &Self { + self + } } impl Drop for Listener { @@ -190,6 +204,13 @@ impl Drop for Listener { } } +impl Iterator for Listener { + type Item = Result; + fn next(&mut self) -> Option> { + Some(self.accept()) + } +} + #[cfg(test)] mod tests { use super::*; From 7b410da53009c19f21344828605f398b4378ea64 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 5 Mar 2023 13:20:40 -0500 Subject: [PATCH 3/5] rust/tsnet-sys: start build process for bundled libtailscale source Signed-off-by: Xe Iaso --- rust/Cargo.toml | 1 + rust/tsnet-sys/Cargo.toml | 4 +++ rust/tsnet-sys/build.rs | 67 +++++++++++++++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 623f8f9..7b9fa94 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -19,6 +19,7 @@ features = ["net", "macros", "rt", "io-util"] [dependencies.tsnet-sys] path = "./tsnet-sys" +features = ["bundled"] [build-dependencies] bindgen = "0.53.1" diff --git a/rust/tsnet-sys/Cargo.toml b/rust/tsnet-sys/Cargo.toml index 293419a..4c05e5d 100644 --- a/rust/tsnet-sys/Cargo.toml +++ b/rust/tsnet-sys/Cargo.toml @@ -5,6 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = [] +bundled = [] + [dependencies] [build-dependencies] diff --git a/rust/tsnet-sys/build.rs b/rust/tsnet-sys/build.rs index df9ac84..f5d7aad 100644 --- a/rust/tsnet-sys/build.rs +++ b/rust/tsnet-sys/build.rs @@ -2,17 +2,70 @@ extern crate bindgen; use std::env; use std::path::PathBuf; + use std::process::Command; fn main() { - // Tell cargo to look for shared libraries in the specified directory - println!("cargo:rustc-link-search=../"); + #[allow(unused_assignments)] + let mut header_location = "../../tailscale.h"; + + // if we bundled libtailscale sources, then build them + #[cfg(feature = "bundled")] + { + // TODO(Xe): extract the bundled tarball once #8 lands + #[cfg(debug_assertions)] + println!( + "cargo:warning=go build started: {}/libtailscale.a", + env::var("OUT_DIR").unwrap() + ); + Command::new("go") // TODO(Xe): change curdir to extracted tarball location + .arg("build") + .arg("-buildmode=c-archive") + .arg("-o") + .arg(&format!("{}/libtailscale.a", env::var("OUT_DIR").unwrap())) + .arg("../..") // TODO(Xe): change location to extracted tarball location + .spawn() + .expect("go build -buildmode=c-archive to work") + .wait() + .expect("go build -buildmode=c-archive to complete successfully"); + #[cfg(debug_assertions)] + println!("cargo:warning=go build finished"); + + // add this to the LDPATH + println!("cargo:rustc-link-search={}", env::var("OUT_DIR").unwrap()); - // Tell cargo to tell rustc to link the system bzip2 - // shared library. - println!("cargo:rustc-link-lib=tailscale"); + // point header to extracted tarball + header_location = "../../tailscale.h"; // TODO(Xe): change location to extracted tarball + } + + // for local development + #[cfg(not(feature = "bundled"))] + { + Command::new("go") + .arg("build") + .arg("-buildmode=c-archive") + .arg("-o") + .arg(&format!("{}/libtailscale.a", env::var("OUT_DIR").unwrap())) + .arg("../..") + .spawn() + .expect("go build -buildmode=c-archive to work") + .wait() + .expect("go build -buildmode=c-archive to complete successfully"); + // add this to the LDPATH + println!("cargo:rustc-link-search={}", env::var("OUT_DIR").unwrap()); + } // Tell cargo to invalidate the built crate whenever the wrapper changes - println!("cargo:rerun-if-changed=wrapper.h"); + println!("cargo:rerun-if-changed={header_location}"); + + // Tell cargo to tell rustc to link the built libtailscale + // static library. + println!("cargo:rustc-link-lib=tailscale"); + + // on macOS, link CoreFoundation and Security + #[cfg(target_os = "macos")] + { + println!("cargo:rustc-flags=-l framework=CoreFoundation -l framework=Security"); + } // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for @@ -20,7 +73,7 @@ fn main() { let bindings = bindgen::Builder::default() // The input header we would like to generate // bindings for. - .header("wrapper.h") + .header(header_location) // Tell cargo to invalidate the built crate whenever any of the // included header files changed. .parse_callbacks(Box::new(bindgen::CargoCallbacks)) From 1808df7ddca03d6676c55fd26fc283c08046956b Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 5 Mar 2023 13:39:27 -0500 Subject: [PATCH 4/5] run code through rustfmt Signed-off-by: Xe Iaso --- rust/src/bin/echoclient.rs | 15 +++++++++++---- rust/src/bin/echoclient_async.rs | 11 +++++++---- rust/src/bin/echoserver.rs | 4 ++-- rust/tsnet-sys/src/lib.rs | 4 ++-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/rust/src/bin/echoclient.rs b/rust/src/bin/echoclient.rs index 97e3eee..8f436bb 100644 --- a/rust/src/bin/echoclient.rs +++ b/rust/src/bin/echoclient.rs @@ -1,15 +1,22 @@ +use std::{env, io::Write}; use tsnet::Server; -use std::{io::Write, env}; fn main() { - let target = env::args().skip(1).next().unwrap(); + let target = env::args() + .skip(1) + .next() + .expect("usage: echoclient host:port"); let srv = Server::new() .hostname("tsnet-rs-echoclient") .ephemeral() - .authkey(env::var("TS_AUTHKEY").unwrap()) + .authkey(env::var("TS_AUTHKEY").expect("set TS_AUTHKEY in environment")) .build() .unwrap(); let mut conn = srv.dial("tcp", &target).unwrap(); - write!(conn, "This is a test of the Tailscale connection service.\n").unwrap(); + write!( + conn, + "This is a test of the Tailscale connection service.\n" + ) + .unwrap(); } diff --git a/rust/src/bin/echoclient_async.rs b/rust/src/bin/echoclient_async.rs index 7a736a9..5252ec8 100644 --- a/rust/src/bin/echoclient_async.rs +++ b/rust/src/bin/echoclient_async.rs @@ -1,10 +1,13 @@ -use tsnet::Server; -use std::{env}; -use tokio::io::AsyncWriteExt; +use std::env; +use tokio::io::AsyncWriteExt; use tokio::runtime::Builder; +use tsnet::Server; fn main() { - let target = env::args().skip(1).next().expect("usage: echoclient_async "); + let target = env::args() + .skip(1) + .next() + .expect("usage: echoclient_async "); let srv = Server::new() .hostname("tsnet-rs-echoclient-async") .ephemeral() diff --git a/rust/src/bin/echoserver.rs b/rust/src/bin/echoserver.rs index 63266c8..58abf18 100644 --- a/rust/src/bin/echoserver.rs +++ b/rust/src/bin/echoserver.rs @@ -7,11 +7,11 @@ use std::{ use tsnet::Server; fn main() { - let hostport = env::args().skip(1).next().unwrap(); + let hostport = env::args().skip(1).next().expect("usage: echoserver host:port"); let srv = Server::new() .hostname("tsnet-rs-echoserver") .ephemeral() - .authkey(env::var("TS_AUTHKEY").unwrap()) + .authkey(env::var("TS_AUTHKEY").expect("set TS_AUTHKEY in environment")) .build() .unwrap(); diff --git a/rust/tsnet-sys/src/lib.rs b/rust/tsnet-sys/src/lib.rs index 3f911f6..3bd4ba5 100644 --- a/rust/tsnet-sys/src/lib.rs +++ b/rust/tsnet-sys/src/lib.rs @@ -10,9 +10,9 @@ mod tests { #[test] fn open_and_close() { - let srv = unsafe { tailscale_new() }; + let srv = unsafe { tailscale_new() }; assert_eq!(unsafe { tailscale_start(srv) }, 0); assert_eq!(unsafe { tailscale_close(srv) }, 0); - drop(srv); + drop(srv); } } From 8bf937702dcf60ab492fb333886394f3a10de324 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 5 Mar 2023 17:24:37 -0500 Subject: [PATCH 5/5] move flake meta to rust folder Signed-off-by: Xe Iaso --- .gitignore | 2 -- .envrc => rust/.envrc | 0 rust/.gitignore | 2 ++ flake.lock => rust/flake.lock | 0 flake.nix => rust/flake.nix | 4 ---- 5 files changed, 2 insertions(+), 6 deletions(-) rename .envrc => rust/.envrc (100%) create mode 100644 rust/.gitignore rename flake.lock => rust/flake.lock (100%) rename flake.nix => rust/flake.nix (91%) diff --git a/.gitignore b/.gitignore index 85ff7b2..3896fe3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,3 @@ libtailscale.h /ruby/ext/libtailscale/go.mod /ruby/ext/libtailscale/go.sum /ruby/LICENSE -.direnv -/rust/target diff --git a/.envrc b/rust/.envrc similarity index 100% rename from .envrc rename to rust/.envrc diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 0000000..bd32e74 --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1,2 @@ +.direnv +target diff --git a/flake.lock b/rust/flake.lock similarity index 100% rename from flake.lock rename to rust/flake.lock diff --git a/flake.nix b/rust/flake.nix similarity index 91% rename from flake.nix rename to rust/flake.nix index a1388b7..72438a8 100644 --- a/flake.nix +++ b/rust/flake.nix @@ -29,10 +29,6 @@ rust-bindgen clang libllvm - - # Ruby - rubyPackages_3_1.rake - ruby_3_1 ]; LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";