From aa0c501fe8010ea2052db39aed7628e64e61acef Mon Sep 17 00:00:00 2001 From: Wang Date: Tue, 1 Sep 2026 00:22:54 +0800 Subject: [PATCH 1/3] feat(runtime-host): accept WebRTC direct upgrades --- deny.toml | 6 + native/runtime-host-peer/Cargo.lock | 800 ++++++- native/runtime-host-peer/Cargo.toml | 12 +- native/runtime-host-peer/src/bindings.rs | 37 + native/runtime-host-peer/src/engine.rs | 136 +- native/runtime-host-peer/src/lib.rs | 1 + .../src/webrtc_direct/mod.rs | 33 + .../src/webrtc_direct/muxer.rs | 484 ++++ .../src/webrtc_direct/signaling.rs | 225 ++ .../src/webrtc_direct/tests.rs | 73 + .../src/webrtc_direct/transport.rs | 194 ++ .../src/webrtc_direct/upgrade.rs | 449 ++++ .../RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv | 69 + .../RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt | 1972 +++++++++++++++-- .../src/__tests__/peer-native.test.ts | 12 +- .../runtime-host/src/client/peer-client.ts | 7 + packages/runtime-host/src/peer-mesh/owner.ts | 2 + .../runtime-host/src/server/peer-listener.ts | 1 + .../runtime-host/src/transport/peer-native.ts | 3 + 19 files changed, 4337 insertions(+), 179 deletions(-) create mode 100644 native/runtime-host-peer/src/webrtc_direct/mod.rs create mode 100644 native/runtime-host-peer/src/webrtc_direct/muxer.rs create mode 100644 native/runtime-host-peer/src/webrtc_direct/signaling.rs create mode 100644 native/runtime-host-peer/src/webrtc_direct/tests.rs create mode 100644 native/runtime-host-peer/src/webrtc_direct/transport.rs create mode 100644 native/runtime-host-peer/src/webrtc_direct/upgrade.rs diff --git a/deny.toml b/deny.toml index 577f4b0b67..7453f5f726 100644 --- a/deny.toml +++ b/deny.toml @@ -34,3 +34,9 @@ allow = [ "Zlib", ] confidence-threshold = 0.8 + +[sources] +allow-git = ["https://github.com/webrtc-rs/webrtc"] +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +unknown-git = "deny" +unknown-registry = "deny" diff --git a/native/runtime-host-peer/Cargo.lock b/native/runtime-host-peer/Cargo.lock index 1fb8cbdcef..254be6e9b2 100644 --- a/native/runtime-host-peer/Cargo.lock +++ b/native/runtime-host-peer/Cargo.lock @@ -49,13 +49,29 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +[[package]] +name = "asn1-rs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +dependencies = [ + "asn1-rs-derive 0.5.1", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + [[package]] name = "asn1-rs" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" dependencies = [ - "asn1-rs-derive", + "asn1-rs-derive 0.6.0", "asn1-rs-impl", "displaydoc", "nom", @@ -65,6 +81,18 @@ dependencies = [ "time", ] +[[package]] +name = "asn1-rs-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + [[package]] name = "asn1-rs-derive" version = "0.6.0" @@ -94,6 +122,30 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4858a9d740c5007a9069007c3b4e91152d0506f13c1b31dd49051fd537656156" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-io" version = "2.6.0" @@ -148,7 +200,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" dependencies = [ - "base64", + "base64 0.22.1", "http", "log", "url", @@ -188,12 +240,33 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.1" @@ -233,6 +306,29 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "bytecheck" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26333eeac754f0ad8a6bcd0eb0ac012156302e4e16b852b72ee399aea4f12c29" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d07918caa9eeaaf06b7873925c53a61daac173539b4f7715090745e44e4e69" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -255,6 +351,18 @@ dependencies = [ "shlex", ] +[[package]] +name = "ccm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" +dependencies = [ + "aead", + "cipher", + "ctr", + "subtle", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -377,6 +485,30 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + [[package]] name = "critical-section" version = "1.2.0" @@ -502,13 +634,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs 0.6.2", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + [[package]] name = "der-parser" version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "asn1-rs", + "asn1-rs 0.7.2", "displaydoc", "nom", "num-bigint", @@ -608,6 +754,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastbloom" version = "0.17.0" @@ -1671,13 +1837,13 @@ dependencies = [ "futures-rustls", "libp2p-core", "libp2p-identity", - "rcgen", + "rcgen 0.13.2", "ring", "rustls", "rustls-webpki", "thiserror 2.0.20", - "x509-parser", - "yasna", + "x509-parser 0.17.0", + "yasna 0.5.2", ] [[package]] @@ -1695,6 +1861,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "libp2p-webrtc-utils" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490abff5ee5f9a7a77f0145c79cc97c76941231a3626f4dee18ebf2abb95618f" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures", + "hex", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.8", + "serde", + "sha2", + "tinytemplate", + "tracing", +] + [[package]] name = "libp2p-yamux" version = "0.47.0" @@ -1747,13 +1935,21 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" name = "maka-runtime-host-peer" version = "0.0.0" dependencies = [ + "async-trait", + "bytes", "futures", "libp2p", + "libp2p-webrtc-utils", "napi", "napi-build", "napi-derive", + "prost", + "serde_json", + "thiserror 2.0.20", "tokio", "tokio-util", + "unsigned-varint 0.8.0", + "webrtc", ] [[package]] @@ -1767,12 +1963,31 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1862,13 +2077,33 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "munge" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "napi" version = "3.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58c5f4d5375213fdb7be2655e152386e82f026f9a5ba36a75556e11359aafe09" dependencies = [ - "bitflags", + "bitflags 2.13.1", "ctor", "futures", "libc", @@ -1936,7 +2171,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" dependencies = [ - "bitflags", + "bitflags 2.13.1", "libc", "log", "netlink-packet-core", @@ -1976,10 +2211,23 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.13.1", "cfg-if", "cfg_aliases", "libc", + "memoffset", ] [[package]] @@ -2032,13 +2280,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oid-registry" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +dependencies = [ + "asn1-rs 0.6.2", +] + [[package]] name = "oid-registry" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ - "asn1-rs", + "asn1-rs 0.7.2", ] [[package]] @@ -2098,7 +2355,17 @@ version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ - "base64", + "base64 0.22.1", + "serde_core", +] + +[[package]] +name = "pem" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d354a98a3d1251555de99e8fdd8afda05573c31b82f59063a7b0a29b5527f120" +dependencies = [ + "base64 0.23.1", "serde_core", ] @@ -2266,6 +2533,26 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "ptr_meta" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743da816b98c921cdbe8628ef7381b76f25ecf4da599fc80aca90eae7ef70cc0" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c8d9ca532f185d5d4db7a7c9d51420b452168ea1c2b913953281bd6fe1fcbd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -2299,7 +2586,7 @@ dependencies = [ "futures-io", "pin-project-lite", "quinn-proto", - "quinn-udp", + "quinn-udp 0.5.15", "rustc-hash", "rustls", "socket2 0.6.5", @@ -2346,6 +2633,19 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "quinn-udp" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76150b617afc75e6e21ac5f39bc196e80b65415ae48d62dbef8e2519d040ce42" +dependencies = [ + "cfg_aliases", + "libc", + "log", + "socket2 0.6.5", + "windows-sys 0.61.2", +] + [[package]] name = "quote" version = "1.0.47" @@ -2367,6 +2667,15 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rancor" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b534442d0fcdb55d66f373d9cac6d33b6293a2335bc2136dbd06ce0e87d2572" +dependencies = [ + "ptr_meta", +] + [[package]] name = "rand" version = "0.8.8" @@ -2458,11 +2767,25 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" dependencies = [ - "pem", + "pem 3.0.6", "ring", "rustls-pki-types", "time", - "yasna", + "yasna 0.5.2", +] + +[[package]] +name = "rcgen" +version = "0.14.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8774e05a7d0de114588e6a28fe7e71694b82614ed569d86d8b389dfbc98b8ad8" +dependencies = [ + "pem 4.0.0", + "ring", + "rustls-pki-types", + "time", + "x509-parser 0.18.1", + "yasna 0.6.0", ] [[package]] @@ -2471,7 +2794,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.1", +] + +[[package]] +name = "rend" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "663ba70707f96e871406fe10d68128412e619b06d1d47cb91c3a4c6501176240" +dependencies = [ + "bytecheck", ] [[package]] @@ -2494,6 +2826,280 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9776093b7ca170454ab1406954f7b7d97a57c51dc6c0642957fb2ef25c2d399" +dependencies = [ + "bytecheck", + "bytes", + "hashbrown 0.17.1", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c25ef604ac7dd839d44d64648952ea23c97866f124ff671b0ed2cf3ad9bb06e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "rtc" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "hex", + "log", + "pem 3.0.6", + "rand 0.10.2", + "rcgen 0.14.10", + "rtc-crypto", + "rtc-datachannel", + "rtc-dtls", + "rtc-ice", + "rtc-interceptor", + "rtc-mdns", + "rtc-media", + "rtc-rtcp", + "rtc-rtp", + "rtc-sctp", + "rtc-sdp", + "rtc-shared", + "rtc-srtp", + "rtc-stun", + "rtc-turn", + "rustls", + "sansio", + "serde", + "serde_json", + "unicase", + "url", + "x509-parser 0.16.0", +] + +[[package]] +name = "rtc-crypto" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "aes", + "ccm", + "ctr", + "hmac", + "md-5", + "rand 0.10.2", + "ring", + "sha1", + "subtle", + "thiserror 2.0.20", + "zeroize", +] + +[[package]] +name = "rtc-datachannel" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "log", + "rtc-sctp", + "rtc-shared", + "sansio", +] + +[[package]] +name = "rtc-dtls" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytecheck", + "byteorder", + "bytes", + "der-parser 9.0.0", + "log", + "pem 3.0.6", + "rcgen 0.14.10", + "rkyv", + "rtc-crypto", + "rtc-shared", + "rustls", + "x509-parser 0.16.0", +] + +[[package]] +name = "rtc-ice" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "crc", + "log", + "rtc-crypto", + "rtc-mdns", + "rtc-shared", + "rtc-stun", + "sansio", + "serde", + "url", + "uuid", +] + +[[package]] +name = "rtc-interceptor" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "log", + "rand 0.10.2", + "rtc-rtcp", + "rtc-rtp", + "rtc-shared", + "sansio", +] + +[[package]] +name = "rtc-mdns" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "log", + "rtc-shared", + "sansio", + "socket2 0.6.5", +] + +[[package]] +name = "rtc-media" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "byteorder", + "bytes", + "rand 0.10.2", + "rtc-rtp", + "rtc-shared", + "thiserror 2.0.20", +] + +[[package]] +name = "rtc-rtcp" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "rtc-shared", +] + +[[package]] +name = "rtc-rtp" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "memchr", + "rand 0.10.2", + "rtc-shared", + "serde", +] + +[[package]] +name = "rtc-sctp" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "crc32c", + "log", + "rand 0.10.2", + "rtc-shared", + "rustc-hash", + "slab", + "thiserror 2.0.20", +] + +[[package]] +name = "rtc-sdp" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "rand 0.10.2", + "rtc-shared", + "url", +] + +[[package]] +name = "rtc-shared" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bitflags 1.3.2", + "bytes", + "nix 0.31.3", + "rand 0.10.2", + "serde", + "substring", + "thiserror 2.0.20", + "url", + "winapi", +] + +[[package]] +name = "rtc-srtp" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "byteorder", + "bytes", + "rtc-crypto", + "rtc-rtcp", + "rtc-rtp", + "rtc-shared", +] + +[[package]] +name = "rtc-stun" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "base64 0.22.1", + "bytes", + "crc", + "lazy_static", + "rand 0.10.2", + "rtc-crypto", + "rtc-shared", + "sansio", + "url", +] + +[[package]] +name = "rtc-turn" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "bytes", + "log", + "rtc-crypto", + "rtc-shared", + "rtc-stun", + "sansio", +] + [[package]] name = "rtnetlink" version = "0.20.0" @@ -2507,7 +3113,7 @@ dependencies = [ "netlink-packet-route", "netlink-proto", "netlink-sys", - "nix", + "nix 0.30.1", "thiserror 1.0.69", "tokio", ] @@ -2542,7 +3148,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -2601,6 +3207,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "sansio" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62751faa8bc286982334a082fe125184a29fc89d17775766e4f891b7d726980" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2643,6 +3255,30 @@ dependencies = [ "syn 3.0.4", ] +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -2669,6 +3305,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.3" @@ -2746,6 +3388,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "substring" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" +dependencies = [ + "autocfg", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2791,7 +3442,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags", + "bitflags 2.13.1", "core-foundation", "system-configuration-sys", ] @@ -2892,6 +3543,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.12.0" @@ -2941,6 +3602,7 @@ checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "futures-util", "libc", @@ -3010,6 +3672,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + [[package]] name = "unicode-ident" version = "1.0.24" @@ -3164,12 +3832,51 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webrtc" +version = "0.21.0-rc.1" +source = "git+https://github.com/webrtc-rs/webrtc?rev=e132552fc67b84c30e63c5ce916a9a63e2484b6f#e132552fc67b84c30e63c5ce916a9a63e2484b6f" +dependencies = [ + "async-broadcast", + "async-channel", + "async-trait", + "bytes", + "event-listener", + "futures", + "log", + "quinn-udp 0.6.1", + "rtc", + "tokio", +] + [[package]] name = "widestring" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.62.2" @@ -3397,18 +4104,53 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs 0.6.2", + "data-encoding", + "der-parser 9.0.0", + "lazy_static", + "nom", + "oid-registry 0.7.1", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + [[package]] name = "x509-parser" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ - "asn1-rs", + "asn1-rs 0.7.2", + "data-encoding", + "der-parser 10.0.0", + "lazy_static", + "nom", + "oid-registry 0.8.1", + "rusticata-macros", + "thiserror 2.0.20", + "time", +] + +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs 0.7.2", "data-encoding", - "der-parser", + "der-parser 10.0.0", "lazy_static", "nom", - "oid-registry", + "oid-registry 0.8.1", + "ring", "rusticata-macros", "thiserror 2.0.20", "time", @@ -3469,6 +4211,16 @@ dependencies = [ "time", ] +[[package]] +name = "yasna" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" +dependencies = [ + "bit-vec", + "time", +] + [[package]] name = "yoke" version = "0.8.3" @@ -3585,3 +4337,9 @@ dependencies = [ "quote", "syn 3.0.4", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/native/runtime-host-peer/Cargo.toml b/native/runtime-host-peer/Cargo.toml index 5a6cec0117..595c03b9a8 100644 --- a/native/runtime-host-peer/Cargo.toml +++ b/native/runtime-host-peer/Cargo.toml @@ -27,6 +27,8 @@ publish = false crate-type = ["cdylib"] [dependencies] +async-trait = "0.1" +bytes = "1" futures = "0.3" libp2p = { version = "0.56", features = [ "dcutr", @@ -43,10 +45,18 @@ libp2p = { version = "0.56", features = [ "tokio", "yamux", ] } +libp2p-webrtc-utils = "0.4" napi = { version = "3.12", features = ["napi8", "tokio_rt"] } napi-derive = "3.5" +prost = "0.14" +serde_json = "1" +thiserror = "2" tokio = { version = "1.53", features = ["fs", "io-util", "rt-multi-thread", "sync", "time"] } -tokio-util = { version = "0.7", features = ["rt"] } +tokio-util = { version = "0.7", features = ["compat", "rt"] } +unsigned-varint = "0.8" +# v0.21.0-rc.1 predates the rtc fixes qualified in apache/maka#4382. +# Keep this immutable until an official release contains those fixes. +webrtc = { git = "https://github.com/webrtc-rs/webrtc", rev = "e132552fc67b84c30e63c5ce916a9a63e2484b6f" } [build-dependencies] napi-build = "2.4" diff --git a/native/runtime-host-peer/src/bindings.rs b/native/runtime-host-peer/src/bindings.rs index 2a9a07ab3e..079c973be0 100644 --- a/native/runtime-host-peer/src/bindings.rs +++ b/native/runtime-host-peer/src/bindings.rs @@ -35,6 +35,8 @@ type IncomingStreamReceiver = mpsc::Receiver, PeerEr const IDENTITY_PAYLOAD_MAX_BYTES: usize = 8 * 1024; const MAX_TRANSIT_PEERS: usize = 64; const MAX_TRANSIT_RELAY_ADDRESSES: usize = 256; +const MAX_WEBRTC_STUN_URLS: usize = 8; +const MAX_WEBRTC_STUN_URL_BYTES: usize = 512; #[napi(object)] pub struct StartPeerEndpointOptions { @@ -43,6 +45,7 @@ pub struct StartPeerEndpointOptions { pub listen_addresses: Option>, pub coordination_relays: Option>, pub automatic_relay_discovery: Option, + pub web_rtc_stun_urls: Option>, } #[napi(object)] @@ -381,6 +384,10 @@ pub fn start_peer_endpoint(options: StartPeerEndpointOptions) -> Result, label: &str) -> Result> { .collect() } +fn parse_webrtc_stun_urls(values: Vec) -> Result> { + if values.len() > MAX_WEBRTC_STUN_URLS { + return Err(Error::new( + Status::InvalidArg, + "WebRTC cannot use more than 8 STUN URLs", + )); + } + for value in &values { + if value.len() > MAX_WEBRTC_STUN_URL_BYTES + || !value.starts_with("stun:") + || value.chars().any(char::is_whitespace) + { + return Err(Error::new( + Status::InvalidArg, + "WebRTC STUN URL must use the stun: scheme and contain no whitespace", + )); + } + } + Ok(values) +} + fn parse_transit_relay_candidates( candidates: Vec, ) -> Result> { @@ -599,4 +627,13 @@ mod tests { vec![coordination.parse().expect("coordination multiaddr")], ); } + + #[test] + fn webrtc_configuration_accepts_explicit_host_only_ice_and_rejects_turn() { + assert_eq!( + parse_webrtc_stun_urls(Vec::new()).expect("host-only ICE"), + Vec::::new() + ); + assert!(parse_webrtc_stun_urls(vec!["turn:relay.example:3478".to_owned()]).is_err()); + } } diff --git a/native/runtime-host-peer/src/engine.rs b/native/runtime-host-peer/src/engine.rs index 6b02f0dc23..ed435b988f 100644 --- a/native/runtime-host-peer/src/engine.rs +++ b/native/runtime-host-peer/src/engine.rs @@ -34,13 +34,20 @@ use libp2p::{ noise, ping, relay, swarm::{ ConnectionId, NetworkBehaviour, SwarmEvent, + behaviour::toggle::Toggle, dial_opts::{DialOpts, PeerCondition}, }, tcp, yamux, }; use tokio::sync::{mpsc, oneshot}; +use tokio::task::JoinSet; use tokio_util::sync::CancellationToken; +use crate::webrtc_direct::{ + SIGNALING_PROTOCOL, UpgradeOptions, UpgradeRole, WebRtcTransport, WebRtcTransportControl, + upgrade_connection, +}; + mod address; mod application_stream; mod identity_store; @@ -59,6 +66,9 @@ const IDENTIFY_PROTOCOL: &str = "/maka/runtime-host/peer-identify/1"; const COMMAND_CAPACITY: usize = 32; const INCOMING_STREAM_CAPACITY: usize = 16; const MESH_INCOMING_STREAM_CAPACITY: usize = 32; +const WEBRTC_SIGNALING_STREAM_CAPACITY: usize = 8; +const MAX_CONCURRENT_WEBRTC_UPGRADES: usize = 4; +const WEBRTC_UPGRADE_DEADLINE: Duration = Duration::from_secs(15); const MAX_PENDING_INCOMING_CONNECTIONS: u32 = 32; const MAX_PENDING_OUTGOING_CONNECTIONS: u32 = 1024; const MAX_ESTABLISHED_INCOMING_CONNECTIONS: u32 = 32; @@ -86,6 +96,7 @@ pub struct StartOptions { pub listen_addresses: Vec, pub coordination_relays: Vec, pub automatic_relay_discovery: bool, + pub web_rtc_stun_urls: Option>, } pub struct StartedEndpoint { @@ -197,6 +208,7 @@ struct Behaviour { ping: ping::Behaviour, application_stream: application_stream::Behaviour, mesh_control: application_stream::Behaviour, + webrtc_signaling: Toggle, } struct PendingConnect { @@ -559,14 +571,23 @@ async fn run_endpoint_async( None => load_or_create_key(&options.key_path).await?, }; let local_peer_id = PeerId::from(key.public()); + let webrtc_stun_urls = options.web_rtc_stun_urls.clone(); let allowed_transit_peers = Arc::new(RwLock::new(HashSet::new())); let trusted_transit_relays = Arc::new(RwLock::new(HashSet::new())); - let (mut swarm, stream_control, mut incoming_streams, mesh_control, mut mesh_incoming) = - build_swarm( - key, - Arc::clone(&allowed_transit_peers), - Arc::clone(&trusted_transit_relays), - )?; + let BuiltSwarm { + mut swarm, + stream_control, + mut incoming_streams, + mesh_control, + mut mesh_incoming, + mut webrtc_signaling_incoming, + webrtc_transport, + } = build_swarm( + key, + Arc::clone(&allowed_transit_peers), + Arc::clone(&trusted_transit_relays), + webrtc_stun_urls.is_some(), + )?; let mut transit = TransitRuntime { allowed_peers: allowed_transit_peers, approved_relays: HashSet::new(), @@ -649,6 +670,11 @@ async fn run_endpoint_async( let mut bound_addresses = bound_addresses.into_iter().collect::>(); bound_addresses.sort_unstable_by_key(ToString::to_string); transit.listen_addresses.clone_from(&bound_addresses); + if webrtc_stun_urls.is_some() { + swarm + .listen_on("/webrtc".parse().expect("constant multiaddr")) + .map_err(|error| PeerError::new("peer_native_failed", error.to_string()))?; + } let _ = ready_tx.send(Ok((local_peer_id, bound_addresses))); let (opened_tx, mut opened_rx) = mpsc::channel::(COMMAND_CAPACITY); @@ -661,6 +687,8 @@ async fn run_endpoint_async( let mut discovered_relays = options .automatic_relay_discovery .then(relay_discovery::spawn); + let webrtc_cancellation = CancellationToken::new(); + let mut incoming_webrtc_upgrades = JoinSet::new(); loop { tokio::select! { @@ -793,10 +821,16 @@ async fn run_endpoint_async( let _ = result.send(()); } Some(EngineCommand::Stop { result }) => { + webrtc_cancellation.cancel(); + incoming_webrtc_upgrades.abort_all(); let _ = result.send(()); return Ok(()); } - None => return Ok(()), + None => { + webrtc_cancellation.cancel(); + incoming_webrtc_upgrades.abort_all(); + return Ok(()); + } }, Some(stream) = incoming_streams.recv() => { *direct.active.entry(stream.connection_id).or_default() += 1; @@ -831,6 +865,50 @@ async fn run_endpoint_async( // Dropping the stream applies bounded backpressure to Mesh control callers. } } + Some(stream) = webrtc_signaling_incoming.recv() => { + if incoming_webrtc_upgrades.len() >= MAX_CONCURRENT_WEBRTC_UPGRADES { + webrtc_debug(format_args!( + "rejected inbound upgrade from {}: concurrency limit reached", + stream.peer_id, + )); + continue; + } + let cancellation = webrtc_cancellation.child_token(); + let stun_urls = webrtc_stun_urls.clone().unwrap_or_default(); + incoming_webrtc_upgrades.spawn(async move { + upgrade_connection( + stream.stream, + stream.peer_id, + stream.peer_id, + UpgradeRole::Answerer, + UpgradeOptions { + stun_urls, + udp_bind_addresses: vec!["0.0.0.0:0".to_owned()], + deadline: WEBRTC_UPGRADE_DEADLINE, + cancellation, + }, + ) + .await + }); + } + Some(upgrade) = incoming_webrtc_upgrades.join_next(), if !incoming_webrtc_upgrades.is_empty() => { + match upgrade { + Ok(Ok((peer, connection))) => { + if let Err(error) = webrtc_transport.inject_inbound(peer, connection) { + webrtc_debug(format_args!( + "discarded completed inbound upgrade from {peer}: {error}", + )); + } + } + Ok(Err(error)) => { + webrtc_debug(format_args!("inbound upgrade failed: {error}")); + } + Err(error) if error.is_cancelled() => {} + Err(error) => { + webrtc_debug(format_args!("inbound upgrade task failed: {error}")); + } + } + } Some(candidate) = async { match &mut discovered_relays { Some(receiver) => receiver.recv().await, @@ -1123,18 +1201,21 @@ fn pending_connect_deadline_error(waiter: &PendingConnect) -> PeerError { PeerError::new(code, message) } -type BuiltSwarm = ( - Swarm, - application_stream::Control, - mpsc::Receiver, - application_stream::Control, - mpsc::Receiver, -); +struct BuiltSwarm { + swarm: Swarm, + stream_control: application_stream::Control, + incoming_streams: mpsc::Receiver, + mesh_control: application_stream::Control, + mesh_incoming: mpsc::Receiver, + webrtc_signaling_incoming: mpsc::Receiver, + webrtc_transport: WebRtcTransportControl, +} fn build_swarm( key: identity::Keypair, allowed_transit_peers: Arc>>, trusted_transit_relays: Arc>>, + webrtc_enabled: bool, ) -> Result { let (application_stream, control, incoming) = application_stream::Behaviour::new( StreamProtocol::new(APPLICATION_PROTOCOL), @@ -1146,6 +1227,13 @@ fn build_swarm( MESH_INCOMING_STREAM_CAPACITY, None, ); + let (webrtc_signaling, _webrtc_signaling_control, webrtc_signaling_incoming) = + application_stream::Behaviour::new( + StreamProtocol::new(SIGNALING_PROTOCOL), + WEBRTC_SIGNALING_STREAM_CAPACITY, + None, + ); + let (webrtc, webrtc_transport) = WebRtcTransport::new(); let swarm = SwarmBuilder::with_existing_identity(key) .with_tokio() .with_tcp( @@ -1155,6 +1243,8 @@ fn build_swarm( ) .map_err(native_error)? .with_quic() + .with_other_transport(move |_| webrtc) + .map_err(native_error)? .with_dns() .map_err(native_error)? .with_relay_client(noise::Config::new, yamux::Config::default) @@ -1182,6 +1272,7 @@ fn build_swarm( ping: ping::Behaviour::new(ping::Config::new()), application_stream, mesh_control: mesh_stream, + webrtc_signaling: Toggle::from(webrtc_enabled.then_some(webrtc_signaling)), }) .map_err(native_error) .map(|builder| { @@ -1190,7 +1281,15 @@ fn build_swarm( }) }) .map(|builder| builder.build())?; - Ok((swarm, control, incoming, mesh_control, mesh_incoming)) + Ok(BuiltSwarm { + swarm, + stream_control: control, + incoming_streams: incoming, + mesh_control, + mesh_incoming, + webrtc_signaling_incoming, + webrtc_transport, + }) } fn transit_relay_config(allowed_peers: Arc>>) -> relay::Config { @@ -2536,6 +2635,12 @@ fn discovery_debug(message: std::fmt::Arguments<'_>) { } } +fn webrtc_debug(message: std::fmt::Arguments<'_>) { + if std::env::var_os("MAKA_WEBRTC_DIAGNOSTICS").is_some() { + eprintln!("[peer-webrtc] {message}"); + } +} + fn retry_connect_routes( swarm: &mut Swarm, direct: &mut DirectConnectState, @@ -3202,6 +3307,7 @@ mod tests { ], coordination_relays: Vec::new(), automatic_relay_discovery: false, + web_rtc_stun_urls: None, } } diff --git a/native/runtime-host-peer/src/lib.rs b/native/runtime-host-peer/src/lib.rs index c243f01b48..e6ea9d0f13 100644 --- a/native/runtime-host-peer/src/lib.rs +++ b/native/runtime-host-peer/src/lib.rs @@ -19,6 +19,7 @@ mod bindings; mod engine; +mod webrtc_direct; pub use bindings::{ ConfigurePeerTransitOptions, ConnectPeerOptions, PeerEndpoint, PeerIdentitySignature, diff --git a/native/runtime-host-peer/src/webrtc_direct/mod.rs b/native/runtime-host-peer/src/webrtc_direct/mod.rs new file mode 100644 index 0000000000..df23ac8ba9 --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/mod.rs @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +mod muxer; +mod signaling; +mod transport; +mod upgrade; + +pub(crate) use muxer::WebRtcConnection; +pub(crate) use signaling::{Signal, SignalingError, read_signal, write_signal}; +pub(crate) use transport::{WebRtcTransport, WebRtcTransportControl}; +pub(crate) use upgrade::{UpgradeOptions, UpgradeRole, upgrade_connection}; + +pub(crate) const SIGNALING_PROTOCOL: &str = "/webrtc-signaling/0.0.1"; + +#[cfg(test)] +mod tests; diff --git a/native/runtime-host-peer/src/webrtc_direct/muxer.rs b/native/runtime-host-peer/src/webrtc_direct/muxer.rs new file mode 100644 index 0000000000..c3e9ce18d1 --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/muxer.rs @@ -0,0 +1,484 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use std::{ + io, + pin::Pin, + sync::{Arc, Mutex}, + task::{Context, Poll, Waker}, + time::Duration, +}; + +use bytes::BytesMut; +use futures::{ + AsyncRead, AsyncWrite, FutureExt, Sink, Stream, StreamExt as _, + channel::{mpsc, oneshot}, + future::BoxFuture, + ready, + stream::FuturesUnordered, +}; +use libp2p::core::muxing::{StreamMuxer, StreamMuxerEvent}; +use libp2p_webrtc_utils::{DropListener, Stream as Libp2pWebRtcStream}; +use webrtc::{ + data_channel::{DataChannel, DataChannelEvent, RTCDataChannelState}, + peer_connection::{PeerConnection, RTCPeerConnectionState}, +}; + +const DATA_CHANNEL_QUEUE_CAPACITY: usize = 16; +const MAX_DATA_CHANNEL_MESSAGE_BYTES: usize = 16 * 1024; + +pub(crate) type ReadySubstream = (WebRtcSubstream, DropListener); + +pub struct WebRtcConnection { + peer_connection: Arc, + incoming: mpsc::Receiver>, + states: mpsc::Receiver, + outbound: Option>>, + closing: Option>>, + drop_listeners: FuturesUnordered>, + no_drop_listener_waker: Option, +} + +impl WebRtcConnection { + pub(crate) fn new( + peer_connection: Arc, + incoming: mpsc::Receiver>, + states: mpsc::Receiver, + ) -> Self { + Self { + peer_connection, + incoming, + states, + outbound: None, + closing: None, + drop_listeners: FuturesUnordered::new(), + no_drop_listener_waker: None, + } + } + + fn track_substream(&mut self, (stream, listener): ReadySubstream) -> WebRtcSubstream { + self.drop_listeners.push(listener); + if let Some(waker) = self.no_drop_listener_waker.take() { + waker.wake(); + } + stream + } +} + +impl StreamMuxer for WebRtcConnection { + type Substream = WebRtcSubstream; + type Error = io::Error; + + fn poll_inbound( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + match ready!(self.incoming.poll_next_unpin(cx)) { + Some(Ok(stream)) => Poll::Ready(Ok(self.track_substream(stream))), + Some(Err(error)) => Poll::Ready(Err(error)), + None => Poll::Ready(Err(io::Error::new( + io::ErrorKind::ConnectionReset, + "WebRTC inbound stream channel closed", + ))), + } + } + + fn poll_outbound( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let peer_connection = Arc::clone(&self.peer_connection); + let future = self.outbound.get_or_insert_with(|| { + async move { + let channel = peer_connection + .create_data_channel("", None) + .await + .map_err(webrtc_io_error)?; + data_channel_diagnostic("created", channel.id(), Some("outbound")); + ready_substream(channel, "outbound").await + } + .boxed() + }); + match ready!(future.poll_unpin(cx)) { + Ok(stream) => { + self.outbound = None; + Poll::Ready(Ok(self.track_substream(stream))) + } + Err(error) => { + self.outbound = None; + Poll::Ready(Err(error)) + } + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let peer_connection = Arc::clone(&self.peer_connection); + let future = self.closing.get_or_insert_with(|| { + async move { peer_connection.close().await.map_err(webrtc_io_error) }.boxed() + }); + future.poll_unpin(cx) + } + + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + loop { + match self.states.poll_next_unpin(cx) { + Poll::Ready(Some(RTCPeerConnectionState::Failed)) + | Poll::Ready(Some(RTCPeerConnectionState::Closed)) => { + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::ConnectionReset, + "WebRTC peer connection closed", + ))); + } + Poll::Ready(Some(_)) => continue, + Poll::Ready(None) | Poll::Pending => break, + } + } + + loop { + match self.drop_listeners.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(()))) => continue, + Poll::Ready(Some(Err(error))) => { + muxer_diagnostic("substream-reset-failed", Some(&error.to_string())); + continue; + } + Poll::Ready(None) => { + self.no_drop_listener_waker = Some(cx.waker().clone()); + return Poll::Pending; + } + Poll::Pending => return Poll::Pending, + } + } + } +} + +pub struct WebRtcSubstream { + inner: Libp2pWebRtcStream, +} + +impl AsyncRead for WebRtcSubstream { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buffer: &mut [u8], + ) -> Poll> { + Pin::new(&mut self.inner).poll_read(cx, buffer) + } +} + +impl AsyncWrite for WebRtcSubstream { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buffer: &[u8], + ) -> Poll> { + Pin::new(&mut self.inner).poll_write(cx, buffer) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner).poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.inner).poll_close(cx) + } +} + +pub(crate) async fn ready_substream( + data_channel: Arc, + origin: &'static str, +) -> Result { + let (outgoing, outgoing_receiver) = mpsc::channel(DATA_CHANNEL_QUEUE_CAPACITY); + let (incoming_sender, incoming) = mpsc::channel(DATA_CHANNEL_QUEUE_CAPACITY); + let io = MessageIo::new(outgoing, incoming); + let (ready_sender, ready_receiver) = oneshot::channel(); + tokio::spawn(drive_data_channel( + data_channel, + outgoing_receiver, + incoming_sender, + ready_sender, + origin, + )); + ready_receiver + .await + .map_err(|_| io::Error::new(io::ErrorKind::ConnectionAborted, "data channel stopped"))??; + let (stream, listener) = Libp2pWebRtcStream::new(io); + Ok((WebRtcSubstream { inner: stream }, listener)) +} + +pub(crate) fn keep_init_channel( + data_channel: Arc, + mut opened: mpsc::Sender>, +) { + tokio::spawn(async move { + data_channel_diagnostic("waiting", data_channel.id(), Some("init")); + let result = wait_for_data_channel_open(&data_channel).await; + let is_open = result.is_ok(); + data_channel_diagnostic( + if is_open { "opened" } else { "open-failed" }, + data_channel.id(), + Some("init"), + ); + let _ = opened.try_send(result); + if is_open { + // Keep the initial channel allocated for the connection lifetime. Closing it lets + // current native WebRTC stacks reuse its SCTP stream id before both peers have + // retired it, causing the first real libp2p substream to fail immediately. + while data_channel.poll().await.is_some() {} + } + }); +} + +async fn drive_data_channel( + data_channel: Arc, + mut outgoing: mpsc::Receiver, + mut incoming: mpsc::Sender>, + ready: oneshot::Sender>, + origin: &'static str, +) { + let mut ready = Some(ready); + data_channel_diagnostic("waiting", data_channel.id(), Some(origin)); + if let Err(error) = wait_for_data_channel_open(&data_channel).await { + data_channel_diagnostic("open-failed", data_channel.id(), Some(origin)); + signal_channel_failure(&mut ready, &mut incoming, error); + return; + } + data_channel_diagnostic("opened", data_channel.id(), Some(origin)); + if let Some(ready) = ready.take() { + let _ = ready.send(Ok(())); + } + + loop { + tokio::select! { + event = data_channel.poll() => { + match event { + Some(DataChannelEvent::OnMessage(message)) => { + data_channel_diagnostic( + "received", + data_channel.id(), + Some(&message.data.len().to_string()), + ); + if incoming.try_send(Ok(message.data)).is_err() { + let _ = data_channel.close().await; + return; + } + } + Some(DataChannelEvent::OnClose) => { + data_channel_diagnostic("closed", data_channel.id(), Some(origin)); + return; + } + Some(DataChannelEvent::OnError) => { + data_channel_diagnostic("error", data_channel.id(), Some(origin)); + return; + } + None => { + data_channel_diagnostic("stopped", data_channel.id(), Some(origin)); + return; + } + _ => {} + } + } + message = outgoing.next() => { + let Some(message) = message else { + drain_data_channel(&data_channel).await; + let _ = data_channel.close().await; + return; + }; + let message_bytes = message.len().to_string(); + if message.len() > MAX_DATA_CHANNEL_MESSAGE_BYTES + || data_channel.send(message).await.is_err() + { + let _ = data_channel.close().await; + return; + } + data_channel_diagnostic("sent", data_channel.id(), Some(&message_bytes)); + } + } + } +} + +async fn drain_data_channel(data_channel: &Arc) { + let _ = tokio::time::timeout(Duration::from_secs(5), async { + loop { + match data_channel.outstanding_bytes().await { + Ok(0) | Err(_) => return, + Ok(_) => tokio::time::sleep(Duration::from_millis(1)).await, + } + } + }) + .await; +} + +async fn wait_for_data_channel_open(data_channel: &Arc) -> Result<(), io::Error> { + match data_channel.ready_state().await.map_err(webrtc_io_error)? { + RTCDataChannelState::Open => return Ok(()), + RTCDataChannelState::Closing | RTCDataChannelState::Closed => { + return Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "data channel closed before opening", + )); + } + RTCDataChannelState::Unspecified | RTCDataChannelState::Connecting => {} + _ => {} + } + + while let Some(event) = data_channel.poll().await { + match event { + DataChannelEvent::OnOpen => return Ok(()), + DataChannelEvent::OnClose | DataChannelEvent::OnError => { + return Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "data channel failed to open", + )); + } + _ => {} + } + } + Err(io::Error::new( + io::ErrorKind::ConnectionAborted, + "data channel stopped before opening", + )) +} + +fn signal_channel_failure( + ready: &mut Option>>, + incoming: &mut mpsc::Sender>, + error: io::Error, +) { + if let Some(ready) = ready.take() { + let _ = ready.send(Err(error)); + } else { + let _ = incoming.try_send(Err(error)); + } +} + +#[derive(Clone)] +pub(crate) struct MessageIo { + inner: Arc>, +} + +struct MessageIoInner { + outgoing: mpsc::Sender, + incoming: mpsc::Receiver>, + read_buffer: BytesMut, +} + +impl MessageIo { + fn new( + outgoing: mpsc::Sender, + incoming: mpsc::Receiver>, + ) -> Self { + Self { + inner: Arc::new(Mutex::new(MessageIoInner { + outgoing, + incoming, + read_buffer: BytesMut::new(), + })), + } + } +} + +impl AsyncRead for MessageIo { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buffer: &mut [u8], + ) -> Poll> { + let mut inner = self.inner.lock().expect("message I/O mutex poisoned"); + if inner.read_buffer.is_empty() { + match ready!(Pin::new(&mut inner.incoming).poll_next(cx)) { + Some(Ok(message)) => inner.read_buffer = message, + Some(Err(error)) => return Poll::Ready(Err(error)), + None => return Poll::Ready(Ok(0)), + } + } + let length = buffer.len().min(inner.read_buffer.len()); + buffer[..length].copy_from_slice(&inner.read_buffer.split_to(length)); + Poll::Ready(Ok(length)) + } +} + +impl AsyncWrite for MessageIo { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buffer: &[u8], + ) -> Poll> { + if buffer.len() > MAX_DATA_CHANNEL_MESSAGE_BYTES { + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "data channel message exceeds the 16 KiB libp2p limit", + ))); + } + let mut inner = self.inner.lock().expect("message I/O mutex poisoned"); + ready!(Pin::new(&mut inner.outgoing).poll_ready(cx)) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "data channel closed"))?; + Pin::new(&mut inner.outgoing) + .start_send(BytesMut::from(buffer)) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "data channel closed"))?; + Poll::Ready(Ok(buffer.len())) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut inner = self.inner.lock().expect("message I/O mutex poisoned"); + Pin::new(&mut inner.outgoing) + .poll_flush(cx) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "data channel closed")) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut inner = self.inner.lock().expect("message I/O mutex poisoned"); + Pin::new(&mut inner.outgoing) + .poll_close(cx) + .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "data channel closed")) + } +} + +fn webrtc_io_error(error: impl std::fmt::Display) -> io::Error { + io::Error::other(error.to_string()) +} + +pub(crate) fn data_channel_diagnostic(event: &str, channel: usize, detail: Option<&str>) { + if std::env::var_os("MAKA_WEBRTC_DIAGNOSTICS").is_none() { + return; + } + eprintln!( + "{}", + serde_json::json!({ + "dataChannel": event, + "channel": channel, + "detail": detail, + }) + ); +} + +fn muxer_diagnostic(event: &str, detail: Option<&str>) { + if std::env::var_os("MAKA_WEBRTC_DIAGNOSTICS").is_none() { + return; + } + eprintln!( + "{}", + serde_json::json!({ + "webRtcMuxer": event, + "detail": detail, + }) + ); +} diff --git a/native/runtime-host-peer/src/webrtc_direct/signaling.rs b/native/runtime-host-peer/src/webrtc_direct/signaling.rs new file mode 100644 index 0000000000..24fada3a89 --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/signaling.rs @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use std::io; + +use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use prost::Message as _; + +const MAX_SIGNAL_FRAME_BYTES: usize = 64 * 1024; +const MAX_SDP_BYTES: usize = 48 * 1024; +const MAX_CANDIDATE_BYTES: usize = 4 * 1024; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Signal { + Offer(String), + Answer(String), + IceCandidate(String), +} + +impl Signal { + fn into_wire(self) -> Result { + let (kind, data, limit) = match self { + Self::Offer(data) => (WireType::SdpOffer, data, MAX_SDP_BYTES), + Self::Answer(data) => (WireType::SdpAnswer, data, MAX_SDP_BYTES), + Self::IceCandidate(data) => (WireType::IceCandidate, data, MAX_CANDIDATE_BYTES), + }; + if data.len() > limit { + return Err(SignalingError::PayloadTooLarge { + actual: data.len(), + limit, + }); + } + Ok(WireMessage { + kind: Some(kind as i32), + data: Some(data), + }) + } + + fn from_wire(message: WireMessage) -> Result { + let kind = message + .kind + .and_then(|kind| WireType::try_from(kind).ok()) + .ok_or(SignalingError::MissingOrInvalidType)?; + let data = message.data.ok_or(SignalingError::MissingData)?; + match kind { + WireType::SdpOffer if data.len() <= MAX_SDP_BYTES => Ok(Self::Offer(data)), + WireType::SdpAnswer if data.len() <= MAX_SDP_BYTES => Ok(Self::Answer(data)), + WireType::IceCandidate if data.len() <= MAX_CANDIDATE_BYTES => { + Ok(Self::IceCandidate(data)) + } + WireType::SdpOffer | WireType::SdpAnswer => Err(SignalingError::PayloadTooLarge { + actual: data.len(), + limit: MAX_SDP_BYTES, + }), + WireType::IceCandidate => Err(SignalingError::PayloadTooLarge { + actual: data.len(), + limit: MAX_CANDIDATE_BYTES, + }), + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum SignalingError { + #[error("signaling I/O failed: {0}")] + Io(#[from] io::Error), + #[error("signaling protobuf was invalid: {0}")] + Protobuf(#[from] prost::DecodeError), + #[error("signaling frame length was invalid")] + InvalidFrameLength, + #[error("signaling frame is {actual} bytes; limit is {limit}")] + FrameTooLarge { actual: usize, limit: usize }, + #[error("signaling payload is {actual} bytes; limit is {limit}")] + PayloadTooLarge { actual: usize, limit: usize }, + #[error("signaling message has no valid type")] + MissingOrInvalidType, + #[error("signaling message has no data")] + MissingData, +} + +pub async fn write_signal(writer: &mut W, signal: Signal) -> Result<(), SignalingError> +where + W: AsyncWrite + Unpin, +{ + let message = signal.into_wire()?; + let mut payload = Vec::with_capacity(message.encoded_len()); + message + .encode(&mut payload) + .expect("encoding protobuf into Vec cannot fail"); + if payload.len() > MAX_SIGNAL_FRAME_BYTES { + return Err(SignalingError::FrameTooLarge { + actual: payload.len(), + limit: MAX_SIGNAL_FRAME_BYTES, + }); + } + frame_diagnostic("write", &payload); + + let mut prefix = unsigned_varint::encode::usize_buffer(); + let prefix = unsigned_varint::encode::usize(payload.len(), &mut prefix); + let mut frame = Vec::with_capacity(prefix.len() + payload.len()); + frame.extend_from_slice(prefix); + frame.extend_from_slice(&payload); + writer.write_all(&frame).await?; + writer.flush().await?; + Ok(()) +} + +pub async fn read_signal(reader: &mut R) -> Result, SignalingError> +where + R: AsyncRead + Unpin, +{ + let Some(length) = read_frame_length(reader).await? else { + return Ok(None); + }; + if length > MAX_SIGNAL_FRAME_BYTES { + return Err(SignalingError::FrameTooLarge { + actual: length, + limit: MAX_SIGNAL_FRAME_BYTES, + }); + } + + let mut payload = vec![0; length]; + reader.read_exact(&mut payload).await?; + frame_diagnostic("read", &payload); + Signal::from_wire(WireMessage::decode(payload.as_slice())?).map(Some) +} + +fn frame_diagnostic(direction: &str, payload: &[u8]) { + if std::env::var_os("MAKA_WEBRTC_DIAGNOSTICS").is_none() { + return; + } + eprintln!( + "{}", + serde_json::json!({ + "signaling": direction, + "bytes": payload.len(), + "firstTag": payload.first(), + }) + ); +} + +async fn read_frame_length(reader: &mut R) -> Result, SignalingError> +where + R: AsyncRead + Unpin, +{ + let mut prefix = unsigned_varint::encode::usize_buffer(); + for index in 0..prefix.len() { + match reader.read_exact(&mut prefix[index..=index]).await { + Ok(_) => {} + Err(error) if error.kind() == io::ErrorKind::UnexpectedEof && index == 0 => { + return Ok(None); + } + Err(error) => return Err(error.into()), + } + if unsigned_varint::decode::is_last(prefix[index]) { + let (length, remainder) = unsigned_varint::decode::usize(&prefix[..=index]) + .map_err(|_| SignalingError::InvalidFrameLength)?; + if !remainder.is_empty() { + return Err(SignalingError::InvalidFrameLength); + } + return Ok(Some(length)); + } + } + Err(SignalingError::InvalidFrameLength) +} + +#[derive(Clone, PartialEq, prost::Message)] +struct WireMessage { + #[prost(enumeration = "WireType", optional, tag = "1")] + kind: Option, + #[prost(string, optional, tag = "2")] + data: Option, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, prost::Enumeration)] +enum WireType { + SdpOffer = 0, + SdpAnswer = 1, + IceCandidate = 2, +} + +#[cfg(test)] +mod tests { + use futures::io::Cursor; + + use super::*; + + #[tokio::test] + async fn standard_signal_round_trip_and_bounds() { + let mut bytes = Cursor::new(Vec::new()); + write_signal(&mut bytes, Signal::Offer("v=0".to_owned())) + .await + .unwrap(); + bytes.set_position(0); + assert_eq!( + read_signal(&mut bytes).await.unwrap(), + Some(Signal::Offer("v=0".to_owned())) + ); + assert_eq!(read_signal(&mut bytes).await.unwrap(), None); + + let error = write_signal( + &mut Cursor::new(Vec::new()), + Signal::IceCandidate("x".repeat(MAX_CANDIDATE_BYTES + 1)), + ) + .await + .unwrap_err(); + assert!(matches!(error, SignalingError::PayloadTooLarge { .. })); + } +} diff --git a/native/runtime-host-peer/src/webrtc_direct/tests.rs b/native/runtime-host-peer/src/webrtc_direct/tests.rs new file mode 100644 index 0000000000..b95631b2bc --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/tests.rs @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use std::{pin::Pin, time::Duration}; + +use futures::{AsyncReadExt as _, AsyncWriteExt as _, future::poll_fn}; +use libp2p::{PeerId, core::muxing::StreamMuxer}; +use tokio_util::compat::TokioAsyncReadCompatExt as _; + +use super::{UpgradeOptions, UpgradeRole, upgrade_connection}; + +#[tokio::test] +async fn authenticated_signaling_yields_a_libp2p_stream() { + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); + let (signaling_a, signaling_b) = tokio::io::duplex(256 * 1024); + let options = UpgradeOptions { + deadline: Duration::from_secs(10), + ..UpgradeOptions::default() + }; + + let (offer, answer) = tokio::join!( + upgrade_connection( + signaling_a.compat(), + peer_b, + peer_b, + UpgradeRole::Offerer, + options.clone(), + ), + upgrade_connection( + signaling_b.compat(), + peer_a, + peer_a, + UpgradeRole::Answerer, + options, + ) + ); + let (_, mut connection_a) = offer.expect("offerer upgrade"); + let (_, mut connection_b) = answer.expect("answerer upgrade"); + + let (outbound, inbound) = tokio::join!( + poll_fn(|cx| Pin::new(&mut connection_a).poll_outbound(cx)), + poll_fn(|cx| Pin::new(&mut connection_b).poll_inbound(cx)), + ); + let mut outbound = outbound.expect("outbound WebRTC stream"); + let mut inbound = inbound.expect("inbound WebRTC stream"); + let payload = b"maka-runtime-host-webrtc"; + + outbound.write_all(payload).await.expect("write payload"); + outbound.flush().await.expect("flush payload"); + let mut received = vec![0; payload.len()]; + inbound + .read_exact(&mut received) + .await + .expect("read payload"); + assert_eq!(received, payload); +} diff --git a/native/runtime-host-peer/src/webrtc_direct/transport.rs b/native/runtime-host-peer/src/webrtc_direct/transport.rs new file mode 100644 index 0000000000..cb9d928ca4 --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/transport.rs @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use std::{ + collections::{HashMap, VecDeque}, + io, + pin::Pin, + task::{Context, Poll}, +}; + +use futures::{Stream as _, channel::mpsc, future}; +use libp2p::{ + Multiaddr, PeerId, + core::transport::{DialOpts, ListenerId, Transport, TransportError, TransportEvent}, + multiaddr::Protocol, +}; + +use super::muxer::WebRtcConnection; + +const INCOMING_CONNECTION_CAPACITY: usize = 4; + +type TransportOutput = (PeerId, WebRtcConnection); + +pub struct WebRtcTransport { + incoming: mpsc::Receiver, + listeners: HashMap, + pending_events: + VecDeque>, io::Error>>, + pending_incoming: VecDeque, +} + +#[derive(Clone)] +pub struct WebRtcTransportControl { + incoming: mpsc::Sender, +} + +impl WebRtcTransport { + pub fn new() -> (Self, WebRtcTransportControl) { + let (incoming_sender, incoming) = mpsc::channel(INCOMING_CONNECTION_CAPACITY); + ( + Self { + incoming, + listeners: HashMap::new(), + pending_events: VecDeque::new(), + pending_incoming: VecDeque::new(), + }, + WebRtcTransportControl { + incoming: incoming_sender, + }, + ) + } +} + +impl WebRtcTransportControl { + pub fn inject_inbound( + &self, + peer: PeerId, + connection: WebRtcConnection, + ) -> Result<(), io::Error> { + let mut incoming = self.incoming.clone(); + incoming.try_send((peer, connection)).map_err(|error| { + io::Error::new( + if error.is_full() { + io::ErrorKind::WouldBlock + } else { + io::ErrorKind::BrokenPipe + }, + if error.is_full() { + "WebRTC transport input is full" + } else { + "WebRTC transport stopped" + }, + ) + }) + } +} + +impl Transport for WebRtcTransport { + type Output = TransportOutput; + type Error = io::Error; + type ListenerUpgrade = future::Ready>; + type Dial = future::Ready>; + + fn listen_on( + &mut self, + id: ListenerId, + address: Multiaddr, + ) -> Result<(), TransportError> { + if !is_webrtc_listener_address(&address) { + return Err(TransportError::MultiaddrNotSupported(address)); + } + if self.listeners.insert(id, address.clone()).is_some() { + return Err(TransportError::Other(io::Error::new( + io::ErrorKind::AlreadyExists, + "WebRTC listener ID is already registered", + ))); + } + self.pending_events.push_back(TransportEvent::NewAddress { + listener_id: id, + listen_addr: address, + }); + Ok(()) + } + + fn remove_listener(&mut self, id: ListenerId) -> bool { + let Some(address) = self.listeners.remove(&id) else { + return false; + }; + self.pending_events + .push_back(TransportEvent::AddressExpired { + listener_id: id, + listen_addr: address, + }); + true + } + + fn dial( + &mut self, + address: Multiaddr, + _options: DialOpts, + ) -> Result> { + Err(TransportError::MultiaddrNotSupported(address)) + } + + fn poll( + mut self: Pin<&mut Self>, + context: &mut Context<'_>, + ) -> Poll> { + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(event); + } + while let Poll::Ready(Some(incoming)) = Pin::new(&mut self.incoming).poll_next(context) { + self.pending_incoming.push_back(incoming); + } + let Some((listener_id, local_address)) = self + .listeners + .iter() + .next() + .map(|(id, address)| (*id, address.clone())) + else { + return Poll::Pending; + }; + let Some((peer, connection)) = self.pending_incoming.pop_front() else { + return Poll::Pending; + }; + Poll::Ready(TransportEvent::Incoming { + listener_id, + upgrade: future::ready(Ok((peer, connection))), + local_addr: local_address, + send_back_addr: webrtc_peer_address(peer), + }) + } +} + +pub fn webrtc_peer_address(peer: PeerId) -> Multiaddr { + Multiaddr::empty() + .with(Protocol::WebRTC) + .with(Protocol::P2p(peer)) +} + +fn is_webrtc_listener_address(address: &Multiaddr) -> bool { + let mut protocols = address.iter(); + matches!(protocols.next(), Some(Protocol::WebRTC)) && protocols.next().is_none() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn private_webrtc_address_is_closed_and_unambiguous() { + let peer = PeerId::random(); + assert_eq!( + webrtc_peer_address(peer).to_string(), + format!("/webrtc/p2p/{peer}"), + ); + } +} diff --git a/native/runtime-host-peer/src/webrtc_direct/upgrade.rs b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs new file mode 100644 index 0000000000..8b9231b1dc --- /dev/null +++ b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs @@ -0,0 +1,449 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use std::{io, sync::Arc, time::Duration}; + +use futures::{ + AsyncRead, AsyncReadExt as _, AsyncWrite, AsyncWriteExt as _, SinkExt as _, StreamExt as _, + channel::mpsc, +}; +use libp2p::PeerId; +use tokio_util::sync::CancellationToken; +use webrtc::{ + data_channel::DataChannel, + peer_connection::{ + PeerConnection, PeerConnectionBuilder, PeerConnectionEventHandler, RTCConfigurationBuilder, + RTCIceCandidateInit, RTCIceServer, RTCPeerConnectionIceEvent, RTCPeerConnectionState, + RTCSessionDescription, + }, +}; + +use super::{ + Signal, SignalingError, WebRtcConnection, + muxer::{ReadySubstream, data_channel_diagnostic, keep_init_channel, ready_substream}, + read_signal, write_signal, +}; + +const EVENT_CAPACITY: usize = 64; +const MAX_CANDIDATES: usize = 64; +const DATA_CHANNEL_SEND_BUFFER_BYTES: usize = 1024 * 1024; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum UpgradeRole { + Offerer, + Answerer, +} + +#[derive(Clone, Debug)] +pub struct UpgradeOptions { + pub stun_urls: Vec, + pub udp_bind_addresses: Vec, + pub deadline: Duration, + pub cancellation: CancellationToken, +} + +impl Default for UpgradeOptions { + fn default() -> Self { + Self { + stun_urls: Vec::new(), + udp_bind_addresses: vec!["127.0.0.1:0".to_owned()], + deadline: Duration::from_secs(10), + cancellation: CancellationToken::new(), + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum UpgradeError { + #[error("authenticated signaling peer {authenticated} did not match expected peer {expected}")] + IdentityMismatch { + authenticated: String, + expected: String, + }, + #[error("WebRTC signaling failed: {0}")] + Signaling(#[from] SignalingError), + #[error("WebRTC operation failed: {0}")] + WebRtc(String), + #[error("WebRTC signaling stream ended before the direct connection was ready")] + SignalingEnded, + #[error("WebRTC signaling message arrived in the wrong phase")] + UnexpectedSignal, + #[error("WebRTC signaling exceeded the candidate limit")] + TooManyCandidates, + #[error("WebRTC event delivery failed: {0}")] + EventDelivery(&'static str), + #[error("WebRTC direct upgrade reached its deadline")] + Deadline, + #[error("WebRTC direct upgrade was cancelled")] + Cancelled, +} + +pub async fn upgrade_connection( + signaling: S, + authenticated_peer: PeerId, + expected_peer: PeerId, + role: UpgradeRole, + options: UpgradeOptions, +) -> Result<(PeerId, WebRtcConnection), UpgradeError> +where + S: AsyncRead + AsyncWrite + Unpin, +{ + if authenticated_peer != expected_peer { + return Err(UpgradeError::IdentityMismatch { + authenticated: authenticated_peer.to_string(), + expected: expected_peer.to_string(), + }); + } + + let channels = EventChannels::new(); + let peer_connection = build_peer_connection(&options, channels.handler()).await?; + let negotiation = negotiate(signaling, role, Arc::clone(&peer_connection), channels); + tokio::pin!(negotiation); + let deadline = tokio::time::sleep(options.deadline); + tokio::pin!(deadline); + + let result = tokio::select! { + biased; + _ = options.cancellation.cancelled() => Err(UpgradeError::Cancelled), + result = &mut negotiation => result, + _ = &mut deadline => Err(UpgradeError::Deadline), + }; + + match result { + Ok(connection) => Ok((authenticated_peer, connection)), + Err(error) => { + let _ = peer_connection.close().await; + Err(error) + } + } +} + +async fn build_peer_connection( + options: &UpgradeOptions, + handler: Arc, +) -> Result, UpgradeError> { + let configuration = RTCConfigurationBuilder::new() + .with_ice_servers(if options.stun_urls.is_empty() { + Vec::new() + } else { + vec![RTCIceServer { + urls: options.stun_urls.clone(), + ..Default::default() + }] + }) + .build(); + let connection = PeerConnectionBuilder::new() + .with_configuration(configuration) + .with_handler(handler) + .with_udp_addrs(options.udp_bind_addresses.clone()) + .with_data_channel_send_buffer_limit(DATA_CHANNEL_SEND_BUFFER_BYTES) + .build() + .await + .map_err(webrtc_upgrade_error)?; + Ok(Arc::new(connection)) +} + +async fn negotiate( + signaling: S, + role: UpgradeRole, + peer_connection: Arc, + channels: EventChannels, +) -> Result +where + S: AsyncRead + AsyncWrite + Unpin, +{ + let (mut reader, mut writer) = signaling.split(); + let EventChannels { + mut candidates, + mut states, + incoming, + init_sender, + mut init_opened, + mut failures, + .. + } = channels; + let mut remote_description_set = false; + let mut pending_candidates = Vec::new(); + let mut local_candidate_count = 0; + let mut remote_candidate_count = 0; + let mut local_signaling_open = true; + let mut remote_signaling_open = true; + let mut peer_connection_connected = false; + let mut init_channel_opened = false; + + match role { + UpgradeRole::Offerer => { + let init = peer_connection + .create_data_channel("init", None) + .await + .map_err(webrtc_upgrade_error)?; + keep_init_channel(init, init_sender); + let offer = peer_connection + .create_offer(None) + .await + .map_err(webrtc_upgrade_error)?; + peer_connection + .set_local_description(offer.clone()) + .await + .map_err(webrtc_upgrade_error)?; + write_signal(&mut writer, Signal::Offer(offer.sdp)).await?; + diagnostic(role, "offer-sent", None); + } + UpgradeRole::Answerer => { + let offer = match read_signal(&mut reader).await? { + Some(Signal::Offer(sdp)) => RTCSessionDescription::offer(sdp), + Some(_) => return Err(UpgradeError::UnexpectedSignal), + None => return Err(UpgradeError::SignalingEnded), + } + .map_err(webrtc_upgrade_error)?; + peer_connection + .set_remote_description(offer) + .await + .map_err(webrtc_upgrade_error)?; + remote_description_set = true; + let answer = peer_connection + .create_answer(None) + .await + .map_err(webrtc_upgrade_error)?; + peer_connection + .set_local_description(answer.clone()) + .await + .map_err(webrtc_upgrade_error)?; + write_signal(&mut writer, Signal::Answer(answer.sdp)).await?; + diagnostic(role, "answer-sent", None); + } + } + + loop { + let direct_connection_ready = peer_connection_connected && init_channel_opened; + if direct_connection_ready && local_signaling_open { + writer.close().await.map_err(SignalingError::Io)?; + local_signaling_open = false; + diagnostic(role, "signaling-write-closed", None); + } + if direct_connection_ready && !remote_signaling_open { + return Ok(WebRtcConnection::new(peer_connection, incoming, states)); + } + tokio::select! { + signal = read_signal(&mut reader), if remote_signaling_open => { + match signal? { + Some(Signal::Answer(sdp)) if role == UpgradeRole::Offerer && !remote_description_set => { + let answer = RTCSessionDescription::answer(sdp).map_err(webrtc_upgrade_error)?; + peer_connection.set_remote_description(answer).await.map_err(webrtc_upgrade_error)?; + remote_description_set = true; + for candidate in pending_candidates.drain(..) { + peer_connection.add_ice_candidate(candidate).await.map_err(webrtc_upgrade_error)?; + } + } + Some(Signal::IceCandidate(candidate)) => { + remote_candidate_count += 1; + if remote_candidate_count > MAX_CANDIDATES { + return Err(UpgradeError::TooManyCandidates); + } + let candidate = serde_json::from_str::(&candidate) + .map_err(|error| UpgradeError::WebRtc(error.to_string()))?; + diagnostic(role, "remote-candidate", candidate_kind(&candidate)); + if remote_description_set { + peer_connection.add_ice_candidate(candidate).await.map_err(webrtc_upgrade_error)?; + } else { + pending_candidates.push(candidate); + } + } + Some(_) => return Err(UpgradeError::UnexpectedSignal), + None if remote_description_set => { + remote_signaling_open = false; + diagnostic(role, "signaling-read-closed", None); + } + None => return Err(UpgradeError::SignalingEnded), + } + } + candidate = candidates.next() => { + let candidate = candidate.ok_or(UpgradeError::EventDelivery("candidate channel closed"))?; + local_candidate_count += 1; + if local_candidate_count > MAX_CANDIDATES { + return Err(UpgradeError::TooManyCandidates); + } + diagnostic(role, "local-candidate", candidate_kind(&candidate)); + let candidate = serde_json::to_string(&candidate) + .map_err(|error| UpgradeError::WebRtc(error.to_string()))?; + if local_signaling_open { + write_signal(&mut writer, Signal::IceCandidate(candidate)).await?; + } + } + state = states.next() => { + let state = state.ok_or(UpgradeError::EventDelivery("connection state channel closed"))?; + diagnostic(role, "connection-state", Some(&format!("{state:?}"))); + match state { + RTCPeerConnectionState::Connected => { + peer_connection_connected = true; + } + RTCPeerConnectionState::Failed | RTCPeerConnectionState::Closed => { + return Err(UpgradeError::WebRtc("peer connection failed".to_owned())); + } + _ => {} + } + } + opened = init_opened.next() => { + opened + .ok_or(UpgradeError::EventDelivery("init data channel event channel closed"))? + .map_err(|error| UpgradeError::WebRtc(error.to_string()))?; + init_channel_opened = true; + diagnostic(role, "init-channel-open", None); + } + failure = failures.next() => { + return Err(UpgradeError::WebRtc( + failure.unwrap_or_else(|| "event handler stopped".to_owned()) + )); + } + } + } +} + +fn candidate_kind(candidate: &RTCIceCandidateInit) -> Option<&str> { + let mut parts = candidate.candidate.split_whitespace(); + while let Some(part) = parts.next() { + if part == "typ" { + return parts.next(); + } + } + None +} + +fn diagnostic(role: UpgradeRole, event: &str, detail: Option<&str>) { + if std::env::var_os("MAKA_WEBRTC_DIAGNOSTICS").is_none() { + return; + } + eprintln!( + "{}", + serde_json::json!({ + "webrtc": event, + "role": match role { + UpgradeRole::Offerer => "offerer", + UpgradeRole::Answerer => "answerer", + }, + "detail": detail, + }) + ); +} + +struct EventChannels { + candidate_sender: mpsc::Sender, + candidates: mpsc::Receiver, + state_sender: mpsc::Sender, + states: mpsc::Receiver, + incoming_sender: mpsc::Sender>, + incoming: mpsc::Receiver>, + init_sender: mpsc::Sender>, + init_opened: mpsc::Receiver>, + failure_sender: mpsc::Sender, + failures: mpsc::Receiver, +} + +impl EventChannels { + fn new() -> Self { + let (candidate_sender, candidates) = mpsc::channel(EVENT_CAPACITY); + let (state_sender, states) = mpsc::channel(EVENT_CAPACITY); + let (incoming_sender, incoming) = mpsc::channel(EVENT_CAPACITY); + let (init_sender, init_opened) = mpsc::channel(1); + let (failure_sender, failures) = mpsc::channel(EVENT_CAPACITY); + Self { + candidate_sender, + candidates, + state_sender, + states, + incoming_sender, + incoming, + init_sender, + init_opened, + failure_sender, + failures, + } + } + + fn handler(&self) -> Arc { + Arc::new(EventHandler { + candidates: self.candidate_sender.clone(), + states: self.state_sender.clone(), + incoming: self.incoming_sender.clone(), + init_opened: self.init_sender.clone(), + failures: self.failure_sender.clone(), + }) + } +} + +#[derive(Clone)] +struct EventHandler { + candidates: mpsc::Sender, + states: mpsc::Sender, + incoming: mpsc::Sender>, + init_opened: mpsc::Sender>, + failures: mpsc::Sender, +} + +#[async_trait::async_trait] +impl PeerConnectionEventHandler for EventHandler { + async fn on_ice_candidate(&self, event: RTCPeerConnectionIceEvent) { + match event.candidate.to_json() { + Ok(candidate) => { + let mut candidates = self.candidates.clone(); + if candidates.try_send(candidate).is_err() { + self.report_failure("local ICE candidate limit exceeded"); + } + } + Err(error) => self.report_failure(&format!("could not encode ICE candidate: {error}")), + } + } + + async fn on_connection_state_change(&self, state: RTCPeerConnectionState) { + let mut states = self.states.clone(); + if states.try_send(state).is_err() { + self.report_failure("connection state delivery overflowed"); + } + } + + async fn on_data_channel(&self, data_channel: Arc) { + data_channel_diagnostic("received", data_channel.id(), Some("incoming")); + match data_channel.label().await { + Ok(label) if label == "init" => { + keep_init_channel(data_channel, self.init_opened.clone()); + } + Ok(_) => { + let mut incoming = self.incoming.clone(); + tokio::spawn(async move { + let stream = ready_substream(data_channel, "incoming").await; + let _ = incoming.send(stream).await; + }); + } + Err(error) => { + self.report_failure(&format!("could not read data channel label: {error}")) + } + } + } +} + +impl EventHandler { + fn report_failure(&self, message: &str) { + let mut failures = self.failures.clone(); + let _ = failures.try_send(message.to_owned()); + } +} + +fn webrtc_upgrade_error(error: impl std::fmt::Display) -> UpgradeError { + UpgradeError::WebRtc(error.to_string()) +} diff --git a/packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv b/packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv index 2da2eca52a..0479ece53d 100644 --- a/packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv +++ b/packages/cli/RUNTIME_HOST_PEER_DEPENDENCIES.rust.tsv @@ -1,10 +1,16 @@ crate Apache-2.0 BSD-2-Clause BSD-3-Clause ISC MIT Unicode-3.0 Unlicense Zlib +aead@0.5.2 X X +aes@0.8.4 X X anyhow@1.0.104 X X arrayref@0.3.9 X +asn1-rs@0.6.2 X X asn1-rs@0.7.2 X X +asn1-rs-derive@0.5.1 X X asn1-rs-derive@0.6.0 X X asn1-rs-impl@0.2.0 X X asn1_der@0.7.7 X X +async-broadcast@0.7.2 X X +async-channel@2.5.0 X X async-trait@0.1.92 X X asynchronous-codec@0.7.0 X autocfg@1.5.1 X X @@ -12,21 +18,31 @@ base-x@0.2.11 X base256emoji@1.0.2 X base45@3.2.0 X base64@0.22.1 X X +base64@0.23.1 X X +bitflags@1.3.2 X X bitflags@2.13.1 X X block-buffer@0.10.4 X X bs58@0.5.1 X X +bytecheck@0.8.3 X +bytecheck_derive@0.8.3 X byteorder@1.5.0 X X bytes@1.12.1 X cc@1.4.4 X X +ccm@0.5.0 X X cfg-if@1.0.4 X X cfg_aliases@0.2.2 X chacha20@0.10.1 X X +cipher@0.4.4 X X +concurrent-queue@2.5.0 X X const-str@0.4.3 X convert_case@0.11.0 X core-foundation@0.9.4 X X core-foundation-sys@0.8.7 X X cpufeatures@0.2.17 X X cpufeatures@0.3.0 X X +crc@3.4.0 X X +crc-catalog@2.5.0 X X +crc32c@0.6.8 X X critical-section@1.2.0 X X crossbeam-channel@0.5.16 X X crossbeam-epoch@0.9.20 X X @@ -34,12 +50,14 @@ crossbeam-utils@0.8.22 X X crunchy@0.2.4 X crypto-common@0.1.7 X X ctor@1.0.13 X X +ctr@0.9.2 X X curve25519-dalek@4.1.3 X curve25519-dalek-derive@0.1.1 X X data-encoding@2.11.1 X data-encoding-macro@0.1.21 X data-encoding-macro-internal@0.1.19 X der-parser@10.0.0 X X +der-parser@9.0.0 X X deranged@0.5.8 X X digest@0.10.7 X X displaydoc@0.2.7 X X @@ -48,6 +66,8 @@ ed25519-dalek@2.2.0 X either@1.18.0 X X enum-as-inner@0.6.1 X X equivalent@1.0.2 X X +event-listener@5.4.2 X X +event-listener-strategy@0.5.4 X X fastbloom@0.17.0 X X find-msvc-tools@0.1.11 X X fnv@1.0.7 X X @@ -71,6 +91,7 @@ getrandom@0.2.17 X X getrandom@0.3.4 X X getrandom@0.4.3 X X hashbrown@0.15.5 X X +hashbrown@0.17.1 X X hashlink@0.10.0 X X heck@0.5.0 X X hex@0.4.3 X X @@ -89,9 +110,11 @@ idna@1.1.0 X X idna_adapter@1.2.2 X X if-addrs@0.15.0 X X if-watch@3.2.2 X X +inout@0.1.4 X X ipconfig@0.3.4 X X ipnet@2.12.1 X X itertools@0.14.0 X X +itoa@1.0.18 X X lazy_static@1.5.0 X X libc@0.2.189 X X libloading@0.9.0 X @@ -113,6 +136,7 @@ libp2p-swarm@0.47.1 X libp2p-swarm-derive@0.35.1 X libp2p-tcp@0.44.1 X libp2p-tls@0.6.2 X +libp2p-webrtc-utils@0.4.0 X libp2p-yamux@0.47.0 X litemap@0.8.3 X lock_api@0.4.14 X X @@ -120,7 +144,9 @@ log@0.4.34 X X lru-slab@0.1.2 X X X maka-runtime-host-peer@0.0.0 X match-lookup@0.1.3 X +md-5@0.10.6 X X memchr@2.8.3 X X +memoffset@0.9.1 X minimal-lexical@0.2.1 X X mio@1.2.2 X moka@0.12.16 X X @@ -128,6 +154,8 @@ multiaddr@0.18.2 X multibase@0.9.3 X multihash@0.19.5 X multistream-select@0.13.0 X +munge@0.4.7 X +munge_macro@0.4.7 X napi@3.12.2 X napi-build@2.4.1 X napi-derive@3.6.3 X @@ -138,18 +166,22 @@ netlink-packet-route@0.28.0 X netlink-proto@0.12.2 X netlink-sys@0.8.8 X nix@0.30.1 X +nix@0.31.3 X nohash-hasher@0.2.0 X X nom@7.1.3 X num-bigint@0.4.8 X X num-conv@0.2.2 X X num-integer@0.1.47 X X num-traits@0.2.19 X X +oid-registry@0.7.1 X X oid-registry@0.8.1 X X once_cell@1.21.4 X X +parking@2.2.1 X X parking_lot@0.12.5 X X parking_lot_core@0.9.12 X X paste@1.0.15 X X pem@3.0.6 X +pem@4.0.0 X percent-encoding@2.3.2 X X pin-project@1.1.13 X X pin-project-internal@1.1.13 X X @@ -161,12 +193,16 @@ ppv-lite86@0.2.21 X X proc-macro2@1.0.107 X X prost@0.14.4 X prost-derive@0.14.4 X +ptr_meta@0.3.2 X +ptr_meta_derive@0.3.2 X quick-protobuf@0.8.1 X quick-protobuf-codec@0.3.1 X quinn@0.11.11 X X quinn-proto@0.11.17 X X quinn-udp@0.5.15 X X +quinn-udp@0.6.1 X X quote@1.0.47 X X +rancor@0.1.3 X rand@0.10.2 X X rand@0.8.8 X X rand@0.9.5 X X @@ -177,8 +213,28 @@ rand_core@0.6.4 X X rand_core@0.9.5 X X rand_pcg@0.10.2 X X rcgen@0.13.2 X X +rcgen@0.14.10 X X +rend@0.5.4 X resolv-conf@0.7.6 X X ring@0.17.14 X X +rkyv@0.8.18 X +rkyv_derive@0.8.18 X +rtc@0.21.0-rc.1 X X +rtc-crypto@0.21.0-rc.1 X X +rtc-datachannel@0.21.0-rc.1 X X +rtc-dtls@0.21.0-rc.1 X X +rtc-ice@0.21.0-rc.1 X X +rtc-interceptor@0.21.0-rc.1 X X +rtc-mdns@0.21.0-rc.1 X X +rtc-media@0.21.0-rc.1 X X +rtc-rtcp@0.21.0-rc.1 X X +rtc-rtp@0.21.0-rc.1 X X +rtc-sctp@0.21.0-rc.1 X X +rtc-sdp@0.21.0-rc.1 X X +rtc-shared@0.21.0-rc.1 X X +rtc-srtp@0.21.0-rc.1 X X +rtc-stun@0.21.0-rc.1 X X +rtc-turn@0.21.0-rc.1 X X rtnetlink@0.20.0 X rustc-hash@2.1.3 X X rustc_version@0.4.1 X X @@ -187,13 +243,18 @@ rustls@0.23.43 X X X rustls-pki-types@1.15.1 X X rustls-webpki@0.103.15 X rw-stream-sink@0.4.0 X +sansio@1.0.1 X X scopeguard@1.2.0 X X semver@1.0.28 X X serde@1.0.229 X X serde_core@1.0.229 X X +serde_derive@1.0.229 X X +serde_json@1.0.151 X X +sha1@0.10.7 X X sha2@0.10.9 X X shlex@2.0.1 X X signature@2.2.0 X X +simdutf8@0.1.5 X X siphasher@1.0.3 X X slab@0.4.12 X smallvec@1.15.2 X X @@ -202,6 +263,7 @@ socket2@0.5.10 X X socket2@0.6.5 X X stable_deref_trait@1.2.1 X X static_assertions@1.1.0 X X +substring@1.4.5 X X subtle@2.6.1 X syn@2.0.119 X X syn@3.0.4 X X @@ -217,6 +279,7 @@ time@0.3.55 X X time-core@0.1.9 X X time-macros@0.2.32 X X tinystr@0.8.4 X +tinytemplate@1.2.1 X X tinyvec@1.12.0 X X X tinyvec_macros@0.1.1 X X X tokio@1.53.1 X @@ -227,6 +290,7 @@ tracing-attributes@0.1.31 X tracing-core@0.1.36 X typenum@1.20.1 X X uint@0.10.1 X X +unicase@2.9.0 X X unicode-ident@1.0.24 X X X unicode-segmentation@1.13.3 X X unsigned-varint@0.7.2 X @@ -237,7 +301,9 @@ utf8_iter@1.0.4 X X uuid@1.25.0 X X version_check@0.9.5 X X web-time@1.1.0 X X +webrtc@0.21.0-rc.1 X X widestring@1.2.1 X X +winapi@0.3.9 X X windows@0.62.2 X X windows-collections@0.3.2 X X windows-core@0.62.2 X X @@ -257,10 +323,12 @@ windows_x86_64_gnu@0.52.6 X X windows_x86_64_msvc@0.52.6 X X writeable@0.6.4 X x25519-dalek@2.0.1 X +x509-parser@0.16.0 X X x509-parser@0.17.0 X X yamux@0.12.1 X X yamux@0.13.10 X X yasna@0.5.2 X X +yasna@0.6.0 X X yoke@0.8.3 X yoke-derive@0.8.2 X zerocopy@0.8.56 X X X @@ -271,3 +339,4 @@ zeroize_derive@1.5.0 X X zerotrie@0.2.5 X zerovec@0.11.8 X zerovec-derive@0.11.6 X +zmij@1.0.23 X diff --git a/packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt b/packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt index b0c88b163f..26fc6d3d4c 100644 --- a/packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt +++ b/packages/cli/RUNTIME_HOST_PEER_THIRD_PARTY_NOTICES.txt @@ -5,12 +5,26 @@ Generated by scripts/generate-runtime-host-peer-notices.mjs from the exact four-target production dependency inventory. Do not edit this file by hand. Manifest: native/runtime-host-peer/Cargo.toml -Cargo.lock SHA-256: fdfaf86fa6b2d4ad405959e6cbb4a8d4b3f77a26bc24215aa3f840b61aaae0e3 -Inventory SHA-256: b33f38e600eaf377fb15ddcfeb787a11e1d30e95a1b904597b306419a7614f28 +Cargo.lock SHA-256: e7d745e06c3d2d65d7a01e15075001e2f5fc95e127b77918ddb0d23c024984cd +Inventory SHA-256: c28a17749fa5f9af237a49dd2b4ad9149b6c4224d383c4a5050eeac3be14073c Packages -------- +aead@0.5.2 +---------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/traits +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: b38f573d5bc805e32f92fa8772ad44f1330a7de85022d133b2cd3d17424f8c22 (LICENSE-MIT) + +aes@0.8.4 +--------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/block-ciphers +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: 33e996382660b2bac31ae8ec48e5dc8ddf44e52ddce0612457301404c9a29111 (LICENSE-MIT) + anyhow@1.0.104 -------------- SPDX license: MIT OR Apache-2.0 @@ -24,6 +38,13 @@ SPDX license: BSD-2-Clause Source: https://github.com/droundy/arrayref License text: 112d1beb5fcb0478799ffe856253e9ac08afe88f71cdde313a2aa629e28f8d58 (LICENSE) +asn1-rs@0.6.2 +------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rusticata/asn1-rs.git +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) + asn1-rs@0.7.2 ------------- SPDX license: MIT OR Apache-2.0 @@ -31,6 +52,13 @@ Source: https://github.com/rusticata/asn1-rs.git License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) +asn1-rs-derive@0.5.1 +-------------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rusticata/asn1-rs.git +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) + asn1-rs-derive@0.6.0 -------------------- SPDX license: MIT OR Apache-2.0 @@ -50,6 +78,20 @@ SPDX license: BSD-2-Clause OR MIT Source: https://github.com/KizzyCode/asn1_der-rust License text: b70b1cc58b6d09afc7bfba35c45cc8613d121563acc5b9cbc519ae3b9a10af8d (MIT.txt) +async-broadcast@0.7.2 +--------------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/smol-rs/async-broadcast +License text: 65bf6afb9643771ab64b3145d7c11f4977a0b0f088718b3727e9c5256c931553 (LICENSE-APACHE) +License text: 48d36a6709db4f01ec2b5d9130df3981192fd7c232bbb9c216626e550a0876dc (LICENSE-MIT) + +async-channel@2.5.0 +------------------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/smol-rs/async-channel +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + async-trait@0.1.92 ------------------ SPDX license: MIT OR Apache-2.0 @@ -95,6 +137,20 @@ Source: https://github.com/marshallpierce/rust-base64 License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 6a8da4c78c729176907b068222cc6e8e612b09c7345628c98cbceb22c0f06979 (LICENSE-MIT) +base64@0.23.1 +------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/marshallpierce/rust-base64 +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 2ff8d973431258f88429889a3a2358d66b167bd3e64764ec88f531293518dda5 (LICENSE-MIT) + +bitflags@1.3.2 +-------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/bitflags/bitflags +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 14435fbcd271e2783f721b57b7bf4f6502c1379249a4300e0e5bb774686c2d90 (LICENSE-MIT) + bitflags@2.13.1 --------------- SPDX license: MIT OR Apache-2.0 @@ -116,6 +172,18 @@ Source: https://github.com/Nullus157/bs58-rs License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 67047503c71f90918a89209a99aaacd9db2d28a6ab6bc6568b8506bcbab5d9d8 (LICENSE-MIT) +bytecheck@0.8.3 +--------------- +SPDX license: MIT +Source: https://github.com/rkyv/bytecheck +License text: 75114f300a13994eaf147b93a628116ecd1bb2a3a948e3244ca5737062ed2e7f (LICENSE) + +bytecheck_derive@0.8.3 +---------------------- +SPDX license: MIT +Source: https://github.com/rkyv/bytecheck +License text: 6cb29bf78c6e512c65df670da014b3e1ee04a1db1f0adffd8147c21e25696241 (LICENSE) + byteorder@1.5.0 --------------- SPDX license: Unlicense OR MIT @@ -136,6 +204,13 @@ Source: https://github.com/rust-lang/cc-rs License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 84e1bbfebd74e4196cfa0ea5cf58e677aa24b47c6661adbb19fb07920d089d1d (LICENSE-MIT) +ccm@0.5.0 +--------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/RustCrypto/AEADs/tree/master/ccm +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: a6d96dff735a59b9677ddc5d9abd02b2add5632f2c2cce5d3c9e990f4f4fdcad (LICENSE-MIT) + cfg-if@1.0.4 ------------ SPDX license: MIT OR Apache-2.0 @@ -156,6 +231,20 @@ Source: https://github.com/RustCrypto/stream-ciphers License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) License text: 1038b7737a0a04bd9268bbb8d17ee4e13c9bb3cf36f39da46c3a1818c798aa20 (LICENSE-MIT) +cipher@0.4.4 +------------ +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/traits +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: 92f01fc7ca904e16f13e27d4897e507b5446e42516bb7efacc4c5ed189008c31 (LICENSE-MIT) + +concurrent-queue@2.5.0 +---------------------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/smol-rs/concurrent-queue +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + const-str@0.4.3 --------------- SPDX license: MIT @@ -196,6 +285,25 @@ Source: https://github.com/RustCrypto/utils License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) License text: 6334e52844d698f528b923f406aeb5bc3a2c6da77916c3b79f1662622fcde897 (LICENSE-MIT) +crc@3.4.0 +--------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/mrhooray/crc-rs.git +License text: 468044e890b145b08173df5ec8146781d2ebff73f851c6899e16cbc14eeb028d (LICENSE-APACHE) +License text: bec1ff6c886313105aabc29823670c41f1baf3f2c97cefe41b0261b3a52d2237 (LICENSE-MIT) + +crc-catalog@2.5.0 +----------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/akhilles/crc-catalog.git +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +crc32c@0.6.8 +------------ +SPDX license: Apache-2.0/MIT +Source: https://github.com/zowens/crc32c +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + critical-section@1.2.0 ---------------------- SPDX license: MIT OR Apache-2.0 @@ -245,6 +353,13 @@ Source: https://github.com/mmastrac/linktime License text: 6dc0e068dcf3a5bc8e054205b85b7720e1d49265bbc64bf515d2cf79197df69a (LICENSE-APACHE) License text: bccaa8b6c09f94e81f06696e179dbe058464bbdfbc823b6d49cada1d71e84ac3 (LICENSE-MIT) +ctr@0.9.2 +--------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/block-modes +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: f3bd9e2e7745e49db37c28033e4da290df8cf528aa21369d6861699804c5e5dd (LICENSE-MIT) + curve25519-dalek@4.1.3 ---------------------- SPDX license: BSD-3-Clause @@ -283,6 +398,13 @@ Source: https://github.com/rusticata/der-parser.git License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) +der-parser@9.0.0 +---------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/rusticata/der-parser.git +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) + deranged@0.5.8 -------------- SPDX license: MIT OR Apache-2.0 @@ -338,6 +460,20 @@ Source: https://github.com/indexmap-rs/equivalent License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 4428cd87371acbd49f9f6380125492cd1e89df621d2fd7f55e30a0891f96a433 (LICENSE-MIT) +event-listener@5.4.2 +-------------------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/smol-rs/event-listener +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + +event-listener-strategy@0.5.4 +----------------------------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/smol-rs/event-listener-strategy +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + fastbloom@0.17.0 ---------------- SPDX license: MIT OR Apache-2.0 @@ -495,6 +631,13 @@ Source: https://github.com/rust-lang/hashbrown License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: ae9791f02f2bbe0ce17b434753af97be6e5284b6f8e9f22db3c1f0f11b2e015a (LICENSE-MIT) +hashbrown@0.17.1 +---------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rust-lang/hashbrown +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: ae9791f02f2bbe0ce17b434753af97be6e5284b6f8e9f22db3c1f0f11b2e015a (LICENSE-MIT) + hashlink@0.10.0 --------------- SPDX license: MIT OR Apache-2.0 @@ -613,6 +756,13 @@ SPDX license: MIT OR Apache-2.0 Source: https://github.com/libp2p/if-watch License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) +inout@0.1.4 +----------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/utils +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: 71366a4092ad07b6fc29c4aa94ceeac8b892f7a24fcdedf8df7cba8112cdc15b (LICENSE-MIT) + ipconfig@0.3.4 -------------- SPDX license: MIT/Apache-2.0 @@ -634,6 +784,13 @@ Source: https://github.com/rust-itertools/itertools License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: fdd1c2117bcf8157d1d013d0953c0a7e6e5fab73df9e36773cd77634428568eb (LICENSE-MIT) +itoa@1.0.18 +----------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/dtolnay/itoa +License text: 95bd3988beee069fa2848f648dab43cc6e0b2add2ad6bcb17360caf749802bcc (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + lazy_static@1.5.0 ----------------- SPDX license: MIT OR Apache-2.0 @@ -762,6 +919,12 @@ SPDX license: MIT Source: https://github.com/libp2p/rust-libp2p License text: 80f847ab8b3d1802dcf33aad57b13d3e5cbae4969fb5990a5ff24ac7ae98ddb6 (MIT.txt) +libp2p-webrtc-utils@0.4.0 +------------------------- +SPDX license: MIT +Source: https://github.com/libp2p/rust-libp2p +License text: dfa6aff25cb0efb547a0bd19a15d4fb18f360feac358dfe5e024fdcc32cc5cea (MIT.txt) + libp2p-yamux@0.47.0 ------------------- SPDX license: MIT @@ -802,6 +965,13 @@ SPDX license: MIT Source: https://github.com/mriise/smol-base-x License text: 847558339dfee15f4f45f7f5b90efb48f75e51f78105c0f968cc4bf51dfde4a0 (MIT.txt) +md-5@0.10.6 +----------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/hashes +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: 4031faf6212ee74481b2597dc84fb61568d6a732480c3efdf317f2ac83d330b4 (LICENSE-MIT) + memchr@2.8.3 ------------ SPDX license: Unlicense OR MIT @@ -809,6 +979,12 @@ Source: https://github.com/BurntSushi/memchr License text: 65314a6c96683f76f7495709bb0ddecb4eaa6fa244b28f23c4812ef8e5524066 (COPYING) License text: 154c1af2b38e25e5c18613dfe352eed29b0863cb39e494007822cdeb39150ac5 (LICENSE-MIT) +memoffset@0.9.1 +--------------- +SPDX license: MIT +Source: https://github.com/Gilnaa/memoffset +License text: 3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1 (LICENSE) + minimal-lexical@0.2.1 --------------------- SPDX license: MIT/Apache-2.0 @@ -855,6 +1031,18 @@ SPDX license: MIT Source: https://github.com/libp2p/rust-libp2p License text: 4104e268c110e0948f82580e90eeb8a4106c388c4c0f6a1b7ed2e4dd1360872a (MIT.txt) +munge@0.4.7 +----------- +SPDX license: MIT +Source: https://github.com/djkoloski/munge +License text: 76e5968f85842714c6a059f78ebf6d3615f0a79e41d0bb115f7ea807508bc41b (LICENSE) + +munge_macro@0.4.7 +----------------- +SPDX license: MIT +Source: https://github.com/djkoloski/munge +License text: 76e5968f85842714c6a059f78ebf6d3615f0a79e41d0bb115f7ea807508bc41b (LICENSE) + napi@3.12.2 ----------- SPDX license: MIT @@ -915,6 +1103,12 @@ SPDX license: MIT Source: https://github.com/nix-rust/nix License text: b9b039b5058cfe9680025ca12f8591df832666baef9f469ea8ba24e73a7fee60 (LICENSE) +nix@0.31.3 +---------- +SPDX license: MIT +Source: https://github.com/nix-rust/nix +License text: b9b039b5058cfe9680025ca12f8591df832666baef9f469ea8ba24e73a7fee60 (LICENSE) + nohash-hasher@0.2.0 ------------------- SPDX license: Apache-2.0 OR MIT @@ -956,6 +1150,13 @@ Source: https://github.com/rust-num/num-traits License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 14435fbcd271e2783f721b57b7bf4f6502c1379249a4300e0e5bb774686c2d90 (LICENSE-MIT) +oid-registry@0.7.1 +------------------ +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rusticata/oid-registry.git +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) + oid-registry@0.8.1 ------------------ SPDX license: MIT OR Apache-2.0 @@ -970,6 +1171,14 @@ Source: https://github.com/matklad/once_cell License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) +parking@2.2.1 +------------- +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/smol-rs/parking +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) +License text: c43e20176655c7a74c12af7470b65065fac4c81cfd511c69520fcc7f738a3f91 (LICENSE-THIRD-PARTY) + parking_lot@0.12.5 ------------------ SPDX license: MIT OR Apache-2.0 @@ -997,6 +1206,12 @@ SPDX license: MIT Source: https://github.com/jcreekmore/pem-rs.git License text: fd270b8c59ed37680ea2106f920afe52ebc4d276d2377283f8b13276b36c09bd (LICENSE.md) +pem@4.0.0 +--------- +SPDX license: MIT +Source: https://github.com/jcreekmore/pem-rs.git +License text: fd270b8c59ed37680ea2106f920afe52ebc4d276d2377283f8b13276b36c09bd (LICENSE.md) + percent-encoding@2.3.2 ---------------------- SPDX license: MIT OR Apache-2.0 @@ -1071,6 +1286,18 @@ SPDX license: Apache-2.0 Source: https://github.com/tokio-rs/prost License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE) +ptr_meta@0.3.2 +-------------- +SPDX license: MIT +Source: https://github.com/rkyv/ptr_meta +License text: a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e (LICENSE) + +ptr_meta_derive@0.3.2 +--------------------- +SPDX license: MIT +Source: https://github.com/rkyv/ptr_meta +License text: a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e (LICENSE) + quick-protobuf@0.8.1 -------------------- SPDX license: MIT @@ -1104,6 +1331,13 @@ Source: https://github.com/quinn-rs/quinn License text: 43070e2d4e532684de521b885f385d0841030efa2b1a20bafb76133a5e1379c1 (LICENSE-APACHE) License text: 05fa1ba3228aab8d2bf637f286d7579ed76256c1dab3fa955c2489b920ffeb35 (LICENSE-MIT) +quinn-udp@0.6.1 +--------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/quinn-rs/quinn +License text: 43070e2d4e532684de521b885f385d0841030efa2b1a20bafb76133a5e1379c1 (LICENSE-APACHE) +License text: 05fa1ba3228aab8d2bf637f286d7579ed76256c1dab3fa955c2489b920ffeb35 (LICENSE-MIT) + quote@1.0.47 ------------ SPDX license: MIT OR Apache-2.0 @@ -1111,6 +1345,12 @@ Source: https://github.com/dtolnay/quote License text: 95bd3988beee069fa2848f648dab43cc6e0b2add2ad6bcb17360caf749802bcc (LICENSE-APACHE) License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) +rancor@0.1.3 +------------ +SPDX license: MIT +Source: https://github.com/rkyv/rancor +License text: 75114f300a13994eaf147b93a628116ecd1bb2a3a948e3244ca5737062ed2e7f (LICENSE) + rand@0.10.2 ----------- SPDX license: MIT OR Apache-2.0 @@ -1180,6 +1420,18 @@ SPDX license: MIT OR Apache-2.0 Source: https://github.com/rustls/rcgen License text: e1c4f4e7314d39c1ba620f549dee2d16c5f3094c8a25a8d4465086af38a6383a (LICENSE) +rcgen@0.14.10 +------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rustls/rcgen +License text: acce84ab5a3a9cf7d12402e67ab27b916a7c28fe6bf5be92b5d21bb3a088715f (LICENSE) + +rend@0.5.4 +---------- +SPDX license: MIT +Source: https://github.com/djkoloski/rend +License text: a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e (LICENSE) + resolv-conf@0.7.6 ----------------- SPDX license: MIT OR Apache-2.0 @@ -1195,6 +1447,115 @@ License text: edb9c6dbff4676b90e729ffdb6c9239076a2e01b3bb8aadf080bdc7a682296da ( License text: f3ba8fc296a970c976b1bdcaecc5939bf9757dbaecd3b4421e3e7ed29392e9b8 (LICENSE-BoringSSL) License text: 07414b6c33f30acfd5e0dda512e77ddbeb9f8a37290568fd056a01a0b50244c1 (LICENSE-other-bits) +rkyv@0.8.18 +----------- +SPDX license: MIT +Source: https://github.com/rkyv/rkyv +License text: a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e (LICENSE) + +rkyv_derive@0.8.18 +------------------ +SPDX license: MIT +Source: https://github.com/rkyv/rkyv +License text: a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e (LICENSE) + +rtc@0.21.0-rc.1 +--------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 6c20917694e80c18e344457d73162f5484985e05f443e0db92d960d6e83630c5 (LICENSE-MIT) + +rtc-crypto@0.21.0-rc.1 +---------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-datachannel@0.21.0-rc.1 +--------------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-dtls@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-ice@0.21.0-rc.1 +------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-interceptor@0.21.0-rc.1 +--------------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-mdns@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-media@0.21.0-rc.1 +--------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-rtcp@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-rtp@0.21.0-rc.1 +------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-sctp@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-sdp@0.21.0-rc.1 +------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-shared@0.21.0-rc.1 +---------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-srtp@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-stun@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + +rtc-turn@0.21.0-rc.1 +-------------------- +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/rtc +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) + rtnetlink@0.20.0 ---------------- SPDX license: MIT @@ -1249,6 +1610,13 @@ SPDX license: MIT Source: https://github.com/libp2p/rust-libp2p License text: 4104e268c110e0948f82580e90eeb8a4106c388c4c0f6a1b7ed2e4dd1360872a (MIT.txt) +sansio@1.0.1 +------------ +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/sansio +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 6c20917694e80c18e344457d73162f5484985e05f443e0db92d960d6e83630c5 (LICENSE-MIT) + scopeguard@1.2.0 ---------------- SPDX license: MIT OR Apache-2.0 @@ -1277,14 +1645,35 @@ Source: https://github.com/serde-rs/serde License text: 95bd3988beee069fa2848f648dab43cc6e0b2add2ad6bcb17360caf749802bcc (LICENSE-APACHE) License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) -sha2@0.10.9 +serde_derive@1.0.229 +-------------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/serde-rs/serde +License text: 95bd3988beee069fa2848f648dab43cc6e0b2add2ad6bcb17360caf749802bcc (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + +serde_json@1.0.151 +------------------ +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/serde-rs/json +License text: 95bd3988beee069fa2848f648dab43cc6e0b2add2ad6bcb17360caf749802bcc (LICENSE-APACHE) +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + +sha1@0.10.7 ----------- SPDX license: MIT OR Apache-2.0 Source: https://github.com/RustCrypto/hashes License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) License text: 4031faf6212ee74481b2597dc84fb61568d6a732480c3efdf317f2ac83d330b4 (LICENSE-MIT) -shlex@2.0.1 +sha2@0.10.9 +----------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/RustCrypto/hashes +License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) +License text: 4031faf6212ee74481b2597dc84fb61568d6a732480c3efdf317f2ac83d330b4 (LICENSE-MIT) + +shlex@2.0.1 ----------- SPDX license: MIT OR Apache-2.0 Source: https://github.com/comex/rust-shlex @@ -1298,6 +1687,13 @@ Source: https://github.com/RustCrypto/traits/tree/master/signature License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (LICENSE-APACHE) License text: 7d9f551458e84cf849649d2659dff470445dd14e1a9a37098da9eca6f7a13f62 (LICENSE-MIT) +simdutf8@0.1.5 +-------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rusticstuff/simdutf8 +License text: 0cec06e0e55fbc3dc5cee4fca9b607f66cb8f4e4dbcf3b3c013594dd156732e9 (LICENSE-Apache) +License text: 1847e0e0698142ed4347c1441a9fa81c8fbddd44b1d8bbcd5e3647f991759d7f (LICENSE-MIT) + siphasher@1.0.3 --------------- SPDX license: MIT/Apache-2.0 @@ -1352,6 +1748,13 @@ Source: https://github.com/nvzqz/static-assertions-rs License text: 58d1e17ffe5109a7ae296caafcadfdbe6a7d176f0bc4ab01e12a689b0499d8bd (LICENSE-APACHE) License text: 95a6a71a30f39d33a1fe6c03a52d1b57f0d1d43305a9137780a0c616231b4a52 (LICENSE-MIT) +substring@1.4.5 +--------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/Anders429/substring +License text: 43070e2d4e532684de521b885f385d0841030efa2b1a20bafb76133a5e1379c1 (LICENSE-APACHE) +License text: 695546eaa4b06e1a70c5d92eec183f4108dd416224c5c7eed3d0303423596993 (LICENSE-MIT) + subtle@2.6.1 ------------ SPDX license: BSD-3-Clause @@ -1454,6 +1857,13 @@ SPDX license: Unicode-3.0 Source: https://github.com/unicode-org/icu4x License text: cde87abe221f413fede55ded0f17985f37b8fdc23e5f6cba9a3955437facb3ae (LICENSE) +tinytemplate@1.2.1 +------------------ +SPDX license: Apache-2.0 OR MIT +Source: https://github.com/bheisler/TinyTemplate +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: e298f3a2b24df9b5cb954b79aecd16909cadb06e88d792a8038f2cc1a7b1b50e (LICENSE-MIT) + tinyvec@1.12.0 -------------- SPDX license: Zlib OR Apache-2.0 OR MIT @@ -1520,6 +1930,13 @@ SPDX license: MIT OR Apache-2.0 Source: https://github.com/paritytech/parity-common License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) +unicase@2.9.0 +------------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/seanmonstar/unicase +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 05f344491a7d18e1a3188acbddf6f921284cb192e49d16391128d453000468ff (LICENSE-MIT) + unicode-ident@1.0.24 -------------------- SPDX license: (MIT OR Apache-2.0) AND Unicode-3.0 @@ -1588,6 +2005,13 @@ Source: https://github.com/daxpedda/web-time License text: ca028ef321c3c013f55315f017a77c4061b15071e3e6d1310fc8549b7a5938b5 (LICENSE-APACHE) License text: 32ae0b6c9e4c00e6df1a408331fce92676e82f5bc1b7fd43f0273a60a0eb646e (LICENSE-MIT) +webrtc@0.21.0-rc.1 +------------------ +SPDX license: MIT/Apache-2.0 +Source: https://github.com/webrtc-rs/webrtc +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 6c20917694e80c18e344457d73162f5484985e05f443e0db92d960d6e83630c5 (LICENSE-MIT) + widestring@1.2.1 ---------------- SPDX license: MIT OR Apache-2.0 @@ -1595,6 +2019,13 @@ Source: https://github.com/VoidStarKat/widestring-rs License text: 59899c6091b540582ed617e8eeaac4919dc985ccfc35459ee9752b699be5205b (LICENSE-APACHE) License text: 1847e0e0698142ed4347c1441a9fa81c8fbddd44b1d8bbcd5e3647f991759d7f (LICENSE-MIT) +winapi@0.3.9 +------------ +SPDX license: MIT/Apache-2.0 +Source: https://github.com/retep998/winapi-rs +License text: c5accbbd8546e94c34aed24afe689a617627d18eed5a6c48277e48db57c23851 (LICENSE-APACHE) +License text: 2d01145596179ab6c55eade02ee8ad2c2172de88f2232625a00f17bb254b8c3a (LICENSE-MIT) + windows@0.62.2 -------------- SPDX license: MIT OR Apache-2.0 @@ -1726,6 +2157,13 @@ SPDX license: BSD-3-Clause Source: https://github.com/dalek-cryptography/curve25519-dalek/tree/main/x25519-dalek License text: f7183775eea50f974ee99591ef2111e7ed5022b68c2ac51bc955268f9de2bfd8 (LICENSE) +x509-parser@0.16.0 +------------------ +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/rusticata/x509-parser.git +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea (LICENSE-MIT) + x509-parser@0.17.0 ------------------ SPDX license: MIT OR Apache-2.0 @@ -1751,6 +2189,13 @@ SPDX license: MIT OR Apache-2.0 Source: https://github.com/qnighy/yasna.rs License text: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 (Apache-2.0.txt) +yasna@0.6.0 +----------- +SPDX license: MIT OR Apache-2.0 +Source: https://github.com/qnighy/yasna.rs +License text: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb (LICENSE-APACHE) +License text: 02273814a856eceb5006b5e1b6548cb2d5b3102b7640259cddabbd087302af16 (LICENSE-MIT) + yoke@0.8.3 ---------- SPDX license: Unicode-3.0 @@ -1815,6 +2260,12 @@ SPDX license: Unicode-3.0 Source: https://github.com/unicode-org/icu4x License text: cde87abe221f413fede55ded0f17985f37b8fdc23e5f6cba9a3955437facb3ae (LICENSE) +zmij@1.0.23 +----------- +SPDX license: MIT +Source: https://github.com/dtolnay/zmij +License text: 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 (LICENSE-MIT) + License texts ------------- @@ -1845,6 +2296,19 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Status API Training Shop Blog About Pricing +02273814a856eceb5006b5e1b6548cb2d5b3102b7640259cddabbd087302af16 +---------------------------------------------------------------- +Used by: +- yasna@0.6.0 (LICENSE-MIT) + +Copyright (c) 2016 Masaki Hara + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 033a9383ff21d1e4811d98dd2e0081b0ba0d9c9a31d6c7ba9e63e3488479bf29 ---------------------------------------------------------------- Used by: @@ -1904,11 +2368,37 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +05f344491a7d18e1a3188acbddf6f921284cb192e49d16391128d453000468ff +---------------------------------------------------------------- +Used by: +- unicase@2.9.0 (LICENSE-MIT) + +Copyright (c) 2014-2026 Sean McArthur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + 05fa1ba3228aab8d2bf637f286d7579ed76256c1dab3fa955c2489b920ffeb35 ---------------------------------------------------------------- Used by: - quinn-proto@0.11.17 (LICENSE-MIT) - quinn-udp@0.5.15 (LICENSE-MIT) +- quinn-udp@0.6.1 (LICENSE-MIT) - quinn@0.11.11 (LICENSE-MIT) Copyright (c) 2018 The quinn Developers @@ -2225,6 +2715,7 @@ Used by: - pin-project-lite@0.2.17 (LICENSE-APACHE) - pin-project@1.1.13 (LICENSE-APACHE) - portable-atomic@1.15.0 (LICENSE-APACHE) +- simdutf8@0.1.5 (LICENSE-Apache) - time-core@0.1.9 (LICENSE-Apache) - time-macros@0.2.32 (LICENSE-Apache) - time@0.3.55 (LICENSE-Apache) @@ -2568,6 +3059,7 @@ DEALINGS IN THE SOFTWARE. 14435fbcd271e2783f721b57b7bf4f6502c1379249a4300e0e5bb774686c2d90 ---------------------------------------------------------------- Used by: +- bitflags@1.3.2 (LICENSE-MIT) - bitflags@2.13.1 (LICENSE-MIT) - log@0.4.34 (LICENSE-MIT) - num-bigint@0.4.8 (LICENSE-MIT) @@ -2631,6 +3123,7 @@ THE SOFTWARE. 1847e0e0698142ed4347c1441a9fa81c8fbddd44b1d8bbcd5e3647f991759d7f ---------------------------------------------------------------- Used by: +- simdutf8@0.1.5 (LICENSE-MIT) - widestring@1.2.1 (LICENSE-MIT) MIT License @@ -3074,6 +3567,31 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +2d01145596179ab6c55eade02ee8ad2c2172de88f2232625a00f17bb254b8c3a +---------------------------------------------------------------- +Used by: +- winapi@0.3.9 (LICENSE-MIT) + +Copyright (c) 2015-2018 The winapi-rs Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + 2dbbc3a33651dcde639666a0fb8419b62eae90fbe5631f52931b2d7b67ae8500 ---------------------------------------------------------------- Used by: @@ -3491,15 +4009,48 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +2ff8d973431258f88429889a3a2358d66b167bd3e64764ec88f531293518dda5 +---------------------------------------------------------------- +Used by: +- base64@0.23.1 (LICENSE-MIT) + +The MIT License (MIT) + +Copyright (c) 2025 Alice Maz, Marshall Pierce + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + 30fefc3a7d6a0041541858293bcbea2dde4caa4c0a5802f996a7f7e8c0085652 ---------------------------------------------------------------- Used by: - anyhow@1.0.104 (LICENSE-MIT) +- async-channel@2.5.0 (LICENSE-MIT) - async-trait@0.1.92 (LICENSE-MIT) +- concurrent-queue@2.5.0 (LICENSE-MIT) - curve25519-dalek-derive@0.1.1 (LICENSE-MIT) - displaydoc@0.2.7 (LICENSE-MIT) +- event-listener-strategy@0.5.4 (LICENSE-MIT) +- event-listener@5.4.2 (LICENSE-MIT) +- itoa@1.0.18 (LICENSE-MIT) - minimal-lexical@0.2.1 (LICENSE-MIT) - once_cell@1.21.4 (LICENSE-MIT) +- parking@2.2.1 (LICENSE-MIT) - paste@1.0.15 (LICENSE-MIT) - pin-project-internal@1.1.13 (LICENSE-MIT) - pin-project-lite@0.2.17 (LICENSE-MIT) @@ -3511,6 +4062,8 @@ Used by: - semver@1.0.28 (LICENSE-MIT) - serde@1.0.229 (LICENSE-MIT) - serde_core@1.0.229 (LICENSE-MIT) +- serde_derive@1.0.229 (LICENSE-MIT) +- serde_json@1.0.151 (LICENSE-MIT) - syn@2.0.119 (LICENSE-MIT) - syn@3.0.4 (LICENSE-MIT) - thiserror-impl@1.0.69 (LICENSE-MIT) @@ -3518,6 +4071,7 @@ Used by: - thiserror@1.0.69 (LICENSE-MIT) - thiserror@2.0.20 (LICENSE-MIT) - unicode-ident@1.0.24 (LICENSE-MIT) +- zmij@1.0.23 (LICENSE-MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -3543,6 +4097,31 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1 +---------------------------------------------------------------- +Used by: +- memoffset@0.9.1 (LICENSE) + +Copyright (c) 2017 Gilad Naaman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + 32a5b6b5bbeeb0419b8a2da5e2db074131046167f9d5af5a346647a419122342 ---------------------------------------------------------------- Used by: @@ -3597,6 +4176,37 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +33e996382660b2bac31ae8ec48e5dc8ddf44e52ddce0612457301404c9a29111 +---------------------------------------------------------------- +Used by: +- aes@0.8.4 (LICENSE-MIT) + +Copyright (c) 2018 Artyom Pavlov + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + 33ed9a8ecf556f161ec5d7e8761712f404d082bf9eeb8f6085d43517b5938be4 ---------------------------------------------------------------- Used by: @@ -3833,6 +4443,8 @@ SOFTWARE. 4031faf6212ee74481b2597dc84fb61568d6a732480c3efdf317f2ac83d330b4 ---------------------------------------------------------------- Used by: +- md-5@0.10.6 (LICENSE-MIT) +- sha1@0.10.7 (LICENSE-MIT) - sha2@0.10.9 (LICENSE-MIT) Copyright (c) 2006-2009 Graydon Hoare @@ -3908,7 +4520,9 @@ SOFTWARE. Used by: - quinn-proto@0.11.17 (LICENSE-APACHE) - quinn-udp@0.5.15 (LICENSE-APACHE) +- quinn-udp@0.6.1 (LICENSE-APACHE) - quinn@0.11.11 (LICENSE-APACHE) +- substring@1.4.5 (LICENSE-APACHE) Apache License Version 2.0, January 2004 @@ -4148,27 +4762,234 @@ DEALINGS IN THE SOFTWARE. Used by: - moka@0.12.16 (LICENSE-MIT) -MIT License +MIT License + +Copyright (c) 2020 - 2026 Tatsuya Kawano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +468044e890b145b08173df5ec8146781d2ebff73f851c6899e16cbc14eeb028d +---------------------------------------------------------------- +Used by: +- crc@3.4.0 (LICENSE-APACHE) + + Apache License + Version 2.0 January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS -Copyright (c) 2020 - 2026 Tatsuya Kawano +APPENDIX: How to apply the Apache License to your work. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Copyright [yyyy] [name of copyright owner] -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. 47248d1ec833e0771ddacb65f2cf9978785f4a9976b5b0b69d1e33c60a50be55 ---------------------------------------------------------------- @@ -4247,6 +5068,33 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +48d36a6709db4f01ec2b5d9130df3981192fd7c232bbb9c216626e550a0876dc +---------------------------------------------------------------- +Used by: +- async-broadcast@0.7.2 (LICENSE-MIT) + +The MIT License (MIT) + +Copyright (c) 2020 Yoshua Wuyts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + 4cc06db819dd6df0c08283e07e42e62b5e200c095b61fd533a157484814c47c8 ---------------------------------------------------------------- Used by: @@ -5242,16 +6090,41 @@ Used by: 59013a5c8d3a19c26a457579105915a5d51bb0c09d579f8cdedf12e4203c3018 ---------------------------------------------------------------- Used by: +- aead@0.5.2 (LICENSE-APACHE) +- aes@0.8.4 (LICENSE-APACHE) - asn1-rs-impl@0.2.0 (Apache-2.0.txt) - block-buffer@0.10.4 (LICENSE-APACHE) +- ccm@0.5.0 (LICENSE-APACHE) - chacha20@0.10.1 (LICENSE-APACHE) +- cipher@0.4.4 (LICENSE-APACHE) - cpufeatures@0.2.17 (LICENSE-APACHE) - cpufeatures@0.3.0 (LICENSE-APACHE) +- crc-catalog@2.5.0 (Apache-2.0.txt) +- crc32c@0.6.8 (Apache-2.0.txt) - crypto-common@0.1.7 (LICENSE-APACHE) +- ctr@0.9.2 (LICENSE-APACHE) - digest@0.10.7 (LICENSE-APACHE) - hkdf@0.12.4 (LICENSE-APACHE) - hmac@0.12.1 (LICENSE-APACHE) - if-watch@3.2.2 (Apache-2.0.txt) +- inout@0.1.4 (LICENSE-APACHE) +- md-5@0.10.6 (LICENSE-APACHE) +- rtc-crypto@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-datachannel@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-dtls@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-ice@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-interceptor@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-mdns@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-media@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-rtcp@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-rtp@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-sctp@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-sdp@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-shared@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-srtp@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-stun@0.21.0-rc.1 (Apache-2.0.txt) +- rtc-turn@0.21.0-rc.1 (Apache-2.0.txt) +- sha1@0.10.7 (LICENSE-APACHE) - sha2@0.10.9 (LICENSE-APACHE) - signature@2.2.0 (LICENSE-APACHE) - uint@0.10.1 (Apache-2.0.txt) @@ -6573,93 +7446,289 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION (b) You must cause any modified files to carry prominent notices stating that You changed the files; and - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +65314a6c96683f76f7495709bb0ddecb4eaa6fa244b28f23c4812ef8e5524066 +---------------------------------------------------------------- +Used by: +- byteorder@1.5.0 (COPYING) +- memchr@2.8.3 (COPYING) + +This project is dual-licensed under the Unlicense and MIT licenses. + +You may use this code under the terms of either license. + +65bf6afb9643771ab64b3145d7c11f4977a0b0f088718b3727e9c5256c931553 +---------------------------------------------------------------- +Used by: +- async-broadcast@0.7.2 (LICENSE-APACHE) + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS -END OF TERMS AND CONDITIONS + Copyright 2020 Yoshua Wuyts -65314a6c96683f76f7495709bb0ddecb4eaa6fa244b28f23c4812ef8e5524066 ----------------------------------------------------------------- -Used by: -- byteorder@1.5.0 (COPYING) -- memchr@2.8.3 (COPYING) + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -This project is dual-licensed under the Unlicense and MIT licenses. + http://www.apache.org/licenses/LICENSE-2.0 -You may use this code under the terms of either license. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. 66b593f9d3287f8e8f9803183f57dcea03f1e427089918cc1d600804b8420692 ---------------------------------------------------------------- @@ -7132,6 +8201,33 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +695546eaa4b06e1a70c5d92eec183f4108dd416224c5c7eed3d0303423596993 +---------------------------------------------------------------- +Used by: +- substring@1.4.5 (LICENSE-MIT) + +MIT License + +Copyright (c) 2021 Anders Evensen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + 6a8da4c78c729176907b068222cc6e8e612b09c7345628c98cbceb22c0f06979 ---------------------------------------------------------------- Used by: @@ -7159,6 +8255,48 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +6c20917694e80c18e344457d73162f5484985e05f443e0db92d960d6e83630c5 +---------------------------------------------------------------- +Used by: +- rtc@0.21.0-rc.1 (LICENSE-MIT) +- sansio@1.0.1 (LICENSE-MIT) +- webrtc@0.21.0-rc.1 (LICENSE-MIT) + +MIT License + +Copyright (c) 2021 WebRTC.rs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +6cb29bf78c6e512c65df670da014b3e1ee04a1db1f0adffd8147c21e25696241 +---------------------------------------------------------------- +Used by: +- bytecheck_derive@0.8.3 (LICENSE) + +Copyright 2020 David Koloski + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 6dc0e068dcf3a5bc8e054205b85b7720e1d49265bbc64bf515d2cf79197df69a ---------------------------------------------------------------- Used by: @@ -7422,6 +8560,38 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +71366a4092ad07b6fc29c4aa94ceeac8b892f7a24fcdedf8df7cba8112cdc15b +---------------------------------------------------------------- +Used by: +- inout@0.1.4 (LICENSE-MIT) + +Copyright (c) 2022 The RustCrypto Project Developers +Copyright (c) 2022 Artyom Pavlov + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + 72de958052e494b0882a16da141b5524dcc8b87153a3a86323ab2e3dc1fc03a1 ---------------------------------------------------------------- Used by: @@ -7677,6 +8847,20 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +75114f300a13994eaf147b93a628116ecd1bb2a3a948e3244ca5737062ed2e7f +---------------------------------------------------------------- +Used by: +- bytecheck@0.8.3 (LICENSE) +- rancor@0.1.3 (LICENSE) + +Copyright 2023 David Koloski + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 75a373c5dfcd3e039b748b325a86cd31b7646e0bba51c00a5eeb82bf276c25e1 ---------------------------------------------------------------- Used by: @@ -7887,14 +9071,20 @@ Used by: 769f80b5bcb42ed0af4e4d2fd74e1ac9bf843cb80c5a29219d1ef3544428a6bb ---------------------------------------------------------------- Used by: +- asn1-rs-derive@0.5.1 (LICENSE-APACHE) - asn1-rs-derive@0.6.0 (LICENSE-APACHE) +- asn1-rs@0.6.2 (LICENSE-APACHE) - asn1-rs@0.7.2 (LICENSE-APACHE) +- async-channel@2.5.0 (LICENSE-APACHE) - autocfg@1.5.1 (LICENSE-APACHE) - base64@0.22.1 (LICENSE-APACHE) +- base64@0.23.1 (LICENSE-APACHE) +- bitflags@1.3.2 (LICENSE-APACHE) - bitflags@2.13.1 (LICENSE-APACHE) - bs58@0.5.1 (LICENSE-APACHE) - cc@1.4.4 (LICENSE-APACHE) - cfg-if@1.0.4 (LICENSE-APACHE) +- concurrent-queue@2.5.0 (LICENSE-APACHE) - core-foundation-sys@0.8.7 (LICENSE-APACHE) - core-foundation@0.9.4 (LICENSE-APACHE) - critical-section@1.2.0 (LICENSE-APACHE) @@ -7903,14 +9093,18 @@ Used by: - crossbeam-utils@0.8.22 (LICENSE-APACHE) - curve25519-dalek-derive@0.1.1 (LICENSE-APACHE) - der-parser@10.0.0 (LICENSE-APACHE) +- der-parser@9.0.0 (LICENSE-APACHE) - displaydoc@0.2.7 (LICENSE-APACHE) - either@1.18.0 (LICENSE-APACHE) - equivalent@1.0.2 (LICENSE-APACHE) +- event-listener-strategy@0.5.4 (LICENSE-APACHE) +- event-listener@5.4.2 (LICENSE-APACHE) - find-msvc-tools@0.1.11 (LICENSE-APACHE) - fnv@1.0.7 (LICENSE-APACHE) - form_urlencoded@1.2.2 (LICENSE-APACHE) - futures-timer@3.0.4 (LICENSE-APACHE) - hashbrown@0.15.5 (LICENSE-APACHE) +- hashbrown@0.17.1 (LICENSE-APACHE) - heck@0.5.0 (LICENSE-APACHE) - idna@1.1.0 (LICENSE-APACHE) - idna_adapter@1.2.2 (LICENSE-APACHE) @@ -7922,16 +9116,20 @@ Used by: - num-bigint@0.4.8 (LICENSE-APACHE) - num-integer@0.1.47 (LICENSE-APACHE) - num-traits@0.2.19 (LICENSE-APACHE) +- oid-registry@0.7.1 (LICENSE-APACHE) - oid-registry@0.8.1 (LICENSE-APACHE) - once_cell@1.21.4 (LICENSE-APACHE) +- parking@2.2.1 (LICENSE-APACHE) - parking_lot@0.12.5 (LICENSE-APACHE) - parking_lot_core@0.9.12 (LICENSE-APACHE) - percent-encoding@2.3.2 (LICENSE-APACHE) - prost-derive@0.14.4 (LICENSE) - prost@0.14.4 (LICENSE) +- rtc@0.21.0-rc.1 (LICENSE-APACHE) - rustc_version@0.4.1 (LICENSE-APACHE) - rusticata-macros@4.1.0 (LICENSE-APACHE) - rustls@0.23.43 (LICENSE-APACHE) +- sansio@1.0.1 (LICENSE-APACHE) - scopeguard@1.2.0 (LICENSE-APACHE) - smallvec@1.15.2 (LICENSE-APACHE) - socket2@0.5.10 (LICENSE-APACHE) @@ -7939,11 +9137,16 @@ Used by: - stable_deref_trait@1.2.1 (LICENSE-APACHE) - system-configuration-sys@0.6.0 (LICENSE-APACHE) - system-configuration@0.7.0 (LICENSE-APACHE) +- tinytemplate@1.2.1 (LICENSE-APACHE) +- unicase@2.9.0 (LICENSE-APACHE) - unicode-segmentation@1.13.3 (LICENSE-APACHE) - url@2.5.8 (LICENSE-APACHE) - uuid@1.25.0 (LICENSE-APACHE) - version_check@0.9.5 (LICENSE-APACHE) +- webrtc@0.21.0-rc.1 (LICENSE-APACHE) +- x509-parser@0.16.0 (LICENSE-APACHE) - x509-parser@0.17.0 (LICENSE-APACHE) +- yasna@0.6.0 (LICENSE-APACHE) Apache License Version 2.0, January 2004 @@ -8147,6 +9350,20 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +76e5968f85842714c6a059f78ebf6d3615f0a79e41d0bb115f7ea807508bc41b +---------------------------------------------------------------- +Used by: +- munge@0.4.7 (LICENSE) +- munge_macro@0.4.7 (LICENSE) + +Copyright 2024 David Koloski + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 778f4b3d16272ce197399cbe26419da5559e5c5ea2e04e5a738cb8bf0742237f ---------------------------------------------------------------- Used by: @@ -8828,11 +10045,16 @@ DEALINGS IN THE SOFTWARE. 9206df1d7be3fb30bcb3e920853805f4984858318d245297209268fac172d5ea ---------------------------------------------------------------- Used by: +- asn1-rs-derive@0.5.1 (LICENSE-MIT) - asn1-rs-derive@0.6.0 (LICENSE-MIT) +- asn1-rs@0.6.2 (LICENSE-MIT) - asn1-rs@0.7.2 (LICENSE-MIT) - der-parser@10.0.0 (LICENSE-MIT) +- der-parser@9.0.0 (LICENSE-MIT) +- oid-registry@0.7.1 (LICENSE-MIT) - oid-registry@0.8.1 (LICENSE-MIT) - rusticata-macros@4.1.0 (LICENSE-MIT) +- x509-parser@0.16.0 (LICENSE-MIT) - x509-parser@0.17.0 (LICENSE-MIT) Copyright (c) 2017 Pierre Chifflier @@ -9122,6 +10344,37 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +92f01fc7ca904e16f13e27d4897e507b5446e42516bb7efacc4c5ed189008c31 +---------------------------------------------------------------- +Used by: +- cipher@0.4.4 (LICENSE-MIT) + +Copyright (c) 2016-2020 RustCrypto Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + 943f36fd309fb5ea67a82f577433f4ed3bc877e5b00f9b874e2f8b7f72bf0bdc ---------------------------------------------------------------- Used by: @@ -9204,6 +10457,7 @@ Used by: - anyhow@1.0.104 (LICENSE-APACHE) - async-trait@0.1.92 (LICENSE-APACHE) - fastbloom@0.17.0 (LICENSE-APACHE) +- itoa@1.0.18 (LICENSE-APACHE) - libc@0.2.189 (LICENSE-APACHE) - paste@1.0.15 (LICENSE-APACHE) - proc-macro2@1.0.107 (LICENSE-APACHE) @@ -9212,6 +10466,8 @@ Used by: - semver@1.0.28 (LICENSE-APACHE) - serde@1.0.229 (LICENSE-APACHE) - serde_core@1.0.229 (LICENSE-APACHE) +- serde_derive@1.0.229 (LICENSE-APACHE) +- serde_json@1.0.151 (LICENSE-APACHE) - syn@2.0.119 (LICENSE-APACHE) - syn@3.0.4 (LICENSE-APACHE) - thiserror-impl@1.0.69 (LICENSE-APACHE) @@ -9682,6 +10938,54 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +a427dbea98ffc849b4d8368d97211afdfef816e5c34090e7024a4787299f0e2e +---------------------------------------------------------------- +Used by: +- ptr_meta@0.3.2 (LICENSE) +- ptr_meta_derive@0.3.2 (LICENSE) +- rend@0.5.4 (LICENSE) +- rkyv@0.8.18 (LICENSE) +- rkyv_derive@0.8.18 (LICENSE) + +Copyright 2021 David Koloski + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +a6d96dff735a59b9677ddc5d9abd02b2add5632f2c2cce5d3c9e990f4f4fdcad +---------------------------------------------------------------- +Used by: +- ccm@0.5.0 (LICENSE-MIT) + +Copyright (c) 2020 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + a759ce38c686a2042f62a0a6b8ea01781e3447726dcb68f4bb8b9f199feff12e ---------------------------------------------------------------- Used by: @@ -9762,57 +11066,277 @@ Used by: Copyright (c) 2017 Liran Ringel -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +aa3694cfba33f6e8650271dd0ff84f6a33da5705d60dff84dcfcb3f9a2c0fdd3 +---------------------------------------------------------------- +Used by: +- multiaddr@0.18.2 (LICENSE) +- multihash@0.19.5 (LICENSE) + +The MIT License + +Copyright (C) 2015-2016 Friedel Ziegelmayer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Status API Training Shop Blog About Pricing + +acce84ab5a3a9cf7d12402e67ab27b916a7c28fe6bf5be92b5d21bb3a088715f +---------------------------------------------------------------- +Used by: +- rcgen@0.14.10 (LICENSE) + +Copyright (c) 2019-2026 est31 and contributors + +Licensed under MIT or Apache License 2.0, +at your option. + +The full list of contributors can be obtained by looking +at the VCS log (originally, this crate was git versioned, +there you can do "git shortlog -sn" for this task). + +MIT License +----------- + +The MIT License (MIT) + +Copyright (c) 2019-2026 est31 and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +Apache License, version 2.0 +--------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -aa3694cfba33f6e8650271dd0ff84f6a33da5705d60dff84dcfcb3f9a2c0fdd3 ----------------------------------------------------------------- -Used by: -- multiaddr@0.18.2 (LICENSE) -- multihash@0.19.5 (LICENSE) + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -The MIT License + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Copyright (C) 2015-2016 Friedel Ziegelmayer + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Status API Training Shop Blog About Pricing + END OF TERMS AND CONDITIONS ad4fcfaf8d5b12b97409c137a03d4a4e4b21024c65c54f976cc3b609c1bd5b0f ---------------------------------------------------------------- @@ -9845,6 +11369,7 @@ ae9791f02f2bbe0ce17b434753af97be6e5284b6f8e9f22db3c1f0f11b2e015a ---------------------------------------------------------------- Used by: - hashbrown@0.15.5 (LICENSE-MIT) +- hashbrown@0.17.1 (LICENSE-MIT) Copyright (c) 2016 Amanieu d'Antras @@ -9997,6 +11522,38 @@ These files were ported from the Java Caffeine library and are not dual-licensed Please refer to the LICENSE-APACHE file for more details on the Apache License 2.0. +b38f573d5bc805e32f92fa8772ad44f1330a7de85022d133b2cd3d17424f8c22 +---------------------------------------------------------------- +Used by: +- aead@0.5.2 (LICENSE-MIT) + +Copyright (c) 2019 The RustCrypto Project Developers +Copyright (c) 2019 MobileCoin, LLC + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + b420d8add23b5cf7663f17f012b06a4c16b722c5dd8fb049b285417214b5702e ---------------------------------------------------------------- Used by: @@ -10109,6 +11666,7 @@ b9b039b5058cfe9680025ca12f8591df832666baef9f469ea8ba24e73a7fee60 ---------------------------------------------------------------- Used by: - nix@0.30.1 (LICENSE) +- nix@0.31.3 (LICENSE) The MIT License (MIT) @@ -10162,6 +11720,33 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +bec1ff6c886313105aabc29823670c41f1baf3f2c97cefe41b0261b3a52d2237 +---------------------------------------------------------------- +Used by: +- crc@3.4.0 (LICENSE-MIT) + +MIT License + +Copyright (c) 2017 crc-rs Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + c0fdcda1a4ffc5fd63c452e40ce25e54f2098669e3415033b228773eea24a871 ---------------------------------------------------------------- Used by: @@ -10463,6 +12048,21 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +c43e20176655c7a74c12af7470b65065fac4c81cfd511c69520fcc7f738a3f91 +---------------------------------------------------------------- +Used by: +- parking@2.2.1 (LICENSE-THIRD-PARTY) + +=============================================================================== + +Copyright 2014-2020 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 or the MIT license +, at your +option. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. + c48b7333c00b9776f5571ecaaabf73b9a5343b049bdad89ed05894b45cdc7cc5 ---------------------------------------------------------------- Used by: @@ -10500,6 +12100,7 @@ Used by: - enum-as-inner@0.6.1 (LICENSE-APACHE) - hex@0.4.3 (LICENSE-APACHE) - resolv-conf@0.7.6 (LICENSE-APACHE) +- winapi@0.3.9 (LICENSE-APACHE) Apache License Version 2.0, January 2004 @@ -12135,6 +13736,33 @@ Used by: MIT OR Apache-2.0 +dfa6aff25cb0efb547a0bd19a15d4fb18f360feac358dfe5e024fdcc32cc5cea +---------------------------------------------------------------- +Used by: +- libp2p-webrtc-utils@0.4.0 (MIT.txt) + +Copyright notice: not included in the published crate +Cargo authors: Doug Anderson +Source: https://github.com/libp2p/rust-libp2p + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + e1c4f4e7314d39c1ba620f549dee2d16c5f3094c8a25a8d4465086af38a6383a ---------------------------------------------------------------- Used by: @@ -12386,6 +14014,37 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +e298f3a2b24df9b5cb954b79aecd16909cadb06e88d792a8038f2cc1a7b1b50e +---------------------------------------------------------------- +Used by: +- tinytemplate@1.2.1 (LICENSE-MIT) + +Copyright (c) 2019 Brook Heisler + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + e337e719e1e9fab1b1f7c39a5ed3446bf0fc399abd5ad5014af018f3b7bcb7dd ---------------------------------------------------------------- Used by: @@ -12893,6 +14552,38 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +f3bd9e2e7745e49db37c28033e4da290df8cf528aa21369d6861699804c5e5dd +---------------------------------------------------------------- +Used by: +- ctr@0.9.2 (LICENSE-MIT) + +Copyright (c) 2018-2022 RustCrypto Developers +Copyright (c) 2018 Artyom Pavlov + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + f7183775eea50f974ee99591ef2111e7ed5022b68c2ac51bc955268f9de2bfd8 ---------------------------------------------------------------- Used by: @@ -12932,6 +14623,7 @@ fd270b8c59ed37680ea2106f920afe52ebc4d276d2377283f8b13276b36c09bd ---------------------------------------------------------------- Used by: - pem@3.0.6 (LICENSE.md) +- pem@4.0.0 (LICENSE.md) The MIT License (MIT) diff --git a/packages/runtime-host/src/__tests__/peer-native.test.ts b/packages/runtime-host/src/__tests__/peer-native.test.ts index 326ef26634..fc12167100 100644 --- a/packages/runtime-host/src/__tests__/peer-native.test.ts +++ b/packages/runtime-host/src/__tests__/peer-native.test.ts @@ -238,11 +238,15 @@ test('rejects an incomplete endpoint API and loads a compatible relative native await writeFile( modulePath, `const stream = { read: async () => null, write: async () => {}, close: async () => {}, abort: () => {} }; +const starts = []; module.exports = { + starts, ensurePeerIdentity: async () => 'peer', signPeerIdentity: async () => ({ publicKey: Buffer.from('public'), signature: Buffer.from('signature') }), verifyPeerIdentity: () => true, - startPeerEndpoint: () => ({ + startPeerEndpoint: (options) => { + starts.push(options); + return ({ peerId: 'peer', listenAddresses: [], activeCoordinationRelays: [], @@ -254,15 +258,19 @@ module.exports = { accept: async () => null, acceptMeshControl: async () => null, close: async () => {}, - }), + }); + }, }; `, ); const endpoint = startRuntimeHostPeerEndpoint({ nativePath: relative(process.cwd(), modulePath), keyPath: 'unused', + webRtcStunUrls: [], }); assert.equal(endpoint.peerId, 'peer'); + const native = await import(modulePath); + assert.deepEqual(native.default.starts, [{ keyPath: 'unused', webRtcStunUrls: [] }]); assert.equal( await ensureRuntimeHostPeerIdentity({ nativePath: modulePath, keyPath: 'unused' }), 'peer', diff --git a/packages/runtime-host/src/client/peer-client.ts b/packages/runtime-host/src/client/peer-client.ts index 3a2b567c15..543efdb2f0 100644 --- a/packages/runtime-host/src/client/peer-client.ts +++ b/packages/runtime-host/src/client/peer-client.ts @@ -92,6 +92,7 @@ export function createRuntimeHostPeerClientFromEnvironment( readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; readonly routeResolver?: RuntimeHostPeerRouteResolver; } = {}, ): RuntimeHostPeerClient { @@ -113,6 +114,7 @@ export function createRuntimeHostPeerClient(input: { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; readonly routeResolver?: RuntimeHostPeerRouteResolver; }): RuntimeHostPeerClient { return new RuntimeHostPeerClientImpl(input); @@ -125,6 +127,7 @@ class RuntimeHostPeerClientImpl implements RuntimeHostPeerClient { readonly #listenAddresses: readonly string[] | undefined; readonly #coordinationRelays: readonly string[] | undefined; readonly #automaticRelayDiscovery: boolean; + readonly #webRtcStunUrls: readonly string[] | undefined; readonly #routeResolver: RuntimeHostPeerRouteResolver | undefined; #endpoint: RuntimeHostPeerNativeEndpoint | undefined; #draining: Promise | undefined; @@ -144,6 +147,7 @@ class RuntimeHostPeerClientImpl implements RuntimeHostPeerClient { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; readonly routeResolver?: RuntimeHostPeerRouteResolver; }) { this.#nativePath = input.nativePath; @@ -152,6 +156,8 @@ class RuntimeHostPeerClientImpl implements RuntimeHostPeerClient { this.#listenAddresses = input.listenAddresses; this.#coordinationRelays = input.coordinationRelays; this.#automaticRelayDiscovery = input.automaticRelayDiscovery ?? false; + this.#webRtcStunUrls = + input.webRtcStunUrls === undefined ? undefined : [...input.webRtcStunUrls]; this.#routeResolver = input.routeResolver; } @@ -390,6 +396,7 @@ class RuntimeHostPeerClientImpl implements RuntimeHostPeerClient { ...(this.#listenAddresses ? { listenAddresses: this.#listenAddresses } : {}), ...(this.#coordinationRelays ? { coordinationRelays: this.#coordinationRelays } : {}), automaticRelayDiscovery: this.#automaticRelayDiscovery, + ...(this.#webRtcStunUrls === undefined ? {} : { webRtcStunUrls: this.#webRtcStunUrls }), }); this.#endpoint = endpoint; this.#draining = this.#drainInbound(endpoint); diff --git a/packages/runtime-host/src/peer-mesh/owner.ts b/packages/runtime-host/src/peer-mesh/owner.ts index bd0b7bffc4..5bde0a8d10 100644 --- a/packages/runtime-host/src/peer-mesh/owner.ts +++ b/packages/runtime-host/src/peer-mesh/owner.ts @@ -43,6 +43,7 @@ export async function openRuntimeHostPeerMeshOwner(input: { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; }): Promise { let mesh: PeerMeshNode | undefined; let resolverMesh: PeerMeshNode | undefined; @@ -60,6 +61,7 @@ export async function openRuntimeHostPeerMeshOwner(input: { ...(input.automaticRelayDiscovery === undefined ? {} : { automaticRelayDiscovery: input.automaticRelayDiscovery }), + ...(input.webRtcStunUrls === undefined ? {} : { webRtcStunUrls: input.webRtcStunUrls }), routeResolver: { resolveRoutes: (peerId) => resolverMesh?.resolveRoutes(peerId), prepareRoutes: async (peerId, signal) => resolverMesh?.prepareRoutes(peerId, signal), diff --git a/packages/runtime-host/src/server/peer-listener.ts b/packages/runtime-host/src/server/peer-listener.ts index 11db805abb..750f40bcce 100644 --- a/packages/runtime-host/src/server/peer-listener.ts +++ b/packages/runtime-host/src/server/peer-listener.ts @@ -43,6 +43,7 @@ export interface RuntimeHostPeerListenerConfiguration { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; } export type RuntimeHostPeerListenerEndpointOptions = diff --git a/packages/runtime-host/src/transport/peer-native.ts b/packages/runtime-host/src/transport/peer-native.ts index e72a542568..1bf423ef04 100644 --- a/packages/runtime-host/src/transport/peer-native.ts +++ b/packages/runtime-host/src/transport/peer-native.ts @@ -128,6 +128,7 @@ interface RuntimeHostPeerNativeModule { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; }): unknown; } @@ -199,6 +200,7 @@ export function startRuntimeHostPeerEndpoint(input: { readonly listenAddresses?: readonly string[]; readonly coordinationRelays?: readonly string[]; readonly automaticRelayDiscovery?: boolean; + readonly webRtcStunUrls?: readonly string[]; }): RuntimeHostPeerNativeEndpoint { try { const endpoint = loadNativeModule(input.nativePath).startPeerEndpoint({ @@ -209,6 +211,7 @@ export function startRuntimeHostPeerEndpoint(input: { ...(input.automaticRelayDiscovery === undefined ? {} : { automaticRelayDiscovery: input.automaticRelayDiscovery }), + ...(input.webRtcStunUrls === undefined ? {} : { webRtcStunUrls: input.webRtcStunUrls }), }); if (!isPeerNativeEndpoint(endpoint)) { throw new RuntimeHostPeerError( From 837c166767eea0c5091a8497708ef52c0fe7e384 Mon Sep 17 00:00:00 2001 From: Wang Date: Tue, 1 Sep 2026 05:39:08 +0800 Subject: [PATCH 2/3] fix(runtime-host): bound WebRTC substream resources --- native/runtime-host-peer/Cargo.toml | 5 + .../src/webrtc_direct/muxer.rs | 104 ++++++++++++------ .../src/webrtc_direct/tests.rs | 100 ++++++++++++++++- .../src/webrtc_direct/upgrade.rs | 46 +++++++- 4 files changed, 216 insertions(+), 39 deletions(-) diff --git a/native/runtime-host-peer/Cargo.toml b/native/runtime-host-peer/Cargo.toml index 595c03b9a8..711ee2eeaa 100644 --- a/native/runtime-host-peer/Cargo.toml +++ b/native/runtime-host-peer/Cargo.toml @@ -64,3 +64,8 @@ napi-build = "2.4" [profile.release] # build.mjs strips the copied addon once; Cargo stripping every intermediate artifact is redundant. strip = "none" +# The CLI ships all four platform addons in one immutable tarball. Optimize the +# network helper for deployed size while preserving unwind semantics at the N-API boundary. +opt-level = "s" +lto = "thin" +codegen-units = 1 diff --git a/native/runtime-host-peer/src/webrtc_direct/muxer.rs b/native/runtime-host-peer/src/webrtc_direct/muxer.rs index c3e9ce18d1..74281009d5 100644 --- a/native/runtime-host-peer/src/webrtc_direct/muxer.rs +++ b/native/runtime-host-peer/src/webrtc_direct/muxer.rs @@ -27,7 +27,7 @@ use std::{ use bytes::BytesMut; use futures::{ - AsyncRead, AsyncWrite, FutureExt, Sink, Stream, StreamExt as _, + AsyncRead, AsyncWrite, FutureExt, Sink, SinkExt as _, Stream, StreamExt as _, channel::{mpsc, oneshot}, future::BoxFuture, ready, @@ -35,6 +35,7 @@ use futures::{ }; use libp2p::core::muxing::{StreamMuxer, StreamMuxerEvent}; use libp2p_webrtc_utils::{DropListener, Stream as Libp2pWebRtcStream}; +use tokio::sync::OwnedSemaphorePermit; use webrtc::{ data_channel::{DataChannel, DataChannelEvent, RTCDataChannelState}, peer_connection::{PeerConnection, RTCPeerConnectionState}, @@ -111,7 +112,7 @@ impl StreamMuxer for WebRtcConnection { .await .map_err(webrtc_io_error)?; data_channel_diagnostic("created", channel.id(), Some("outbound")); - ready_substream(channel, "outbound").await + ready_substream(channel, "outbound", None).await } .boxed() }); @@ -172,6 +173,7 @@ impl StreamMuxer for WebRtcConnection { pub struct WebRtcSubstream { inner: Libp2pWebRtcStream, + _inbound_permit: Option, } impl AsyncRead for WebRtcSubstream { @@ -205,6 +207,7 @@ impl AsyncWrite for WebRtcSubstream { pub(crate) async fn ready_substream( data_channel: Arc, origin: &'static str, + inbound_permit: Option, ) -> Result { let (outgoing, outgoing_receiver) = mpsc::channel(DATA_CHANNEL_QUEUE_CAPACITY); let (incoming_sender, incoming) = mpsc::channel(DATA_CHANNEL_QUEUE_CAPACITY); @@ -221,7 +224,13 @@ pub(crate) async fn ready_substream( .await .map_err(|_| io::Error::new(io::ErrorKind::ConnectionAborted, "data channel stopped"))??; let (stream, listener) = Libp2pWebRtcStream::new(io); - Ok((WebRtcSubstream { inner: stream }, listener)) + Ok(( + WebRtcSubstream { + inner: stream, + _inbound_permit: inbound_permit, + }, + listener, + )) } pub(crate) fn keep_init_channel( @@ -254,19 +263,40 @@ async fn drive_data_channel( ready: oneshot::Sender>, origin: &'static str, ) { - let mut ready = Some(ready); data_channel_diagnostic("waiting", data_channel.id(), Some(origin)); if let Err(error) = wait_for_data_channel_open(&data_channel).await { data_channel_diagnostic("open-failed", data_channel.id(), Some(origin)); - signal_channel_failure(&mut ready, &mut incoming, error); + let _ = ready.send(Err(error)); return; } data_channel_diagnostic("opened", data_channel.id(), Some(origin)); - if let Some(ready) = ready.take() { - let _ = ready.send(Ok(())); - } + let _ = ready.send(Ok(())); + let mut pending_incoming = None; loop { + if pending_incoming.is_some() { + tokio::select! { + ready = futures::future::poll_fn(|context| { + Pin::new(&mut incoming).poll_ready(context) + }) => { + if ready.is_err() { + let _ = data_channel.close().await; + return; + } + let message = pending_incoming.take().expect("pending message exists"); + if Pin::new(&mut incoming).start_send(Ok(message)).is_err() { + let _ = data_channel.close().await; + return; + } + } + message = outgoing.next() => { + if !send_outgoing_message(&data_channel, message).await { + return; + } + } + } + continue; + } tokio::select! { event = data_channel.poll() => { match event { @@ -276,10 +306,7 @@ async fn drive_data_channel( data_channel.id(), Some(&message.data.len().to_string()), ); - if incoming.try_send(Ok(message.data)).is_err() { - let _ = data_channel.close().await; - return; - } + pending_incoming = Some(message.data); } Some(DataChannelEvent::OnClose) => { data_channel_diagnostic("closed", data_channel.id(), Some(origin)); @@ -287,34 +314,53 @@ async fn drive_data_channel( } Some(DataChannelEvent::OnError) => { data_channel_diagnostic("error", data_channel.id(), Some(origin)); + send_channel_reset(&mut incoming, "WebRTC data channel failed").await; return; } None => { data_channel_diagnostic("stopped", data_channel.id(), Some(origin)); + send_channel_reset(&mut incoming, "WebRTC data channel stopped").await; return; } _ => {} } } message = outgoing.next() => { - let Some(message) = message else { - drain_data_channel(&data_channel).await; - let _ = data_channel.close().await; - return; - }; - let message_bytes = message.len().to_string(); - if message.len() > MAX_DATA_CHANNEL_MESSAGE_BYTES - || data_channel.send(message).await.is_err() - { - let _ = data_channel.close().await; + if !send_outgoing_message(&data_channel, message).await { return; } - data_channel_diagnostic("sent", data_channel.id(), Some(&message_bytes)); } } } } +async fn send_outgoing_message( + data_channel: &Arc, + message: Option, +) -> bool { + let Some(message) = message else { + drain_data_channel(data_channel).await; + let _ = data_channel.close().await; + return false; + }; + let message_bytes = message.len().to_string(); + if message.len() > MAX_DATA_CHANNEL_MESSAGE_BYTES || data_channel.send(message).await.is_err() { + let _ = data_channel.close().await; + return false; + } + data_channel_diagnostic("sent", data_channel.id(), Some(&message_bytes)); + true +} + +async fn send_channel_reset( + incoming: &mut mpsc::Sender>, + message: &'static str, +) { + let _ = incoming + .send(Err(io::Error::new(io::ErrorKind::ConnectionReset, message))) + .await; +} + async fn drain_data_channel(data_channel: &Arc) { let _ = tokio::time::timeout(Duration::from_secs(5), async { loop { @@ -358,18 +404,6 @@ async fn wait_for_data_channel_open(data_channel: &Arc) -> Resu )) } -fn signal_channel_failure( - ready: &mut Option>>, - incoming: &mut mpsc::Sender>, - error: io::Error, -) { - if let Some(ready) = ready.take() { - let _ = ready.send(Err(error)); - } else { - let _ = incoming.try_send(Err(error)); - } -} - #[derive(Clone)] pub(crate) struct MessageIo { inner: Arc>, diff --git a/native/runtime-host-peer/src/webrtc_direct/tests.rs b/native/runtime-host-peer/src/webrtc_direct/tests.rs index b95631b2bc..9f74396c9b 100644 --- a/native/runtime-host-peer/src/webrtc_direct/tests.rs +++ b/native/runtime-host-peer/src/webrtc_direct/tests.rs @@ -23,7 +23,7 @@ use futures::{AsyncReadExt as _, AsyncWriteExt as _, future::poll_fn}; use libp2p::{PeerId, core::muxing::StreamMuxer}; use tokio_util::compat::TokioAsyncReadCompatExt as _; -use super::{UpgradeOptions, UpgradeRole, upgrade_connection}; +use super::{UpgradeOptions, UpgradeRole, upgrade::MAX_INBOUND_SUBSTREAMS, upgrade_connection}; #[tokio::test] async fn authenticated_signaling_yields_a_libp2p_stream() { @@ -71,3 +71,101 @@ async fn authenticated_signaling_yields_a_libp2p_stream() { .expect("read payload"); assert_eq!(received, payload); } + +#[tokio::test] +async fn a_slow_reader_backpressures_without_losing_bytes() { + let (mut connection_a, mut connection_b) = connected_pair().await; + let (outbound, inbound) = tokio::join!( + poll_fn(|cx| Pin::new(&mut connection_a).poll_outbound(cx)), + poll_fn(|cx| Pin::new(&mut connection_b).poll_inbound(cx)), + ); + let mut outbound = outbound.expect("outbound WebRTC stream"); + let mut inbound = inbound.expect("inbound WebRTC stream"); + let payload = vec![0x5a; 20 * 16 * 1024]; + let expected = payload.clone(); + let writer = tokio::spawn(async move { + outbound.write_all(&payload).await.expect("write payload"); + outbound.flush().await.expect("flush payload"); + }); + + tokio::time::sleep(Duration::from_millis(100)).await; + let mut received = vec![0; expected.len()]; + tokio::time::timeout(Duration::from_secs(10), inbound.read_exact(&mut received)) + .await + .expect("slow-reader receive timeout") + .expect("slow-reader receive failed"); + tokio::time::timeout(Duration::from_secs(10), writer) + .await + .expect("slow-reader writer timeout") + .expect("slow-reader writer task failed"); + assert_eq!(received, expected); +} + +#[tokio::test] +async fn inbound_substreams_are_bounded_per_connection() { + let (mut connection_a, mut connection_b) = connected_pair().await; + let mut outbound = Vec::new(); + for _ in 0..=MAX_INBOUND_SUBSTREAMS { + outbound.push( + tokio::time::timeout( + Duration::from_secs(5), + poll_fn(|cx| Pin::new(&mut connection_a).poll_outbound(cx)), + ) + .await + .expect("outbound substream timeout") + .expect("outbound substream failed"), + ); + } + let mut inbound = Vec::new(); + for _ in 0..MAX_INBOUND_SUBSTREAMS { + inbound.push( + tokio::time::timeout( + Duration::from_secs(5), + poll_fn(|cx| Pin::new(&mut connection_b).poll_inbound(cx)), + ) + .await + .expect("inbound substream timeout") + .expect("inbound substream failed"), + ); + } + assert!( + tokio::time::timeout( + Duration::from_millis(250), + poll_fn(|cx| Pin::new(&mut connection_b).poll_inbound(cx)), + ) + .await + .is_err(), + "the excess inbound substream escaped the per-connection bound", + ); + drop((outbound, inbound)); +} + +async fn connected_pair() -> (super::WebRtcConnection, super::WebRtcConnection) { + let peer_a = PeerId::random(); + let peer_b = PeerId::random(); + let (signaling_a, signaling_b) = tokio::io::duplex(256 * 1024); + let options = UpgradeOptions { + deadline: Duration::from_secs(10), + ..UpgradeOptions::default() + }; + let (offer, answer) = tokio::join!( + upgrade_connection( + signaling_a.compat(), + peer_b, + peer_b, + UpgradeRole::Offerer, + options.clone(), + ), + upgrade_connection( + signaling_b.compat(), + peer_a, + peer_a, + UpgradeRole::Answerer, + options, + ) + ); + ( + offer.expect("offerer upgrade").1, + answer.expect("answerer upgrade").1, + ) +} diff --git a/native/runtime-host-peer/src/webrtc_direct/upgrade.rs b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs index 8b9231b1dc..c705fa6f37 100644 --- a/native/runtime-host-peer/src/webrtc_direct/upgrade.rs +++ b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs @@ -17,13 +17,21 @@ * under the License. */ -use std::{io, sync::Arc, time::Duration}; +use std::{ + io, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, + time::Duration, +}; use futures::{ AsyncRead, AsyncReadExt as _, AsyncWrite, AsyncWriteExt as _, SinkExt as _, StreamExt as _, channel::mpsc, }; use libp2p::PeerId; +use tokio::sync::Semaphore; use tokio_util::sync::CancellationToken; use webrtc::{ data_channel::DataChannel, @@ -43,6 +51,7 @@ use super::{ const EVENT_CAPACITY: usize = 64; const MAX_CANDIDATES: usize = 64; const DATA_CHANNEL_SEND_BUFFER_BYTES: usize = 1024 * 1024; +pub(super) const MAX_INBOUND_SUBSTREAMS: usize = 16; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UpgradeRole { @@ -176,6 +185,7 @@ where init_sender, mut init_opened, mut failures, + init_claimed, .. } = channels; let mut remote_description_set = false; @@ -189,6 +199,7 @@ where match role { UpgradeRole::Offerer => { + init_claimed.store(true, Ordering::Release); let init = peer_connection .create_data_channel("init", None) .await @@ -353,6 +364,8 @@ struct EventChannels { init_opened: mpsc::Receiver>, failure_sender: mpsc::Sender, failures: mpsc::Receiver, + init_claimed: Arc, + inbound_substreams: Arc, } impl EventChannels { @@ -373,6 +386,8 @@ impl EventChannels { init_opened, failure_sender, failures, + init_claimed: Arc::new(AtomicBool::new(false)), + inbound_substreams: Arc::new(Semaphore::new(MAX_INBOUND_SUBSTREAMS)), } } @@ -383,6 +398,8 @@ impl EventChannels { incoming: self.incoming_sender.clone(), init_opened: self.init_sender.clone(), failures: self.failure_sender.clone(), + init_claimed: Arc::clone(&self.init_claimed), + inbound_substreams: Arc::clone(&self.inbound_substreams), }) } } @@ -394,6 +411,8 @@ struct EventHandler { incoming: mpsc::Sender>, init_opened: mpsc::Sender>, failures: mpsc::Sender, + init_claimed: Arc, + inbound_substreams: Arc, } #[async_trait::async_trait] @@ -421,12 +440,33 @@ impl PeerConnectionEventHandler for EventHandler { data_channel_diagnostic("received", data_channel.id(), Some("incoming")); match data_channel.label().await { Ok(label) if label == "init" => { - keep_init_channel(data_channel, self.init_opened.clone()); + if self + .init_claimed + .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire) + .is_ok() + { + keep_init_channel(data_channel, self.init_opened.clone()); + } else { + data_channel_diagnostic("rejected", data_channel.id(), Some("duplicate-init")); + let _ = data_channel.close().await; + } } Ok(_) => { + let permit = match Arc::clone(&self.inbound_substreams).try_acquire_owned() { + Ok(permit) => permit, + Err(_) => { + data_channel_diagnostic( + "rejected", + data_channel.id(), + Some("inbound-limit"), + ); + let _ = data_channel.close().await; + return; + } + }; let mut incoming = self.incoming.clone(); tokio::spawn(async move { - let stream = ready_substream(data_channel, "incoming").await; + let stream = ready_substream(data_channel, "incoming", Some(permit)).await; let _ = incoming.send(stream).await; }); } From e1f2022932cdd9d18698d26d9acdd4be1efa13a3 Mon Sep 17 00:00:00 2001 From: Wang Date: Tue, 1 Sep 2026 06:13:12 +0800 Subject: [PATCH 3/3] fix(native): close discarded WebRTC transports --- .../src/webrtc_direct/muxer.rs | 9 ++++++ .../src/webrtc_direct/transport.rs | 7 ++-- .../src/webrtc_direct/upgrade.rs | 32 ++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/native/runtime-host-peer/src/webrtc_direct/muxer.rs b/native/runtime-host-peer/src/webrtc_direct/muxer.rs index 74281009d5..4a91623988 100644 --- a/native/runtime-host-peer/src/webrtc_direct/muxer.rs +++ b/native/runtime-host-peer/src/webrtc_direct/muxer.rs @@ -80,6 +80,15 @@ impl WebRtcConnection { } stream } + + pub(crate) fn close_in_background(self) { + let peer_connection = Arc::clone(&self.peer_connection); + if let Ok(runtime) = tokio::runtime::Handle::try_current() { + runtime.spawn(async move { + let _ = peer_connection.close().await; + }); + } + } } impl StreamMuxer for WebRtcConnection { diff --git a/native/runtime-host-peer/src/webrtc_direct/transport.rs b/native/runtime-host-peer/src/webrtc_direct/transport.rs index cb9d928ca4..0615d26e03 100644 --- a/native/runtime-host-peer/src/webrtc_direct/transport.rs +++ b/native/runtime-host-peer/src/webrtc_direct/transport.rs @@ -75,13 +75,16 @@ impl WebRtcTransportControl { ) -> Result<(), io::Error> { let mut incoming = self.incoming.clone(); incoming.try_send((peer, connection)).map_err(|error| { + let full = error.is_full(); + let (_, connection) = error.into_inner(); + connection.close_in_background(); io::Error::new( - if error.is_full() { + if full { io::ErrorKind::WouldBlock } else { io::ErrorKind::BrokenPipe }, - if error.is_full() { + if full { "WebRTC transport input is full" } else { "WebRTC transport stopped" diff --git a/native/runtime-host-peer/src/webrtc_direct/upgrade.rs b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs index c705fa6f37..09a7f61a29 100644 --- a/native/runtime-host-peer/src/webrtc_direct/upgrade.rs +++ b/native/runtime-host-peer/src/webrtc_direct/upgrade.rs @@ -103,6 +103,31 @@ pub enum UpgradeError { Cancelled, } +struct PeerConnectionGuard(Option>); + +impl PeerConnectionGuard { + fn new(peer_connection: Arc) -> Self { + Self(Some(peer_connection)) + } + + fn disarm(&mut self) { + self.0 = None; + } +} + +impl Drop for PeerConnectionGuard { + fn drop(&mut self) { + let Some(peer_connection) = self.0.take() else { + return; + }; + if let Ok(runtime) = tokio::runtime::Handle::try_current() { + runtime.spawn(async move { + let _ = peer_connection.close().await; + }); + } + } +} + pub async fn upgrade_connection( signaling: S, authenticated_peer: PeerId, @@ -122,6 +147,7 @@ where let channels = EventChannels::new(); let peer_connection = build_peer_connection(&options, channels.handler()).await?; + let mut peer_connection_guard = PeerConnectionGuard::new(Arc::clone(&peer_connection)); let negotiation = negotiate(signaling, role, Arc::clone(&peer_connection), channels); tokio::pin!(negotiation); let deadline = tokio::time::sleep(options.deadline); @@ -135,9 +161,13 @@ where }; match result { - Ok(connection) => Ok((authenticated_peer, connection)), + Ok(connection) => { + peer_connection_guard.disarm(); + Ok((authenticated_peer, connection)) + } Err(error) => { let _ = peer_connection.close().await; + peer_connection_guard.disarm(); Err(error) } }