diff --git a/Cargo.lock b/Cargo.lock index 504308f5628..0a844b03c09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arbitrary" @@ -211,7 +211,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure 0.13.1", ] @@ -234,7 +234,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -383,7 +383,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -406,9 +406,9 @@ dependencies = [ [[package]] name = "async-std" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ "async-attributes", "async-channel 1.9.0", @@ -466,7 +466,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -477,13 +477,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -559,7 +559,7 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -592,7 +592,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "mime", @@ -631,12 +631,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -651,9 +645,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bimap" @@ -731,6 +725,29 @@ dependencies = [ "piper", ] +[[package]] +name = "browser-to-browser-webrtc-example" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "futures", + "getrandom 0.2.16", + "js-sys", + "libp2p", + "libp2p-core 0.43.1", + "libp2p-identity", + "libp2p-relay", + "libp2p-swarm", + "libp2p-webrtc-utils 0.3.0", + "libp2p-webrtc-websys", + "libp2p-websocket-websys", + "tracing", + "tracing-wasm", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "browser-webrtc-example" version = "0.1.0" @@ -768,9 +785,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "serde", @@ -823,9 +840,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" dependencies = [ "shlex", ] @@ -928,9 +945,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -938,9 +955,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -950,14 +967,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1100,9 +1117,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -1215,20 +1232,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-encoding-macro" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9724adfcf41f45bf652b3995837669d73c4d49a1b5ac1ff82905ac7d9b5558" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1236,12 +1253,12 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1259,9 +1276,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -1298,9 +1315,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -1328,23 +1345,23 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -1355,7 +1372,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1458,7 +1475,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1483,14 +1500,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -1502,9 +1519,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1529,9 +1546,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener 5.4.0", "pin-project-lite", @@ -1571,6 +1588,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "fnv" version = "1.0.7" @@ -1579,9 +1602,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -1687,7 +1710,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -1697,7 +1720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.23", + "rustls 0.23.26", "rustls-pki-types", ] @@ -1790,9 +1813,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", @@ -1803,14 +1826,16 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1885,17 +1910,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.2.0", - "indexmap 2.7.1", + "http 1.3.1", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -1904,9 +1929,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ "cfg-if", "crunchy", @@ -2006,7 +2031,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.0", + "rand 0.9.1", "socket2", "thiserror 2.0.12", "tinyvec", @@ -2027,8 +2052,8 @@ dependencies = [ "ipconfig", "moka", "once_cell", - "parking_lot", - "rand 0.9.0", + "parking_lot 0.12.3", + "rand 0.9.1", "resolv-conf", "smallvec", "thiserror 2.0.12", @@ -2081,7 +2106,7 @@ version = "0.1.0" dependencies = [ "anyhow", "either", - "env_logger 0.11.6", + "env_logger 0.11.8", "futures", "libp2p", "redis", @@ -2093,13 +2118,13 @@ dependencies = [ [[package]] name = "hostname" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" dependencies = [ + "cfg-if", "libc", - "match_cfg", - "winapi", + "windows-link", ] [[package]] @@ -2115,9 +2140,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -2131,18 +2156,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.2.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.2.0", + "futures-core", + "http 1.3.1", "http-body", "pin-project-lite", ] @@ -2165,12 +2190,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "1.6.0" @@ -2181,7 +2200,7 @@ dependencies = [ "futures-channel", "futures-util", "h2", - "http 1.2.0", + "http 1.3.1", "http-body", "httparse", "httpdate", @@ -2199,10 +2218,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http 1.2.0", + "http 1.3.1", "hyper", "hyper-util", - "rustls 0.23.23", + "rustls 0.23.26", "rustls-pki-types", "tokio", "tokio-rustls", @@ -2241,16 +2260,17 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "hyper", + "libc", "pin-project-lite", "socket2", "tokio", @@ -2299,9 +2319,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -2323,9 +2343,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -2344,9 +2364,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -2373,7 +2393,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -2451,7 +2471,7 @@ dependencies = [ "attohttpc", "bytes", "futures", - "http 1.2.0", + "http 1.3.1", "http-body-util", "hyper", "hyper-util", @@ -2474,9 +2494,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2492,6 +2512,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "integer-encoding" version = "3.0.4" @@ -2528,7 +2557,7 @@ dependencies = [ "futures-timer", "libp2p", "libp2p-mplex", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-tls", "libp2p-webrtc", "libp2p-webrtc-websys", @@ -2632,6 +2661,30 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jiff" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -2680,9 +2733,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.170" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libp2p" @@ -2693,11 +2746,11 @@ dependencies = [ "either", "futures", "futures-timer", - "getrandom 0.2.15", + "getrandom 0.2.16", "libp2p-allow-block-list", "libp2p-autonat", "libp2p-connection-limits", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-dcutr", "libp2p-dns", "libp2p-floodsub", @@ -2709,7 +2762,7 @@ dependencies = [ "libp2p-memory-connection-limits", "libp2p-metrics", "libp2p-mplex", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-peer-store", "libp2p-ping", "libp2p-plaintext", @@ -2730,7 +2783,7 @@ dependencies = [ "libp2p-yamux", "multiaddr", "pin-project", - "rw-stream-sink", + "rw-stream-sink 0.4.0", "thiserror 2.0.12", "tokio", "tracing-subscriber", @@ -2740,7 +2793,7 @@ dependencies = [ name = "libp2p-allow-block-list" version = "0.5.0" dependencies = [ - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-derive", @@ -2758,14 +2811,14 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", "libp2p-request-response", "libp2p-swarm", "libp2p-swarm-test", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "rand 0.8.5", "rand_core 0.6.4", "thiserror 2.0.12", @@ -2779,7 +2832,7 @@ dependencies = [ name = "libp2p-connection-limits" version = "0.5.1" dependencies = [ - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", "libp2p-ping", @@ -2791,6 +2844,34 @@ dependencies = [ "tokio", ] +[[package]] +name = "libp2p-core" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a61f26c83ed111104cd820fe9bc3aaabbac5f1652a1d213ed6e900b7918a1298" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "libp2p-identity", + "multiaddr", + "multihash", + "multistream-select 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", + "parking_lot 0.12.3", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", + "thiserror 1.0.69", + "tracing", + "unsigned-varint 0.8.0", + "void", + "web-time 1.1.0", +] + [[package]] name = "libp2p-core" version = "0.43.1" @@ -2801,19 +2882,19 @@ dependencies = [ "futures-timer", "libp2p-identity", "libp2p-mplex", - "libp2p-noise", + "libp2p-noise 0.46.1", "multiaddr", "multihash", - "multistream-select", - "parking_lot", + "multistream-select 0.13.0", + "parking_lot 0.12.3", "pin-project", "quick-protobuf", "rand 0.8.5", - "rw-stream-sink", + "rw-stream-sink 0.4.0", "thiserror 2.0.12", "tokio", "tracing", - "unsigned-varint", + "unsigned-varint 0.8.0", "web-time 1.1.0", ] @@ -2826,7 +2907,7 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", "libp2p-plaintext", @@ -2837,7 +2918,7 @@ dependencies = [ "libp2p-yamux", "lru", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "thiserror 2.0.12", "tokio", "tracing", @@ -2854,9 +2935,9 @@ dependencies = [ "async-trait", "futures", "hickory-resolver", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "parking_lot", + "parking_lot 0.12.3", "smallvec", "tokio", "tracing", @@ -2872,11 +2953,11 @@ dependencies = [ "cuckoofilter", "fnv", "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "rand 0.8.5", "smallvec", "thiserror 2.0.12", @@ -2896,16 +2977,16 @@ dependencies = [ "fnv", "futures", "futures-timer", - "getrandom 0.2.15", + "getrandom 0.2.16", "hashlink", "hex_fmt", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", "prometheus-client", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "quickcheck-ext", "rand 0.8.5", "regex", @@ -2926,12 +3007,12 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "smallvec", "thiserror 2.0.12", "tokio", @@ -2955,7 +3036,7 @@ dependencies = [ "quick-protobuf", "quickcheck-ext", "rand 0.8.5", - "ring 0.17.13", + "ring 0.17.14", "rmp-serde", "sec1", "serde", @@ -2977,15 +3058,15 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-swarm", "libp2p-swarm-test", "libp2p-yamux", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "quickcheck-ext", "rand 0.8.5", "serde", @@ -3008,7 +3089,7 @@ dependencies = [ "futures", "hickory-proto", "if-watch", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3024,7 +3105,7 @@ dependencies = [ name = "libp2p-memory-connection-limits" version = "0.4.0" dependencies = [ - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", "libp2p-swarm", @@ -3040,7 +3121,7 @@ name = "libp2p-metrics" version = "0.16.1" dependencies = [ "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-dcutr", "libp2p-gossipsub", "libp2p-identify", @@ -3063,19 +3144,19 @@ dependencies = [ "bytes", "criterion", "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-muxer-test-harness", "libp2p-plaintext", "libp2p-tcp", "nohash-hasher", - "parking_lot", + "parking_lot 0.12.3", "quickcheck-ext", "rand 0.8.5", "smallvec", "tracing", "tracing-subscriber", - "unsigned-varint", + "unsigned-varint 0.8.0", ] [[package]] @@ -3085,8 +3166,34 @@ dependencies = [ "futures", "futures-timer", "futures_ringbuf", - "libp2p-core", + "libp2p-core 0.43.1", + "tracing", +] + +[[package]] +name = "libp2p-noise" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b137cb1ae86ee39f8e5d6245a296518912014eaa87427d24e6ff58cfc1b28c" +dependencies = [ + "asynchronous-codec", + "bytes", + "curve25519-dalek", + "futures", + "libp2p-core 0.42.0", + "libp2p-identity", + "multiaddr", + "multihash", + "once_cell", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "snow", + "static_assertions", + "thiserror 1.0.69", "tracing", + "x25519-dalek", + "zeroize", ] [[package]] @@ -3097,7 +3204,7 @@ dependencies = [ "bytes", "futures", "futures_ringbuf", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "multiaddr", "multihash", @@ -3118,7 +3225,7 @@ name = "libp2p-peer-store" version = "0.1.0" dependencies = [ "libp2p", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3137,7 +3244,7 @@ dependencies = [ "futures-bounded", "futures-timer", "libp2p", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3159,7 +3266,7 @@ version = "0.46.0" dependencies = [ "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3178,10 +3285,10 @@ dependencies = [ "bytes", "futures", "futures_ringbuf", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "quickcheck-ext", "tracing", "tracing-subscriber", @@ -3192,9 +3299,9 @@ name = "libp2p-pnet" version = "0.26.0" dependencies = [ "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-swarm", "libp2p-tcp", "libp2p-websocket", @@ -3216,18 +3323,18 @@ dependencies = [ "futures", "futures-timer", "if-watch", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-muxer-test-harness", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-tcp", "libp2p-tls", "libp2p-yamux", "quickcheck", "quinn", "rand 0.8.5", - "ring 0.17.13", - "rustls 0.23.23", + "ring 0.17.14", + "rustls 0.23.26", "socket2", "thiserror 2.0.12", "tokio", @@ -3245,7 +3352,7 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-ping", "libp2p-plaintext", @@ -3253,7 +3360,7 @@ dependencies = [ "libp2p-swarm-test", "libp2p-yamux", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "quickcheck-ext", "rand 0.8.5", "static_assertions", @@ -3272,13 +3379,13 @@ dependencies = [ "bimap", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-request-response", "libp2p-swarm", "libp2p-swarm-test", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "rand 0.8.5", "thiserror 2.0.12", "tokio", @@ -3298,7 +3405,7 @@ dependencies = [ "futures", "futures-bounded", "futures_ringbuf", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3333,7 +3440,7 @@ name = "libp2p-stream" version = "0.3.0-alpha" dependencies = [ "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-swarm-test", @@ -3353,8 +3460,8 @@ dependencies = [ "fnv", "futures", "futures-timer", - "getrandom 0.2.15", - "libp2p-core", + "getrandom 0.2.16", + "libp2p-core 0.43.1", "libp2p-identify", "libp2p-identity", "libp2p-kad", @@ -3364,7 +3471,7 @@ dependencies = [ "libp2p-swarm-test", "libp2p-yamux", "lru", - "multistream-select", + "multistream-select 0.13.0", "quickcheck-ext", "rand 0.8.5", "smallvec", @@ -3382,7 +3489,7 @@ version = "0.35.1" dependencies = [ "heck", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -3392,7 +3499,7 @@ dependencies = [ "async-trait", "futures", "futures-timer", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-plaintext", "libp2p-swarm", @@ -3411,7 +3518,7 @@ dependencies = [ "futures-timer", "if-watch", "libc", - "libp2p-core", + "libp2p-core 0.43.1", "socket2", "tokio", "tracing", @@ -3425,13 +3532,13 @@ dependencies = [ "futures", "futures-rustls", "hex-literal", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", "libp2p-swarm", "libp2p-yamux", "rcgen 0.13.2", - "ring 0.17.13", - "rustls 0.23.23", + "ring 0.17.14", + "rustls 0.23.26", "rustls-webpki 0.101.7", "thiserror 2.0.12", "tokio", @@ -3445,7 +3552,7 @@ version = "0.42.0" dependencies = [ "async-std", "futures", - "libp2p-core", + "libp2p-core 0.43.1", "tempfile", "tokio", "tracing", @@ -3458,7 +3565,7 @@ dependencies = [ "futures", "futures-timer", "igd-next", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-swarm", "tokio", "tracing", @@ -3473,10 +3580,10 @@ dependencies = [ "futures-timer", "hex", "if-watch", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", - "libp2p-webrtc-utils", + "libp2p-noise 0.46.1", + "libp2p-webrtc-utils 0.4.0", "multihash", "quickcheck", "rand 0.8.5", @@ -3491,6 +3598,29 @@ dependencies = [ "webrtc-ice", ] +[[package]] +name = "libp2p-webrtc-utils" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da43128cff2ef91579b9f8c3f30991821d4d6b40db00ac4f17e3c1f75bfa019" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "hex", + "libp2p-core 0.42.0", + "libp2p-identity", + "libp2p-noise 0.45.0", + "quick-protobuf", + "quick-protobuf-codec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.8.5", + "serde", + "sha2 0.10.8", + "thiserror 1.0.69", + "tinytemplate", + "tracing", +] + [[package]] name = "libp2p-webrtc-utils" version = "0.4.0" @@ -3500,11 +3630,11 @@ dependencies = [ "futures", "hex", "hex-literal", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "quick-protobuf", - "quick-protobuf-codec", + "quick-protobuf-codec 0.3.1", "rand 0.8.5", "serde", "sha2 0.10.8", @@ -3518,17 +3648,32 @@ version = "0.4.0" dependencies = [ "bytes", "futures", - "getrandom 0.2.15", + "getrandom 0.2.16", + "gloo-timers 0.3.0", "hex", "js-sys", - "libp2p-core", + "libp2p-core 0.43.1", + "libp2p-identify", "libp2p-identity", - "libp2p-webrtc-utils", + "libp2p-noise 0.46.1", + "libp2p-ping", + "libp2p-relay", + "libp2p-swarm", + "libp2p-webrtc-utils 0.4.0", + "libp2p-websocket-websys", + "libp2p-yamux", + "multistream-select 0.13.0", + "oneshot", + "pin-project", + "prost", + "prost-build", "send_wrapper 0.6.0", + "serde_json", "thiserror 2.0.12", "tracing", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-timer", "web-sys", ] @@ -3540,14 +3685,14 @@ dependencies = [ "either", "futures", "futures-rustls", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-dns", "libp2p-identity", "libp2p-tcp", - "parking_lot", + "parking_lot 0.12.3", "pin-project-lite", "rcgen 0.13.2", - "rw-stream-sink", + "rw-stream-sink 0.4.0", "soketto", "thiserror 2.0.12", "tracing", @@ -3562,9 +3707,9 @@ dependencies = [ "bytes", "futures", "js-sys", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-yamux", "send_wrapper 0.6.0", "thiserror 2.0.12", @@ -3579,9 +3724,9 @@ version = "0.5.1" dependencies = [ "futures", "js-sys", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "multiaddr", "multibase", "multihash", @@ -3599,7 +3744,7 @@ version = "0.47.0" dependencies = [ "either", "futures", - "libp2p-core", + "libp2p-core 0.43.1", "libp2p-muxer-test-harness", "thiserror 2.0.12", "tokio", @@ -3620,12 +3765,12 @@ dependencies = [ [[package]] name = "libsecp256k1" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" dependencies = [ "arrayref", - "base64 0.13.1", + "base64 0.22.1", "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", @@ -3674,9 +3819,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" @@ -3696,9 +3841,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "value-bag", ] @@ -3725,12 +3870,6 @@ dependencies = [ "hashbrown 0.15.2", ] -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.1.0" @@ -3832,9 +3971,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -3860,7 +3999,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "loom", - "parking_lot", + "parking_lot 0.12.3", "portable-atomic", "rustc_version", "smallvec", @@ -3884,7 +4023,7 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint", + "unsigned-varint 0.8.0", "url", ] @@ -3910,9 +4049,15 @@ dependencies = [ "quickcheck", "rand 0.8.5", "serde", - "unsigned-varint", + "unsigned-varint 0.8.0", ] +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + [[package]] name = "multistream-select" version = "0.13.0" @@ -3923,11 +4068,25 @@ dependencies = [ "futures_ringbuf", "pin-project", "quickcheck-ext", - "rw-stream-sink", + "rw-stream-sink 0.4.0", "smallvec", "tracing", "tracing-subscriber", - "unsigned-varint", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "multistream-select" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" +dependencies = [ + "bytes", + "futures", + "log", + "pin-project", + "smallvec", + "unsigned-varint 0.7.2", ] [[package]] @@ -4133,9 +4292,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "oneshot" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "b4ce411919553d3f9fa53a0880544cda985a112117a0444d5ff1e870a893d6ea" [[package]] name = "oorandom" @@ -4151,9 +4316,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.9.0", "cfg-if", @@ -4172,7 +4337,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -4183,9 +4348,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -4201,7 +4366,7 @@ checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ "futures-core", "futures-sink", - "indexmap 2.7.1", + "indexmap 2.9.0", "js-sys", "once_cell", "pin-project-lite", @@ -4247,7 +4412,7 @@ checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" dependencies = [ "async-trait", "futures-core", - "http 1.2.0", + "http 1.3.1", "opentelemetry 0.27.1", "opentelemetry-proto", "opentelemetry_sdk 0.27.1", @@ -4382,6 +4547,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.3" @@ -4389,7 +4565,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.10", +] + +[[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]] @@ -4400,7 +4590,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.11", "smallvec", "windows-targets 0.52.6", ] @@ -4436,6 +4626,16 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap 2.9.0", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -4453,7 +4653,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -4577,6 +4777,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -4589,7 +4798,17 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.8.25", +] + +[[package]] +name = "prettyplease" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +dependencies = [ + "proc-macro2", + "syn 2.0.101", ] [[package]] @@ -4603,9 +4822,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -4618,7 +4837,7 @@ checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", - "parking_lot", + "parking_lot 0.12.3", "prometheus-client-derive-encode", ] @@ -4630,7 +4849,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -4643,6 +4862,26 @@ dependencies = [ "prost-derive", ] +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.101", + "tempfile", +] + [[package]] name = "prost-derive" version = "0.13.5" @@ -4653,14 +4892,17 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "prost-types" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost", +] [[package]] name = "quick-protobuf" @@ -4682,7 +4924,20 @@ dependencies = [ "quick-protobuf", "quickcheck-ext", "thiserror 2.0.12", - "unsigned-varint", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "quick-protobuf-codec" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a0580ab32b169745d7a39db2ba969226ca16738931be152a3209b409de2474" +dependencies = [ + "asynchronous-codec", + "bytes", + "quick-protobuf", + "thiserror 1.0.69", + "unsigned-varint 0.8.0", ] [[package]] @@ -4706,37 +4961,39 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" dependencies = [ "async-io", "async-std", "bytes", + "cfg_aliases", "futures-io", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.23", + "rustls 0.23.26", "socket2", "thiserror 2.0.12", "tokio", "tracing", + "web-time 1.1.0", ] [[package]] name = "quinn-proto" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +checksum = "bcbafbbdbb0f638fe3f35f3c56739f77a8a1d070cb25603226c83339b391472b" dependencies = [ "bytes", - "getrandom 0.2.15", - "rand 0.8.5", - "ring 0.17.13", + "getrandom 0.3.2", + "rand 0.9.1", + "ring 0.17.14", "rustc-hash", - "rustls 0.23.23", + "rustls 0.23.26", "rustls-pki-types", "slab", "thiserror 2.0.12", @@ -4747,9 +5004,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" dependencies = [ "cfg_aliases", "libc", @@ -4761,13 +5018,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.7.3" @@ -4794,13 +5057,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -4848,7 +5110,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -4857,7 +5119,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.2", ] [[package]] @@ -4909,7 +5171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" dependencies = [ "pem", - "ring 0.17.13", + "ring 0.17.14", "rustls-pki-types", "time", "yasna", @@ -4936,22 +5198,31 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", - "thiserror 1.0.69", + "thiserror 2.0.12", ] [[package]] @@ -5005,7 +5276,9 @@ dependencies = [ "clap", "futures", "libp2p", + "rand 0.8.5", "tokio", + "tracing", "tracing-subscriber", ] @@ -5022,9 +5295,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.12" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64 0.22.1", "bytes", @@ -5032,7 +5305,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -5048,7 +5321,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.23", + "rustls 0.23.26", "rustls-pemfile", "rustls-pki-types", "serde", @@ -5071,12 +5344,11 @@ dependencies = [ [[package]] name = "resolv-conf" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" dependencies = [ "hostname", - "quick-error", ] [[package]] @@ -5106,13 +5378,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted 0.9.0", "windows-sys 0.52.0", @@ -5207,9 +5479,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3aba5104622db5c9fc61098de54708feb732e7763d7faa2fa625899f00bf6f" +checksum = "e5fbc0ee50fcb99af7cebb442e5df7b5b45e9460ffa3f8f549cd26b862bec49d" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -5218,23 +5490,23 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f198c73be048d2c5aa8e12f7960ad08443e56fd39cc26336719fdb4ea0ebaae" +checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.100", + "syn 2.0.101", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.6.0" +version = "8.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2fcdc9f40c8dc2922842ca9add611ad19f332227fc651d015881ad1552bd9a" +checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" dependencies = [ "globset", "sha2 0.10.8", @@ -5286,14 +5558,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags 2.9.0", "errno", "libc", - "linux-raw-sys 0.9.2", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -5304,21 +5576,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.13", + "ring 0.17.14", "rustls-webpki 0.101.7", "sct", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" dependencies = [ "once_cell", - "ring 0.17.13", + "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki 0.103.1", "subtle", "zeroize", ] @@ -5347,17 +5619,17 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.13", + "ring 0.17.14", "untrusted 0.9.0", ] [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ - "ring 0.17.13", + "ring 0.17.14", "rustls-pki-types", "untrusted 0.9.0", ] @@ -5378,6 +5650,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "rw-stream-sink" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" +dependencies = [ + "futures", + "pin-project", + "static_assertions", +] + [[package]] name = "ryu" version = "1.0.20" @@ -5429,7 +5712,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.13", + "ring 0.17.14", "untrusted 0.9.0", ] @@ -5520,7 +5803,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5529,7 +5812,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.9.0", "itoa", "memchr", "ryu", @@ -5554,7 +5837,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5634,9 +5917,9 @@ dependencies = [ [[package]] name = "shellexpand" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ "dirs", ] @@ -5649,9 +5932,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -5677,9 +5960,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "smol" @@ -5718,7 +6001,7 @@ dependencies = [ "chacha20poly1305", "curve25519-dalek", "rand_core 0.6.4", - "ring 0.17.13", + "ring 0.17.14", "rustc_version", "sha2 0.10.8", "subtle", @@ -5726,9 +6009,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5825,7 +6108,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5839,7 +6122,7 @@ dependencies = [ "lazy_static", "md-5", "rand 0.8.5", - "ring 0.17.13", + "ring 0.17.14", "subtle", "thiserror 1.0.69", "tokio", @@ -5858,7 +6141,7 @@ dependencies = [ "lazy_static", "md-5", "rand 0.8.5", - "ring 0.17.13", + "ring 0.17.14", "subtle", "thiserror 1.0.69", "tokio", @@ -5894,9 +6177,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -5932,7 +6215,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -5984,15 +6267,14 @@ checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" [[package]] name = "tempfile" -version = "3.18.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c317e0a526ee6120d8dabad239c8dadca62b24b6f168914bbbc8e2fb1f0e567" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.2", "once_cell", - "rustix 1.0.1", + "rustix 1.0.5", "windows-sys 0.59.0", ] @@ -6014,9 +6296,9 @@ dependencies = [ "async-trait", "base64 0.22.1", "futures", - "http 1.2.0", - "indexmap 2.7.1", - "parking_lot", + "http 1.3.1", + "indexmap 2.9.0", + "parking_lot 0.12.3", "paste", "reqwest", "serde", @@ -6039,7 +6321,7 @@ checksum = "b72d056365e368fc57a56d0cec9e41b02fb4a3474a61c8735262b1cfebe67425" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6068,7 +6350,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6079,7 +6361,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6116,9 +6398,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -6131,15 +6413,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -6182,15 +6464,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.0" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", @@ -6206,7 +6488,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6225,7 +6507,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.23", + "rustls 0.23.26", "tokio", ] @@ -6242,9 +6524,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" dependencies = [ "bytes", "futures-core", @@ -6256,9 +6538,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231" dependencies = [ "serde", "serde_spanned", @@ -6268,26 +6550,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976" + [[package]] name = "tonic" version = "0.12.3" @@ -6300,7 +6589,7 @@ dependencies = [ "base64 0.22.1", "bytes", "h2", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -6363,7 +6652,7 @@ dependencies = [ "bitflags 2.9.0", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "http-range-header", @@ -6411,7 +6700,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6533,7 +6822,7 @@ dependencies = [ "log", "md-5", "rand 0.8.5", - "ring 0.17.13", + "ring 0.17.14", "stun 0.5.1", "thiserror 1.0.69", "tokio", @@ -6587,6 +6876,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" + [[package]] name = "unsigned-varint" version = "0.8.0" @@ -6656,11 +6951,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.2", ] [[package]] @@ -6671,9 +6966,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vcpkg" @@ -6687,6 +6982,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + [[package]] name = "waitgroup" version = "0.1.2" @@ -6729,9 +7030,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -6758,7 +7059,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -6793,7 +7094,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6828,7 +7129,7 @@ checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -6842,6 +7143,21 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.77" @@ -7118,10 +7434,10 @@ name = "webtransport-tests" version = "0.1.0" dependencies = [ "futures", - "getrandom 0.2.15", - "libp2p-core", + "getrandom 0.2.16", + "libp2p-core 0.43.1", "libp2p-identity", - "libp2p-noise", + "libp2p-noise 0.46.1", "libp2p-webtransport-websys", "multiaddr", "multihash", @@ -7133,9 +7449,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" [[package]] name = "winapi" @@ -7229,7 +7545,7 @@ dependencies = [ "windows-implement 0.58.0", "windows-interface 0.58.0", "windows-result 0.2.0", - "windows-strings", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] @@ -7241,7 +7557,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -7252,7 +7568,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -7263,7 +7579,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -7274,18 +7590,24 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ - "windows-result 0.2.0", - "windows-strings", - "windows-targets 0.52.6", + "windows-result 0.3.2", + "windows-strings 0.3.1", + "windows-targets 0.53.0", ] [[package]] @@ -7306,6 +7628,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" @@ -7316,6 +7647,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -7367,13 +7707,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -7386,6 +7742,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -7398,6 +7760,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -7410,12 +7778,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -7428,6 +7808,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -7440,6 +7826,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -7452,6 +7844,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -7464,11 +7862,17 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" dependencies = [ "memchr", ] @@ -7485,9 +7889,9 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags 2.9.0", ] @@ -7553,9 +7957,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "xmltree" @@ -7575,7 +7979,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.12.3", "pin-project", "rand 0.8.5", "static_assertions", @@ -7590,7 +7994,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.12.3", "pin-project", "rand 0.8.5", "static_assertions", @@ -7626,7 +8030,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure 0.13.1", ] @@ -7641,11 +8045,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive 0.8.25", ] [[package]] @@ -7656,18 +8060,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -7687,7 +8091,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", "synstructure 0.13.1", ] @@ -7708,7 +8112,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] [[package]] @@ -7730,5 +8134,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.101", ] diff --git a/Cargo.toml b/Cargo.toml index 334fd420e63..de3b6504a6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "examples/autonat", "examples/autonatv2", "examples/browser-webrtc", + "examples/browser-to-browser-webrtc", "examples/chat", "examples/dcutr", "examples/distributed-key-value-store", diff --git a/examples/browser-to-browser-webrtc/Cargo.toml b/examples/browser-to-browser-webrtc/Cargo.toml new file mode 100644 index 00000000000..6034090cc17 --- /dev/null +++ b/examples/browser-to-browser-webrtc/Cargo.toml @@ -0,0 +1,43 @@ +[package] +authors = ["Elijah Hampton "] +description = "Example use of WebRTC transport in a browser wasm environment" +edition.workspace = true +license = "MIT" +name = "browser-to-browser-webrtc-example" +publish = false +repository = "https://github.com/libp2p/rust-libp2p" +rust-version = { workspace = true } +version = "0.1.0" + +[package.metadata.release] +release = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +futures = { workspace = true, default-features = false } +console_error_panic_hook = "0.1" +tracing = { workspace = true } +libp2p-swarm = { workspace = true } +libp2p = { path = "../../libp2p", features = ["relay", "noise", "yamux", "ed25519", "macros", "identify", "ping", "wasm-bindgen"] } +libp2p-identity = { version = "0.2" } +libp2p-webrtc-utils = { version = "0.3"} +libp2p-relay = { workspace = true} +libp2p-core = { workspace = true} +libp2p-webrtc-websys = { workspace = true } +libp2p-websocket-websys = { workspace = true } +tracing-wasm = "0.2" +getrandom = { version = "0.2", features = ["js"] } +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" +web-sys = { version = "0.3", features = ["RtcPeerConnection", "RtcDataChannel", "RtcConfiguration", "Window", "Navigator", "MediaDevices"] } +js-sys = "0.3" + +[profile.release] +opt-level = 3 +lto = true +codegen-units = 1 + +[package.metadata.wasm-pack] +"wasm-pack" = ["cdylib"] \ No newline at end of file diff --git a/examples/browser-to-browser-webrtc/src/lib.rs b/examples/browser-to-browser-webrtc/src/lib.rs new file mode 100644 index 00000000000..95370f829fd --- /dev/null +++ b/examples/browser-to-browser-webrtc/src/lib.rs @@ -0,0 +1,310 @@ +use std::str::FromStr; + +use futures::{channel::mpsc, StreamExt}; +use js_sys::{Object, Reflect}; +use libp2p::{ + identify, identity::Keypair, multiaddr::Protocol, noise, ping, swarm::SwarmEvent, yamux, + Multiaddr, Swarm, Transport, +}; +use libp2p_core::{muxing::StreamMuxerBox, upgrade::Version}; +use libp2p_swarm::NetworkBehaviour; +use libp2p_webrtc_websys::browser::{self, Behaviour, Transport as BrowserWebrtcTransport}; +use tracing; +use tracing_wasm; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::spawn_local; + +#[wasm_bindgen(start)] +pub fn start() { + console_error_panic_hook::set_once(); +} + +#[wasm_bindgen] +pub fn initialize() { + tracing_wasm::set_as_global_default_with_config( + tracing_wasm::WASMLayerConfigBuilder::new() + .set_max_level(tracing::Level::TRACE) + .set_console_config(tracing_wasm::ConsoleConfig::ReportWithConsoleColor) + .build(), + ); +} + +#[wasm_bindgen] +pub struct BrowserTransport { + cmd_sender: mpsc::UnboundedSender, + event_receiver: std::sync::Arc>>, + peer_id: String, +} + +enum Command { + ListenOnRelay { addr: Multiaddr }, + DialPeer { addr: Multiaddr }, +} + +#[derive(Debug, Clone)] +enum Event { + ReservationCreated, + ConnectionEstablished { peer_id: String }, + PingSuccess { peer_id: String, rtt_ms: f64 }, + Error { msg: String }, +} + +#[derive(NetworkBehaviour)] +pub struct WebRTCBehaviour { + relay: libp2p_relay::client::Behaviour, + webrtc: Behaviour, + identify: identify::Behaviour, + ping: ping::Behaviour, +} + +#[wasm_bindgen] +impl BrowserTransport { + #[wasm_bindgen] + pub fn new() -> Result { + let keypair = Keypair::generate_ed25519(); + let local_peer_id = keypair.public().to_peer_id(); + + // Create a relay transport and behaviour for the relay connection + let (relay_transport, relay_behaviour) = libp2p_relay::client::new(local_peer_id); + + let relay_transport_upgraded = relay_transport + .upgrade(Version::V1) + .authenticate(noise::Config::new(&keypair)?) + .multiplex(yamux::Config::default()) + .boxed(); + + // Create a websocket transport to faciliate connection to the relay server + let ws_transport = libp2p_websocket_websys::Transport::default() + .upgrade(Version::V1) + .authenticate(noise::Config::new(&keypair)?) + .multiplex(yamux::Config::default()) + .boxed(); + + + let webrtc_config = libp2p_webrtc_websys::browser::Config { + keypair: keypair.clone(), + }; + let signaling_config = libp2p_webrtc_websys::browser::SignalingConfig::default(); + + let (webrtc_transport, webrtc_behaviour) = + BrowserWebrtcTransport::new(webrtc_config, signaling_config); + let webrtc_transport_boxed = webrtc_transport.boxed(); + + // A WebRTC behaviour faciliating coordination between the relay connection and webrtc signaling + let behaviour = WebRTCBehaviour { + relay: relay_behaviour, + webrtc: webrtc_behaviour, + identify: identify::Behaviour::new(identify::Config::new( + "browser-to-browser-webrtc/1.0.0".into(), + keypair.public(), + )), + ping: ping::Behaviour::new(ping::Config::default()), + }; + + // The final transport consisting of a webrtc, relay and websocket transport + let final_transport = webrtc_transport_boxed + .or_transport(relay_transport_upgraded) + .or_transport(ws_transport) + .map(|either_output, _| match either_output { + futures::future::Either::Left(futures::future::Either::Left(( + peer_id, + connection, + ))) => (peer_id, StreamMuxerBox::new(connection)), + futures::future::Either::Left(futures::future::Either::Right(output)) => output, + futures::future::Either::Right(output) => output, + }) + .boxed(); + + let mut swarm = Swarm::new( + final_transport, + behaviour, + local_peer_id, + libp2p::swarm::Config::with_executor(Box::new(|fut| { + wasm_bindgen_futures::spawn_local(fut); + })), + ); + + let (cmd_sender, mut cmd_receiver) = mpsc::unbounded(); + let (event_sender, event_receiver) = mpsc::unbounded(); + + spawn_local(async move { + loop { + futures::select! { + cmd = cmd_receiver.next() => { + if let Some(cmd) = cmd { + match cmd { + Command::ListenOnRelay { addr } => { + // Build the circuit address for reservation by adding /p2p-circuit + let circuit_addr = addr.with(Protocol::P2pCircuit); + + match swarm.listen_on(circuit_addr.clone()) { + Ok(listener_id) => { + tracing::info!("Swarm successfully listening on address {} with listener id {}.", circuit_addr, listener_id); + } + Err(e) => { + tracing::error!("Swarm failed to listen on address {}: {}", circuit_addr, e); + let _ = event_sender.unbounded_send(Event::Error { + msg: format!("{}", e) + }); + } + } + } + Command::DialPeer { addr } => { + tracing::info!("Dialing peer: {}", addr); + if let Err(e) = swarm.dial(addr) { + let _ = event_sender.unbounded_send(Event::Error { + msg: format!("Failed to dial peer: {}", e) + }); + } + } + } + } + } + + event = swarm.select_next_some() => { + match event { + SwarmEvent::ConnectionEstablished { peer_id, connection_id, endpoint, .. } => { + + let remote_addr = endpoint.get_remote_address().to_string(); + + if remote_addr.contains("/webrtc") { + tracing::info!( + "Connection established with: {} via {} (remote: WebRTC, connection_id: {})", + peer_id, remote_addr, connection_id + ); + } + + let _ = event_sender.unbounded_send(Event::ConnectionEstablished { + peer_id: peer_id.to_string() + }); + } + SwarmEvent::ConnectionClosed { peer_id, cause, .. } => { + tracing::info!("Connection closed with {}: {:?}", peer_id, cause); + } + SwarmEvent::OutgoingConnectionError { peer_id, error, .. } => { + tracing::error!("Outgoing connection error to {:?}: {}", peer_id, error); + let _ = event_sender.unbounded_send(Event::Error { + msg: format!("Connection error: {}", error) + }); + } + SwarmEvent::NewListenAddr { address, .. } => { + tracing::info!("Listening on: {}", address); + if address.iter().any(|p| matches!(p, Protocol::P2pCircuit)) { + tracing::info!("Relay reservation address: {}", address); + let _ = event_sender.unbounded_send(Event::ReservationCreated); + } + } + SwarmEvent::Behaviour(event) => { + match event { + WebRTCBehaviourEvent::Webrtc(webrtc_event) => { + match webrtc_event { + browser::SignalingEvent::NewWebRTCConnection(_connection) => { + tracing::info!("Successfully established WebRTC connection"); + } + browser::SignalingEvent::WebRTCConnectionError(_error) => { + tracing::error!("Failed to establish WebRTC connection.") + } + } + } + WebRTCBehaviourEvent::Ping(ping_event) => { + match ping_event { + ping::Event { peer, result: Ok(rtt), .. } => { + let rtt_ms = rtt.as_millis() as f64; + tracing::info!("Ping successful: from {}", peer); + let _ = event_sender.unbounded_send(Event::PingSuccess { + peer_id: peer.to_string(), + rtt_ms, + }); + } + ping::Event { peer, result: Err(e), .. } => { + tracing::error!("Ping failed to {}: {}", peer, e); + let _ = event_sender.unbounded_send(Event::Error { + msg: format!("Ping failed to {}: {}", peer, e) + }); + } + } + } + _ => {} + } + } + _ => {} + } + } + } + } + }); + + Ok(BrowserTransport { + cmd_sender, + event_receiver: std::sync::Arc::new(futures::lock::Mutex::new(event_receiver)), + peer_id: local_peer_id.to_string(), + }) + } + + #[wasm_bindgen] + pub async fn listen_on_relay(&self, relay_addr: &str) -> Result<(), JsValue> { + let addr = Multiaddr::from_str(relay_addr) + .map_err(|e| JsValue::from_str(&format!("Invalid relay addr: {}", e)))?; + + self.cmd_sender + .unbounded_send(Command::ListenOnRelay { addr }) + .map_err(|e| JsValue::from_str(&format!("Failed to send command: {}", e)))?; + + Ok(()) + } + + #[wasm_bindgen(getter)] + pub fn peer_id(&self) -> String { + self.peer_id.clone() + } + + #[wasm_bindgen] + pub async fn dial(&self, peer_addr: &str) -> Result<(), JsValue> { + let addr = Multiaddr::from_str(peer_addr) + .map_err(|e| JsValue::from_str(&format!("Invalid peer addr: {}", e)))?; + + self.cmd_sender + .unbounded_send(Command::DialPeer { addr }) + .map_err(|e| JsValue::from_str(&format!("Failed to send command: {}", e)))?; + + Ok(()) + } + + #[wasm_bindgen] + pub async fn next_event(&self) -> Result { + let mut receiver = self.event_receiver.lock().await; + + if let Some(event) = receiver.next().await { + let obj = Object::new(); + + match event { + Event::ReservationCreated => { + Reflect::set(&obj, &"type".into(), &"reservationCreated".into())?; + } + Event::ConnectionEstablished { peer_id } => { + Reflect::set(&obj, &"type".into(), &"connectionEstablished".into())?; + Reflect::set(&obj, &"peerId".into(), &peer_id.into())?; + } + Event::PingSuccess { peer_id, rtt_ms } => { + Reflect::set(&obj, &"type".into(), &"pingSuccess".into())?; + Reflect::set(&obj, &"peerId".into(), &peer_id.into())?; + Reflect::set(&obj, &"rttMs".into(), &rtt_ms.into())?; + } + Event::Error { msg } => { + Reflect::set(&obj, &"type".into(), &"error".into())?; + Reflect::set(&obj, &"message".into(), &msg.into())?; + } + } + + Ok(obj.into()) + } else { + Err(JsValue::from_str("No events available")) + } + } +} + +#[wasm_bindgen] +pub fn generate_peer_id() -> String { + let keypair = Keypair::generate_ed25519(); + keypair.public().to_peer_id().to_string() +} diff --git a/examples/browser-to-browser-webrtc/static/index.html b/examples/browser-to-browser-webrtc/static/index.html new file mode 100644 index 00000000000..e0c495d8ec0 --- /dev/null +++ b/examples/browser-to-browser-webrtc/static/index.html @@ -0,0 +1,401 @@ + + + + + + libp2p WebRTC Browser-to-Browser Demo + + + +

libp2p WebRTC Browser-to-Browser Demo

+ +
+ + +
+ + +
+
+ Listener Instructions: +
    +
  1. Initialize the listener
  2. +
  3. Enter relay address and click "Listen on Relay"
  4. +
  5. Copy your address and share it with the dialer
  6. +
  7. Wait for connection
  8. +
+
+ +
+ Listener Peer ID: Not initialized + Disconnected +
+ +
+

Initialize

+ +
+ +
+

Listen on Relay

+ + +
+ +
+

Your Address

+ + +
+ +

Logs

+
+
+ + +
+
+ Dialer Instructions: +
    +
  1. Initialize the dialer
  2. +
  3. Get the listener's address from the other tab
  4. +
  5. Paste the address and click "Dial Peer"
  6. +
  7. Start chatting once connected
  8. +
+
+ +
+ Dialer Peer ID: Not initialized + Disconnected +
+ +
+

Initialize

+ +
+ +
+

Dial Peer

+ + +
+s +

Logs

+
+
+ + + + \ No newline at end of file diff --git a/examples/relay-server/Cargo.toml b/examples/relay-server/Cargo.toml index 1e0e2a780ba..e6dc2f6b632 100644 --- a/examples/relay-server/Cargo.toml +++ b/examples/relay-server/Cargo.toml @@ -12,8 +12,10 @@ release = false clap = { version = "4.5.6", features = ["derive"] } tokio = { version = "1.37.0", features = ["full"] } futures = { workspace = true } -libp2p = { path = "../../libp2p", features = ["tokio", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic"] } +libp2p = { path = "../../libp2p", features = ["tokio", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic", "websocket", "dns"] } tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing = "0.1" +rand = "0.8" [lints] workspace = true diff --git a/examples/relay-server/src/main.rs b/examples/relay-server/src/main.rs index b7868418fb0..1eef2699bf7 100644 --- a/examples/relay-server/src/main.rs +++ b/examples/relay-server/src/main.rs @@ -32,8 +32,9 @@ use libp2p::{ core::{multiaddr::Protocol, Multiaddr}, identify, identity, noise, ping, relay, swarm::{NetworkBehaviour, SwarmEvent}, - tcp, yamux, + tcp, yamux, PeerId, Swarm, }; +use tracing; use tracing_subscriber::EnvFilter; #[tokio::main] @@ -46,6 +47,8 @@ async fn main() -> Result<(), Box> { // Create a static known PeerId based on given secret let local_key: identity::Keypair = generate_ed25519(opt.secret_key_seed); + let local_peer_id = PeerId::from(local_key.public()); + tracing::info!(?local_peer_id, "Local peer id"); let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_key) .with_tokio() @@ -55,6 +58,9 @@ async fn main() -> Result<(), Box> { yamux::Config::default, )? .with_quic() + .with_dns()? + .with_websocket(noise::Config::new, yamux::Config::default) + .await? .with_behaviour(|key| Behaviour { relay: relay::Behaviour::new(key.public().to_peer_id(), Default::default()), ping: ping::Behaviour::new(ping::Config::new()), @@ -83,6 +89,8 @@ async fn main() -> Result<(), Box> { .with(Protocol::QuicV1); swarm.listen_on(listen_addr_quic)?; + listen_on_websocket(&mut swarm, &opt)?; + loop { match swarm.next().await.expect("Infinite Stream.") { SwarmEvent::Behaviour(event) => { @@ -96,12 +104,30 @@ async fn main() -> Result<(), Box> { println!("{event:?}") } - SwarmEvent::NewListenAddr { address, .. } => { + SwarmEvent::NewListenAddr { mut address, .. } => { + address.push(Protocol::P2p(local_peer_id)); println!("Listening on {address:?}"); } _ => {} } } + + fn listen_on_websocket(swarm: &mut Swarm, opt: &Opt) -> Result<(), Box> { + match opt.ws_port { + Some(port) => { + let address = Multiaddr::from(Ipv4Addr::UNSPECIFIED) + .with(Protocol::Tcp(port)) + .with(Protocol::Ws(std::borrow::Cow::Borrowed("/"))); + + tracing::info!(?address, "Listening on webSocket"); + swarm.listen_on(address.clone())?; + } + None => { + tracing::info!("Does not use websocket"); + } + } + Ok(()) + } } #[derive(NetworkBehaviour)] @@ -132,4 +158,8 @@ struct Opt { /// The port used to listen on all interfaces #[clap(long)] port: u16, + + /// The websocket port used to listen on all interfaces + #[arg(long)] + ws_port: Option, } diff --git a/misc/webrtc-utils/src/fingerprint.rs b/misc/webrtc-utils/src/fingerprint.rs index c32d33d5bab..bde29b4ceb8 100644 --- a/misc/webrtc-utils/src/fingerprint.rs +++ b/misc/webrtc-utils/src/fingerprint.rs @@ -33,6 +33,15 @@ type Multihash = multihash::Multihash<64>; #[derive(Eq, PartialEq, Copy, Clone)] pub struct Fingerprint([u8; 32]); +impl Default for Fingerprint { + fn default() -> Self { + // For browser-to-browser connections via circuit relay, we might use a default fingerprint + // This is because the actual certificate verification will happen during the WebRTC + // handshake + Fingerprint([0; 32]) + } +} + impl Fingerprint { pub const FF: Fingerprint = Fingerprint([0xFF; 32]); diff --git a/misc/webrtc-utils/src/transport.rs b/misc/webrtc-utils/src/transport.rs index 60b1934082f..91dd803893f 100644 --- a/misc/webrtc-utils/src/transport.rs +++ b/misc/webrtc-utils/src/transport.rs @@ -24,6 +24,7 @@ pub fn parse_webrtc_dial_addr(addr: &Multiaddr) -> Option<(SocketAddr, Fingerpri (port, fingerprint) } + _ => return None, }; diff --git a/protocols/relay/src/lib.rs b/protocols/relay/src/lib.rs index dba07015765..a4a371fcd60 100644 --- a/protocols/relay/src/lib.rs +++ b/protocols/relay/src/lib.rs @@ -32,10 +32,9 @@ mod protocol; mod proto { #![allow(unreachable_pub)] include!("generated/mod.rs"); - pub use self::message_v2::pb::mod_StopMessage::Type as StopMessageType; pub(crate) use self::message_v2::pb::{ - mod_HopMessage::Type as HopMessageType, HopMessage, Limit, Peer, Reservation, Status, - StopMessage, + mod_HopMessage::Type as HopMessageType, mod_StopMessage::Type as StopMessageType, + HopMessage, Limit, Peer, Reservation, Status, StopMessage, }; } diff --git a/protocols/relay/src/priv_client/transport.rs b/protocols/relay/src/priv_client/transport.rs index ed9faa946db..87826248849 100644 --- a/protocols/relay/src/priv_client/transport.rs +++ b/protocols/relay/src/priv_client/transport.rs @@ -166,6 +166,7 @@ impl libp2p_core::Transport for Transport { is_closed: false, waker: None, }; + self.listeners.push(listener); Ok(()) } @@ -192,6 +193,11 @@ impl libp2p_core::Transport for Transport { return Err(TransportError::MultiaddrNotSupported(addr)); } + if !addr.is_relayed() { + // This is not a relay address at all, pass it to next transport + return Err(TransportError::MultiaddrNotSupported(addr)); + } + let RelayedMultiaddr { relay_peer_id, relay_addr, diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index fb368bf975c..10fb56defd3 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -1663,8 +1663,12 @@ impl fmt::Display for ListenError { f, "Listen error: Unexpected peer ID {obtained} at {endpoint:?}." ), - ListenError::Transport(_) => { - write!(f, "Listen error: Failed to negotiate transport protocol(s)") + ListenError::Transport(e) => { + write!( + f, + "Listen error: Failed to negotiate transport protocol(s) {}", + e.to_string() + ) } ListenError::Denied { cause } => { write!(f, "Listen error: Denied: {cause}") diff --git a/transports/webrtc-websys/Cargo.toml b/transports/webrtc-websys/Cargo.toml index e5596da90e4..6199554038b 100644 --- a/transports/webrtc-websys/Cargo.toml +++ b/transports/webrtc-websys/Cargo.toml @@ -11,6 +11,9 @@ rust-version = { workspace = true } version = "0.4.0" publish = true +[build-dependencies] +prost-build = "0.13.5" + [dependencies] bytes = "1" futures = { workspace = true } @@ -18,14 +21,56 @@ getrandom = { workspace = true, features = ["js"] } hex = "0.4.3" js-sys = { version = "0.3" } libp2p-core = { workspace = true } +libp2p-identify = { workspace = true } +libp2p-ping = { workspace = true } libp2p-identity = { workspace = true } libp2p-webrtc-utils = { workspace = true } +libp2p-relay = { workspace = true } +libp2p-swarm = { workspace = true } +libp2p-yamux = { workspace = true } +libp2p-noise = { workspace = true } +libp2p-websocket-websys = { workspace = true } send_wrapper = { version = "0.6.0", features = ["futures"] } thiserror = { workspace = true } -tracing = { workspace = true } +tracing = { workspace = true, features = ["attributes"] } wasm-bindgen = { version = "0.2.90" } wasm-bindgen-futures = { version = "0.4.42" } -web-sys = { version = "0.3.70", features = ["Document", "Location", "MessageEvent", "Navigator", "RtcCertificate", "RtcConfiguration", "RtcDataChannel", "RtcDataChannelEvent", "RtcDataChannelInit", "RtcDataChannelState", "RtcDataChannelType", "RtcPeerConnection", "RtcSdpType", "RtcSessionDescription", "RtcSessionDescriptionInit", "Window"] } +web-sys = { version = "0.3.70", features = [ + "RtcPeerConnection", + "RtcConfiguration", + "RtcSessionDescription", + "RtcSessionDescriptionInit", + "RtcSdpType", + "RtcDataChannel", + "RtcDataChannelEvent", + "RtcDataChannelInit", + "RtcDataChannelState", + "RtcDataChannelType", + "RtcIceConnectionState", + "RtcIceGatheringState", + "RtcIceCandidate", + "RtcIceCandidateInit", + "RtcPeerConnectionIceEvent", + "Event", + "EventTarget", + "MessageEvent", + "Window", + "Document", + "Navigator", + "RtcCertificate", + "RtcPeerConnectionState", + "RtcSignalingState", + "Location", + "HtmlDocument", + "WebSocket" +]} +oneshot = "0.1.11" +prost = "0.13.5" +multistream-select.workspace = true +pin-project = "1.1.10" +gloo-timers = { version = "0.3.0", features = ["futures"] } +serde_json = "1.0.140" +wasm-timer = "0.2.5" [lints] workspace = true diff --git a/transports/webrtc-websys/build.rs b/transports/webrtc-websys/build.rs new file mode 100644 index 00000000000..4942593fdd3 --- /dev/null +++ b/transports/webrtc-websys/build.rs @@ -0,0 +1,7 @@ +fn main() { + prost_build::compile_protos( + &["src/browser/protocol/proto/message.proto"], + &["src/browser/protocol/proto/"], + ) + .unwrap(); +} diff --git a/transports/webrtc-websys/src/browser/behaviour.rs b/transports/webrtc-websys/src/browser/behaviour.rs new file mode 100644 index 00000000000..8692c1c615c --- /dev/null +++ b/transports/webrtc-websys/src/browser/behaviour.rs @@ -0,0 +1,215 @@ +use std::{ + collections::{HashMap, VecDeque}, + task::Poll, + time::Duration +}; + +use wasm_timer::Instant; + +use libp2p_core::PeerId; +use libp2p_swarm::{ConnectionId, NetworkBehaviour, NotifyHandler, ToSwarm}; + +use crate::browser::handler::{FromBehaviourEvent, SignalingHandler, ToBehaviourEvent}; + +#[derive(Clone, Debug)] +pub struct SignalingConfig { + /// Maximum number of times to retry the signaling process before giving up. + pub(crate) max_signaling_retries: u8, + /// Delay before initiating or retrying the signaling process. + pub(crate) signaling_delay: Duration, + /// Time to wait between each check for an established WebRTC connection. + pub(crate) connection_establishment_delay_in_millis: Duration, + /// Maximum number of checks to attempt for establishing the WebRTC connection. + pub(crate) max_connection_establishment_checks: u32 +} + +impl Default for SignalingConfig { + fn default() -> Self { + Self { + max_signaling_retries: 3, + signaling_delay: Duration::from_millis(100), + connection_establishment_delay_in_millis: Duration::from_millis(100), + max_connection_establishment_checks: 300 + } + } +} + +impl SignalingConfig { + pub fn new(max_retries: u8, signaling_delay: Duration, connection_establishment_delay_in_millis: Duration, max_connection_establishment_checks: u32) -> Self { + Self { + max_signaling_retries: max_retries, + signaling_delay, + connection_establishment_delay_in_millis, + max_connection_establishment_checks + } + } +} + +/// Signaling events returned to the swarm. +#[derive(Debug)] +pub enum SignalingEvent { + NewWebRTCConnection(crate::Connection), + WebRTCConnectionError(crate::Error), +} + +/// State for tracking signaling with a specific peer +#[derive(Debug)] +struct PeerSignalingState { + /// The time at which this peer was discovered. + discovered_at: Instant, + /// Whether this peer initiated the signaling process. + initiated: bool, + // Connection ID for this peer + connection_id: ConnectionId, +} + +/// A [`Behaviour`] used to cooordinate signaling between peers +/// over a relay connection. +pub struct Behaviour { + /// Queued events to send to the swarm. + queued_events: VecDeque>, + /// Configuration parameters for the signaling process. + signaling_config: SignalingConfig, + /// Tracking state of peers involved in signaling (to be signaled or already signaled). + peers: HashMap, +} + +impl Behaviour { + pub fn new(config: SignalingConfig) -> Self { + Self { + queued_events: VecDeque::new(), + signaling_config: config, + peers: HashMap::new(), + } + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = SignalingHandler; + type ToSwarm = SignalingEvent; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: libp2p_swarm::ConnectionId, + peer: PeerId, + _local_addr: &libp2p_core::Multiaddr, + _remote_addr: &libp2p_core::Multiaddr, + ) -> Result, libp2p_swarm::ConnectionDenied> { + Ok(SignalingHandler::new( + peer, + false, + self.signaling_config.clone(), + )) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: libp2p_swarm::ConnectionId, + peer: PeerId, + _addr: &libp2p_core::Multiaddr, + _role_override: libp2p_core::Endpoint, + _port_use: libp2p_core::transport::PortUse, + ) -> Result, libp2p_swarm::ConnectionDenied> { + Ok(SignalingHandler::new( + peer, + true, + self.signaling_config.clone(), + )) + } + + fn on_swarm_event(&mut self, event: libp2p_swarm::FromSwarm) { + match event { + libp2p_swarm::FromSwarm::ConnectionEstablished(connection_established) => { + let dst_peer = connection_established.peer_id; + let connection_id = connection_established.connection_id; + let endpoint = connection_established.endpoint; + + // Check to see if the connected was made over a relay. If so, we know this is + // the connection we need to initiate the signaling protocol. + if endpoint.is_relayed() { + self.peers.insert( + dst_peer, + PeerSignalingState { + discovered_at: Instant::now(), + initiated: false, + connection_id, + }, + ); + } + } + libp2p_swarm::FromSwarm::ConnectionClosed(connection_closed) => { + if self + .peers + .get(&connection_closed.peer_id) + .map(|state| state.connection_id == connection_closed.connection_id) + .unwrap_or(false) + { + self.peers.remove(&connection_closed.peer_id); + } + } + _ => {} + } + } + + fn on_connection_handler_event( + &mut self, + peer_id: PeerId, + _connection_id: libp2p_swarm::ConnectionId, + event: libp2p_swarm::THandlerOutEvent, + ) { + match event { + ToBehaviourEvent::WebRTCConnectionSuccess(connection) => { + tracing::info!("Successfully webrtc connection to peer {}", peer_id); + self.queued_events.push_back(ToSwarm::GenerateEvent( + SignalingEvent::NewWebRTCConnection(connection), + )); + self.peers.remove(&peer_id); + } + ToBehaviourEvent::WebRTCConnectionFailure(error) => { + tracing::error!("WebRTC connection failed: {:?}", error); + self.queued_events.push_back(ToSwarm::GenerateEvent( + SignalingEvent::WebRTCConnectionError(error), + )); + self.peers.remove(&peer_id); + } + ToBehaviourEvent::SignalingRetry => { + tracing::info!("Scheduling signaling retry for peer {}", peer_id); + if let Some(state) = self.peers.get_mut(&peer_id) { + state.initiated = false; + state.discovered_at = Instant::now(); + } + } + } + } + + fn poll( + &mut self, + _cx: &mut std::task::Context<'_>, + ) -> std::task::Poll>> + { + // Check if there are any queued events to send to the swarm + if !self.queued_events.is_empty() { + if let Some(event) = self.queued_events.pop_front() { + return Poll::Ready(event); + } + } + + let now = Instant::now(); + let delay = self.signaling_config.signaling_delay; + + for (peer_id, state) in self.peers.iter_mut() { + if !state.initiated && now.duration_since(state.discovered_at) >= delay { + tracing::info!("Initiated signaling with peer {}", peer_id); + state.initiated = true; + + return Poll::Ready(ToSwarm::NotifyHandler { + peer_id: peer_id.clone(), + handler: NotifyHandler::One(state.connection_id), + event: FromBehaviourEvent::InitiateSignaling, + }); + } + } + + Poll::Pending + } +} diff --git a/transports/webrtc-websys/src/browser/handler.rs b/transports/webrtc-websys/src/browser/handler.rs new file mode 100644 index 00000000000..5b26333f1b6 --- /dev/null +++ b/transports/webrtc-websys/src/browser/handler.rs @@ -0,0 +1,264 @@ +use std::task::Poll; + +use futures::FutureExt; +use libp2p_core::{upgrade::ReadyUpgrade, PeerId}; +use libp2p_swarm::{ConnectionHandler, ConnectionHandlerEvent, StreamProtocol, SubstreamProtocol}; + +use crate::browser::{ + protocol::signaling::ProtocolHandler, Signaling, SignalingConfig, SignalingStream, + SIGNALING_STREAM_PROTOCOL, +}; + +/// Events sent from the Handler to the Behaviour. +#[derive(Debug)] +pub enum ToBehaviourEvent { + WebRTCConnectionSuccess(crate::Connection), + WebRTCConnectionFailure(crate::Error), + SignalingRetry +} + +/// Events sent from the Behaviour to the Handler. +#[derive(Debug)] +pub enum FromBehaviourEvent { + /// Start signaling with this peer + InitiateSignaling, +} + +/// The current status of the signaling process +/// for this handler. +#[derive(Debug, PartialEq)] +pub(crate) enum SignalingStatus { + /// Relay connection has been established but no signaling + /// attempts have been made + Idle, + /// Currently signaling (either as initiator or responder) + Negotiating, + /// Awaiting the initiator to start signaling + AwaitingInitiation, + /// Waiting before signaling retry + WaitingForRetry, + /// Signaling completed + Complete, + /// Signaling failed + Fail, +} + +#[derive(PartialEq)] +enum SignalingRole { + Initiator, + Responder, +} + +pub struct SignalingHandler { + /// Whether we are the initiator of the signaling protocol + /// or responder + role: Option, + /// The peer we are signaling with + peer: PeerId, + is_dialer: bool, + /// Current number of retries signaling has been attempted + retry_count: u8, + signaling_config: SignalingConfig, + /// Current status of the signaling process + signaling_status: SignalingStatus, + /// Channel holding the signaling result + signaling_result_receiver: + Option>>, +} + +impl SignalingHandler { + pub fn new(peer: PeerId, is_dialer: bool, config: SignalingConfig) -> Self { + Self { + role: None, + peer, + is_dialer, + retry_count: 0, + signaling_config: config, + signaling_status: SignalingStatus::Idle, + signaling_result_receiver: None, + } + } +} + +impl ConnectionHandler for SignalingHandler { + type FromBehaviour = FromBehaviourEvent; + + type ToBehaviour = ToBehaviourEvent; + + type InboundProtocol = ReadyUpgrade; + + type OutboundProtocol = ReadyUpgrade; + + type InboundOpenInfo = (); + + type OutboundOpenInfo = (); + + fn listen_protocol( + &self, + ) -> libp2p_swarm::SubstreamProtocol { + SubstreamProtocol::new(ReadyUpgrade::new(SIGNALING_STREAM_PROTOCOL), ()) + } + + fn poll( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll< + libp2p_swarm::ConnectionHandlerEvent< + Self::OutboundProtocol, + Self::OutboundOpenInfo, + Self::ToBehaviour, + >, + > { + if let Some(mut receiver) = self.signaling_result_receiver.take() { + match receiver.poll_unpin(cx) { + Poll::Ready(Ok(Ok(connection))) => { + tracing::info!("WebRTC connection established"); + self.signaling_status = SignalingStatus::Complete; + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + ToBehaviourEvent::WebRTCConnectionSuccess(connection), + )); + } + Poll::Ready(Ok(Err(err))) => { + tracing::error!("WebRTC signaling failed: {:?}", err); + // If the signaling attempt failed the initiator can retry the attempt up to + // a configurable max retry count. + if self.role == Some(SignalingRole::Initiator) + && self.retry_count < self.signaling_config.max_signaling_retries + { + self.signaling_status = SignalingStatus::WaitingForRetry; + self.retry_count += 1; + self.role = None; + + tracing::info!( + "Retrying signaling attempt {} of {} with peer {}", + self.retry_count, + self.signaling_config.max_signaling_retries, + self.peer + ); + + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + ToBehaviourEvent::SignalingRetry, + )); + } else { + self.signaling_status = SignalingStatus::Fail; + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + ToBehaviourEvent::WebRTCConnectionFailure(err), + )); + } + } + Poll::Ready(Err(_)) => { + tracing::error!("Signaling result channel dropped"); + self.signaling_status = SignalingStatus::Fail; + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + ToBehaviourEvent::WebRTCConnectionFailure(crate::Error::Signaling( + "Channel dropped".to_string(), + )), + )); + } + Poll::Pending => { + // Put the signaling result channel back to poll again later + self.signaling_result_receiver = Some(receiver); + } + } + } + + // Check the signaling status for this handler for any pending outbound signaling + // attempts + if self.signaling_status == SignalingStatus::AwaitingInitiation { + tracing::info!("Requesting OutboundSubstream for signaling protocol"); + self.signaling_status = SignalingStatus::Negotiating; + return Poll::Ready(ConnectionHandlerEvent::OutboundSubstreamRequest { + protocol: SubstreamProtocol::new(ReadyUpgrade::new(SIGNALING_STREAM_PROTOCOL), ()), + }); + } + + Poll::Pending + } + + fn on_behaviour_event(&mut self, event: Self::FromBehaviour) { + match event { + FromBehaviourEvent::InitiateSignaling => { + if self.signaling_status == SignalingStatus::Idle + || self.signaling_status == SignalingStatus::WaitingForRetry + { + self.signaling_status = SignalingStatus::AwaitingInitiation; + } + } + } + } + + fn on_connection_event( + &mut self, + event: libp2p_swarm::handler::ConnectionEvent< + Self::InboundProtocol, + Self::OutboundProtocol, + Self::InboundOpenInfo, + Self::OutboundOpenInfo, + >, + ) { + match event { + libp2p_swarm::handler::ConnectionEvent::FullyNegotiatedInbound( + fully_negotiated_inbound, + ) => { + if self.role.is_some() { + return; + } + + tracing::info!("Negotiated full inbound substream for signaling"); + self.role = Some(SignalingRole::Responder); + self.signaling_status = SignalingStatus::Negotiating; + + let _ = self.on_behaviour_event(FromBehaviourEvent::InitiateSignaling); + + let substream = fully_negotiated_inbound.protocol; + let signaling_protocol = ProtocolHandler::new(self.signaling_config.clone()); + + let (tx, rx) = futures::channel::oneshot::channel(); + self.signaling_result_receiver = Some(rx); + + wasm_bindgen_futures::spawn_local(async move { + let signaling_result = signaling_protocol + .signaling_as_responder(SignalingStream::new(substream)) + .await; + + let _ = tx.send(signaling_result); + }); + } + libp2p_swarm::handler::ConnectionEvent::FullyNegotiatedOutbound( + fully_negotiated_outbound, + ) => { + if self.role.is_some() { + return; + } + + tracing::info!("Negotiated full outbound substream for signaling"); + self.role = Some(SignalingRole::Initiator); + + let substream = fully_negotiated_outbound.protocol; + let signaling_protocol = ProtocolHandler::new(self.signaling_config.clone()); + + let (tx, rx) = futures::channel::oneshot::channel(); + self.signaling_result_receiver = Some(rx); + + wasm_bindgen_futures::spawn_local(async move { + let signaling_result = signaling_protocol + .signaling_as_initiator(SignalingStream::new(substream)) + .await; + + let _ = tx.send(signaling_result); + }); + } + libp2p_swarm::handler::ConnectionEvent::DialUpgradeError(_) => { + if self.role == Some(SignalingRole::Initiator) { + self.signaling_status = SignalingStatus::Fail; + } + } + libp2p_swarm::handler::ConnectionEvent::ListenUpgradeError(_) => { + if self.role == Some(SignalingRole::Responder) { + self.signaling_status = SignalingStatus::Fail; + } + } + _ => {} + } + } +} diff --git a/transports/webrtc-websys/src/browser/mod.rs b/transports/webrtc-websys/src/browser/mod.rs new file mode 100644 index 00000000000..b86e1505fbe --- /dev/null +++ b/transports/webrtc-websys/src/browser/mod.rs @@ -0,0 +1,13 @@ +pub(crate) mod behaviour; +pub(crate) mod handler; +pub(crate) mod protocol; +pub(crate) mod stream; +pub(crate) mod transport; + +pub use behaviour::{Behaviour, SignalingConfig, SignalingEvent}; +pub use protocol::{ + ProtocolHandler, Signaling, SignalingProtocolUpgrade, SIGNALING_PROTOCOL_ID, + SIGNALING_STREAM_PROTOCOL, +}; +pub use stream::SignalingStream; +pub use transport::{Config, Transport}; diff --git a/transports/webrtc-websys/src/browser/protocol/mod.rs b/transports/webrtc-websys/src/browser/protocol/mod.rs new file mode 100644 index 00000000000..b45e481a8ca --- /dev/null +++ b/transports/webrtc-websys/src/browser/protocol/mod.rs @@ -0,0 +1,11 @@ +pub(crate) mod pb { + include!(concat!(env!("OUT_DIR"), "/signaling.rs")); +} + +pub(crate) mod protocol; +pub(crate) mod signaling; +pub(crate) mod upgrade; + +pub use protocol::{SIGNALING_PROTOCOL_ID, SIGNALING_STREAM_PROTOCOL}; +pub use signaling::{ProtocolHandler, Signaling}; +pub use upgrade::SignalingProtocolUpgrade; diff --git a/transports/webrtc-websys/src/browser/protocol/proto/message.proto b/transports/webrtc-websys/src/browser/protocol/proto/message.proto new file mode 100644 index 00000000000..db987a7b365 --- /dev/null +++ b/transports/webrtc-websys/src/browser/protocol/proto/message.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package signaling; + +message SignalingMessage { + enum Type { + SDP_OFFER = 0; + SDP_ANSWER = 1; + ICE_CANDIDATE = 2; + } + + Type type = 1; + string data = 2; +} \ No newline at end of file diff --git a/transports/webrtc-websys/src/browser/protocol/protocol.rs b/transports/webrtc-websys/src/browser/protocol/protocol.rs new file mode 100644 index 00000000000..9f37f8170d6 --- /dev/null +++ b/transports/webrtc-websys/src/browser/protocol/protocol.rs @@ -0,0 +1,4 @@ +use libp2p_swarm::StreamProtocol; + +pub const SIGNALING_PROTOCOL_ID: &'static str = "/webrtc-signaling/0.0.1"; +pub const SIGNALING_STREAM_PROTOCOL: StreamProtocol = StreamProtocol::new(SIGNALING_PROTOCOL_ID); diff --git a/transports/webrtc-websys/src/browser/protocol/signaling.rs b/transports/webrtc-websys/src/browser/protocol/signaling.rs new file mode 100644 index 00000000000..8ada6c0cf2b --- /dev/null +++ b/transports/webrtc-websys/src/browser/protocol/signaling.rs @@ -0,0 +1,616 @@ +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +use futures::{lock::Mutex, AsyncRead, AsyncWrite, SinkExt, StreamExt}; +use tracing::instrument; +use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; +use wasm_bindgen_futures::{spawn_local, JsFuture}; +use web_sys::{ + RtcIceCandidate, RtcIceCandidateInit, RtcIceConnectionState, RtcIceGatheringState, + RtcPeerConnectionIceEvent, RtcPeerConnectionState, RtcSdpType, RtcSessionDescriptionInit, + RtcSignalingState, +}; + +use crate::{ + browser::{ + protocol::pb::{signaling_message, SignalingMessage}, SignalingConfig, SignalingStream + }, + connection::RtcPeerConnection, + error::Error, + Connection, +}; + +// Implementation of WebRTC signaling protocol between two peers. This implementation follows +// the specification here: https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md. + +/// Connection states for ICE connection, ICE gathering, signaling +/// and the peer connection. +#[derive(Clone, Debug)] +struct ConnectionState { + pub(crate) ice_connection: RtcIceConnectionState, + pub(crate) ice_gathering: RtcIceGatheringState, + pub(crate) signaling: RtcSignalingState, + pub(crate) peer_connection: RtcPeerConnectionState, +} + +/// Callbacks for ICE connection, ICE gathering, peer connection signaling +/// and ice candidate retrieval. +struct ConnectionCallbacks { + _ice_connection_callback: Closure, + _ice_gathering_callback: Closure, + _peer_connection_callback: Closure, + _signaling_callback: Closure, + _ice_candidate_callback: Option>, +} + +/// Helper function to safely convert ice connection state +fn safe_ice_connection_state_from_js(js_val: JsValue) -> RtcIceConnectionState { + if let Some(state_str) = js_val.as_string() { + match state_str.as_str() { + "new" => RtcIceConnectionState::New, + "checking" => RtcIceConnectionState::Checking, + "connected" => RtcIceConnectionState::Connected, + "completed" => RtcIceConnectionState::Completed, + "failed" => RtcIceConnectionState::Failed, + "disconnected" => RtcIceConnectionState::Disconnected, + "closed" => RtcIceConnectionState::Closed, + _ => { + tracing::warn!( + "Unknown ICE connection state: '{}', defaulting to New", + state_str + ); + RtcIceConnectionState::New + } + } + } else { + tracing::warn!("ICE connection state is not a string: {:?}", js_val); + RtcIceConnectionState::New + } +} + +/// Helper function to safely convert ice gathering state +fn safe_ice_gathering_state_from_js(js_val: JsValue) -> RtcIceGatheringState { + if let Some(state_str) = js_val.as_string() { + match state_str.as_str() { + "new" => RtcIceGatheringState::New, + "gathering" => RtcIceGatheringState::Gathering, + "complete" => RtcIceGatheringState::Complete, + _ => { + tracing::warn!( + "Unknown ICE gathering state: '{}', defaulting to New", + state_str + ); + RtcIceGatheringState::New + } + } + } else { + tracing::warn!("ICE gathering state is not a string: {:?}", js_val); + RtcIceGatheringState::New + } +} + +/// Helper function to safely convert peer connection state +fn safe_peer_connection_state_from_js(js_val: JsValue) -> RtcPeerConnectionState { + if let Some(state_str) = js_val.as_string() { + match state_str.as_str() { + "new" => RtcPeerConnectionState::New, + "connecting" => RtcPeerConnectionState::Connecting, + "connected" => RtcPeerConnectionState::Connected, + "disconnected" => RtcPeerConnectionState::Disconnected, + "failed" => RtcPeerConnectionState::Failed, + "closed" => RtcPeerConnectionState::Closed, + _ => { + tracing::warn!( + "Unknown peer connection state: '{}', defaulting to New", + state_str + ); + RtcPeerConnectionState::New + } + } + } else { + tracing::warn!("Peer connection state is not a string: {:?}", js_val); + RtcPeerConnectionState::New + } +} + +/// Helper function to safely convert signaling state +fn safe_signaling_state_from_js(js_val: JsValue) -> RtcSignalingState { + if let Some(state_str) = js_val.as_string() { + match state_str.as_str() { + "stable" => RtcSignalingState::Stable, + "have-local-offer" => RtcSignalingState::HaveLocalOffer, + "have-remote-offer" => RtcSignalingState::HaveRemoteOffer, + "have-local-pranswer" => RtcSignalingState::HaveLocalPranswer, + "have-remote-pranswer" => RtcSignalingState::HaveRemotePranswer, + "closed" => RtcSignalingState::Closed, + _ => { + tracing::warn!( + "Unknown signaling state: '{}', defaulting to Closed", + state_str + ); + RtcSignalingState::Closed + } + } + } else { + tracing::warn!("Signaling state is not a string: {:?}", js_val); + RtcSignalingState::Closed + } +} + +pub trait Signaling { + /// Performs WebRTC signaling as an initiator. + async fn signaling_as_initiator( + &self, + stream: SignalingStream, + ) -> Result; + + /// Performs WebRTC signaling as a responder. + async fn signaling_as_responder( + &self, + stream: SignalingStream, + ) -> Result; +} + +#[derive(Debug)] +pub struct ProtocolHandler { + states: send_wrapper::SendWrapper>>, + config: SignalingConfig +} + +impl ProtocolHandler { + pub fn new(config: SignalingConfig) -> Self { + Self { + states: send_wrapper::SendWrapper::new(Rc::new(RefCell::new(ConnectionState { + ice_connection: RtcIceConnectionState::New, + ice_gathering: RtcIceGatheringState::New, + signaling: RtcSignalingState::Closed, + peer_connection: RtcPeerConnectionState::Closed, + }))), + config + } + } +} + +impl ProtocolHandler { + /// Sets up the peer connection statee callbacks including ICE connection, ICE gathering, + /// peer connectiona and signaling. + fn setup_peer_connection_state_callbacks( + &self, + connection: &web_sys::RtcPeerConnection, + ) -> ConnectionCallbacks { + tracing::trace!("Setting up peer connection state callbacks"); + + // Setup callbacks for state management + // ICE connection state callback + let states = self.states.clone(); + let ice_connection_callback = Closure::wrap(Box::new(move |event: web_sys::Event| { + if let Some(target) = event.target() { + if let Some(pc) = target.dyn_ref::() { + let state_js = pc.ice_connection_state(); + let state = safe_ice_connection_state_from_js(state_js.into()); + + tracing::debug!("ICE connection state changed to: {:?}", state); + states.borrow_mut().ice_connection = state; + } + } + }) as Box); + + connection.set_oniceconnectionstatechange(Some( + &ice_connection_callback.as_ref().unchecked_ref(), + )); + + // ICE gathering state callback + let states = self.states.clone(); + let ice_gathering_callback = Closure::wrap(Box::new(move |event: web_sys::Event| { + if let Some(target) = event.target() { + if let Some(pc) = target.dyn_ref::() { + let state_js = pc.ice_gathering_state(); + let state = safe_ice_gathering_state_from_js(state_js.into()); + + tracing::debug!("ICE gathering state changed to: {:?}", state); + states.borrow_mut().ice_gathering = state; + } + } + }) as Box); + + connection + .set_onicegatheringstatechange(Some(&ice_gathering_callback.as_ref().unchecked_ref())); + + // Peer connection state callback + let states = self.states.clone(); + let peer_connection_callback = Closure::wrap(Box::new(move |event: web_sys::Event| { + if let Some(target) = event.target() { + if let Some(pc) = target.dyn_ref::() { + let state_js = pc.connection_state(); + let state = safe_peer_connection_state_from_js(state_js.into()); + + tracing::debug!("Peer connection state changed to: {:?}", state); + states.borrow_mut().peer_connection = state; + } + } + }) as Box); + + connection + .set_onconnectionstatechange(Some(&peer_connection_callback.as_ref().unchecked_ref())); + + // Signaling state callback + let states = self.states.clone(); + let signaling_callback = Closure::wrap(Box::new(move |event: web_sys::Event| { + if let Some(target) = event.target() { + if let Some(pc) = target.dyn_ref::() { + let state_js = pc.signaling_state(); + let state = safe_signaling_state_from_js(state_js.into()); + + tracing::debug!("Signaling state changed to: {:?}", state); + states.borrow_mut().signaling = state; + } + } + }) as Box); + + connection.set_onsignalingstatechange(Some(&signaling_callback.as_ref().unchecked_ref())); + + // Create the callbacks struct to keep closures alive + let callbacks = ConnectionCallbacks { + _ice_connection_callback: ice_connection_callback, + _ice_gathering_callback: ice_gathering_callback, + _peer_connection_callback: peer_connection_callback, + _signaling_callback: signaling_callback, + _ice_candidate_callback: None, + }; + + callbacks + } + + /// Waits for the RtcPeerConnection to establish + async fn wait_for_established_conn(&self) -> Result<(), Error> { + let mut attempts = 0; + + loop { + let current_states = self.states.borrow().clone(); + + tracing::debug!( + "Connection status check #{}: ICE={:?}, Peer={:?}, Signaling={:?}, Gathering={:?}", + attempts + 1, + current_states.ice_connection, + current_states.peer_connection, + current_states.signaling, + current_states.ice_gathering + ); + + match current_states.peer_connection { + RtcPeerConnectionState::Connected => { + tracing::info!("Peer connection is connected"); + break; + } + RtcPeerConnectionState::Failed => { + tracing::error!("Peer connection failed"); + return Err(Error::Signaling("Peer connection failed".to_string())); + } + _ => { + attempts += 1; + if attempts >= self.config.max_connection_establishment_checks { + tracing::error!( + "Final states: ICE={:?}, Peer={:?}, Signaling={:?}, Gathering={:?}", + current_states.ice_connection, + current_states.peer_connection, + current_states.signaling, + current_states.ice_gathering + ); + return Err(Error::Signaling("Connection timeout".to_string())); + } + + gloo_timers::future::sleep(self.config.connection_establishment_delay_in_millis).await; + } + } + } + + Ok(()) + } + +/// Parse ICE candidate from JSON message +fn parse_ice_candidate(message: &SignalingMessage) -> Option { + if let Ok(candidate_json) = serde_json::from_str::(&message.data) { + if let Some(candidate_str) = candidate_json.get("candidate").and_then(|v| v.as_str()) { + let candidate_init = RtcIceCandidateInit::new(candidate_str); + + if let Some(sdp_mid) = candidate_json.get("sdpMid").and_then(|v| v.as_str()) { + candidate_init.set_sdp_mid(Some(sdp_mid)); + } + + if let Some(sdp_m_line_index) = candidate_json.get("sdpMLineIndex").and_then(|v| v.as_u64()) { + candidate_init.set_sdp_m_line_index(Some(sdp_m_line_index as u16)); + } + + return Some(candidate_init); + } + } + + None +} +} + +impl Signaling for ProtocolHandler { + #[instrument(skip(stream), fields(initiator = false))] + async fn signaling_as_responder( + &self, + stream: SignalingStream, + ) -> Result { + tracing::info!("Starting WebRTC signaling"); + let rtc_conn = RtcPeerConnection::new("sha-256".to_string()).await?; + let connection = rtc_conn.inner(); + + let pb_stream = Arc::new(Mutex::new(stream)); + let (ice_candidate_sender, mut ice_candidate_receiver) = + futures::channel::mpsc::channel::(100); + + let mut callbacks = self.setup_peer_connection_state_callbacks(connection); + + // Read SDP offer + let offer_message = pb_stream.lock().await.read().await.map_err(|_| { + Error::ProtoSerialization("Failure to read SDP offer from signaling stream".to_string()) + })?; + + if offer_message.r#type != signaling_message::Type::SdpOffer as i32 { + return Err(Error::Signaling("Expected SDP offer".to_string())); + } + + // Set remote description with remote offer + let offer_init = RtcSessionDescriptionInit::new(RtcSdpType::Offer); + offer_init.set_sdp(&offer_message.data); + + JsFuture::from(connection.set_remote_description(&offer_init)) + .await + .map_err(|_| Error::Js("Could not set remote description".to_string()))?; + + // Create answer and set local description + let answer = JsFuture::from(connection.create_answer()).await?; + let answer_sdp = js_sys::Reflect::get(&answer, &JsValue::from_str("sdp"))? + .as_string() + .ok_or_else(|| Error::Js("Could not extract SDP from answer".to_string()))?; + + let answer_init = RtcSessionDescriptionInit::new(RtcSdpType::Answer); + answer_init.set_sdp(&answer_sdp); + + JsFuture::from(connection.set_local_description(&answer_init)) + .await + .map_err(|_| Error::Js("Could not set local description".to_string()))?; + + // Send SDP answer + let answer_message = SignalingMessage { + r#type: signaling_message::Type::SdpAnswer as i32, + data: answer_sdp, + }; + + pb_stream + .lock() + .await + .write(answer_message) + .await + .map_err(|_| { + Error::ProtoSerialization( + "Failure to write SDP answer to signaling stream".to_string(), + ) + })?; + + // Set up ICE candidate callback for non-initiator + let sender_for_closure = ice_candidate_sender.clone(); + let ice_candidate_callback = + Closure::wrap(Box::new(move |event: RtcPeerConnectionIceEvent| { + if let Some(candidate) = event.candidate() { + tracing::trace!("Generated ICE candidate: {}", candidate.candidate()); + let candidate_for_task = candidate.clone(); + let mut sender_for_task = sender_for_closure.clone(); + spawn_local(async move { + tracing::trace!("Sending ICE candidate"); + if let Err(e) = sender_for_task.send(candidate_for_task).await { + tracing::error!("Failed to send ICE candidate: {:?}", e); + } + }); + } else { + tracing::info!("End of ICE candidates (null candidate)"); + } + }) as Box); + + connection.set_onicecandidate(Some(ice_candidate_callback.as_ref().unchecked_ref())); + callbacks._ice_candidate_callback = Some(ice_candidate_callback); + + // Send ICE candidates to remote peer + let ice_sender_stream = pb_stream.clone(); + spawn_local(async move { + while let Some(candidate) = ice_candidate_receiver.next().await { + let candidate_json = candidate.to_json(); + let candidate_as_str = js_sys::JSON::stringify(&candidate_json) + .unwrap() + .as_string() + .unwrap_or_default(); + + let message = SignalingMessage { + r#type: signaling_message::Type::IceCandidate as i32, + data: candidate_as_str, + }; + + if let Err(e) = ice_sender_stream.lock().await.write(message).await { + tracing::error!("Failed to send ICE candidate: {:?}", e); + break; + } + } + }); + + // Receive and add ice candidates from remote peer + let ice_reader_stream = pb_stream.clone(); + let connection_clone = connection.clone(); + spawn_local(async move { + while let Ok(message) = ice_reader_stream.lock().await.read().await { + if message.r#type == signaling_message::Type::IceCandidate as i32 { + tracing::trace!("Received remote ICE candidate: {}", message.data); + + if let Some(candidate_init) = ProtocolHandler::parse_ice_candidate(&message) { + match JsFuture::from( + connection_clone.add_ice_candidate_with_opt_rtc_ice_candidate_init( + Some(&candidate_init), + ), + ) + .await + { + Ok(_) => {} + Err(e) => tracing::error!( + "Failed to add remote ICE candidate: {:?}", + e + ), + } + } + + + } + } + }); + + self.wait_for_established_conn().await?; + drop(callbacks); + + tracing::info!("Successfully created WebRTC connection"); + Ok(Connection::new(rtc_conn)) + } + + #[instrument(skip(stream), fields(initiator = true))] + async fn signaling_as_initiator( + &self, + stream: SignalingStream, + ) -> Result { + tracing::info!("Starting signaling"); + let rtc_conn = RtcPeerConnection::new("sha-256".to_string()).await?; + let connection = rtc_conn.inner(); + + let pb_stream = Arc::new(Mutex::new(stream)); + let (ice_candidate_sender, mut ice_candidate_receiver) = + futures::channel::mpsc::channel::(100); + + let mut callbacks = self.setup_peer_connection_state_callbacks(connection); + + // Create a data channel to ensure ICE information is shared in the SDP + tracing::trace!("Creating data channel"); + let data_channel = connection.create_data_channel("init"); + + // Set a callback to handle ice candidates + let sender_for_closure = ice_candidate_sender.clone(); + let ice_candidate_callback = + Closure::wrap(Box::new(move |event: RtcPeerConnectionIceEvent| { + if let Some(candidate) = event.candidate() { + let candidate_for_task = candidate.clone(); + let mut sender_for_task = sender_for_closure.clone(); + + spawn_local(async move { + if let Err(e) = sender_for_task.send(candidate_for_task).await { + tracing::error!("Failed to send ICE candidate: {:?}", e); + } + }); + } else { + tracing::info!("End of ICE candidates (null candidate)"); + } + }) as Box); + + connection.set_onicecandidate(Some(ice_candidate_callback.as_ref().unchecked_ref())); + callbacks._ice_candidate_callback = Some(ice_candidate_callback); + + let pb_stream_clone = Arc::clone(&pb_stream); + + // Send ICE candidates to remote peer through the signaling stream + spawn_local(async move { + while let Some(candidate) = ice_candidate_receiver.next().await { + tracing::trace!("New ICE candidate: {}", candidate.to_string()); + let candidate_json = candidate.to_json(); + let candidate_as_str = js_sys::JSON::stringify(&candidate_json) + .unwrap() + .as_string() + .unwrap_or_default(); + + let message = SignalingMessage { + r#type: signaling_message::Type::IceCandidate as i32, + data: candidate_as_str, + }; + + let mut guard = pb_stream_clone.lock().await; + if let Err(e) = guard.write(message).await { + tracing::error!( + "Failure to write ICE candidate to signaling stream: {:?}", + e + ); + break; + } + } + }); + + // Create offer + let offer = JsFuture::from(connection.create_offer()).await?; + let offer_sdp = js_sys::Reflect::get(&offer, &JsValue::from_str("sdp"))? + .as_string() + .ok_or_else(|| Error::Js("Could not extract SDP from offer".to_string()))?; + + let offer_init = RtcSessionDescriptionInit::new(RtcSdpType::Offer); + offer_init.set_sdp(&offer_sdp); + + JsFuture::from(connection.set_local_description(&offer_init)) + .await + .map_err(|_| Error::Js("Could not set local description".to_string()))?; + + // Write SDP offer to the signaling stream + let message = SignalingMessage { + r#type: signaling_message::Type::SdpOffer as i32, + data: offer_sdp, + }; + + pb_stream.lock().await.write(message).await.map_err(|_| { + Error::ProtoSerialization("Failure to write SDP offer to signaling stream".to_string()) + })?; + + // Read SDP answer + let answer_message = pb_stream.lock().await.read().await.map_err(|_| { + Error::ProtoSerialization( + "Failure to read SDP answer from signaling stream".to_string(), + ) + })?; + + if answer_message.r#type != signaling_message::Type::SdpAnswer as i32 { + return Err(Error::Signaling("Expected SDP answer".to_string())); + } + + let answer_init = RtcSessionDescriptionInit::new(RtcSdpType::Answer); + answer_init.set_sdp(&answer_message.data); + + // Set answer as remote description + JsFuture::from(connection.set_remote_description(&answer_init)) + .await + .map_err(|_| Error::Js("Could not set remote description".to_string()))?; + + // Receive and add ice candidates from remote peer until connected + let connection_clone = connection.clone(); + spawn_local(async move { + while let Ok(message) = pb_stream.lock().await.read().await { + if message.r#type == signaling_message::Type::IceCandidate as i32 { + if let Some(candidate_init) = ProtocolHandler::parse_ice_candidate(&message) { + match JsFuture::from( + connection_clone.add_ice_candidate_with_opt_rtc_ice_candidate_init( + Some(&candidate_init), + ), + ) + .await + { + Ok(_) => {} + Err(e) => tracing::error!( + "Failed to add remote ICE candidate: {:?}", + e + ), + } + } + + } + } + }); + + self.wait_for_established_conn().await?; + data_channel.close(); + drop(callbacks); + + tracing::info!("Successfully created WebRTC connection"); + Ok(Connection::new(rtc_conn)) + } +} diff --git a/transports/webrtc-websys/src/browser/protocol/upgrade.rs b/transports/webrtc-websys/src/browser/protocol/upgrade.rs new file mode 100644 index 00000000000..e6f6d4d3485 --- /dev/null +++ b/transports/webrtc-websys/src/browser/protocol/upgrade.rs @@ -0,0 +1,44 @@ +use std::{future::Future, pin::Pin}; + +use futures::{AsyncRead, AsyncWrite}; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_swarm::StreamProtocol; + +use crate::browser::{stream::SignalingStream, SIGNALING_STREAM_PROTOCOL}; + +pub struct SignalingProtocolUpgrade; + +impl UpgradeInfo for SignalingProtocolUpgrade { + type Info = StreamProtocol; + type InfoIter = std::iter::Once; + + fn protocol_info(&self) -> Self::InfoIter { + std::iter::once(SIGNALING_STREAM_PROTOCOL) + } +} + +impl InboundUpgrade for SignalingProtocolUpgrade +where + T: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = SignalingStream; + type Error = std::io::Error; + type Future = Pin> + Send>>; + + fn upgrade_inbound(self, socket: T, _info: Self::Info) -> Self::Future { + Box::pin(async move { Ok(SignalingStream::new(socket)) }) + } +} + +impl OutboundUpgrade for SignalingProtocolUpgrade +where + T: AsyncRead + AsyncWrite + Unpin + Send + 'static, +{ + type Output = SignalingStream; + type Error = std::io::Error; + type Future = Pin> + Send>>; + + fn upgrade_outbound(self, socket: T, _info: Self::Info) -> Self::Future { + Box::pin(async move { Ok(SignalingStream::new(socket)) }) + } +} diff --git a/transports/webrtc-websys/src/browser/stream.rs b/transports/webrtc-websys/src/browser/stream.rs new file mode 100644 index 00000000000..e562787b98b --- /dev/null +++ b/transports/webrtc-websys/src/browser/stream.rs @@ -0,0 +1,43 @@ +use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use prost::Message; + +use crate::browser::protocol::pb::SignalingMessage; + +/// A wrapper over a async stream for reading and writing SignalingMesssages. +pub struct SignalingStream { + inner: T, +} + +impl SignalingStream +where + T: AsyncRead + AsyncWrite + Unpin, +{ + pub fn new(inner: T) -> Self { + Self { inner } + } + + /// Encodes and writes a signaling message to the stream. + pub async fn write(&mut self, message: SignalingMessage) -> Result<(), std::io::Error> { + let mut buf = Vec::new(); + message.encode(&mut buf)?; + let len = buf.len() as u32; + + self.inner.write_all(&len.to_be_bytes()).await?; + self.inner.write_all(&buf).await?; + self.inner.flush().await?; + Ok(()) + } + + /// Reads and decodes a signaling message from the stream. + pub async fn read(&mut self) -> Result { + let mut len_buf = [0u8; 4]; + self.inner.read_exact(&mut len_buf).await?; + let len = u32::from_be_bytes(len_buf) as usize; + + let mut buf = vec![0u8; len]; + self.inner.read_exact(&mut buf).await?; + + let message = SignalingMessage::decode(&buf[..])?; + Ok(message) + } +} diff --git a/transports/webrtc-websys/src/browser/transport.rs b/transports/webrtc-websys/src/browser/transport.rs new file mode 100644 index 00000000000..33e2d7cc2ec --- /dev/null +++ b/transports/webrtc-websys/src/browser/transport.rs @@ -0,0 +1,82 @@ +use std::{ + collections::VecDeque, + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + +use libp2p_core::{ + multiaddr::Multiaddr, + muxing::StreamMuxerBox, + transport::{DialOpts, ListenerId, Transport as _, TransportError, TransportEvent}, +}; +use libp2p_identity::{Keypair, PeerId}; + +use crate::{ + browser::{behaviour::Behaviour, SignalingConfig}, + Error, +}; + +/// Config for the [`Transport`]. +#[derive(Debug, Clone)] +pub struct Config { + pub keypair: Keypair, +} + +/// A WebTransport [`Transport`](libp2p_core::Transport) that faciliates a WebRTC [`Connection`]. +pub struct Transport { + config: Config, +} + +impl Transport { + /// Constructs a new [`Transport`] with the given [`Config`] and [`Behaviour`] for Signaling. + pub fn new(config: Config, signaling_config: SignalingConfig) -> (Self, Behaviour) { + let transport = Self { + config: config.clone(), + }; + let behaviour = Behaviour::new(signaling_config); + + (transport, behaviour) + } + + /// Wraps `Transport` in [`Boxed`] and makes it ready to be consumed by + /// SwarmBuilder. + pub fn boxed(self) -> libp2p_core::transport::Boxed<(PeerId, StreamMuxerBox)> { + self.map(|(peer_id, muxer), _| (peer_id, StreamMuxerBox::new(muxer))) + .boxed() + } +} + +impl libp2p_core::Transport for Transport { + type Output = (PeerId, crate::Connection); + type Error = Error; + type ListenerUpgrade = Pin> + Send>>; + type Dial = Pin> + Send>>; + + fn listen_on( + &mut self, + _id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError> { + Err(TransportError::MultiaddrNotSupported(addr)) + } + + fn remove_listener(&mut self, _id: ListenerId) -> bool { + false + } + + fn dial( + &mut self, + addr: Multiaddr, + _opts: DialOpts, + ) -> Result> { + return Err(TransportError::MultiaddrNotSupported(addr.clone())); + } + + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + Poll::Pending + } +} diff --git a/transports/webrtc-websys/src/connection.rs b/transports/webrtc-websys/src/connection.rs index 01c1a8b3b60..554193b5e56 100644 --- a/transports/webrtc-websys/src/connection.rs +++ b/transports/webrtc-websys/src/connection.rs @@ -24,6 +24,7 @@ use crate::stream::DropListener; /// /// All connections need to be [`Send`] which is why some fields are wrapped in [`SendWrapper`]. /// This is safe because WASM is single-threaded. +#[derive(Debug)] pub struct Connection { /// The [RtcPeerConnection] that is used for the WebRTC Connection inner: SendWrapper, @@ -173,6 +174,7 @@ impl StreamMuxer for Connection { } } +#[derive(Debug)] pub(crate) struct RtcPeerConnection { inner: web_sys::RtcPeerConnection, } @@ -201,6 +203,10 @@ impl RtcPeerConnection { Ok(Self { inner }) } + pub(crate) fn inner(&self) -> &web_sys::RtcPeerConnection { + &self.inner + } + /// Creates the stream for the initial noise handshake. /// /// The underlying data channel MUST have `negotiated` set to `true` and carry the ID 0. diff --git a/transports/webrtc-websys/src/error.rs b/transports/webrtc-websys/src/error.rs index a2df1a182ea..e24db131723 100644 --- a/transports/webrtc-websys/src/error.rs +++ b/transports/webrtc-websys/src/error.rs @@ -21,6 +21,12 @@ pub enum Error { #[error("Authentication error")] Authentication(#[from] AuthenticationError), + + #[error("Serialization error: {0}")] + ProtoSerialization(String), + + #[error("Signaling error: {0}")] + Signaling(String), } /// New-type wrapper to hide `libp2p_noise` from the public API. diff --git a/transports/webrtc-websys/src/lib.rs b/transports/webrtc-websys/src/lib.rs index 07207eb0ae8..c2dee88faa0 100644 --- a/transports/webrtc-websys/src/lib.rs +++ b/transports/webrtc-websys/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] +pub mod browser; mod connection; mod error; mod sdp; @@ -8,6 +9,7 @@ mod transport; mod upgrade; pub use self::{ + browser::{Config as BrowserConfig, Transport as BrowserTransport}, connection::Connection, error::Error, stream::Stream,