diff --git a/browser-echo/Cargo.lock b/browser-echo/Cargo.lock index 02c79ef2..02705cdf 100644 --- a/browser-echo/Cargo.lock +++ b/browser-echo/Cargo.lock @@ -144,6 +144,45 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "asn1-rs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-channel" version = "2.5.0" @@ -178,12 +217,33 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "attohttpc" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" +dependencies = [ + "base64", + "http 1.4.0", + "log", + "url", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -228,6 +288,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "2.11.1" @@ -276,6 +345,7 @@ dependencies = [ "console_error_panic_hook", "getrandom 0.3.4", "iroh", + "iroh-services", "n0-future", "serde", "serde-wasm-bindgen 0.6.5", @@ -289,17 +359,47 @@ dependencies = [ "wasm-streams", ] +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" +dependencies = [ + "cargo-lock", +] + [[package]] name = "bumpalo" version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-lock" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63585cdf8572aa7adf0e30a253f988f2b77233bfac1973d52efb6dd53a75920e" +dependencies = [ + "semver", + "serde", + "toml", + "url", +] [[package]] name = "cc" @@ -695,6 +795,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + [[package]] name = "deranged" version = "0.5.8" @@ -971,7 +1085,7 @@ dependencies = [ "diatomic-waker", "futures-core", "pin-project-lite", - "spin", + "spin 0.10.0", ] [[package]] @@ -1335,6 +1449,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -1355,12 +1478,32 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin 0.9.8", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hickory-net" version = "0.26.1" @@ -1513,6 +1656,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2", "http 1.4.0", "http-body", "httparse", @@ -1707,6 +1851,26 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "igd-next" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de7238d487a9aff61f81b5ab41c0a841532a115a398b5fa92a2fadd0885e2581" +dependencies = [ + "attohttpc", + "bytes", + "futures", + "http 1.4.0", + "http-body-util", + "hyper", + "hyper-util", + "log", + "rand", + "tokio", + "url", + "xmltree", +] + [[package]] name = "indexmap" version = "2.14.0" @@ -1783,6 +1947,7 @@ dependencies = [ "papaya", "pin-project", "portable-atomic", + "portmapper", "rand", "reqwest", "rustc-hash", @@ -1916,6 +2081,106 @@ dependencies = [ "ws_stream_wasm", ] +[[package]] +name = "iroh-services" +version = "1.0.0" +source = "git+https://github.com/n0-computer/iroh-services?branch=Frando%2Ffix-wasm#136229c3c4688171dff50d1c2acb0f37e0f622cd" +dependencies = [ + "anyhow", + "base64", + "built", + "bytes", + "data-encoding", + "derive_more", + "ed25519-dalek", + "futures-buffered", + "getrandom 0.4.2", + "iroh", + "iroh-metrics", + "iroh-tickets", + "irpc", + "irpc-iroh", + "n0-error", + "n0-future", + "portmapper", + "postcard", + "rand", + "rcan", + "serde", + "serde_json", + "strum", + "thiserror 2.0.18", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", +] + +[[package]] +name = "iroh-tickets" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da53233419ca36bf521ed45683b7748366f9b233032891eefc2d70567a84ac54" +dependencies = [ + "data-encoding", + "derive_more", + "iroh-base", + "n0-error", + "postcard", + "serde", +] + +[[package]] +name = "irpc" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3623d6ff582b415904b29bbe6ebcb4a4f9a262ccdee05a45fdd003ef0950c386" +dependencies = [ + "futures-buffered", + "futures-util", + "irpc-derive", + "n0-error", + "n0-future", + "noq", + "postcard", + "rcgen", + "rustls", + "serde", + "smallvec", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "irpc-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c254013736de16472140d26904e6ac98e8f3887284dcf4af40f88c77411b56" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "irpc-iroh" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2342daed629b312f61e57e452b0750a59da162f261b97f260a6354de61d4fb0e" +dependencies = [ + "getrandom 0.3.4", + "iroh", + "iroh-base", + "irpc", + "n0-error", + "n0-future", + "postcard", + "serde", + "tokio", + "tracing", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -2102,6 +2367,12 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "1.2.0" @@ -2313,6 +2584,16 @@ dependencies = [ "wmi", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "noq" version = "1.0.0" @@ -2384,12 +2665,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2520,6 +2820,15 @@ dependencies = [ "objc2-security", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -2593,6 +2902,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + [[package]] name = "pem-rfc7468" version = "1.0.0" @@ -2688,6 +3007,35 @@ dependencies = [ "serde", ] +[[package]] +name = "portmapper" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc716c56a0a50f7e4e25f41446419599d47c6197cc5c9858174220e97c272e6" +dependencies = [ + "base64", + "bytes", + "derive_more", + "hyper-util", + "igd-next", + "iroh-metrics", + "libc", + "n0-error", + "n0-future", + "netwatch", + "num_enum", + "rand", + "serde", + "smallvec", + "socket2", + "time", + "tokio", + "tokio-util", + "tower-layer", + "tracing", + "url", +] + [[package]] name = "postcard" version = "1.1.3" @@ -2697,6 +3045,7 @@ dependencies = [ "cobs", "embedded-io 0.4.0", "embedded-io 0.6.1", + "heapless", "postcard-derive", "serde", ] @@ -2822,6 +3171,36 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rcan" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a624a4a4742f8c6e58fba99712e606cea0491b76f5b2345f06af5802101027" +dependencies = [ + "anyhow", + "derive_more", + "ed25519-dalek", + "hex", + "n0-future", + "postcard", + "serde", + "serdect", +] + +[[package]] +name = "rcgen" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57f6d249aad744e274e682777a50283a225a32705394ee6d5fcc01efa25e4055" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -2920,6 +3299,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustls" version = "0.23.40" @@ -3075,6 +3463,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" @@ -3157,6 +3549,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3291,6 +3692,15 @@ dependencies = [ "syn", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spin" version = "0.10.0" @@ -3599,6 +4009,30 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -3615,9 +4049,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.2", ] [[package]] @@ -3626,9 +4060,15 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.2", ] +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tower" version = "0.5.3" @@ -3718,6 +4158,16 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.23" @@ -3728,12 +4178,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -3826,6 +4279,7 @@ checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", + "serde_core", "wasm-bindgen", ] @@ -4367,6 +4821,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + [[package]] name = "winnow" version = "1.0.2" @@ -4510,6 +4970,49 @@ dependencies = [ "web-sys", ] +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + +[[package]] +name = "yasna" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" +dependencies = [ + "bit-vec", + "time", +] + [[package]] name = "yoke" version = "0.8.2" diff --git a/browser-echo/Cargo.toml b/browser-echo/Cargo.toml index 0e169550..466fa4fd 100644 --- a/browser-echo/Cargo.toml +++ b/browser-echo/Cargo.toml @@ -18,6 +18,7 @@ clap = { version = "4.5.30", features = ["derive"], optional = true } console_error_panic_hook = "0.1.7" getrandom = { version = "0.3", features = ["wasm_js"] } iroh = { version = "1.0.0", default-features = false, features = ["tls-ring"] } +iroh-services = "1.0.0" n0-future = "0.3" serde = "1.0.217" serde-wasm-bindgen = "0.6.5" @@ -40,3 +41,6 @@ debug = false lto = true opt-level = "z" panic = 'abort' + +[patch.crates-io] +iroh-services = { git = "https://github.com/n0-computer/iroh-services", branch = "Frando/fix-wasm" } diff --git a/browser-echo/README.md b/browser-echo/README.md index 8f199b07..56e90380 100644 --- a/browser-echo/README.md +++ b/browser-echo/README.md @@ -33,6 +33,15 @@ To initiate a connection: cargo run --features cli -- connect ``` +## Use iroh-services + +To send metrics or net reports to iroh-services, set the environment variable `BUILD_IROH_SERVICES_API_SECRET` when building the Wasm bundle to bake an iroh-services secret into the bundle: + +``` +export BUILD_IROH_SERVICES_API_SECRET=yourapikey +npm run build +``` + ## Navigate the code This folder contains a single Rust crate that can be compiled to both webassembly for the browser and to a commad line. diff --git a/browser-echo/src/node.rs b/browser-echo/src/node.rs index c6db3c01..5d98c820 100644 --- a/browser-echo/src/node.rs +++ b/browser-echo/src/node.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use anyhow::Result; use async_channel::Sender; use iroh::{ @@ -5,6 +7,9 @@ use iroh::{ endpoint::Connection, protocol::{AcceptError, ProtocolHandler, Router}, }; +use iroh_services::{ + API_SECRET_ENV_VAR_NAME, ApiSecret, CLIENT_HOST_ALPN, ClientHost, caps::NetDiagnosticsCap, +}; use n0_future::{Stream, StreamExt, boxed::BoxStream, task}; use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; @@ -15,6 +20,7 @@ use tracing::info; pub struct EchoNode { router: Router, accept_events: broadcast::Sender, + _svc_client: Option, } impl EchoNode { @@ -23,12 +29,21 @@ impl EchoNode { .alpns(vec![Echo::ALPN.to_vec()]) .bind() .await?; + let svc = enable_services(endpoint.clone()).await?; let (event_sender, _event_receiver) = broadcast::channel(128); let echo = Echo::new(event_sender.clone()); - let router = Router::builder(endpoint).accept(Echo::ALPN, echo).spawn(); + let mut router_builder = Router::builder(endpoint).accept(Echo::ALPN, echo); + let svc_client = if let Some((svc_client, svc_host)) = svc { + router_builder = router_builder.accept(CLIENT_HOST_ALPN, svc_host); + Some(svc_client) + } else { + None + }; + let router = router_builder.spawn(); Ok(Self { router, accept_events: event_sender, + _svc_client: svc_client, }) } @@ -187,3 +202,57 @@ async fn connect( send_task.await??; Ok(()) } + +async fn enable_services( + endpoint: Endpoint, +) -> Result> { + // 2. Parse the ApiSecret separately so we can extract the remote + // EndpointID. Normally we'd pass it straight to the client builder. + let secret = match ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME) { + Ok(secret) => Some(secret), + Err(_) => match std::option_env!("BUILD_IROH_SERVICES_API_SECRET") { + Some(secret) => ApiSecret::from_str(secret).ok(), + None => None, + }, + }; + let Some(secret) = secret else { + tracing::info!("iroh services integration disabled: IROH_SERVICES_API_SECRET is not set"); + return Ok(None); + }; + tracing::info!("iroh services integration enabled"); + + // optional: name the endpoint. Here we generate a name from the endpoint id + // to keep name unique. in your app this would be used to connect with + // something like a userId or machine name + let name = format!("wasm-echo-{}", endpoint.id().fmt_short()); + + // 3. Build a Client that dials iroh-services (as in all other examples). + let client = iroh_services::Client::builder(&endpoint) + .api_secret(secret.clone())? + .name(name)? + .build() + .await?; + + // 4. grant the ability to get diagnostics to the remote EndpointID associated + // with our project on iroh-services. This will create a capability token, send it to + // the remote for storage & confirm receipt. We do this in a task to avoid + // blocking the local node startup in the rare case that remote endpoint is + // down when this process starts. + let client2 = client.clone(); + let remote_id = secret.addr().id; + let _task = n0_future::task::spawn(async move { + if let Err(err) = client2 + .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) + .await + { + tracing::warn!("Failed to grant capability: {err:?}"); + } else { + tracing::info!("Capability granted to services"); + } + }); + + // 5. Set up a ClientHost so iroh-services can dial *back* into this endpoint. + // Incoming connections must present an RCAN issued by this endpoint. + let host = ClientHost::new(&endpoint); + Ok(Some((client, host))) +}