diff --git a/build.sh b/build.sh index bd8b7b8..31fb4ea 100755 --- a/build.sh +++ b/build.sh @@ -350,6 +350,8 @@ host() mkdir -p $BIN_OUTPUT_DIR $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + rm -f $BUILD_OUTPUT_DIR/native + ln -s $TARGET_BUILD_DIR $BUILD_OUTPUT_DIR/native cp -f $CACHE_DIR/lib/libzt.* $LIB_OUTPUT_DIR cp -f $CACHE_DIR/bin/* $BIN_OUTPUT_DIR echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" diff --git a/pkg/crate/libzt/Cargo.lock b/pkg/crate/libzt/Cargo.lock index d7bcabd..113d535 100644 --- a/pkg/crate/libzt/Cargo.lock +++ b/pkg/crate/libzt/Cargo.lock @@ -20,17 +20,78 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.18", "libc", "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.58.1" @@ -40,8 +101,8 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", - "env_logger", + "clap 2.33.3", + "env_logger 0.8.3", "lazy_static", "lazycell", "log", @@ -101,12 +162,63 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "401a4694d2bf92537b6867d94de48c4842089645fdcdf6c71865b175d836e9c2" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap-num" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488557e97528174edaa2ee268b23a809e0c598213a4bbcb4f34575a46fda147e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "clap_builder" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim 0.10.0", +] + +[[package]] +name = "clap_derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + [[package]] name = "cmake" version = "0.1.45" @@ -116,6 +228,33 @@ dependencies = [ "cc", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + [[package]] name = "env_logger" version = "0.8.3" @@ -129,12 +268,63 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -144,12 +334,41 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -164,9 +383,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.95" +version = "0.2.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81" [[package]] name = "libloading" @@ -182,19 +401,39 @@ dependencies = [ name = "libzt" version = "0.1.2" dependencies = [ + "anyhow", "bindgen", + "clap 4.3.2", + "clap-num", "cmake", + "dirs", + "env_logger 0.10.0", "libc", + "log", + "parking_lot", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "memchr" @@ -212,6 +451,50 @@ dependencies = [ "version_check", ] +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -220,22 +503,51 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" version = "1.5.6" @@ -259,18 +571,61 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.37.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "shlex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -289,6 +644,32 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + [[package]] name = "unicode-width" version = "0.1.8" @@ -296,10 +677,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "vec_map" @@ -313,6 +694,12 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[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" @@ -352,3 +739,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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/pkg/crate/libzt/Cargo.toml b/pkg/crate/libzt/Cargo.toml index b1e8207..b9e9a89 100644 --- a/pkg/crate/libzt/Cargo.toml +++ b/pkg/crate/libzt/Cargo.toml @@ -13,6 +13,15 @@ keywords = ["zerotier", "p2p", "vpn", "socket", "network"] categories = ["network-programming", "cryptography"] [dependencies] +log = "0.4.18" +dirs = "5.0.1" + +[dev-dependencies] +anyhow = "1.0" +clap = { version = "4.3.0", features = ["derive"] } +clap-num = "1.0" +env_logger = "0.10" +parking_lot = { version = "0.12", features = ["send_guard"] } [build-dependencies] bindgen = "0.58" @@ -22,8 +31,3 @@ cmake = "0.1" [lib] name = "libzt" path = "src/lib.rs" - -[[example]] -name = "libzt-test-app" -path = "src/examples/libzt-test-app.rs" - diff --git a/pkg/crate/libzt/build.rs b/pkg/crate/libzt/build.rs index aabcc1b..7521feb 100644 --- a/pkg/crate/libzt/build.rs +++ b/pkg/crate/libzt/build.rs @@ -1,10 +1,15 @@ extern crate bindgen; use std::env; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; fn main() { - println!("cargo:rustc-link-lib=zt"); + let dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let lib_dir = Path::new(&dir).join("../../../dist/native/lib").canonicalize().unwrap(); + + println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy()); + println!("cargo:rustc-link-lib=static=zt"); + println!("cargo:rustc-link-lib=dylib=c++"); let bindings = bindgen::Builder::default() .header("src/include/ZeroTierSockets.h") diff --git a/pkg/crate/libzt/examples/forwarding.rs b/pkg/crate/libzt/examples/forwarding.rs new file mode 100644 index 0000000..217486a --- /dev/null +++ b/pkg/crate/libzt/examples/forwarding.rs @@ -0,0 +1,202 @@ +use std::{ + error::Error, + fmt, fs, + io::{self, Read, Write}, + net::{self, Shutdown}, + sync::Arc, + thread, + time::Duration, +}; + +use anyhow::Result; +use clap::Parser; +use parking_lot::FairMutex; + +use libzt::{node::ZeroTierNode, tcp as zt_tcp}; + +const BUF_SIZE: usize = 1024; +const SOCKET_IO_TIMEOUT: Duration = Duration::new(1, 0); +const DEFAULT_LISTEN_PORT: u16 = 9080; + +#[derive(Debug)] +enum ForwardingError { + BindFailed(String), + ConnectFailed(String), + CopyFailed(String), +} + +impl Error for ForwardingError {} + +#[derive(Parser, Debug)] +struct Args { + #[arg(short, long, value_parser=clap_num::maybe_hex::)] + network_id: u64, + #[arg(short, long)] + connect: String, + #[arg(short, long, default_value_t = DEFAULT_LISTEN_PORT)] + port: u16, +} + +fn setup_node(network_id: u64) -> Result { + log::info!("joining network: {:#x}", network_id); + + let mut storage_path = dirs::data_local_dir().unwrap(); + storage_path.push("libzt"); + storage_path.push("forwarding"); + + fs::create_dir_all(&storage_path)?; + + log::debug!( + "initializing from state dir: {}", + storage_path.to_string_lossy() + ); + + let node = ZeroTierNode {}; + + node.init_set_port(0); + node.init_from_storage(&storage_path.join("libzt-examples").to_string_lossy()); + node.start(); + + log::debug!("waiting for node to come online..."); + while !node.is_online() { + node.delay(250); + } + + log::info!("node id: {:#x}", node.id()); + + node.net_join(network_id); + + log::debug!("waiting for transport..."); + while !node.net_transport_is_ready(network_id) { + node.delay(250); + } + + let addr = node.addr_get(network_id).unwrap(); + log::info!("got ZT addr: {}", addr.to_string()); + + Ok(node) +} + +impl fmt::Display for ForwardingError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +fn main() -> Result<()> { + env_logger::init(); + + let Args { + connect: remote_addr, + network_id, + port: local_port, + } = Args::parse(); + + let _node = setup_node(network_id)?; + + let local_addr = format!("localhost:{}", local_port); + let listener = net::TcpListener::bind(&local_addr) + .map_err(|_| ForwardingError::BindFailed(local_addr.clone()))?; + + log::info!("listener bound to {}", local_addr); + + for conn in listener.incoming() { + log::debug!("incoming: {:?}", conn); + + if let Ok(client) = conn { + client.set_read_timeout(Some(SOCKET_IO_TIMEOUT))?; + client.set_write_timeout(Some(SOCKET_IO_TIMEOUT))?; + + let client = Arc::new(FairMutex::new(client)); + + log::info!("connecting to remote: {}", remote_addr); + + let remote = zt_tcp::TcpStream::connect(&remote_addr) + .map_err(|_| ForwardingError::ConnectFailed(remote_addr.clone()))?; + + remote.set_read_timeout(Some(SOCKET_IO_TIMEOUT))?; + remote.set_write_timeout(Some(SOCKET_IO_TIMEOUT))?; + + let remote = Arc::new(FairMutex::new(remote)); + + log::info!("connected"); + + let client_ = client.clone(); + let remote_ = remote.clone(); + + thread::spawn(move || { + let mut buf = [0u8; BUF_SIZE]; + let mut running = true; + + while running { + let mut client = client.lock(); + let mut remote = remote.lock(); + + match client.read(&mut buf) { + Ok(n) if n > 0 => { + log::debug!("got {} bytes from remote", n); + running = remote + .write(&buf) + .map(|_| { + remote.flush().unwrap(); + true + }) + .unwrap_or_else(|e| { + let msg = format!("failed to write to remote: {:?}", e); + log::error!("{}", msg); + false + }); + } + Err(e) if e.kind() == io::ErrorKind::WouldBlock => { + thread::sleep(Duration::new(0, 5000)); + } + other => { + log::debug!("closing client connection: {:?}", other); + let _ = client.shutdown(Shutdown::Read); + let _ = remote.shutdown(Shutdown::Write); + break; + } + } + + buf.fill(0); + } + }); + thread::spawn(move || { + let mut buf = [0u8; BUF_SIZE]; + let mut running = true; + + while running { + let mut client = client_.lock(); + let mut remote = remote_.lock(); + + match remote.read(&mut buf) { + Ok(n) if n > 0 => { + log::debug!("got {} bytes from remote", n); + running = client + .write(&buf) + .map(|_| { + client.flush().unwrap(); + true + }) + .unwrap_or_else(|e| { + let msg = format!("failed to write to remote: {:?}", e); + log::error!("{}", msg); + false + }); + } + other => { + log::debug!("closing remote connection: {:?}", other); + let _ = remote.shutdown(Shutdown::Read); + let _ = client.shutdown(Shutdown::Write); + break; + } + } + + buf.fill(0); + } + }); + } + } + + Ok(()) +} diff --git a/pkg/crate/libzt/src/examples/libzt-test-app.rs b/pkg/crate/libzt/examples/libzt-test-app.rs similarity index 100% rename from pkg/crate/libzt/src/examples/libzt-test-app.rs rename to pkg/crate/libzt/examples/libzt-test-app.rs