diff --git a/Makefile b/Makefile index 3937e0a38..a7a421112 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,9 @@ install-tunnel: core/target/$(ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core $(call mkdir,$(DESTDIR)/lib/systemd/system) $(call cp,core/startos/start-tunneld.service,$(DESTDIR)/lib/systemd/system/start-tunneld.service) + $(call mkdir,$(DESTDIR)/usr/lib/startos/scripts) + $(call cp,build/lib/scripts/forward-port,$(DESTDIR)/usr/lib/startos/scripts/forward-port) + core/target/$(ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox: $(CORE_SRC) $(ENVIRONMENT_FILE) web/dist/static/start-tunnel/index.html ARCH=$(ARCH) PROFILE=$(PROFILE) ./core/build-tunnelbox.sh diff --git a/core/Cargo.lock b/core/Cargo.lock index 76b377fab..9bc7d3cb3 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -157,12 +157,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] -name = "ansi-width" +name = "ansi-regex" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219e3ce6f2611d83b51ec2098a12702112c29e57203a6b0a0929b2cddb486608" +checksum = "74e74db1232b47053a58c3b009baf5d07cdb83354058af912eb6a30745c29081" dependencies = [ - "unicode-width 0.1.14", + "regex", ] [[package]] @@ -221,6 +221,15 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "ar_archive_writer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +dependencies = [ + "object 0.32.2", +] + [[package]] name = "arbitrary" version = "1.4.2" @@ -404,7 +413,7 @@ dependencies = [ "pem", "rcgen", "ring", - "rustls 0.23.34", + "rustls 0.23.35", "rustls-pemfile", "serde", "serde_json", @@ -845,11 +854,20 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.37.3", "rustc-demangle", "windows-link 0.2.1", ] +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + [[package]] name = "backtrace-on-stack-overflow" version = "0.3.0" @@ -1077,7 +1095,7 @@ dependencies = [ "cc", "cfg-if", "constant_time_eq", - "memmap2", + "memmap2 0.9.9", "rayon-core", ] @@ -1092,6 +1110,12 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.9.0" @@ -1159,9 +1183,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", @@ -1223,9 +1247,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.42" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bbf3b3619004ad9bd139f62a9ab5cfe467f307455a0d307b0cf58bf070feaa" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", "jobserver", @@ -1254,6 +1278,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "cfg_aliases" version = "0.2.1" @@ -1344,9 +1374,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -1354,14 +1384,15 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim 0.11.1", + "terminal_size", ] [[package]] @@ -1382,6 +1413,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +[[package]] +name = "clipboard-win" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342" +dependencies = [ + "lazy-bytes-cast", + "winapi", +] + [[package]] name = "cmake" version = "0.1.54" @@ -1435,6 +1476,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "colorgrad" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faedab4fd8670120c2be7f49225fbdb8b6db6d46f04ce4f864b1f1cdd55e6400" +dependencies = [ + "csscolorparser", +] + [[package]] name = "combine" version = "4.6.7" @@ -1630,6 +1680,32 @@ dependencies = [ "url", ] +[[package]] +name = "copypasta" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133fc8675ee3a4ec9aa513584deda9aa0faeda3586b87f7f0f2ba082c66fb172" +dependencies = [ + "clipboard-win", + "objc", + "objc-foundation", + "objc_id", + "smithay-clipboard", + "x11-clipboard", +] + +[[package]] +name = "copypasta-ext" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9455f470ea0c7d50c3fe3d22389c3a482f38a9f5fbab1c8ee368121356c56718" +dependencies = [ + "copypasta", + "libc", + "which", + "x11-clipboard", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1796,7 +1872,7 @@ dependencies = [ "document-features", "futures-core", "mio", - "parking_lot", + "parking_lot 0.12.5", "rustix 1.1.2", "signal-hook", "signal-hook-mio", @@ -1850,6 +1926,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "csscolorparser" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda6aace1fbef3aa217b27f4c8d7d071ef2a70a5ca51050b1f17d40299d3f16" +dependencies = [ + "phf 0.11.3", +] + [[package]] name = "csv" version = "1.4.0" @@ -2058,9 +2143,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", "serde_core", @@ -2199,6 +2284,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -2288,6 +2379,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82" +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dns-lookup" version = "2.1.1" @@ -2315,6 +2415,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "downcast-rs" version = "2.0.2" @@ -2357,7 +2463,7 @@ dependencies = [ "byteorder", "dynasm", "fnv", - "memmap2", + "memmap2 0.9.9", ] [[package]] @@ -2747,6 +2853,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "filetime" version = "0.2.26" @@ -2858,6 +2975,16 @@ dependencies = [ "walkdir", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -2956,7 +3083,7 @@ checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot", + "parking_lot 0.12.5", ] [[package]] @@ -3007,7 +3134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.34", + "rustls 0.23.35", "rustls-pki-types", ] @@ -3041,6 +3168,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.9" @@ -3071,6 +3207,16 @@ dependencies = [ "webpki-roots 0.26.11", ] +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -3554,11 +3700,12 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.34", + "rustls 0.23.35", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", + "webpki-roots 1.0.4", ] [[package]] @@ -3642,9 +3789,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -3655,9 +3802,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -3668,11 +3815,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -3683,42 +3829,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -3929,10 +4071,19 @@ dependencies = [ ] [[package]] -name = "integer-encoding" -version = "4.0.2" +name = "instant" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d762194228a2f1c11063e46e32e5acb96e66e906382b9eb5441f2e0504bbd5a" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-encoding" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c00403deb17c3221a1fe4fb571b9ed0370b3dcd116553c77fa294a3d918699" dependencies = [ "async-trait", "tokio", @@ -3958,9 +4109,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -3977,6 +4128,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -4133,9 +4290,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -4210,6 +4367,21 @@ dependencies = [ "libc", ] +[[package]] +name = "kv" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "620727085ac39ee9650b373fe6d8073a0aee6f99e52a9c72b25f7671078039ab" +dependencies = [ + "bincode 1.3.3", + "pin-project-lite", + "serde", + "serde_json", + "sled", + "thiserror 1.0.69", + "toml 0.5.11", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -4250,6 +4422,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "lazy-bytes-cast" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" + [[package]] name = "lazy_async_pool" version = "0.3.3" @@ -4296,7 +4474,7 @@ dependencies = [ "nom 8.0.0", "percent-encoding", "quoted_printable", - "rustls 0.23.34", + "rustls 0.23.35", "rustls-platform-verifier", "socket2 0.6.1", "tokio", @@ -4359,6 +4537,16 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libmimalloc-sys" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libredox" version = "0.1.10" @@ -4391,6 +4579,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -4405,9 +4599,9 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" @@ -4433,6 +4627,21 @@ dependencies = [ "value-bag", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.2.0" @@ -4483,6 +4692,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + [[package]] name = "memmap2" version = "0.9.9" @@ -4522,6 +4740,45 @@ dependencies = [ "zeroize", ] +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "mimalloc" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "mime" version = "0.3.17" @@ -4546,14 +4803,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "log", "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4571,6 +4828,7 @@ dependencies = [ "lazy_static", "lettre", "mbrman", + "miette", "num_enum", "openssl", "patch-db", @@ -4578,7 +4836,7 @@ dependencies = [ "regex", "reqwest", "rpc-toolkit", - "rustls 0.23.34", + "rustls 0.23.35", "serde", "serde_json", "ssh-key", @@ -4594,9 +4852,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c588e11a3082784af229e23e8e4ecf5bcc6fbe4f69101e0421ce8d79da7f0b40" +checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" dependencies = [ "num-traits", "pxfm", @@ -4669,6 +4927,18 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases 0.1.1", + "libc", +] + [[package]] name = "nix" version = "0.30.1" @@ -4677,7 +4947,7 @@ checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.10.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.2.1", "libc", "memoffset 0.9.1", ] @@ -4781,11 +5051,10 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", @@ -4896,6 +5165,26 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc2-core-foundation" version = "0.3.2" @@ -4915,6 +5204,24 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "object" version = "0.37.3" @@ -4957,6 +5264,28 @@ dependencies = [ "futures", ] +[[package]] +name = "onig" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" +dependencies = [ + "bitflags 2.10.0", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "oorandom" version = "11.1.5" @@ -4971,9 +5300,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssh-keys" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb830a82898b2ac17c9620ddce839ac3b34b9cb8a1a037cbdbfb9841c756c3e" +checksum = "351339c4d45e6bdf2defef3ef1ce0b153810bd59b171b92b6a42e7bb0f32a4ad" dependencies = [ "base64 0.21.7", "byteorder", @@ -5120,6 +5449,17 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -5127,7 +5467,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.12", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -5278,17 +5632,37 @@ dependencies = [ "indexmap 2.12.0", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + [[package]] name = "phf" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_macros", + "phf_macros 0.13.1", "phf_shared 0.13.1", "serde", ] +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + [[package]] name = "phf_generator" version = "0.13.1" @@ -5299,13 +5673,26 @@ dependencies = [ "phf_shared 0.13.1", ] +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "phf_macros" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator", + "phf_generator 0.13.1", "phf_shared 0.13.1", "proc-macro2", "quote", @@ -5406,6 +5793,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plist" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +dependencies = [ + "base64 0.22.1", + "indexmap 2.12.0", + "quick-xml", + "serde", + "time", +] + [[package]] name = "plotters" version = "0.3.7" @@ -5454,6 +5854,27 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +[[package]] +name = "portable-pty" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a596a2b3d2752d94f51fac2d4a96737b8705dddd311a32b9af47211f08671e" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "downcast-rs 1.2.1", + "filedescriptor", + "lazy_static", + "libc", + "log", + "nix 0.28.0", + "serial2", + "shared_library", + "shell-words", + "winapi", + "winreg", +] + [[package]] name = "postage" version = "0.5.0" @@ -5463,7 +5884,7 @@ dependencies = [ "atomic 0.5.3", "crossbeam-queue", "futures", - "parking_lot", + "parking_lot 0.12.5", "pin-project", "static_assertions", "thiserror 1.0.69", @@ -5471,9 +5892,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -5509,6 +5930,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -5620,14 +6051,13 @@ dependencies = [ [[package]] name = "proptest" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", "bitflags 2.10.0", - "lazy_static", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", @@ -5689,10 +6119,11 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "psm" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e66fcd288453b748497d8fb18bccc83a16b0518e3906d4b8df0a8d42d93dbb1c" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" dependencies = [ + "ar_archive_writer", "cc", ] @@ -5751,6 +6182,70 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-xml" +version = "0.38.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases 0.2.1", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.35", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls 0.23.35", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases 0.2.1", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.41" @@ -5772,6 +6267,55 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r3bl_tui" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "105ab0982b9aa4e3e1d6896036e92beb06ab14f6fcba408b56bca7c928353673" +dependencies = [ + "async-stream", + "bincode 2.0.1", + "chrono", + "clap", + "colorgrad", + "const_format", + "copypasta-ext", + "crossterm", + "flate2", + "futures-core", + "futures-util", + "is_ci", + "kv", + "miette", + "mimalloc", + "nom 8.0.0", + "portable-pty", + "pretty_assertions", + "rand 0.9.2", + "reqwest", + "rustc-hash", + "serde", + "serde_json", + "sha2 0.10.9", + "smallstr", + "smallvec", + "strip-ansi", + "strip-ansi-escapes", + "strum", + "strum_macros", + "syntect", + "textwrap", + "thiserror 2.0.17", + "tokio", + "tracing", + "tracing-appender", + "tracing-core", + "tracing-subscriber", + "unicode-segmentation", + "unicode-width 0.2.2", + "uuid", +] + [[package]] name = "radium" version = "0.5.3" @@ -6098,6 +6642,8 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.35", "rustls-pki-types", "serde", "serde_json", @@ -6105,6 +6651,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.4", "tokio-util", "tower 0.5.2", "tower-http", @@ -6114,6 +6661,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots 1.0.4", ] [[package]] @@ -6171,7 +6719,7 @@ dependencies = [ [[package]] name = "rpc-toolkit" version = "0.3.2" -source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#23ecbda1c6b549fd2778e2847a53ea75a4103577" +source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#068db905ee38a7da97cc4a43b806409204e73723" dependencies = [ "async-stream", "async-trait", @@ -6325,16 +6873,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.34" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.7", + "rustls-webpki 0.103.8", "subtle", "zeroize", ] @@ -6362,10 +6910,11 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ + "web-time", "zeroize", ] @@ -6380,10 +6929,10 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.34", + "rustls 0.23.35", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.7", + "rustls-webpki 0.103.8", "security-framework 3.5.1", "security-framework-sys", "webpki-root-certs", @@ -6409,9 +6958,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.7" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "aws-lc-rs", "ring", @@ -6437,21 +6986,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "rustyline-async" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e07ddce8399c61495b405dc94d4f30d01fc1c5e1238f10b9c09940678bc81ab" -dependencies = [ - "ansi-width", - "crossterm", - "futures-util", - "pin-project", - "thingbuf", - "thiserror 2.0.17", - "unicode-segmentation", -] - [[package]] name = "ryu" version = "1.0.20" @@ -6511,9 +7045,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "1317c3bf3e7df961da95b0a56a172a02abead31276215a0497241a7624b487ce" dependencies = [ "dyn-clone", "ref-cast", @@ -6521,6 +7055,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -6753,7 +7293,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.12.0", "schemars 0.9.0", - "schemars 1.0.4", + "schemars 1.0.5", "serde_core", "serde_json", "serde_with_macros", @@ -6787,6 +7327,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "serial2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc76fa68e25e771492ca1e3c53d447ef0be3093e05cd3b47f4b712ba10c6f3c" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + [[package]] name = "sha-crypt" version = "0.5.0" @@ -6865,6 +7416,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_library" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" +dependencies = [ + "lazy_static", + "libc", +] + [[package]] name = "shell-words" version = "1.1.0" @@ -6900,9 +7461,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -6969,6 +7530,22 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "slotmap" version = "1.0.7" @@ -6991,6 +7568,16 @@ dependencies = [ "void", ] +[[package]] +name = "smallstr" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862077b1e764f04c251fe82a2ef562fd78d7cadaeb072ca7c2bcaf7217b1ff3b" +dependencies = [ + "serde", + "smallvec", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -7006,6 +7593,34 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +[[package]] +name = "smithay-client-toolkit" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" +dependencies = [ + "bitflags 1.3.2", + "dlib", + "lazy_static", + "log", + "memmap2 0.5.10", + "nix 0.24.3", + "pkg-config", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + +[[package]] +name = "smithay-clipboard" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +dependencies = [ + "smithay-client-toolkit", + "wayland-client", +] + [[package]] name = "socket2" version = "0.5.10" @@ -7089,7 +7704,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.34", + "rustls 0.23.35", "serde", "serde_json", "sha2 0.10.9", @@ -7177,9 +7792,9 @@ dependencies = [ [[package]] name = "sscanf" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c713ebd15ce561dd4a13ed62bc2a0368e16806fc30dcaf66ecf1256b2a3fdde6" +checksum = "569fdd714955aad3acdde5d13129eaa6c4576b759c0585488c84ad395263138a" dependencies = [ "const_format", "lazy_static", @@ -7189,15 +7804,15 @@ dependencies = [ [[package]] name = "sscanf_macro" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84955aa74a157e5834d58a07be11af7f0ab923f0194a0bb2ea6b3db8b5d1611d" +checksum = "77faf04b02dc0dd55e6713fcae44aa6e8882570bae2bd873949924d6e57cca82" dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", "regex-syntax 0.6.29", - "strsim 0.10.0", + "strsim 0.11.1", "syn 2.0.108", "unicode-width 0.1.14", ] @@ -7336,6 +7951,7 @@ dependencies = [ "libc", "log", "mbrman", + "miette", "mio", "models", "new_mime_guess", @@ -7358,6 +7974,7 @@ dependencies = [ "proptest-derive", "pty-process", "qrcode", + "r3bl_tui", "rand 0.9.2", "regex", "reqwest", @@ -7365,7 +7982,6 @@ dependencies = [ "rpassword", "rpc-toolkit", "rust-argon2", - "rustyline-async", "safelog", "semver", "serde", @@ -7433,7 +8049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "parking_lot", + "parking_lot 0.12.5", "phf_shared 0.11.3", "precomputed-hash", ] @@ -7449,6 +8065,24 @@ dependencies = [ "unicode-properties", ] +[[package]] +name = "strip-ansi" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e397af0b9266a4e521ed5a4891cc715902af8dd221cba1a187f552bd044d970" +dependencies = [ + "ansi-regex", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.10.0" @@ -7488,6 +8122,27 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + [[package]] name = "syn" version = "1.0.109" @@ -7530,6 +8185,27 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "syntect" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" +dependencies = [ + "bincode 1.3.3", + "flate2", + "fnv", + "once_cell", + "onig", + "plist", + "regex-syntax 0.8.8", + "serde", + "serde_derive", + "serde_json", + "thiserror 2.0.17", + "walkdir", + "yaml-rust", +] + [[package]] name = "sysinfo" version = "0.36.1" @@ -7615,6 +8291,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +dependencies = [ + "rustix 1.1.2", + "windows-sys 0.60.2", +] + [[package]] name = "termion" version = "4.0.5" @@ -7638,16 +8324,6 @@ dependencies = [ "unicode-width 0.2.2", ] -[[package]] -name = "thingbuf" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662b54ef6f7b4e71f683dadc787bbb2d8e8ef2f91b682ebed3164a5a7abca905" -dependencies = [ - "parking_lot", - "pin-project", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -7750,11 +8426,12 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] @@ -7792,7 +8469,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", + "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", "socket2 0.6.1", @@ -7839,7 +8516,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.34", + "rustls 0.23.35", "tokio", ] @@ -7897,9 +8574,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -7909,6 +8586,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" @@ -8184,7 +8870,7 @@ dependencies = [ "derive-deftly 1.2.0", "derive_builder_fork_arti", "derive_more 2.0.1", - "downcast-rs", + "downcast-rs 2.0.2", "dyn-clone", "educe", "futures", @@ -8323,7 +9009,7 @@ dependencies = [ "humantime", "humantime-serde", "itertools 0.14.0", - "memmap2", + "memmap2 0.9.9", "oneshot-fused-workaround", "paste", "postage", @@ -8564,7 +9250,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit dependencies = [ "derive-deftly 1.2.0", "derive_more 2.0.1", - "downcast-rs", + "downcast-rs 2.0.2", "paste", "rand 0.9.2", "signature 2.2.0", @@ -8588,7 +9274,7 @@ dependencies = [ "derive-deftly 1.2.0", "derive_builder_fork_arti", "derive_more 2.0.1", - "downcast-rs", + "downcast-rs 2.0.2", "dyn-clone", "fs-mistrust", "glob-match", @@ -8774,7 +9460,7 @@ dependencies = [ "itertools 0.14.0", "memchr", "paste", - "phf", + "phf 0.13.1", "rand 0.9.2", "serde", "serde_with", @@ -8940,7 +9626,7 @@ dependencies = [ "paste", "pin-project", "rustls-pki-types", - "rustls-webpki 0.103.7", + "rustls-webpki 0.103.8", "thiserror 2.0.17", "tokio", "tokio-util", @@ -9104,6 +9790,18 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror 1.0.69", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.30" @@ -9358,9 +10056,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -9370,18 +10068,18 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" @@ -9547,6 +10245,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + [[package]] name = "wait-timeout" version = "0.2.1" @@ -9613,9 +10320,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -9624,25 +10331,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.108", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -9653,9 +10346,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9663,22 +10356,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.108", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -9696,6 +10389,79 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +dependencies = [ + "bitflags 1.3.2", + "downcast-rs 1.2.1", + "libc", + "nix 0.24.3", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +dependencies = [ + "nix 0.24.3", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +dependencies = [ + "nix 0.24.3", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +dependencies = [ + "bitflags 1.3.2", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + [[package]] name = "weak-table" version = "0.3.2" @@ -9704,9 +10470,9 @@ checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -9724,9 +10490,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d651ec480de84b762e7be71e6efa7461699c19d9e2c272c8d93455f567786e" +checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" dependencies = [ "rustls-pki-types", ] @@ -9737,18 +10503,30 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.3", + "webpki-roots 1.0.4", ] [[package]] name = "webpki-roots" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "whoami" version = "1.6.1" @@ -9784,6 +10562,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eafc5f679c576995526e81635d0cf9695841736712b4e892f87abbe6fed3f28" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -10255,6 +11042,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "wit-bindgen" version = "0.46.0" @@ -10263,9 +11059,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -10282,6 +11078,37 @@ dependencies = [ "tap", ] +[[package]] +name = "x11-clipboard" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980b9aa9226c3b7de8e2adb11bf20124327c054e0e5812d2aac0b5b5a87e7464" +dependencies = [ + "x11rb", +] + +[[package]] +name = "x11rb" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" +dependencies = [ + "gethostname", + "nix 0.24.3", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" +dependencies = [ + "nix 0.24.3", +] + [[package]] name = "x25519-dalek" version = "2.0.1" @@ -10330,6 +11157,18 @@ dependencies = [ "rustix 1.1.2", ] +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + [[package]] name = "xxhash-rust" version = "0.8.15" @@ -10348,6 +11187,21 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yasi" version = "0.1.11" @@ -10373,11 +11227,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -10385,9 +11238,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -10519,9 +11372,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -10530,10 +11383,11 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", @@ -10541,9 +11395,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/core/models/Cargo.toml b/core/models/Cargo.toml index 635ce8da3..7abe1b302 100644 --- a/core/models/Cargo.toml +++ b/core/models/Cargo.toml @@ -1,7 +1,7 @@ [package] +edition = "2021" name = "models" version = "0.1.0" -edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,14 +14,15 @@ axum = "0.8.4" base64 = "0.22.1" color-eyre = "0.6.2" ed25519-dalek = { version = "2.0.0", features = ["serde"] } -gpt = "4.1.0" -lazy_static = "1.4" -lettre = { version = "0.11", default-features = false } -mbrman = "0.6.0" exver = { version = "0.2.0", git = "https://github.com/Start9Labs/exver-rs.git", features = [ "serde", ] } +gpt = "4.1.0" ipnet = "2.8.0" +lazy_static = "1.4" +lettre = { version = "0.11", default-features = false } +mbrman = "0.6.0" +miette = "7.6.0" num_enum = "0.7.1" openssl = { version = "0.10.57", features = ["vendored"] } patch-db = { version = "*", path = "../../patch-db/patch-db", features = [ @@ -35,11 +36,11 @@ rustls = "0.23" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" ssh-key = "0.6.2" -ts-rs = "9" thiserror = "2.0" tokio = { version = "1", features = ["full"] } torut = "0.2.1" tracing = "0.1.39" +ts-rs = "9" typeid = "1" yasi = { version = "0.1.6", features = ["serde", "ts-rs"] } zbus = "5" diff --git a/core/startos/Cargo.toml b/core/startos/Cargo.toml index ad4dc76a3..f8308c97d 100644 --- a/core/startos/Cargo.toml +++ b/core/startos/Cargo.toml @@ -4,18 +4,18 @@ description = "The core of StartOS" documentation = "https://docs.rs/start-os" edition = "2024" keywords = [ - "self-hosted", - "raspberry-pi", - "privacy", "bitcoin", "full-node", "lightning", + "privacy", + "raspberry-pi", + "self-hosted", ] +license = "MIT" name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" version = "0.4.0-alpha.12" # VERSION_BUMP -license = "MIT" [lib] name = "startos" @@ -44,58 +44,58 @@ path = "src/main.rs" [features] arti = [ "arti-client", - "tor-rtcompat", - "tor-keymgr", - "tor-proto", - "tor-hscrypto", - "tor-llcrypto", - "tor-cell", - "tor-hsservice", - "safelog", "models/arti", + "safelog", + "tor-cell", + "tor-hscrypto", + "tor-hsservice", + "tor-keymgr", + "tor-llcrypto", + "tor-proto", + "tor-rtcompat", ] -cli = ["cli-startd", "cli-registry", "cli-tunnel"] +cli = ["cli-registry", "cli-startd", "cli-tunnel"] cli-container = ["procfs", "pty-process"] cli-registry = [] cli-startd = [] cli-tunnel = [] -default = ["cli", "startd", "registry", "cli-container", "tunnel"] +console = ["console-subscriber", "tokio/tracing"] +default = ["cli", "cli-container", "registry", "startd", "tunnel"] dev = ["backtrace-on-stack-overflow"] docker = [] registry = [] startd = [] test = [] tunnel = [] -console = ["console-subscriber", "tokio/tracing"] unstable = ["backtrace-on-stack-overflow"] [dependencies] +aes = { version = "0.7.5", features = ["ctr"] } arti-client = { version = "0.33", features = [ "compression", + "ephemeral-keystore", "experimental-api", + "onion-service-client", + "onion-service-service", "rustls", "static", "tokio", - "ephemeral-keystore", - "onion-service-client", - "onion-service-service", ], default-features = false, git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true } -aes = { version = "0.7.5", features = ["ctr"] } async-acme = { version = "0.6.0", git = "https://github.com/dr-bonez/async-acme.git", features = [ "use_rustls", "use_tokio", ] } async-compression = { version = "0.4.32", features = [ - "gzip", "brotli", - "zstd", + "gzip", "tokio", + "zstd", ] } async-stream = "0.3.5" async-trait = "0.1.74" axum = { version = "0.8.4", features = ["ws"] } -barrage = "0.2.3" backtrace-on-stack-overflow = { version = "0.3.0", optional = true } +barrage = "0.2.3" base32 = "0.5.0" base64 = "0.22.1" base64ct = "1.6.0" @@ -115,14 +115,14 @@ der = { version = "0.7.9", features = ["derive", "pem"] } digest = "0.10.7" divrem = "1.0.0" dns-lookup = "2.1.0" -ed25519 = { version = "2.2.3", features = ["pkcs8", "pem", "alloc"] } +ed25519 = { version = "2.2.3", features = ["alloc", "pem", "pkcs8"] } ed25519-dalek = { version = "2.2.0", features = [ + "digest", + "hazmat", + "pkcs8", + "rand_core", "serde", "zeroize", - "rand_core", - "digest", - "pkcs8", - "hazmat", ] } ed25519-dalek-v1 = { package = "ed25519-dalek", version = "1" } exver = { version = "0.2.0", git = "https://github.com/Start9Labs/exver-rs.git", features = [ @@ -139,14 +139,14 @@ hickory-server = "0.25.2" hmac = "0.12.1" http = "1.0.0" http-body-util = "0.1" -hyper = { version = "1.5", features = ["server", "http1", "http2"] } +hyper = { version = "1.5", features = ["http1", "http2", "server"] } hyper-util = { version = "0.1.10", features = [ + "http1", + "http2", "server", "server-auto", "server-graceful", "service", - "http1", - "http2", "tokio", ] } id-pool = { version = "0.2.2", default-features = false, features = [ @@ -172,18 +172,19 @@ lazy_async_pool = "0.3.3" lazy_format = "2.0" lazy_static = "1.4.0" lettre = { version = "0.11.18", default-features = false, features = [ - "smtp-transport", - "pool", - "hostname", - "builder", - "tokio1-rustls", - "rustls-platform-verifier", "aws-lc-rs", + "builder", + "hostname", + "pool", + "rustls-platform-verifier", + "smtp-transport", + "tokio1-rustls", ] } libc = "0.2.149" log = "0.4.20" -mio = "1" mbrman = "0.6.0" +miette = { version = "7.6.0", features = ["fancy"] } +mio = "1" models = { version = "*", path = "../models" } new_mime_guess = "4" nix = { version = "0.30.1", features = [ @@ -197,8 +198,8 @@ nix = { version = "0.30.1", features = [ ] } nom = "8.0.0" num = "0.4.1" -num_enum = "0.7.0" num_cpus = "1.16.0" +num_enum = "0.7.0" once_cell = "1.19.0" openssh-keys = "0.6.2" openssl = { version = "0.10.57", features = ["vendored"] } @@ -215,14 +216,14 @@ proptest = "1.3.1" proptest-derive = "0.5.0" pty-process = { version = "0.5.1", optional = true } qrcode = "0.14.1" +r3bl_tui = "0.7.6" rand = "0.9.2" regex = "1.10.2" -reqwest = { version = "0.12.4", features = ["stream", "json", "socks"] } +reqwest = { version = "0.12.4", features = ["json", "socks", "stream"] } reqwest_cookie_store = "0.8.0" rpassword = "7.2.0" rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" } rust-argon2 = "2.0.0" -rustyline-async = "0.4.7" safelog = { version = "0.4.8", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true } semver = { version = "1.0.20", features = ["serde"] } serde = { version = "1.0", features = ["derive", "rc"] } @@ -230,7 +231,7 @@ serde_cbor = { package = "ciborium", version = "0.2.1" } serde_json = "1.0" serde_toml = { package = "toml", version = "0.8.2" } serde_urlencoded = "0.7" -serde_with = { version = "3.4.0", features = ["macros", "json"] } +serde_with = { version = "3.4.0", features = ["json", "macros"] } serde_yaml = { package = "serde_yml", version = "0.0.12" } sha-crypt = "0.5.0" sha2 = "0.10.2" @@ -238,20 +239,20 @@ shell-words = "1" signal-hook = "0.3.17" simple-logging = "2.0.2" socket2 = { version = "0.6.0", features = ["all"] } -socks5-impl = { version = "0.7.2", features = ["server", "client"] } +socks5-impl = { version = "0.7.2", features = ["client", "server"] } sqlx = { version = "0.8.6", features = [ - "runtime-tokio-rustls", "postgres", + "runtime-tokio-rustls", ], default-features = false } sscanf = "0.4.1" ssh-key = { version = "0.6.2", features = ["ed25519"] } tar = "0.4.40" termion = "4.0.5" -thiserror = "2.0.12" textwrap = "0.16.1" +thiserror = "2.0.12" tokio = { version = "1.38.1", features = ["full"] } tokio-rustls = "0.26.0" -tokio-stream = { version = "0.1.14", features = ["io-util", "sync", "net"] } +tokio-stream = { version = "0.1.14", features = ["io-util", "net", "sync"] } tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" } tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] } tokio-util = { version = "0.7.9", features = ["io"] } @@ -268,8 +269,8 @@ tor-llcrypto = { version = "0.33", features = [ ], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true } tor-proto = { version = "0.33", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true } tor-rtcompat = { version = "0.33", features = [ - "tokio", "rustls", + "tokio", ], git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true } torut = "0.2.1" tower-service = "0.3.3" diff --git a/core/startos/src/install/mod.rs b/core/startos/src/install/mod.rs index 0deb2da91..5a13204f5 100644 --- a/core/startos/src/install/mod.rs +++ b/core/startos/src/install/mod.rs @@ -7,7 +7,7 @@ use clap::builder::ValueParserFactory; use clap::{CommandFactory, FromArgMatches, Parser, value_parser}; use color_eyre::eyre::eyre; use exver::VersionRange; -use futures::{AsyncWriteExt, StreamExt}; +use futures::StreamExt; use imbl_value::{InternedString, json}; use itertools::Itertools; use models::{FromStrParser, VersionString}; @@ -15,7 +15,6 @@ use reqwest::Url; use reqwest::header::{CONTENT_LENGTH, HeaderMap}; use rpc_toolkit::HandlerArgs; use rpc_toolkit::yajrc::RpcError; -use rustyline_async::ReadlineEvent; use serde::{Deserialize, Serialize}; use tokio::sync::oneshot; use tokio_tungstenite::tungstenite::protocol::frame::coding::CloseCode; @@ -34,6 +33,7 @@ use crate::upload::upload; use crate::util::Never; use crate::util::io::open_file; use crate::util::net::WebSocketExt; +use crate::util::tui::choose; pub const PKG_ARCHIVE_DIR: &str = "package-data/archive"; pub const PKG_PUBLIC_DIR: &str = "package-data/public"; @@ -483,47 +483,19 @@ pub async fn cli_install( let version = if packages.best.len() == 1 { packages.best.pop_first().map(|(k, _)| k).unwrap() } else { - println!( - "Multiple flavors of {id} found. Please select one of the following versions to install:" - ); - let version; - loop { - let (mut read, mut output) = rustyline_async::Readline::new("> ".into()) - .with_kind(ErrorKind::Filesystem)?; - for (idx, version) in packages.best.keys().enumerate() { - output - .write_all(format!(" {}) {}\n", idx + 1, version).as_bytes()) - .await?; - read.add_history_entry(version.to_string()); - } - if let ReadlineEvent::Line(line) = read.readline().await? { - let trimmed = line.trim(); - match trimmed.parse() { - Ok(v) => { - if let Some((k, _)) = packages.best.remove_entry(&v) { - version = k; - break; - } - } - Err(_) => match trimmed.parse::() { - Ok(i) if (1..=packages.best.len()).contains(&i) => { - version = packages.best.keys().nth(i - 1).unwrap().clone(); - break; - } - _ => (), - }, - } - eprintln!("invalid selection: {trimmed}"); - println!("Please select one of the following versions to install:"); - } else { - return Err(Error::new( - eyre!("Could not determine precise version to install"), - ErrorKind::InvalidRequest, - ) - .into()); - } - } - version + let versions = packages.best.keys().collect::>(); + let version = choose( + &format!( + concat!( + "Multiple flavors of {id} found. ", + "Please select one of the following versions to install:" + ), + id = id + ), + &versions, + ) + .await?; + (*version).clone() }; ctx.call_remote::( &method.join("."), diff --git a/core/startos/src/lib.rs b/core/startos/src/lib.rs index 896d7ad03..7b0d83e1f 100644 --- a/core/startos/src/lib.rs +++ b/core/startos/src/lib.rs @@ -80,7 +80,7 @@ use imbl_value::Value; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{ CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn, from_fn_async, - from_fn_blocking, + from_fn_async_local, from_fn_blocking, }; use serde::{Deserialize, Serialize}; use ts_rs::TS; @@ -392,7 +392,7 @@ pub fn package() -> ParentHandler { ) .subcommand( "install", - from_fn_async(install::cli_install) + from_fn_async_local(install::cli_install) .no_display() .with_about("Install a package from a marketplace or via sideloading"), ) @@ -513,13 +513,6 @@ pub fn package() -> ParentHandler { backup::package_backup::() .with_about("Commands for restoring package(s) from backup"), ) - .subcommand("connect", from_fn_async(service::connect_rpc).no_cli()) - .subcommand( - "connect", - from_fn_async(service::connect_rpc_cli) - .no_display() - .with_about("Connect to a LXC container"), - ) .subcommand( "attach", from_fn_async(service::attach) diff --git a/core/startos/src/lxc/mod.rs b/core/startos/src/lxc/mod.rs index ff9f0fc24..869e58c09 100644 --- a/core/startos/src/lxc/mod.rs +++ b/core/startos/src/lxc/mod.rs @@ -10,7 +10,6 @@ use imbl_value::{InOMap, InternedString}; use models::{FromStrParser, InvalidId, PackageId}; use rpc_toolkit::yajrc::RpcError; use rpc_toolkit::{GenericRpcMethod, RpcRequest, RpcResponse}; -use rustyline_async::{ReadlineEvent, SharedWriter}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::process::Command; @@ -470,115 +469,6 @@ pub async fn connect(ctx: &RpcContext, container: &LxcContainer) -> Result Result<(), Error> { - use futures::SinkExt; - use tokio_tungstenite::tungstenite::Message; - - let mut ws = ctx.ws_continuation(guid).await?; - let (mut input, mut output) = - rustyline_async::Readline::new("> ".into()).with_kind(ErrorKind::Filesystem)?; - - async fn handle_message( - msg: Option>, - output: &mut SharedWriter, - ) -> Result { - match msg { - None => return Ok(true), - Some(Ok(Message::Text(txt))) => match serde_json::from_str::(&txt) { - Ok(RpcResponse { result: Ok(a), .. }) => { - output - .write_all( - (serde_json::to_string(&a).with_kind(ErrorKind::Serialization)? + "\n") - .as_bytes(), - ) - .await?; - } - Ok(RpcResponse { result: Err(e), .. }) => { - let e: Error = e.into(); - tracing::error!("{e}"); - tracing::debug!("{e:?}"); - } - Err(e) => { - tracing::error!("Error Parsing RPC response: {e}"); - tracing::debug!("{e:?}"); - } - }, - Some(Ok(_)) => (), - Some(Err(e)) => { - return Err(Error::new(e, ErrorKind::Network)); - } - }; - Ok(false) - } - - loop { - tokio::select! { - line = input.readline() => { - let line = line.with_kind(ErrorKind::Filesystem)?; - if let ReadlineEvent::Line(line) = line { - input.add_history_entry(line.clone()); - if serde_json::from_str::(&line).is_ok() { - ws.send(Message::Text(line.into())) - .await - .with_kind(ErrorKind::Network)?; - } else { - match shell_words::split(&line) { - Ok(command) => { - if let Some((method, rest)) = command.split_first() { - let mut params = InOMap::new(); - for arg in rest { - if let Some((name, value)) = arg.split_once('=') { - params.insert(InternedString::intern(name), if value.is_empty() { - Value::Null - } else if let Ok(v) = serde_json::from_str(value) { - v - } else { - Value::String(Arc::new(value.into())) - }); - } else { - tracing::error!("argument without a value: {arg}"); - tracing::debug!("help: set the value of {arg} with `{arg}=...`"); - continue; - } - } - ws.send(Message::Text(match serde_json::to_string(&RpcRequest { - id: None, - method: GenericRpcMethod::new(method.into()), - params: Value::Object(params), - }) { - Ok(a) => a.into(), - Err(e) => { - tracing::error!("Error Serializing Request: {e}"); - tracing::debug!("{e:?}"); - continue; - } - })).await.with_kind(ErrorKind::Network)?; - if handle_message(ws.next().await, &mut output).await? { - break - } - } - } - Err(e) => { - tracing::error!("{e}"); - tracing::debug!("{e:?}"); - } - } - } - } else { - ws.send(Message::Close(None)).await.with_kind(ErrorKind::Network)?; - } - } - msg = ws.next() => { - if handle_message(msg, &mut output).await? { - break; - } - } - } - } - - Ok(()) -} - pub async fn stats(ctx: RpcContext) -> Result>, Error> { let ids = ctx.db.peek().await.as_public().as_package_data().keys()?; diff --git a/core/startos/src/net/tunnel.rs b/core/startos/src/net/tunnel.rs index f61023401..b4b89783d 100644 --- a/core/startos/src/net/tunnel.rs +++ b/core/startos/src/net/tunnel.rs @@ -9,6 +9,7 @@ use ts_rs::TS; use crate::context::{CliContext, RpcContext}; use crate::db::model::public::{NetworkInterfaceInfo, NetworkInterfaceType}; +use crate::net::host::all_hosts; use crate::prelude::*; use crate::util::Invoke; use crate::util::io::{TmpDir, write_file_atomic}; @@ -132,7 +133,37 @@ pub async fn remove_tunnel( )); } + ctx.db + .mutate(|db| { + for host in all_hosts(db) { + let host = host?; + host.as_public_domains_mut() + .mutate(|p| Ok(p.retain(|_, v| v.gateway != id)))?; + } + + Ok(()) + }) + .await + .result?; + ctx.net_controller.net_iface.delete_iface(&id).await?; + ctx.db + .mutate(|db| { + for host in all_hosts(db) { + let host = host?; + host.as_bindings_mut().mutate(|b| { + Ok(b.values_mut().for_each(|v| { + v.net.private_disabled.remove(&id); + v.net.public_enabled.remove(&id); + })) + })?; + } + + Ok(()) + }) + .await + .result?; + Ok(()) } diff --git a/core/startos/src/service/mod.rs b/core/startos/src/service/mod.rs index 8df13ee9d..b4c895ee0 100644 --- a/core/startos/src/service/mod.rs +++ b/core/startos/src/service/mod.rs @@ -20,7 +20,7 @@ use itertools::Itertools; use models::{ActionId, HostId, ImageId, PackageId}; use nix::sys::signal::Signal; use persistent_container::{PersistentContainer, Subcontainer}; -use rpc_toolkit::{CallRemoteHandler, Empty, HandlerArgs, HandlerFor, from_fn_async}; +use rpc_toolkit::{HandlerArgs, HandlerFor}; use serde::{Deserialize, Serialize}; use service_actor::ServiceActor; use start_stop::StartStop; @@ -707,57 +707,6 @@ pub async fn rebuild(ctx: RpcContext, RebuildParams { id }: RebuildParams) -> Re Ok(()) } -#[derive(Deserialize, Serialize, Parser, TS)] -pub struct ConnectParams { - pub id: PackageId, -} - -pub async fn connect_rpc( - ctx: RpcContext, - ConnectParams { id }: ConnectParams, -) -> Result { - let id_ref = &id; - crate::lxc::connect( - &ctx, - ctx.services - .get(&id) - .await - .as_ref() - .or_not_found(lazy_format!("service for {id_ref}"))? - .seed - .persistent_container - .lxc_container - .get() - .or_not_found(lazy_format!("container for {id_ref}"))?, - ) - .await -} - -pub async fn connect_rpc_cli( - HandlerArgs { - context, - parent_method, - method, - params, - inherited_params, - raw_params, - }: HandlerArgs, -) -> Result<(), Error> { - let ctx = context.clone(); - let guid = CallRemoteHandler::::new(from_fn_async(connect_rpc)) - .handle_async(HandlerArgs { - context, - parent_method, - method, - params: rpc_toolkit::util::Flat(params, Empty {}), - inherited_params, - raw_params, - }) - .await?; - - crate::lxc::connect_cli(&ctx, guid).await -} - #[derive(Deserialize, Serialize, TS)] #[serde(rename_all = "camelCase")] pub struct AttachParams { diff --git a/core/startos/src/tunnel/api.rs b/core/startos/src/tunnel/api.rs index 3add85a8b..af8a48831 100644 --- a/core/startos/src/tunnel/api.rs +++ b/core/startos/src/tunnel/api.rs @@ -366,15 +366,16 @@ pub async fn add_forward( ctx: TunnelContext, AddPortForwardParams { source, target }: AddPortForwardParams, ) -> Result<(), Error> { + let rc = ctx.forward.add_forward(source, target).await?; + ctx.active_forwards.mutate(|m| { + m.insert(source, rc); + }); + ctx.db .mutate(|db| db.as_port_forwards_mut().insert(&source, &target)) .await .result?; - let rc = ctx.forward.add_forward(source, target).await?; - ctx.active_forwards.mutate(|m| { - m.insert(source, rc); - }); Ok(()) } diff --git a/core/startos/src/tunnel/auth.rs b/core/startos/src/tunnel/auth.rs index 123ea9982..03beab7f5 100644 --- a/core/startos/src/tunnel/auth.rs +++ b/core/startos/src/tunnel/auth.rs @@ -141,6 +141,12 @@ pub fn auth_api() -> ParentHandler { .with_about("Set user interface password") .no_display(), ) + .subcommand( + "reset-password", + from_fn_async(reset_password) + .with_about("Reset user interface password") + .no_display(), + ) .subcommand( "key", ParentHandler::::new() @@ -286,3 +292,32 @@ pub async fn set_password_cli( Ok(()) } + +pub async fn reset_password( + HandlerArgs { + context, + parent_method, + method, + .. + }: HandlerArgs, +) -> Result<(), Error> { + println!("Generating a random password..."); + let params = SetPasswordParams { + password: base32::encode( + base32::Alphabet::Rfc4648Lower { padding: false }, + &rand::random::<[u8; 10]>(), + ), + }; + + context + .call_remote::( + &parent_method.iter().chain(method.iter()).join("."), + to_value(¶ms)?, + ) + .await?; + + println!("Your new password is:"); + println!("{}", params.password); + + Ok(()) +} diff --git a/core/startos/src/tunnel/db.rs b/core/startos/src/tunnel/db.rs index 1db6e105b..cbdbd46d2 100644 --- a/core/startos/src/tunnel/db.rs +++ b/core/startos/src/tunnel/db.rs @@ -5,11 +5,10 @@ use std::time::Duration; use axum::extract::ws; use clap::Parser; -use clap::builder::ValueParserFactory; use imbl::{HashMap, OrdMap}; use imbl_value::InternedString; use itertools::Itertools; -use models::{FromStrParser, GatewayId}; +use models::GatewayId; use patch_db::Dump; use patch_db::json_ptr::{JsonPointer, ROOT}; use rpc_toolkit::yajrc::RpcError; @@ -31,20 +30,27 @@ use crate::tunnel::wg::WgServer; use crate::util::net::WebSocketExt; use crate::util::serde::{HandlerExtSerde, apply_expr}; -#[derive(Default, Deserialize, Serialize, HasModel)] +#[derive(Default, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] #[model = "Model"] pub struct TunnelDatabase { pub webserver: WebserverInfo, pub sessions: Sessions, pub password: Option, + #[ts(as = "std::collections::HashMap::")] pub auth_pubkeys: HashMap, + #[ts(as = "std::collections::BTreeMap::")] pub gateways: OrdMap, pub wg: WgServer, pub port_forwards: PortForwards, } -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[test] +fn export_bindings_tunnel_db() { + TunnelDatabase::export_all_to("bindings/tunnel").unwrap(); +} + +#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)] pub struct PortForwards(pub BTreeMap); impl Map for PortForwards { type Key = SocketAddrV4; diff --git a/core/startos/src/tunnel/web.rs b/core/startos/src/tunnel/web.rs index 6be4cab65..eba414711 100644 --- a/core/startos/src/tunnel/web.rs +++ b/core/startos/src/tunnel/web.rs @@ -1,31 +1,36 @@ use std::collections::VecDeque; -use std::io::Write; use std::net::{IpAddr, Ipv6Addr, SocketAddr}; use std::sync::Arc; use clap::Parser; +use hickory_client::proto::rr::rdata::cert; use imbl_value::{InternedString, json}; use itertools::Itertools; use openssl::pkey::{PKey, Private}; use openssl::x509::X509; -use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; +use rpc_toolkit::{ + Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async, from_fn_async_local, +}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio_rustls::rustls::ServerConfig; use tokio_rustls::rustls::crypto::CryptoProvider; use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use tokio_rustls::rustls::server::ClientHello; +use ts_rs::TS; use crate::context::CliContext; use crate::net::ssl::SANInfo; use crate::net::tls::TlsHandler; use crate::net::web_server::Accept; use crate::prelude::*; +use crate::tunnel::auth::SetPasswordParams; use crate::tunnel::context::TunnelContext; use crate::tunnel::db::TunnelDatabase; -use crate::util::serde::{HandlerExtSerde, Pem}; +use crate::util::serde::{HandlerExtSerde, Pem, display_serializable}; +use crate::util::tui::{choose, parse_as, prompt, prompt_multiline}; -#[derive(Debug, Default, Deserialize, Serialize, HasModel)] +#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] #[model = "Model"] pub struct WebserverInfo { @@ -34,7 +39,7 @@ pub struct WebserverInfo { pub certificate: Option, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, TS)] #[serde(rename_all = "camelCase")] pub struct TunnelCertData { pub key: Pem>, @@ -91,7 +96,7 @@ pub fn web_api() -> ParentHandler { ParentHandler::new() .subcommand( "init", - from_fn_async(init_web) + from_fn_async_local(init_web) .no_display() .with_about("Initialize the webserver"), ) @@ -122,7 +127,7 @@ pub fn web_api() -> ParentHandler { ) .subcommand( "import-certificate", - from_fn_async(import_certificate_cli) + from_fn_async_local(import_certificate_cli) .no_display() .with_about("Import a certificate to use for the webserver"), ) @@ -132,6 +137,22 @@ pub fn web_api() -> ParentHandler { .with_about("Generate a self signed certificaet to use for the webserver") .with_call_remote::(), ) + .subcommand( + "get-certificate", + from_fn_async(get_certificate) + .with_display_serializable() + .with_custom_display_fn(|HandlerArgs { params, .. }, res| { + if let Some(format) = params.format { + return display_serializable(format, res); + } + if let Some(res) = res { + println!("{res}"); + } + Ok(()) + }) + .with_about("Get the certificate for the webserver") + .with_call_remote::(), + ) .subcommand( "enable", from_fn_async(enable_web) @@ -178,58 +199,61 @@ pub async fn import_certificate_cli( .. }: HandlerArgs, ) -> Result<(), Error> { - println!("Please paste in your PEM encoded private key: "); - let mut stdin_lines = BufReader::new(tokio::io::stdin()).lines(); let mut key_string = String::new(); - - while let Some(line) = stdin_lines.next_line().await? { - key_string.push_str(&line); - key_string.push_str("\n"); - if line.trim().starts_with("-----END") { - break; - } - } - - let key: Pem> = key_string.parse()?; - - println!("Please paste in your PEM encoded certificate (or certificate chain): "); + let key: Pem> = + prompt_multiline("Please paste in your PEM encoded private key: ", |line| { + key_string.push_str(&line); + key_string.push_str("\n"); + if line.trim().starts_with("-----END") { + return key_string.parse().map(Some).map_err(|e| { + key_string.truncate(0); + e + }); + } + Ok(None) + }) + .await?; let mut chain = Vec::::new(); - - loop { - let mut cert_string = String::new(); - - while let Some(line) = stdin_lines.next_line().await? { + let mut cert_string = String::new(); + prompt_multiline( + concat!( + "Please paste in your PEM encoded certificate", + " (or certificate chain):" + ), + |line| { cert_string.push_str(&line); cert_string.push_str("\n"); if line.trim().starts_with("-----END") { - break; + let cert = cert_string.parse::>(); + cert_string.truncate(0); + let cert = cert?; + + let key = cert.0.public_key()?; + + if let Some(prev) = chain.last() { + if !prev.verify(&key)? { + return Err(Error::new( + eyre!(concat!( + "Invalid Fullchain: ", + "Previous cert was not signed by this certificate's key" + )), + ErrorKind::InvalidSignature, + )); + } + } + + let is_root = cert.0.verify(&key)?; + + chain.push(cert.0); + + if is_root { Ok(Some(())) } else { Ok(None) } + } else { + Ok(None) } - } - - let cert: Pem = cert_string.parse()?; - - let key = cert.0.public_key()?; - - if let Some(prev) = chain.last() { - if !prev.verify(&key)? { - return Err(Error::new( - eyre!( - "Invalid Fullchain: Previous cert was not signed by this certificate's key" - ), - ErrorKind::InvalidSignature, - )); - } - } - - let is_root = cert.0.verify(&key)?; - - chain.push(cert.0); - - if is_root { - break; - } - } + }, + ) + .await?; context .call_remote::( @@ -274,6 +298,17 @@ pub async fn generate_certificate( Ok(Pem(cert)) } +pub async fn get_certificate(ctx: TunnelContext) -> Result>>, Error> { + ctx.db + .peek() + .await + .as_webserver() + .as_certificate() + .de()? + .map(|cert_data| Ok(cert_data.cert)) + .transpose() +} + #[derive(Debug, Deserialize, Serialize, Parser)] #[serde(rename_all = "camelCase")] pub struct SetListenParams { @@ -371,27 +406,115 @@ pub async fn reset_web(ctx: TunnelContext) -> Result<(), Error> { .result } +fn is_valid_domain(domain: &str) -> bool { + if domain.is_empty() || domain.len() > 253 || domain.starts_with('.') || domain.ends_with('.') { + return false; + } + + let labels: Vec<&str> = domain.split('.').collect(); + + for label in labels { + if label.is_empty() || label.len() > 63 { + return false; + } + + if !label.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') { + return false; + } + + if label.chars().next().map_or(true, |c| c == '-') + || label.chars().next_back().map_or(true, |c| c == '-') + { + return false; + } + } + + true +} + pub async fn init_web(ctx: CliContext) -> Result<(), Error> { + let mut password = None; loop { match ctx .call_remote::("web.enable", json!({})) .await { Ok(_) => { - println!("Webserver Initialized"); + let listen = from_value::( + ctx.call_remote::("web.get-listen", json!({})) + .await?, + )?; + + println!("✅ Success! ✅"); + println!( + "The webserver is running. Below is your URL{} and SSL certificate.", + if password.is_some() { + ", password," + } else { + "" + } + ); + println!(); + println!("🌐 URL"); + println!("https://{listen}"); + if listen.ip().is_unspecified() { + println!(concat!( + "Note: this is the unspecified address. ", + "This means you can use any IP address available to this device to connect. ", + "Using the above address as-is will only work from this device." + )); + } else if listen.ip().is_loopback() { + println!(concat!( + "Note: this is a loopback address. ", + "This is only recommended if you are planning to run a proxy in front of the web ui. ", + "Using the above address as-is will only work from this device." + )); + } + println!(); + + if let Some(password) = password { + println!("🔒 Password"); + println!("{password}"); + println!(); + println!(concat!( + "If you lose or forget your password, you can reset it using the command: ", + "start-tunnel auth reset-password" + )); + } else { + println!(concat!( + "Your password was set up previously. ", + "If you don't remember it, you can reset it using the command: ", + "start-tunnel auth reset-password" + )); + } + println!(); + + let cert = from_value::>>( + ctx.call_remote::("web.get-certificate", json!({})) + .await?, + )?; + println!("📝 SSL Certificate:"); + println!("{cert}"); + println!(); + + println!(concat!( + "If you haven't already, ", + "trust the certificate in your system keychain and/or browser." + )); + return Ok(()); } Err(e) if e.kind == ErrorKind::ParseNetAddress => { - println!("A listen address has not been set yet. Setting one up now..."); + println!("Select the IP address at which to host the web interface:"); let available_ips = from_value::>( ctx.call_remote::("web.get-available-ips", json!({})) .await?, )?; - let suggested_addr = available_ips + let suggested_addrs = available_ips .into_iter() - .find(|ip| match ip { + .filter(|ip| match ip { IpAddr::V4(ipv4) => !ipv4.is_private() && !ipv4.is_loopback(), IpAddr::V6(ipv6) => { !ipv6.is_loopback() @@ -399,148 +522,132 @@ pub async fn init_web(ctx: CliContext) -> Result<(), Error> { && !ipv6.is_unicast_link_local() } }) - .map(|ip| SocketAddr::new(ip, 8443)) - .unwrap_or_else(|| SocketAddr::from((Ipv6Addr::UNSPECIFIED, 8443))); + .chain([Ipv6Addr::UNSPECIFIED.into()]) + .collect::>(); - let (mut readline, _writer) = rustyline_async::Readline::new(format!( - "Listen Address [{}]: ", - suggested_addr - )) - .with_kind(ErrorKind::Filesystem)?; - - let listen: SocketAddr = loop { - match readline.readline().await.with_kind(ErrorKind::Filesystem)? { - rustyline_async::ReadlineEvent::Line(l) if !l.trim().is_empty() => { - match l.trim().parse() { - Ok(addr) => break addr, - Err(_) => { - println!( - "Invalid socket address. Please enter in format IP:PORT (e.g., 0.0.0.0:8443)" - ); - readline.clear_history(); - } - } - } - rustyline_async::ReadlineEvent::Line(_) => { - break suggested_addr; - } - _ => return Err(Error::new(eyre!("Aborted"), ErrorKind::Unknown)), - } + let ip = if suggested_addrs.len() > 16 { + prompt( + &format!("Listen Address [{}]: ", suggested_addrs[0]), + parse_as::("IP Address"), + Some(suggested_addrs[0]), + ) + .await? + } else { + *choose("Listen Address:", &suggested_addrs).await? }; + println!(concat!( + "Enter the port at which to host the web interface. ", + "The recommended default is 8443. ", + "If you change the default, choose an uncommon port to avoid conflicts: " + )); + let port = prompt("Port [8443]: ", parse_as::("port"), Some(8443)).await?; + + let listen = SocketAddr::new(ip, port); + ctx.call_remote::( "web.set-listen", to_value(&SetListenParams { listen })?, ) .await?; + + println!(); } Err(e) if e.kind == ErrorKind::OpenSsl => { - println!( - "StartTunnel has not been set up with an SSL Certificate yet. Setting one up now..." - ); - println!("[1]: Generate a Self Signed Certificate"); - println!("[2]: Provide your own certificate and key"); - let (mut readline, mut writer) = - rustyline_async::Readline::new("What would you like to do? [1-2]: ".into()) - .with_kind(ErrorKind::Filesystem)?; - readline.add_history_entry("1".into()); - readline.add_history_entry("2".into()); - let self_signed; - loop { - match readline.readline().await.with_kind(ErrorKind::Filesystem)? { - rustyline_async::ReadlineEvent::Line(l) - if l.trim_matches(|c: char| c.is_whitespace() || c == '"') == "1" => - { - self_signed = true; - break; + enum Choice { + Generate, + Provide, + } + impl std::fmt::Display for Choice { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Generate => write!(f, "Generate a Self Signed Certificate"), + Self::Provide => write!(f, "Provide your own certificate and key"), } - rustyline_async::ReadlineEvent::Line(l) - if l.trim_matches(|c: char| c.is_whitespace() || c == '"') == "2" => - { - self_signed = false; - break; - } - rustyline_async::ReadlineEvent::Line(_) => { - readline.clear_history(); - readline.add_history_entry("1".into()); - readline.add_history_entry("2".into()); - writeln!(writer, "Invalid response. Enter either \"1\" or \"2\".")?; - } - _ => return Err(Error::new(eyre!("Aborted"), ErrorKind::Unknown)), } } - if self_signed { - let listen = from_value::>( - ctx.call_remote::("web.get-listen", json!({})) - .await?, - )? - .filter(|a| !a.ip().is_unspecified()); - writeln!( - writer, - "Enter the name(s) to sign the certificate for, separated by commas." - )?; - readline.clear_history(); - let default_prompt = if let Some(listen) = listen { - format!("Subject Alternative Name(s) [{}]: ", listen.ip()) - } else { - "Subject Alternative Name(s): ".to_string() - }; - readline - .update_prompt(&default_prompt) - .with_kind(ErrorKind::Filesystem)?; - let mut saninfo = Vec::new(); - loop { - match readline.readline().await.with_kind(ErrorKind::Filesystem)? { - rustyline_async::ReadlineEvent::Line(l) if !l.trim().is_empty() => { - saninfo.extend(l.split(",").map(|h| h.trim().into())); - break; - } - rustyline_async::ReadlineEvent::Line(_) => { - saninfo.extend( - listen - .map(|l| l.ip()) - .as_ref() - .map(InternedString::from_display), - ); - readline.clear_history(); - if !saninfo.is_empty() { - break; - } - } - _ => return Err(Error::new(eyre!("Aborted"), ErrorKind::Unknown)), - } - } + let options = vec![Choice::Generate, Choice::Provide]; + let choice = choose( + concat!( + "Select whether to autogenerate a self-signed SSL certificate ", + "or provide your own certificate and key:" + ), + &options, + ) + .await?; - ctx.call_remote::( - "web.generate-certificate", - to_value(&GenerateCertParams { subject: saninfo })?, - ) - .await?; - } else { - drop((readline, writer)); - import_certificate_cli(HandlerArgs { - context: ctx.clone(), - parent_method: vec!["web", "import-certificate"].into(), - method: VecDeque::new(), - params: Empty {}, - inherited_params: Empty {}, - raw_params: json!({}), - }) - .await?; + match choice { + Choice::Generate => { + let listen = from_value::>( + ctx.call_remote::("web.get-listen", json!({})) + .await?, + )? + .filter(|a| !a.ip().is_unspecified()); + + let default_prompt = if let Some(listen) = listen { + format!("Subject Alternative Name(s) [{}]: ", listen.ip()) + } else { + "Subject Alternative Name(s): ".to_string() + }; + + println!( + "List all IP addresses and domains for which to sign the certificate, separated by commas." + ); + let san_info = prompt( + &default_prompt, + |s| { + s.split(",") + .map(|s| { + let s = s.trim(); + if let Ok(ip) = s.parse::() { + Ok(InternedString::from_display(&ip)) + } else if is_valid_domain(s) { + Ok(s.into()) + } else { + Err(format!("{s} is not a valid ip address or domain")) + } + }) + .collect() + }, + listen.map(|l| vec![InternedString::from_display(&l.ip())]), + ) + .await?; + + ctx.call_remote::( + "web.generate-certificate", + to_value(&GenerateCertParams { subject: san_info })?, + ) + .await?; + } + Choice::Provide => { + import_certificate_cli(HandlerArgs { + context: ctx.clone(), + parent_method: vec!["web", "import-certificate"].into(), + method: VecDeque::new(), + params: Empty {}, + inherited_params: Empty {}, + raw_params: json!({}), + }) + .await?; + } } + + println!(); } Err(e) if e.kind == ErrorKind::Authorization => { - println!("A password has not been setup yet. Setting one up now..."); + println!("Generating a random password..."); + let params = SetPasswordParams { + password: base32::encode( + base32::Alphabet::Rfc4648 { padding: false }, + &rand::random::<[u8; 10]>(), + ), + }; + ctx.call_remote::("auth.set-password", to_value(¶ms)?) + .await?; - super::auth::set_password_cli(HandlerArgs { - context: ctx.clone(), - parent_method: vec!["auth", "set-password"].into(), - method: VecDeque::new(), - params: Empty {}, - inherited_params: Empty {}, - raw_params: json!({}), - }) - .await?; + password = Some(params.password); + + println!(); } Err(e) => return Err(e.into()), } diff --git a/core/startos/src/tunnel/wg.rs b/core/startos/src/tunnel/wg.rs index 16374beb4..539a7438e 100644 --- a/core/startos/src/tunnel/wg.rs +++ b/core/startos/src/tunnel/wg.rs @@ -6,6 +6,7 @@ use ipnet::Ipv4Net; use itertools::Itertools; use serde::{Deserialize, Serialize}; use tokio::process::Command; +use ts_rs::TS; use x25519_dalek::{PublicKey, StaticSecret}; use crate::prelude::*; @@ -15,7 +16,7 @@ use crate::util::serde::Base64; pub const WIREGUARD_INTERFACE_NAME: &str = "wg-start-tunnel"; -#[derive(Deserialize, Serialize, HasModel)] +#[derive(Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] #[model = "Model"] pub struct WgServer { @@ -64,8 +65,10 @@ impl WgServer { } } -#[derive(Default, Deserialize, Serialize)] -pub struct WgSubnetMap(pub BTreeMap); +#[derive(Default, Deserialize, Serialize, TS)] +pub struct WgSubnetMap( + #[ts(as = "BTreeMap::")] pub BTreeMap, +); impl Map for WgSubnetMap { type Key = Ipv4Net; type Value = WgSubnetConfig; @@ -77,7 +80,7 @@ impl Map for WgSubnetMap { } } -#[derive(Default, Deserialize, Serialize, HasModel)] +#[derive(Default, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] #[model = "Model"] pub struct WgSubnetConfig { @@ -93,8 +96,7 @@ impl WgSubnetConfig { } } -#[derive(Default, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] +#[derive(Default, Deserialize, Serialize, TS)] pub struct WgSubnetClients(pub BTreeMap); impl Map for WgSubnetClients { type Key = Ipv4Addr; @@ -143,7 +145,7 @@ impl Base64 { } } -#[derive(Clone, Deserialize, Serialize, HasModel)] +#[derive(Clone, Deserialize, Serialize, HasModel, TS)] #[serde(rename_all = "camelCase")] #[model = "Model"] pub struct WgConfig { diff --git a/core/startos/src/util/future.rs b/core/startos/src/util/future.rs index 7ac34ff02..d9a8369e2 100644 --- a/core/startos/src/util/future.rs +++ b/core/startos/src/util/future.rs @@ -1,10 +1,13 @@ use std::pin::Pin; use std::task::{Context, Poll}; +use axum::middleware::FromFn; use futures::future::{BoxFuture, FusedFuture, abortable, pending}; use futures::stream::{AbortHandle, Abortable, BoxStream}; use futures::{Future, FutureExt, Stream, StreamExt}; +use rpc_toolkit::from_fn_blocking; use tokio::sync::watch; +use tokio::task::LocalSet; use crate::prelude::*; @@ -158,6 +161,31 @@ impl<'a> Until<'a> { } } +pub async fn make_send(f: F) -> Result +where + F: FnOnce() -> Fut + Send + 'static, + Fut: Future> + 'static, + T: Send + 'static, +{ + tokio::task::spawn_blocking(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + + let local = LocalSet::new(); + + local.block_on(&rt, async move { f().await }) + }) + .await + .map_err(|e| { + Error::new( + eyre!("Task running non-Send future panicked: {}", e), + ErrorKind::Unknown, + ) + })? +} + #[tokio::test] async fn test_cancellable() { use std::sync::Arc; diff --git a/core/startos/src/util/mod.rs b/core/startos/src/util/mod.rs index 96444af7a..7c2d00471 100644 --- a/core/startos/src/util/mod.rs +++ b/core/startos/src/util/mod.rs @@ -51,6 +51,7 @@ pub mod rpc_client; pub mod serde; pub mod squashfs; pub mod sync; +pub mod tui; #[derive(Clone, Copy, Debug, ::serde::Deserialize, ::serde::Serialize)] pub enum Never {} diff --git a/core/startos/src/util/tui.rs b/core/startos/src/util/tui.rs new file mode 100644 index 000000000..ae30246b6 --- /dev/null +++ b/core/startos/src/util/tui.rs @@ -0,0 +1,139 @@ +use std::io::Write; +use std::str::FromStr; + +use r3bl_tui::{DefaultIoDevices, ReadlineAsyncContext, ReadlineEvent}; + +use crate::prelude::*; + +fn map_miette(m: miette::Error) -> Error { + Error::new(eyre!("{m}"), ErrorKind::Filesystem) +} +fn noninteractive_err() -> Error { + Error::new( + eyre!("Terminal must be in interactive mode for this wizard"), + ErrorKind::Filesystem, + ) +} + +pub fn parse_as<'a, T>(what: &'a str) -> impl Fn(&str) -> Result + 'a +where + T: FromStr, +{ + move |s| { + s.parse::() + .map_err(|_| format!("Please enter a valid {what}.")) + } +} + +pub async fn prompt Result>( + prompt: &str, + mut parse: Parse, + default: Option, +) -> Result { + let mut rl_ctx = ReadlineAsyncContext::try_new(Some(prompt)) + .await + .map_err(map_miette)? + .ok_or_else(noninteractive_err)?; + let res = loop { + match rl_ctx.read_line().await.map_err(map_miette)? { + ReadlineEvent::Line(l) => { + let l = l.trim(); + if !l.is_empty() { + match parse(l) { + Ok(a) => break a, + Err(e) => { + writeln!(&mut rl_ctx.shared_writer, "{e}")?; + } + } + } else if let Some(default) = default { + break default; + } + } + ReadlineEvent::Eof | ReadlineEvent::Interrupted => { + return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled)); + } + _ => (), + } + }; + + rl_ctx.request_shutdown(None).await.map_err(map_miette)?; + rl_ctx.await_shutdown().await; + + Ok(res) +} + +pub async fn prompt_multiline< + T, + E: std::fmt::Display, + HandleLine: FnMut(String) -> Result, E>, +>( + prompt: &str, + mut handle_line: HandleLine, +) -> Result { + println!("{prompt}"); + let mut rl_ctx = ReadlineAsyncContext::try_new(None::<&str>) + .await + .map_err(map_miette)? + .ok_or_else(noninteractive_err)?; + let res = loop { + match rl_ctx.read_line().await.map_err(map_miette)? { + ReadlineEvent::Line(l) => match handle_line(l) { + Ok(Some(a)) => break a, + Ok(None) => (), + Err(e) => writeln!(&mut rl_ctx.shared_writer, "{e}")?, + }, + ReadlineEvent::Eof | ReadlineEvent::Interrupted => { + return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled)); + } + _ => (), + } + }; + + rl_ctx.request_shutdown(None).await.map_err(map_miette)?; + rl_ctx.await_shutdown().await; + + Ok(res) +} + +pub async fn choose<'t, T: std::fmt::Display>( + prompt: &str, + choices: &'t [T], +) -> Result<&'t T, Error> { + let mut io = DefaultIoDevices::default(); + let style = r3bl_tui::readline_async::StyleSheet::default(); + let string_choices = choices + .into_iter() + .map(|c| c.to_string()) + .collect::>(); + let choice = r3bl_tui::readline_async::choose( + prompt, + string_choices.clone(), + None, + None, + r3bl_tui::HowToChoose::Single, + style, + ( + &mut io.output_device, + &mut io.input_device, + io.maybe_shared_writer, + ), + ) + .await + .map_err(map_miette)?; + if choice.len() < 1 { + return Err(Error::new(eyre!("Aborted"), ErrorKind::Cancelled)); + } + let (idx, _) = string_choices + .iter() + .enumerate() + .find(|(_, s)| s.as_str() == choice[0].as_str()) + .ok_or_else(|| { + Error::new( + eyre!("selected choice does not appear in input"), + ErrorKind::Incoherent, + ) + })?; + let choice = &choices[idx]; + println!("{prompt} {choice}"); + Ok(&choice) +} diff --git a/debian/start-tunnel/postinst b/debian/start-tunnel/postinst index 542ff8cff..a4b70bc89 100755 --- a/debian/start-tunnel/postinst +++ b/debian/start-tunnel/postinst @@ -7,3 +7,4 @@ if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ]; then fi $SYSTEMCTL enable start-tunneld.service +$SYSTEMCTL restart start-tunneld.service \ No newline at end of file diff --git a/sdk/base/lib/osBindings/tunnel/AnyVerifyingKey.ts b/sdk/base/lib/osBindings/tunnel/AnyVerifyingKey.ts new file mode 100644 index 000000000..58a45aaa7 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/AnyVerifyingKey.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AnyVerifyingKey = string diff --git a/sdk/base/lib/osBindings/tunnel/Base64.ts b/sdk/base/lib/osBindings/tunnel/Base64.ts new file mode 100644 index 000000000..597227fc9 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/Base64.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Base64 = string diff --git a/sdk/base/lib/osBindings/tunnel/Pem.ts b/sdk/base/lib/osBindings/tunnel/Pem.ts new file mode 100644 index 000000000..1ec1cd375 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/Pem.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Pem = string diff --git a/sdk/base/lib/osBindings/tunnel/PortForwards.ts b/sdk/base/lib/osBindings/tunnel/PortForwards.ts new file mode 100644 index 000000000..aa9991452 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/PortForwards.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PortForwards = { [key: string]: string } diff --git a/sdk/base/lib/osBindings/tunnel/Session.ts b/sdk/base/lib/osBindings/tunnel/Session.ts new file mode 100644 index 000000000..36ebd2766 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/Session.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Session = { + loggedIn: string + lastActive: string + userAgent: string | null +} diff --git a/sdk/base/lib/osBindings/tunnel/Sessions.ts b/sdk/base/lib/osBindings/tunnel/Sessions.ts new file mode 100644 index 000000000..6a15449e2 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/Sessions.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Session } from "./Session" + +export type Sessions = { [key: string]: Session } diff --git a/sdk/base/lib/osBindings/tunnel/SignerInfo.ts b/sdk/base/lib/osBindings/tunnel/SignerInfo.ts new file mode 100644 index 000000000..76cbdafce --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/SignerInfo.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SignerInfo = { name: string } diff --git a/sdk/base/lib/osBindings/tunnel/TunnelCertData.ts b/sdk/base/lib/osBindings/tunnel/TunnelCertData.ts new file mode 100644 index 000000000..7a6aa0d13 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/TunnelCertData.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Pem } from "./Pem" + +export type TunnelCertData = { key: Pem; cert: Pem } diff --git a/sdk/base/lib/osBindings/tunnel/TunnelDatabase.ts b/sdk/base/lib/osBindings/tunnel/TunnelDatabase.ts new file mode 100644 index 000000000..813b4996f --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/TunnelDatabase.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AnyVerifyingKey } from "./AnyVerifyingKey" +import type { PortForwards } from "./PortForwards" +import type { Sessions } from "./Sessions" +import type { SignerInfo } from "./SignerInfo" +import type { WebserverInfo } from "./WebserverInfo" +import type { WgServer } from "./WgServer" + +export type TunnelDatabase = { + webserver: WebserverInfo + sessions: Sessions + password: string | null + authPubkeys: { [key: AnyVerifyingKey]: SignerInfo } + gateways: { [key: AnyVerifyingKey]: SignerInfo } + wg: WgServer + portForwards: PortForwards +} diff --git a/sdk/base/lib/osBindings/tunnel/WebserverInfo.ts b/sdk/base/lib/osBindings/tunnel/WebserverInfo.ts new file mode 100644 index 000000000..9eea3361f --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WebserverInfo.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TunnelCertData } from "./TunnelCertData" + +export type WebserverInfo = { + enabled: boolean + listen: string | null + certificate: TunnelCertData | null +} diff --git a/sdk/base/lib/osBindings/tunnel/WgConfig.ts b/sdk/base/lib/osBindings/tunnel/WgConfig.ts new file mode 100644 index 000000000..441177578 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WgConfig.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Base64 } from "./Base64" + +export type WgConfig = { name: string; key: Base64; psk: Base64 } diff --git a/sdk/base/lib/osBindings/tunnel/WgServer.ts b/sdk/base/lib/osBindings/tunnel/WgServer.ts new file mode 100644 index 000000000..b56e310bb --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WgServer.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Base64 } from "./Base64" +import type { WgSubnetMap } from "./WgSubnetMap" + +export type WgServer = { port: number; key: Base64; subnets: WgSubnetMap } diff --git a/sdk/base/lib/osBindings/tunnel/WgSubnetClients.ts b/sdk/base/lib/osBindings/tunnel/WgSubnetClients.ts new file mode 100644 index 000000000..608b52b14 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WgSubnetClients.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WgConfig } from "./WgConfig" + +export type WgSubnetClients = { [key: string]: WgConfig } diff --git a/sdk/base/lib/osBindings/tunnel/WgSubnetConfig.ts b/sdk/base/lib/osBindings/tunnel/WgSubnetConfig.ts new file mode 100644 index 000000000..adfd68110 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WgSubnetConfig.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WgSubnetClients } from "./WgSubnetClients" + +export type WgSubnetConfig = { name: string; clients: WgSubnetClients } diff --git a/sdk/base/lib/osBindings/tunnel/WgSubnetMap.ts b/sdk/base/lib/osBindings/tunnel/WgSubnetMap.ts new file mode 100644 index 000000000..a38e09650 --- /dev/null +++ b/sdk/base/lib/osBindings/tunnel/WgSubnetMap.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WgSubnetConfig } from "./WgSubnetConfig" + +export type WgSubnetMap = { [key: string]: WgSubnetConfig }