diff --git a/Cargo.lock b/Cargo.lock index 61d3c91..cecc3ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,13 +167,37 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" -version = "0.6.0-rc.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "bytes", - "crypto-common 0.2.0-rc.4", - "inout", + "crypto-common 0.1.6", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", ] [[package]] @@ -413,19 +437,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "async-compat" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ba85bc55464dcbf728b56d97e119d673f4cf9062be330a9a26f3acf504a590" -dependencies = [ - "futures-core", - "futures-io", - "once_cell", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -767,12 +778,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base16ct" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" - [[package]] name = "base32" version = "0.5.1" @@ -878,7 +883,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" dependencies = [ "hybrid-array", - "zeroize", ] [[package]] @@ -891,10 +895,13 @@ dependencies = [ ] [[package]] -name = "btparse" -version = "0.2.0" +name = "built" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387e80962b798815a2b5c4bcfdb6bf626fa922ffe9f74e373103b858738e9f31" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" +dependencies = [ + "cargo-lock", +] [[package]] name = "built" @@ -969,6 +976,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "cargo-lock" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06acb4f71407ba205a07cb453211e0e6a67b21904e47f6ba1f9589e38f2e454" +dependencies = [ + "semver", + "serde", + "toml", + "url", +] + [[package]] name = "cc" version = "1.2.59" @@ -1020,18 +1039,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chacha20" -version = "0.10.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", - "zeroize", -] - [[package]] name = "charset" version = "0.1.5" @@ -1085,14 +1092,12 @@ dependencies = [ [[package]] name = "cipher" -version = "0.5.0-rc.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "block-buffer 0.11.0", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.1.6", "inout", - "zeroize", ] [[package]] @@ -1189,7 +1194,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308329d5d62e877ba02943db3a8e8c052de9fde7ab48283395ba0e6494efbabd" dependencies = [ "backtrace", - "btparse", "termcolor", ] @@ -1542,44 +1546,11 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.0-rc.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" -dependencies = [ - "hybrid-array", - "rand_core 0.9.5", -] - -[[package]] -name = "crypto_box" -version = "0.10.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bda4de3e070830cf3a27a394de135b6709aefcc54d1e16f2f029271254a6ed9" -dependencies = [ - "aead", - "chacha20", - "crypto_secretbox", - "curve25519-dalek 5.0.0-pre.1", - "salsa20", - "serdect", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto_secretbox" -version = "0.2.0-pre.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54532aae6546084a52cef855593daf9555945719eeeda9974150e0def854873e" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ - "aead", - "chacha20", - "cipher", "hybrid-array", - "poly1305", - "salsa20", - "subtle", - "zeroize", ] [[package]] @@ -1609,6 +1580,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1634,7 +1614,7 @@ dependencies = [ "cfg-if", "cpufeatures 0.2.17", "curve25519-dalek-derive", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.10", "fiat-crypto 0.3.0", "rand_core 0.9.5", "rustc_version", @@ -1654,6 +1634,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + [[package]] name = "darling" version = "0.21.3" @@ -1674,6 +1664,20 @@ dependencies = [ "darling_macro 0.23.0", ] +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + [[package]] name = "darling_core" version = "0.21.3" @@ -1701,6 +1705,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.117", +] + [[package]] name = "darling_macro" version = "0.21.3" @@ -1739,7 +1754,7 @@ dependencies = [ "hickory-proto", "hickory-server", "humantime", - "iroh-base", + "iroh-base 0.97.0", "lib", "n0-error", "rand 0.9.2", @@ -1768,8 +1783,8 @@ dependencies = [ "hex", "image", "iroh", - "iroh-base", - "iroh-metrics 0.38.3", + "iroh-base 0.97.0", + "iroh-metrics", "iroh-quinn", "lib", "n0-error", @@ -1857,6 +1872,37 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.117", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -1913,13 +1959,13 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.0-rc.3" +version = "0.11.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" +checksum = "afa94b64bfc6549e6e4b5a3216f22593224174083da7a90db47e951c4fb31725" dependencies = [ "block-buffer 0.11.0", "const-oid 0.10.2", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.1", ] [[package]] @@ -2190,7 +2236,7 @@ dependencies = [ "js-sys", "mime", "pin-project", - "reqwest 0.12.28", + "reqwest", "rustversion", "send_wrapper", "serde", @@ -2740,7 +2786,7 @@ version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct 0.2.0", + "base16ct", "crypto-bigint", "digest 0.10.7", "ff", @@ -2788,6 +2834,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "enum-assoc" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "enumset" version = "1.1.10" @@ -2870,6 +2927,18 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fastbloom" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" +dependencies = [ + "getrandom 0.3.4", + "libm", + "rand 0.9.2", + "siphasher 1.0.2", +] + [[package]] name = "fastrand" version = "2.4.1" @@ -3405,6 +3474,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gif" version = "0.14.1" @@ -3714,7 +3793,7 @@ dependencies = [ "http 1.4.0", "httpdate", "mime", - "sha1 0.10.6", + "sha1", ] [[package]] @@ -3954,7 +4033,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "typenum", - "zeroize", ] [[package]] @@ -4045,7 +4123,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2 0.6.3", - "system-configuration 0.7.0", + "system-configuration", "tokio", "tower-layer", "tower-service", @@ -4171,6 +4249,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "identity-hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdd7caa900436d8f13b2346fe10257e0c05c1f1f9e351f4f5d57c03bd5f45da" + [[package]] name = "idna" version = "1.1.0" @@ -4293,11 +4377,11 @@ dependencies = [ [[package]] name = "inout" -version = "0.2.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "hybrid-array", + "generic-array", ] [[package]] @@ -4309,18 +4393,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "interpolate_name" version = "0.2.4" @@ -4375,15 +4447,13 @@ dependencies = [ [[package]] name = "iroh" -version = "0.95.1" +version = "0.97.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2374ba3cdaac152dc6ada92d971f7328e6408286faab3b7350842b2ebbed4789" +checksum = "feb56e7e4b0ec7fba7efa6a236b016a52b5d927d50244aceb9e20566159b1a32" dependencies = [ - "aead", "backon", "bytes", "cfg_aliases", - "crypto_box", "data-encoding", "derive_more 2.1.1", "ed25519-dalek 3.0.0-pre.1", @@ -4391,32 +4461,33 @@ dependencies = [ "getrandom 0.3.4", "hickory-resolver", "http 1.4.0", - "igd-next", - "instant", - "iroh-base", - "iroh-metrics 0.37.0", - "iroh-quinn", - "iroh-quinn-proto", - "iroh-quinn-udp", + "ipnet", + "iroh-base 0.97.0", + "iroh-metrics", "iroh-relay", "n0-error", "n0-future", "n0-watcher", - "netdev", "netwatch", + "noq", + "noq-proto", + "noq-udp", + "papaya", "pin-project", "pkarr", "pkcs8 0.11.0-rc.11", + "portable-atomic", "portmapper", "rand 0.9.2", - "reqwest 0.12.28", + "reqwest", + "rustc-hash 2.1.2", "rustls", "rustls-pki-types", - "rustls-platform-verifier 0.5.3", "rustls-webpki", "serde", "smallvec", - "strum", + "strum 0.28.0", + "sync_wrapper", "time", "tokio", "tokio-stream", @@ -4425,7 +4496,6 @@ dependencies = [ "url", "wasm-bindgen-futures", "webpki-roots", - "z32", ] [[package]] @@ -4447,12 +4517,31 @@ dependencies = [ ] [[package]] -name = "iroh-blobs" +name = "iroh-base" version = "0.97.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c901304c1c28f257fcf9aae8c9149e54e0baf62f5eb2788cecde3bf1206a04e6" +checksum = "55a354e3396b62c14717ee807dfee9a7f43f6dad47e4ac0fd1d49f1ffad14ef0" +dependencies = [ + "curve25519-dalek 5.0.0-pre.1", + "data-encoding", + "derive_more 2.1.1", + "digest 0.11.0-rc.10", + "ed25519-dalek 3.0.0-pre.1", + "n0-error", + "rand_core 0.9.5", + "serde", + "sha2 0.11.0-rc.2", + "url", + "zeroize", + "zeroize_derive", +] + +[[package]] +name = "iroh-blobs" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b06914e77bd07bc1b3600096be66e2a63d391e8f4a901f61771630e20f2116" dependencies = [ - "anyhow", "arrayvec", "bao-tree", "bytes", @@ -4464,16 +4553,15 @@ dependencies = [ "genawaiter", "hex", "iroh", - "iroh-base", + "iroh-base 0.97.0", "iroh-io", - "iroh-metrics 0.37.0", - "iroh-quinn", - "iroh-tickets", + "iroh-metrics", + "iroh-tickets 0.4.0", "irpc", "n0-error", "n0-future", - "n0-snafu", "nested_enum_utils", + "noq", "postcard", "rand 0.9.2", "range-collections", @@ -4483,7 +4571,6 @@ dependencies = [ "self_cell", "serde", "smallvec", - "snafu", "tokio", "tracing", ] @@ -4501,21 +4588,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "iroh-metrics" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e3381da7c93c12d353230c74bba26131d1c8bf3a4d8af0fec041546454582e" -dependencies = [ - "iroh-metrics-derive", - "itoa", - "n0-error", - "postcard", - "ryu", - "serde", - "tracing", -] - [[package]] name = "iroh-metrics" version = "0.38.3" @@ -4544,54 +4616,11 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "iroh-n0des" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c691355d4b62e98a55e7d3fcf98ea3b800e7948c633cf937e7d31abe332f53" -dependencies = [ - "anyhow", - "bytes", - "derive_more 2.1.1", - "ed25519-dalek 3.0.0-pre.1", - "futures-buffered", - "getrandom 0.3.4", - "iroh", - "iroh-metrics 0.37.0", - "iroh-n0des-macro", - "iroh-tickets", - "irpc", - "irpc-iroh", - "n0-error", - "n0-future", - "postcard", - "rand 0.9.2", - "rcan", - "serde", - "serde_json", - "strum", - "thiserror 2.0.18", - "tokio", - "tracing", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "iroh-n0des-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e15d38b6ae3d9480e49883bea72880f80d595276e34090f5096d844e6f7f5e40" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "iroh-proxy-utils" version = "0.1.0" -source = "git+https://github.com/n0-computer/iroh-proxy-utils?branch=main#38ef14f7bc215348d47987563bb1b5198cc91f40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250d4c136ea9b2226f7f50abc774129e8c59328eede75396d9dc618ec5548150" dependencies = [ "bytes", "derive_more 2.1.1", @@ -4603,11 +4632,11 @@ dependencies = [ "hyper-util", "iroh", "iroh-blobs", - "iroh-metrics 0.38.3", + "iroh-metrics", "n0-error", "n0-future", "pin-project", - "reqwest 0.12.28", + "reqwest", "tokio", "tokio-util", "tracing", @@ -4670,9 +4699,9 @@ dependencies = [ [[package]] name = "iroh-relay" -version = "0.95.1" +version = "0.97.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fbdf2aeffa7d6ede1a31f6570866c2199b1cee96a0b563994623795d1bac2c" +checksum = "d786b260cadfe82ae0b6a9e372e8c78949096a06c857d1c3521355cefced0f55" dependencies = [ "blake3", "bytes", @@ -4685,36 +4714,70 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "iroh-base", - "iroh-metrics 0.37.0", - "iroh-quinn", - "iroh-quinn-proto", + "iroh-base 0.97.0", + "iroh-metrics", "lru", "n0-error", "n0-future", + "noq", + "noq-proto", "num_enum", "pin-project", "pkarr", "postcard", "rand 0.9.2", - "reqwest 0.12.28", + "reqwest", "rustls", "rustls-pki-types", "serde", "serde_bytes", - "sha1 0.11.0-rc.2", - "strum", + "strum 0.28.0", "tokio", "tokio-rustls", "tokio-util", "tokio-websockets", "tracing", "url", + "vergen-gitcl", "webpki-roots", "ws_stream_wasm", "z32", ] +[[package]] +name = "iroh-services" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983bab90919b719b2f0c73277c78f7d77c9eccb5e9fdcbab4383be97a233c489" +dependencies = [ + "anyhow", + "built 0.7.7", + "bytes", + "derive_more 2.1.1", + "ed25519-dalek 3.0.0-pre.1", + "futures-buffered", + "getrandom 0.3.4", + "iroh", + "iroh-metrics", + "iroh-tickets 0.4.0", + "irpc", + "irpc-iroh", + "n0-error", + "n0-future", + "portmapper", + "postcard", + "rand 0.9.2", + "rcan", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 2.0.18", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", +] + [[package]] name = "iroh-tickets" version = "0.2.0" @@ -4723,7 +4786,21 @@ checksum = "1a322053cacddeca222f0999ce3cf6aa45c64ae5ad8c8911eac9b66008ffbaa5" dependencies = [ "data-encoding", "derive_more 2.1.1", - "iroh-base", + "iroh-base 0.95.1", + "n0-error", + "postcard", + "serde", +] + +[[package]] +name = "iroh-tickets" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab64bac4bb573b9cfd2142bd2876ed65ca792efbc4398361a4ee51a0f9afbed6" +dependencies = [ + "data-encoding", + "derive_more 2.1.1", + "iroh-base 0.97.0", "n0-error", "postcard", "serde", @@ -4731,16 +4808,16 @@ dependencies = [ [[package]] name = "irpc" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bee97aaa18387c4f0aae61058195dc9f9dea3e41c0e272973fe3e9bf611563d" +checksum = "4f47b7c52662d673df377b5ac40c121c7ff56eb764e520fae6543686132f7957" dependencies = [ "futures-buffered", "futures-util", - "iroh-quinn", "irpc-derive", "n0-error", "n0-future", + "noq", "postcard", "rcgen", "rustls", @@ -4753,9 +4830,9 @@ dependencies = [ [[package]] name = "irpc-derive" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58148196d2230183c9679431ac99b57e172000326d664e8456fa2cd27af6505a" +checksum = "83c1a4b460634aeed6dc01236a0047867de70e30562d91a0ad031dcb3ac33fb4" dependencies = [ "proc-macro2", "quote", @@ -4764,13 +4841,13 @@ dependencies = [ [[package]] name = "irpc-iroh" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b254105bdaf86bc63786a37f81ba40e84d861b870d7626b51e14ebbb2ba50" +checksum = "6dd882f8cc059ac28ff54195a4933226807206c939c14680281c0ddb8434b3a8" dependencies = [ "getrandom 0.3.4", "iroh", - "iroh-base", + "iroh-base 0.97.0", "irpc", "n0-error", "n0-future", @@ -5137,26 +5214,25 @@ dependencies = [ "hyper", "hyper-util", "iroh", - "iroh-base", + "iroh-base 0.97.0", "iroh-blobs", - "iroh-metrics 0.38.3", - "iroh-n0des", + "iroh-metrics", "iroh-proxy-utils", "iroh-quinn", "iroh-relay", - "iroh-tickets", + "iroh-services", + "iroh-tickets 0.2.0", "k8s-openapi", "kube", "log", "n0-error", "n0-future", "n0-tracing-test", - "n0des-local", "open", "openidconnect", "postcard", "rand 0.9.2", - "reqwest 0.12.28", + "reqwest", "secrecy", "semver", "sentry", @@ -5373,6 +5449,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "mac-addr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d25b0e0b648a86960ac23b7ad4abb9717601dec6f66c165f5b037f3f03065f" + [[package]] name = "macro-string" version = "0.1.4" @@ -5684,19 +5766,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "n0-snafu" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1815107e577a95bfccedb4cfabc73d709c0db6d12de3f14e0f284a8c5036dc4f" -dependencies = [ - "anyhow", - "btparse", - "color-backtrace", - "snafu", - "tracing-error", -] - [[package]] name = "n0-tracing-test" version = "0.3.0" @@ -5720,30 +5789,15 @@ dependencies = [ [[package]] name = "n0-watcher" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38acf13c1ddafc60eb7316d52213467f8ccb70b6f02b65e7d97f7799b1f50be4" +checksum = "38795f7932e6e9d1c6e989270ef5b3ff24ebb910e2c9d4bed2d28d8bae3007dc" dependencies = [ "derive_more 2.1.1", "n0-error", "n0-future", ] -[[package]] -name = "n0des-local" -version = "0.1.0" -dependencies = [ - "iroh", - "iroh-n0des", - "irpc", - "irpc-iroh", - "n0-error", - "rand 0.9.2", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "native-tls" version = "0.2.18" @@ -5805,18 +5859,23 @@ dependencies = [ [[package]] name = "netdev" -version = "0.38.2" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ab878b4c90faf36dab10ea51d48c69ae9019bcca47c048a7c9b273d5d7a823" +checksum = "1b0a0096d9613ee878dba89bbe595f079d373e3f1960d882e4f2f78ff9c30a0a" dependencies = [ + "block2", + "dispatch2", "dlopen2 0.5.0", "ipnet", "libc", + "mac-addr", "netlink-packet-core", "netlink-packet-route", "netlink-sys", + "objc2-core-foundation", + "objc2-system-configuration", "once_cell", - "system-configuration 0.6.1", + "plist", "windows-sys 0.59.0", ] @@ -5831,9 +5890,9 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" +checksum = "df9854ea6ad14e3f4698a7f03b65bce0833dd2d81d594a0e4a984170537146b6" dependencies = [ "bitflags 2.11.0", "libc", @@ -5870,15 +5929,14 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f2acd376ef48b6c326abf3ba23c449e0cb8aa5c2511d189dd8a8a3bfac889b" +checksum = "3b1b27babe89ef9f2237bc6c028bea24fa84163a1b6f8f17ff93573ebd7d861f" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", "derive_more 2.1.1", - "iroh-quinn-udp", "js-sys", "libc", "n0-error", @@ -5889,6 +5947,9 @@ dependencies = [ "netlink-packet-route", "netlink-proto", "netlink-sys", + "noq-udp", + "objc2-core-foundation", + "objc2-system-configuration", "pin-project-lite", "serde", "socket2 0.6.3", @@ -5927,29 +5988,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] -name = "nom" -version = "7.1.3" +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "noq" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "8df966fb44ac763bc86da97fa6c811c54ae82ef656575949f93c6dae0c9f09bf" dependencies = [ - "memchr", - "minimal-lexical", + "bytes", + "cfg_aliases", + "noq-proto", + "noq-udp", + "pin-project-lite", + "rustc-hash 2.1.2", + "rustls", + "socket2 0.6.3", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "web-time", ] [[package]] -name = "nom" -version = "8.0.0" +name = "noq-proto" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +checksum = "5c61b72abd670eebc05b5cf720e077b04a3ef3354bc7bc19f1c3524cb424db7b" dependencies = [ - "memchr", + "aes-gcm", + "bytes", + "derive_more 2.1.1", + "enum-assoc", + "fastbloom", + "getrandom 0.3.4", + "identity-hash", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier 0.6.2", + "slab", + "sorted-index-buffer", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", ] [[package]] -name = "noop_proc_macro" -version = "0.3.0" +name = "noq-udp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" +checksum = "bb9be4fedd6b98f3ba82ccd3506f4d0219fb723c3f97c67e12fe1494aa020e44" +dependencies = [ + "cfg_aliases", + "libc", + "socket2 0.6.3", + "tracing", + "windows-sys 0.61.2", +] [[package]] name = "ntimestamp" @@ -6101,7 +6224,7 @@ dependencies = [ "getrandom 0.2.17", "http 1.4.0", "rand 0.8.5", - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "serde_path_to_error", @@ -6179,7 +6302,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.11.0", + "block2", "dispatch2", + "libc", "objc2", ] @@ -6292,6 +6417,31 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "libc", + "objc2", + "objc2-core-foundation", + "objc2-security", +] + [[package]] name = "objc2-ui-kit" version = "0.3.2" @@ -6380,6 +6530,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "open" version = "5.3.3" @@ -6546,6 +6702,16 @@ dependencies = [ "system-deps", ] +[[package]] +name = "papaya" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" +dependencies = [ + "equivalent", + "seize", +] + [[package]] name = "parking" version = "2.2.1" @@ -6832,29 +6998,17 @@ version = "5.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bfb9143bbba379f246211eb68074d78db9cc048e4c5701f3b0e6cb1ec67ca2" dependencies = [ - "async-compat", "base32", "bytes", "cfg_aliases", "document-features", - "dyn-clone", "ed25519-dalek 3.0.0-pre.1", - "futures-buffered", - "futures-lite", "getrandom 0.4.2", - "log", - "lru", "ntimestamp", - "reqwest 0.13.2", "self_cell", "serde", - "sha1_smol", "simple-dns", "thiserror 2.0.18", - "tokio", - "tracing", - "url", - "wasm-bindgen-futures", ] [[package]] @@ -6894,6 +7048,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.13.1", + "quick-xml", + "serde", + "time", +] + [[package]] name = "png" version = "0.17.16" @@ -6927,12 +7094,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" [[package]] -name = "poly1305" -version = "0.9.0-rc.2" +name = "polyval" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ + "cfg-if", "cpufeatures 0.2.17", + "opaque-debug", "universal-hash", ] @@ -6947,9 +7116,9 @@ dependencies = [ [[package]] name = "portmapper" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b575f975dcf03e258b0c7ab3f81497d7124f508884c37da66a7314aa2a8d467" +checksum = "74748bc706fa6b6aebac6bbe0bbe0de806b384cb5c557ea974f771360a4e3858" dependencies = [ "base64 0.22.1", "bytes", @@ -6958,7 +7127,7 @@ dependencies = [ "futures-util", "hyper-util", "igd-next", - "iroh-metrics 0.37.0", + "iroh-metrics", "libc", "n0-error", "netwatch", @@ -7231,6 +7400,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" version = "0.11.9" @@ -7257,7 +7435,6 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ - "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -7444,7 +7621,7 @@ dependencies = [ "av-scenechange", "av1-grain", "bitstream-io", - "built", + "built 0.8.0", "cfg-if", "interpolate_name", "itertools 0.14.0", @@ -7703,41 +7880,6 @@ dependencies = [ "webpki-roots", ] -[[package]] -name = "reqwest" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "http 1.4.0", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier 0.6.2", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "resolv-conf" version = "0.7.6" @@ -7977,16 +8119,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "salsa20" -version = "0.11.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ff3b81c8a6e381bc1673768141383f9328048a60edddcfc752a8291a138443" -dependencies = [ - "cfg-if", - "cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -8060,7 +8192,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct 0.2.0", + "base16ct", "der 0.7.10", "generic-array", "pkcs8 0.10.2", @@ -8100,6 +8232,16 @@ dependencies = [ "libc", ] +[[package]] +name = "seize" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "selectors" version = "0.24.0" @@ -8129,6 +8271,10 @@ name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "send_wrapper" @@ -8147,7 +8293,7 @@ checksum = "989425268ab5c011e06400187eed6c298272f8ef913e49fcadc3fda788b45030" dependencies = [ "httpdate", "native-tls", - "reqwest 0.12.28", + "reqwest", "sentry-actix", "sentry-backtrace", "sentry-contexts", @@ -8467,16 +8613,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "serdect" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af4a3e75ebd5599b30d4de5768e00b5095d518a79fefc3ecbaf77e665d1ec06" -dependencies = [ - "base16ct 1.0.0", - "serde", -] - [[package]] name = "servo_arc" version = "0.2.0" @@ -8498,23 +8634,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha1" -version = "0.11.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e046edf639aa2e7afb285589e5405de2ef7e61d4b0ac1e30256e3eab911af9" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.11.0-rc.3", -] - -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - [[package]] name = "sha2" version = "0.10.9" @@ -8534,7 +8653,7 @@ checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" dependencies = [ "cfg-if", "cpufeatures 0.2.17", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.10", ] [[package]] @@ -8700,7 +8819,6 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" dependencies = [ - "backtrace", "snafu-derive", ] @@ -8736,6 +8854,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "sorted-index-buffer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea06cc588e43c632923a55450401b8f25e628131571d4e1baea1bdfdb2b5ed06" + [[package]] name = "soup3" version = "0.5.0" @@ -8851,7 +8975,16 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "strum_macros", + "strum_macros 0.27.2", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", ] [[package]] @@ -8866,6 +8999,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "subsecond" version = "0.7.4" @@ -8953,17 +9098,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.11.0", - "core-foundation 0.9.4", - "system-configuration-sys", -] - [[package]] name = "system-configuration" version = "0.7.0" @@ -9483,16 +9617,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -9596,7 +9720,7 @@ dependencies = [ "native-tls", "rand 0.9.2", "rustls", - "sha1 0.10.6", + "sha1", "thiserror 2.0.18", "utf-8", ] @@ -9613,7 +9737,7 @@ dependencies = [ "httparse", "log", "rand 0.9.2", - "sha1 0.10.6", + "sha1", "thiserror 2.0.18", "utf-8", ] @@ -9665,11 +9789,11 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" -version = "0.6.0-rc.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.1.6", "subtle", ] @@ -9786,6 +9910,54 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "vergen-lib 9.1.0", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9dfc1de6eb2e08a4ddf152f1b179529638bedc0ea95e6d667c014506377aefe" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib 0.1.6", +] + +[[package]] +name = "vergen-lib" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version-compare" version = "0.2.1" @@ -10724,9 +10896,9 @@ dependencies = [ [[package]] name = "wmi" -version = "0.17.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120d8c2b6a7c96c27bf4a7947fd7f02d73ca7f5958b8bd72a696e46cb5521ee6" +checksum = "7c81b85c57a57500e56669586496bf2abd5cf082b9d32995251185d105208b64" dependencies = [ "chrono", "futures", diff --git a/Cargo.toml b/Cargo.toml index 8715482..10fc977 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,13 @@ members = [ "cli", "lib", - "n0des-local", "ui" ] +exclude = ["n0des-local"] resolver = "2" [workspace.dependencies] -iroh-proxy-utils = { git = "https://github.com/n0-computer/iroh-proxy-utils", branch = "main" } +iroh-proxy-utils = "0.1.0" lib = { path = "lib" } # n0-snafu 0.2.2 requires ^0.7.0 but color-backtrace 0.7.3 removed # `is_dependency_code` which n0-snafu uses. This constraint intersects with @@ -26,12 +26,12 @@ hex = "0.4.3" http = "1" hyper = "1" hyper-util = { version = "0.1.19", features = ["full"] } -iroh = { version = "0.95", default-features = false } -iroh-base = { version = "0.95" } +iroh = { version = "0.97", default-features = false } +iroh-base = { version = "0.97" } iroh-tickets = "0.2" iroh-metrics = "0.38" -iroh-n0des = { version = "0.8" } -iroh-relay = { version = "0.95" } +iroh-services = { version = "0.12", features = ["net_diagnostics", "client_host"] } +iroh-relay = { version = "0.97" } log = "0.4" open = "5" openidconnect = "4.0.1" diff --git a/Dockerfile b/Dockerfile index 9fb60d9..ce87f96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.88-bookworm AS builder +FROM rust:1.89-bookworm AS builder WORKDIR /app diff --git a/lib/Cargo.toml b/lib/Cargo.toml index db8f1dc..9c96eda 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -18,7 +18,7 @@ hyper.workspace = true hyper-util.workspace = true iroh-base.workspace = true iroh-metrics.workspace = true -iroh-n0des.workspace = true +iroh-services.workspace = true iroh-proxy-utils.workspace = true iroh-tickets.workspace = true iroh.workspace = true @@ -46,7 +46,7 @@ tracing-subscriber.workspace = true tracing.workspace = true url.workspace = true uuid.workspace = true -iroh-blobs = "0.97.0" +iroh-blobs = "0.99.0" httparse = "1.10.1" ttl_cache = "0.5.1" askama = "0.15.1" @@ -60,7 +60,6 @@ http-body-util = "0.1.3" hyper = { version = "1.8.1", features = ["full"] } hyper-util = { version = "0.1.19", features = ["full"] } n0-tracing-test = "0.3.0" -n0des-local = { path = "../n0des-local" } tempfile = "3" [features] diff --git a/lib/src/diagnostics.rs b/lib/src/diagnostics.rs new file mode 100644 index 0000000..f9d6148 --- /dev/null +++ b/lib/src/diagnostics.rs @@ -0,0 +1,126 @@ +use std::{str::FromStr, sync::Arc}; + +use iroh::Endpoint; +use iroh_services::{ApiSecret, Client, ClientHost, caps::NetDiagnosticsCap}; +use n0_error::{Result, StackResultExt, StdResultExt}; +use serde::{Deserialize, Serialize}; +use tracing::{info, warn}; + +use crate::Repo; + +const IROH_SERVICES_API_KEY: &str = "IROH_SERVICES_API_KEY"; + +/// Persisted diagnostics preferences. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DiagnosticsSettings { + /// Whether network diagnostics collection is enabled. + #[serde(default = "default_enabled")] + pub enabled: bool, + /// Whether the user has seen the opt-in prompt. + #[serde(default)] + pub prompted: bool, +} + +fn default_enabled() -> bool { + true +} + +impl Default for DiagnosticsSettings { + fn default() -> Self { + Self { + enabled: true, + prompted: false, + } + } +} + +/// Read the iroh-services API key from the environment, falling back to a +/// build-time value. Returns `None` when neither is set. +pub(crate) fn iroh_services_api_key_from_env() -> Result> { + let key_str = match std::env::var(IROH_SERVICES_API_KEY) { + Ok(s) => s, + Err(_) => match option_env!("BUILD_IROH_SERVICES_API_KEY") { + None => return Ok(None), + Some(s) => s.to_string(), + }, + }; + let api_secret = + ApiSecret::from_str(&key_str).context("Failed to parse iroh-services API key from env")?; + Ok(Some(api_secret)) +} + +/// State returned after diagnostics are started, kept alive to maintain +/// the ClientHost connection. +#[derive(Debug, Clone)] +pub struct DiagnosticsHandle { + _client: Arc, +} + +/// Start net diagnostics: connect to iroh-services, grant the +/// `NetDiagnosticsCap::GetAny` capability, and return a [`ClientHost`] that +/// must be registered on the Router so the service can dial back in. +/// +/// Returns `(ClientHost, DiagnosticsHandle)` on success. The caller must +/// `.accept(CLIENT_HOST_ALPN, host)` on its Router builder. +pub async fn start_diagnostics( + endpoint: &Endpoint, + api_secret: ApiSecret, +) -> Result<(ClientHost, DiagnosticsHandle)> { + let remote_id = api_secret.addr().id; + info!(remote=%remote_id.fmt_short(), "connecting to iroh-services for net diagnostics"); + + let client = Client::builder(endpoint) + .api_secret(api_secret)? + .build() + .await + .std_context("Failed to connect to iroh-services for diagnostics")?; + + // Grant the capability in a background task so we don't block startup + // if the remote is temporarily unavailable. + let grant_client = client.clone(); + tokio::spawn(async move { + if let Err(err) = grant_client + .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) + .await + { + warn!("Failed to grant net diagnostics capability: {err:#}"); + } else { + info!("Granted NetDiagnosticsCap::GetAny to iroh-services"); + } + }); + + let host = ClientHost::new(endpoint); + let handle = DiagnosticsHandle { + _client: Arc::new(client), + }; + Ok((host, handle)) +} + +impl Repo { + const DIAGNOSTICS_SETTINGS_FILE: &str = "diagnostics_settings.yml"; + + /// Load diagnostics settings from disk, returning defaults if the file + /// does not exist. + pub async fn diagnostics_settings(&self) -> Result { + let path = self.path().join(Self::DIAGNOSTICS_SETTINGS_FILE); + if !path.exists() { + return Ok(DiagnosticsSettings::default()); + } + let data = tokio::fs::read_to_string(&path) + .await + .context("failed to read diagnostics settings")?; + let settings: DiagnosticsSettings = + serde_yml::from_str(&data).std_context("failed to parse diagnostics settings")?; + Ok(settings) + } + + /// Persist diagnostics settings to disk. + pub async fn write_diagnostics_settings(&self, settings: &DiagnosticsSettings) -> Result<()> { + let path = self.path().join(Self::DIAGNOSTICS_SETTINGS_FILE); + let data = serde_yml::to_string(settings).anyerr()?; + tokio::fs::write(&path, data) + .await + .context("failed to write diagnostics settings")?; + Ok(()) + } +} diff --git a/lib/src/gateway.rs b/lib/src/gateway.rs index a0f06e3..c238bab 100644 --- a/lib/src/gateway.rs +++ b/lib/src/gateway.rs @@ -300,15 +300,10 @@ impl ErrorResponseWriter { fn has_existing_peer_conn(endpoint: &Endpoint) -> bool { let endpoint_metrics = endpoint.metrics(); - let direct_current = endpoint_metrics - .magicsock - .num_direct_conns_added + let conns_current = endpoint_metrics + .socket + .num_conns_opened .get() - .saturating_sub(endpoint_metrics.magicsock.num_direct_conns_removed.get()); - let relay_current = endpoint_metrics - .magicsock - .num_relay_conns_added - .get() - .saturating_sub(endpoint_metrics.magicsock.num_relay_conns_removed.get()); - direct_current + relay_current > 0 + .saturating_sub(endpoint_metrics.socket.num_conns_closed.get()); + conns_current > 0 } diff --git a/lib/src/gateway/metrics.rs b/lib/src/gateway/metrics.rs index d8c626c..a19d73b 100644 --- a/lib/src/gateway/metrics.rs +++ b/lib/src/gateway/metrics.rs @@ -173,30 +173,25 @@ impl GatewayMetrics { fn render(&self, endpoint: &Endpoint, downstream_metrics: &Arc) -> String { let endpoint_metrics = endpoint.metrics(); - let direct_added = endpoint_metrics.magicsock.num_direct_conns_added.get(); - let direct_removed = endpoint_metrics.magicsock.num_direct_conns_removed.get(); - let relay_added = endpoint_metrics.magicsock.num_relay_conns_added.get(); - let relay_removed = endpoint_metrics.magicsock.num_relay_conns_removed.get(); - let relay_send_errors = endpoint_metrics.magicsock.send_relay_error.get(); - let relay_home_changes = endpoint_metrics.magicsock.relay_home_change.get(); - let handshake_success = endpoint_metrics - .magicsock - .connection_handshake_success - .get(); - let endpoints_contacted = endpoint_metrics.magicsock.endpoints_contacted.get(); - let endpoints_contacted_directly = endpoint_metrics - .magicsock - .endpoints_contacted_directly - .get(); - let path_ping_failures = endpoint_metrics.magicsock.path_ping_failures.get(); - let path_marked_outdated = endpoint_metrics.magicsock.path_marked_outdated.get(); - let path_failure_resets = endpoint_metrics.magicsock.path_failure_resets.get(); + let direct_added = endpoint_metrics.socket.transport_ip_paths_added.get(); + let direct_removed = endpoint_metrics.socket.transport_ip_paths_removed.get(); + let relay_added = endpoint_metrics.socket.transport_relay_paths_added.get(); + let relay_removed = endpoint_metrics.socket.transport_relay_paths_removed.get(); + let relay_home_changes = endpoint_metrics.socket.relay_home_change.get(); + let conns_opened = endpoint_metrics.socket.num_conns_opened.get(); + let conns_closed = endpoint_metrics.socket.num_conns_closed.get(); + let conns_direct = endpoint_metrics.socket.num_conns_direct.get(); + let paths_direct = endpoint_metrics.socket.paths_direct.get(); + let paths_relay = endpoint_metrics.socket.paths_relay.get(); + let holepunch_attempts = endpoint_metrics.socket.holepunch_attempts.get(); let direct_current = direct_added.saturating_sub(direct_removed); let relay_current = relay_added.saturating_sub(relay_removed); - let recv_total = endpoint_metrics.magicsock.recv_data_ipv4.get() - + endpoint_metrics.magicsock.recv_data_ipv6.get() - + endpoint_metrics.magicsock.recv_data_relay.get(); - let send_total = endpoint_metrics.magicsock.send_data.get(); + let recv_total = endpoint_metrics.socket.recv_data_ipv4.get() + + endpoint_metrics.socket.recv_data_ipv6.get() + + endpoint_metrics.socket.recv_data_relay.get(); + let send_total = endpoint_metrics.socket.send_ipv4.get() + + endpoint_metrics.socket.send_ipv6.get() + + endpoint_metrics.socket.send_relay.get(); let mut downstream_openmetrics = String::new(); let mut registry = Registry::default(); @@ -246,10 +241,10 @@ impl GatewayMetrics { "# TYPE iroh_gateway_upstream_failures_total counter\n", "iroh_gateway_upstream_failures_total{{class=\"5xx\",peer_conn_state=\"with_existing\"}} {}\n", "iroh_gateway_upstream_failures_total{{class=\"5xx\",peer_conn_state=\"without_existing\"}} {}\n", - "# HELP iroh_gateway_iroh_recv_bytes_total Total iroh magicsock bytes received.\n", + "# HELP iroh_gateway_iroh_recv_bytes_total Total iroh socket bytes received.\n", "# TYPE iroh_gateway_iroh_recv_bytes_total counter\n", "iroh_gateway_iroh_recv_bytes_total {}\n", - "# HELP iroh_gateway_iroh_send_bytes_total Total iroh magicsock bytes sent.\n", + "# HELP iroh_gateway_iroh_send_bytes_total Total iroh socket bytes sent.\n", "# TYPE iroh_gateway_iroh_send_bytes_total counter\n", "iroh_gateway_iroh_send_bytes_total {}\n\n", "# HELP iroh_gateway_quic_connections_opened_total QUIC peer connections opened by transport path.\n", @@ -264,16 +259,17 @@ impl GatewayMetrics { "# TYPE iroh_gateway_quic_connections_current gauge\n", "iroh_gateway_quic_connections_current{{path=\"direct\"}} {}\n", "iroh_gateway_quic_connections_current{{path=\"relay\"}} {}\n\n", - "# HELP iroh_gateway_tunnel_connectivity_events_total Tunnel connectivity events from iroh magicsock state.\n", + "# HELP iroh_gateway_tunnel_connectivity_events_total Tunnel connectivity events from iroh socket state.\n", "# TYPE iroh_gateway_tunnel_connectivity_events_total counter\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"relay_send_error\"}} {}\n", "iroh_gateway_tunnel_connectivity_events_total{{event=\"relay_home_change\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"connection_handshake_success\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"endpoints_contacted\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"endpoints_contacted_directly\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"path_ping_failures\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"path_marked_outdated\"}} {}\n", - "iroh_gateway_tunnel_connectivity_events_total{{event=\"path_failure_resets\"}} {}\n\n", + "iroh_gateway_tunnel_connectivity_events_total{{event=\"conns_opened\"}} {}\n", + "iroh_gateway_tunnel_connectivity_events_total{{event=\"conns_closed\"}} {}\n", + "iroh_gateway_tunnel_connectivity_events_total{{event=\"conns_direct\"}} {}\n", + "iroh_gateway_tunnel_connectivity_events_total{{event=\"holepunch_attempts\"}} {}\n", + "# HELP iroh_gateway_active_paths Current active paths by transport type.\n", + "# TYPE iroh_gateway_active_paths gauge\n", + "iroh_gateway_active_paths{{transport=\"direct\"}} {}\n", + "iroh_gateway_active_paths{{transport=\"relay\"}} {}\n\n", ), self.requests_tunnel_total.load(Ordering::Relaxed), self.requests_origin_total.load(Ordering::Relaxed), @@ -316,14 +312,13 @@ impl GatewayMetrics { relay_removed, direct_current, relay_current, - relay_send_errors, relay_home_changes, - handshake_success, - endpoints_contacted, - endpoints_contacted_directly, - path_ping_failures, - path_marked_outdated, - path_failure_resets, + conns_opened, + conns_closed, + conns_direct, + holepunch_attempts, + paths_direct, + paths_relay, ) + &downstream_openmetrics } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 2a81243..39df5fc 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -2,6 +2,7 @@ mod auth; pub mod config; pub mod datum_apis; pub mod datum_cloud; +pub mod diagnostics; pub mod gateway; pub mod heartbeat; mod http_user_agent; @@ -13,6 +14,7 @@ pub mod tunnels; pub mod update; pub use config::{Config, DiscoveryMode, GatewayConfig}; +pub use diagnostics::DiagnosticsSettings; pub use heartbeat::HeartbeatAgent; pub use http_user_agent::datum_http_user_agent; pub use node::*; diff --git a/lib/src/node.rs b/lib/src/node.rs index 92e21d7..ed80592 100644 --- a/lib/src/node.rs +++ b/lib/src/node.rs @@ -1,11 +1,12 @@ use std::{fmt::Debug, net::SocketAddr, str::FromStr, sync::Arc, time::Duration}; use iroh::{ - Endpoint, EndpointId, SecretKey, discovery::dns::DnsDiscovery, endpoint::default_relay_mode, + Endpoint, EndpointId, SecretKey, + address_lookup::dns::DnsAddressLookup, + endpoint::{default_relay_mode, presets}, protocol::Router, }; use iroh_base::RelayUrl; -use iroh_n0des::ApiSecret; use iroh_proxy_utils::upstream::UpstreamMetrics; use iroh_proxy_utils::{ ALPN as IROH_HTTP_CONNECT_ALPN, Authority, HttpProxyRequest, HttpProxyRequestKind, @@ -16,6 +17,7 @@ use iroh_proxy_utils::{ }; use iroh_relay::dns::{DnsProtocol, DnsResolver}; use iroh_relay::{RelayConfig, RelayMap}; +use iroh_services::{ApiSecret, CLIENT_HOST_ALPN}; use n0_error::{Result, StackResultExt, StdResultExt}; use tokio::{ net::TcpListener, @@ -24,6 +26,7 @@ use tokio::{ }; use tracing::{Instrument, debug, error_span, info, instrument, warn}; +use crate::diagnostics::{self, DiagnosticsHandle}; use crate::{ProxyState, Repo, StateWrapper, TcpProxyData, config::Config}; #[derive(Debug, Clone)] @@ -52,7 +55,8 @@ pub struct ListenNode { state: StateWrapper, repo: Repo, metrics: Arc, - _n0des: Option>, + _n0des: Option>, + _diagnostics: Option, } impl ListenNode { @@ -75,6 +79,31 @@ impl ListenNode { let upstream_proxy = UpstreamProxy::new(state.clone())?; let metrics = upstream_proxy.metrics(); + // Optionally start net diagnostics based on persisted settings. + let diagnostics_handle = match setup_diagnostics(&repo, &endpoint).await { + Ok(Some((host, handle))) => { + let router = Router::builder(endpoint) + .accept(IROH_HTTP_CONNECT_ALPN, upstream_proxy) + .accept(CLIENT_HOST_ALPN, host) + .spawn(); + + let this = Self { + repo, + router, + state, + metrics, + _n0des: n0des, + _diagnostics: Some(handle), + }; + return Ok(this); + } + Ok(None) => None, + Err(err) => { + warn!("Failed to start net diagnostics, continuing without: {err:#}"); + None + } + }; + let router = Router::builder(endpoint) .accept(IROH_HTTP_CONNECT_ALPN, upstream_proxy) .spawn(); @@ -85,6 +114,7 @@ impl ListenNode { state, metrics, _n0des: n0des, + _diagnostics: diagnostics_handle, }; Ok(this) } @@ -217,7 +247,7 @@ impl AuthHandler for StateWrapper { pub struct ConnectNode { endpoint: Endpoint, proxy: DownstreamProxy, - _n0des: Option>, + _n0des: Option>, } impl ConnectNode { @@ -305,20 +335,20 @@ impl OutboundProxyHandle { pub(crate) async fn build_endpoint(secret_key: SecretKey, common: &Config) -> Result { let relay_mode = relay_mode_from_env_or_build().await?; let mut builder = match common.discovery_mode { - crate::config::DiscoveryMode::Dns => { - Endpoint::empty_builder(relay_mode).secret_key(secret_key) - } + crate::config::DiscoveryMode::Dns => Endpoint::empty_builder() + .relay_mode(relay_mode) + .secret_key(secret_key), crate::config::DiscoveryMode::Default | crate::config::DiscoveryMode::Hybrid => { - Endpoint::builder() + Endpoint::builder(presets::N0) .relay_mode(relay_mode) .secret_key(secret_key) } }; if let Some(addr) = common.ipv4_addr { - builder = builder.bind_addr_v4(addr); + builder = builder.bind_addr(addr)?; } if let Some(addr) = common.ipv6_addr { - builder = builder.bind_addr_v6(addr); + builder = builder.bind_addr(addr)?; } match common.discovery_mode { crate::config::DiscoveryMode::Default => {} @@ -335,7 +365,7 @@ pub(crate) async fn build_endpoint(secret_key: SecretKey, common: &Config) -> Re .build(); builder = builder.dns_resolver(resolver); } - builder = builder.discovery(DnsDiscovery::builder(origin)); + builder = builder.address_lookup(DnsAddressLookup::builder(origin)); } } let endpoint = builder.bind().await?; @@ -568,6 +598,30 @@ fn relays_to_map(relays: Vec) -> RelayMap { RelayMap::from_iter(relays.into_iter().map(RelayConfig::from)) } +/// Check diagnostics settings and API key availability; if enabled, start +/// the diagnostics client and return a ClientHost to register on the Router. +async fn setup_diagnostics( + repo: &Repo, + endpoint: &Endpoint, +) -> Result> { + let settings = repo.diagnostics_settings().await?; + if !settings.enabled { + info!("Net diagnostics disabled by user preference"); + return Ok(None); + } + + let api_secret = match diagnostics::iroh_services_api_key_from_env()? { + Some(s) => s, + None => { + info!("Net diagnostics disabled: IROH_SERVICES_API_KEY not set"); + return Ok(None); + } + }; + + let (host, handle) = diagnostics::start_diagnostics(endpoint, api_secret).await?; + Ok(Some((host, handle))) +} + pub(crate) fn n0des_api_secret_from_env() -> Result> { let api_secret_str = match std::env::var("N0DES_API_SECRET") { Ok(s) => s, @@ -584,7 +638,7 @@ pub(crate) fn n0des_api_secret_from_env() -> Result> { pub(crate) async fn build_n0des_client_opt( endpoint: &Endpoint, api_secret: Option, -) -> Option> { +) -> Option> { match api_secret { None => { info!("Disabling metrics collection: N0DES_API_SECRET is not set"); @@ -603,10 +657,10 @@ pub(crate) async fn build_n0des_client_opt( pub(crate) async fn build_n0des_client( endpoint: &Endpoint, api_secret: ApiSecret, -) -> Result> { +) -> Result> { let remote_id = api_secret.remote.id; debug!(remote=%remote_id.fmt_short(), "connecting to n0des endpoint"); - let client = iroh_n0des::Client::builder(endpoint) + let client = iroh_services::Client::builder(endpoint) .api_secret(api_secret)? .build() .await @@ -627,11 +681,11 @@ mod tests { assert_eq!(parsed[0].scheme(), "https"); assert_eq!( parsed[0].host_str(), - Some("iroh-relay.us-east-1.datumconnect.net.") + Some("iroh-relay.us-east-1.datumconnect.net") ); assert_eq!( parsed[1].host_str(), - Some("iroh-relay.us-west-1.datumconnect.net.") + Some("iroh-relay.us-west-1.datumconnect.net") ); } @@ -640,7 +694,7 @@ mod tests { let input = " relay-a.example.com, relay-a.example.com;;relay-b.example.com "; let parsed = parse_relay_urls(input).expect("should parse"); assert_eq!(parsed.len(), 2); - assert_eq!(parsed[0].host_str(), Some("relay-a.example.com.")); - assert_eq!(parsed[1].host_str(), Some("relay-b.example.com.")); + assert_eq!(parsed[0].host_str(), Some("relay-a.example.com")); + assert_eq!(parsed[1].host_str(), Some("relay-b.example.com")); } } diff --git a/lib/src/tests.rs b/lib/src/tests.rs index b87cb00..4bf1f45 100644 --- a/lib/src/tests.rs +++ b/lib/src/tests.rs @@ -3,7 +3,7 @@ use std::net::Ipv4Addr; use http_body_util::BodyExt; use hyper::{Request, StatusCode, client::conn::http2}; use hyper_util::rt::{TokioExecutor, TokioIo}; -use iroh::{Endpoint, discovery::static_provider::StaticProvider}; +use iroh::{Endpoint, address_lookup::memory::MemoryLookup, endpoint::presets}; use n0_error::{Result, StdResultExt}; use n0_future::task::AbortOnDropHandle; use n0_tracing_test::traced_test; @@ -15,11 +15,14 @@ use tokio::{ use crate::{Advertisment, ListenNode, ProxyState, Repo, TcpProxyData, gateway}; #[derive(Default)] -struct TestDiscovery(StaticProvider); +struct TestDiscovery(MemoryLookup); impl TestDiscovery { fn add(&self, endpoint: &Endpoint) { - endpoint.discovery().add(self.0.clone()); + endpoint + .address_lookup() + .expect("address lookup not configured") + .add(self.0.clone()); self.0.add_endpoint_info(endpoint.addr()); } } @@ -49,7 +52,7 @@ async fn gateway_end_to_end_to_upstream_http() -> Result<()> { let (gateway_addr, _gateway_task) = { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; - let endpoint = Endpoint::bind().await?; + let endpoint = Endpoint::bind(presets::N0).await?; discovery.add(&endpoint); let task = tokio::task::spawn(gateway::serve(endpoint, listener)); (addr, AbortOnDropHandle::new(task)) @@ -102,7 +105,7 @@ async fn gateway_forward_connect_tunnel() -> Result<()> { let (gateway_addr, _gateway_task) = { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; - let endpoint = Endpoint::bind().await?; + let endpoint = Endpoint::bind(presets::N0).await?; discovery.add(&endpoint); let task = tokio::task::spawn(gateway::serve(endpoint, listener)); (addr, AbortOnDropHandle::new(task)) @@ -170,7 +173,7 @@ async fn gateway_forward_h2c_requests_are_stable() -> Result<()> { let (gateway_addr, _gateway_task) = { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; - let endpoint = Endpoint::bind().await?; + let endpoint = Endpoint::bind(presets::N0).await?; discovery.add(&endpoint); let task = tokio::task::spawn(gateway::serve(endpoint, listener)); (addr, AbortOnDropHandle::new(task)) @@ -242,7 +245,7 @@ async fn gateway_forward_h2c_handles_closed_origin_connections() -> Result<()> { let (gateway_addr, _gateway_task) = { let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; - let endpoint = Endpoint::bind().await?; + let endpoint = Endpoint::bind(presets::N0).await?; discovery.add(&endpoint); let task = tokio::task::spawn(gateway::serve(endpoint, listener)); (addr, AbortOnDropHandle::new(task)) diff --git a/n0des-local/Cargo.toml b/n0des-local/Cargo.toml index df9d2a5..ffb4264 100644 --- a/n0des-local/Cargo.toml +++ b/n0des-local/Cargo.toml @@ -6,9 +6,9 @@ publish = false [dependencies] iroh = { workspace = true } -iroh-n0des = { workspace = true, features = ["tickets"] } -irpc = "0.11" -irpc-iroh = "0.11" +iroh-n0des = "0.10" +irpc = "0.13" +irpc-iroh = "0.13" n0-error = { workspace = true } rand = { workspace = true } tokio = { workspace = true } diff --git a/ui/src/main.rs b/ui/src/main.rs index fe36794..d3e1d7c 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -79,6 +79,15 @@ pub struct UpdateCheckContext { pub update_channel: Signal, } +/// Context for network diagnostics opt-in state. +#[derive(Clone)] +pub struct DiagnosticsContext { + /// Whether diagnostics collection is enabled. + pub enabled: Signal, + /// Whether the user has already seen the opt-in prompt. + pub prompted: Signal, +} + // Assets for favicons const FAVICON_DARK_196: Asset = asset!("/assets/icons/favicon-dark-196x196.png"); const FAVICON_LIGHT_196: Asset = asset!("/assets/icons/favicon-light-196x196.png"); @@ -570,6 +579,33 @@ fn App() -> Element { update_channel, }); + // Diagnostics opt-in state (loaded from repo settings). + let mut diag_enabled = use_signal(|| true); + let mut diag_prompted = use_signal(|| true); // default true to hide prompt until loaded + use_future(move || async move { + let repo = match lib::Repo::open_or_create(lib::Repo::default_location()).await { + Ok(r) => r, + Err(e) => { + tracing::warn!("Failed to open repo for diagnostics settings: {e:#}"); + return; + } + }; + match repo.diagnostics_settings().await { + Ok(s) => { + diag_enabled.set(s.enabled); + diag_prompted.set(s.prompted); + } + Err(e) => { + tracing::warn!("Failed to load diagnostics settings: {e:#}"); + } + } + }); + + provide_context(DiagnosticsContext { + enabled: diag_enabled, + prompted: diag_prompted, + }); + // Handle install now (toast or Settings). Read path from update_ready before clearing it — // the toast handler must not clear update_ready before this runs, or we rely only on disk. use_effect(move || { @@ -648,6 +684,90 @@ fn App() -> Element { } } } + // One-time diagnostics opt-in prompt + if !diag_prompted() { + DiagnosticsPrompt { + on_continue: move |_| { + // Accept defaults (enabled: true) and mark prompted + diag_prompted.set(true); + spawn(async move { + save_diagnostics_prompt(true).await; + }); + }, + on_opt_out: move |_| { + diag_enabled.set(false); + diag_prompted.set(true); + spawn(async move { + save_diagnostics_prompt(false).await; + }); + }, + } + } + } + } +} + +/// Save the diagnostics prompt response to disk. +async fn save_diagnostics_prompt(enabled: bool) { + let repo = match lib::Repo::open_or_create(lib::Repo::default_location()).await { + Ok(r) => r, + Err(e) => { + tracing::warn!("Failed to open repo for diagnostics prompt: {e:#}"); + return; + } + }; + let settings = lib::DiagnosticsSettings { + enabled, + prompted: true, + }; + if let Err(e) = repo.write_diagnostics_settings(&settings).await { + tracing::warn!("Failed to save diagnostics settings: {e:#}"); + } +} + +/// One-time prompt shown on first launch for network diagnostics opt-in. +#[component] +fn DiagnosticsPrompt( + on_continue: EventHandler, + on_opt_out: EventHandler, +) -> Element { + use crate::components::{Button, ButtonKind}; + + rsx! { + div { + class: "mt-[32px] fixed inset-0 z-50 flex items-center justify-center animate-in fade-in duration-100", + style: "background-color: rgba(0,0,0,0.2); -webkit-backdrop-filter: blur(1px); backdrop-filter: blur(1px);", + onclick: move |evt| { + evt.stop_propagation(); + on_continue.call(evt); + }, + div { + class: "w-full max-w-lg mx-auto p-8 bg-card-background rounded-lg border border-card-border shadow-card relative z-50", + onclick: move |evt| evt.stop_propagation(), + div { class: "mb-4", + h2 { class: "text-sm font-semibold text-foreground", + "Network diagnostics are enabled" + } + } + p { class: "text-1xs text-foreground/80 leading-relaxed", + "We collect network diagnostic data to help us identify and resolve connectivity issues faster. Your desktop identifier will always be anonymous." + } + p { class: "text-1xs text-foreground/60 leading-relaxed mt-4", + "Not willing to help us improve reliability? No worries! You can always opt out at any time in Settings \u{2192} Privacy \u{2192} Network Diagnostics." + } + div { class: "flex gap-2 mt-6", + Button { + text: "Continue", + kind: ButtonKind::Primary, + onclick: move |evt| on_continue.call(evt), + } + Button { + text: "Opt Out", + kind: ButtonKind::Outline, + onclick: move |evt| on_opt_out.call(evt), + } + } + } } } } diff --git a/ui/src/views/settings.rs b/ui/src/views/settings.rs index bd22a29..db05ac1 100644 --- a/ui/src/views/settings.rs +++ b/ui/src/views/settings.rs @@ -1,7 +1,7 @@ use crate::{ - components::{input::Input, Button, ButtonKind, Icon, IconSource}, + components::{input::Input, Button, ButtonKind, Icon, IconSource, Switch, SwitchThumb}, state::AppState, - Route, UpdateCheckContext, + DiagnosticsContext, Route, UpdateCheckContext, }; use dioxus::prelude::*; use lib::UpdateChannel; @@ -229,6 +229,69 @@ pub fn Settings() -> Element { } } } + // Privacy section + {PrivacySection()} + } + } +} + +#[component] +fn PrivacySection() -> Element { + let diag_ctx = consume_context::(); + let enabled = (diag_ctx.enabled)(); + + rsx! { + div { class: "bg-card-background border border-card-border rounded-lg", + div { class: "px-4 py-3 border-b border-card-border", + h2 { class: "text-sm text-foreground", "Privacy" } + } + div { class: "p-4 flex flex-col gap-4 max-w-md", + div { class: "flex flex-col gap-2", + p { class: "text-sm text-foreground font-medium", "Network Diagnostics" } + p { class: "text-1xs text-foreground/60", + "We collect network diagnostic data to help us identify and resolve connectivity issues faster. Your desktop identifier will always be anonymous." + } + div { class: "flex items-center gap-3 mt-1", + Switch { + checked: enabled, + on_checked_change: move |next: bool| { + let mut sig = diag_ctx.enabled; + spawn(async move { + let repo = match lib::Repo::open_or_create(lib::Repo::default_location()) + .await + { + Ok(r) => r, + Err(e) => { + tracing::warn!("Failed to open repo for diagnostics toggle: {e:#}"); + return; + } + }; + let mut settings = match repo.diagnostics_settings().await { + Ok(s) => s, + Err(e) => { + tracing::warn!("Failed to load diagnostics settings: {e:#}"); + return; + } + }; + settings.enabled = next; + if let Err(e) = repo.write_diagnostics_settings(&settings).await { + tracing::warn!("Failed to save diagnostics settings: {e:#}"); + return; + } + sig.set(next); + }); + }, + SwitchThumb {} + } + p { class: "text-1xs text-foreground/60", + if enabled { "Enabled" } else { "Disabled" } + } + } + p { class: "text-1xs text-foreground/40", + "Changes take effect on next app restart." + } + } + } } } }