diff --git a/composeApp/Cargo.lock b/composeApp/Cargo.lock index 428f5064..1897105f 100644 --- a/composeApp/Cargo.lock +++ b/composeApp/Cargo.lock @@ -29,6 +29,20 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "anyhow" version = "1.0.103" @@ -198,12 +212,24 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "basic-toml" version = "0.1.10" @@ -243,6 +269,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -316,6 +351,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.4.3" @@ -350,6 +394,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + [[package]] name = "chacha20" version = "0.10.1" @@ -361,6 +416,19 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20 0.9.1", + "cipher", + "poly1305", + "zeroize", +] + [[package]] name = "cipher" version = "0.4.4" @@ -369,6 +437,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -379,6 +448,7 @@ dependencies = [ "bytes", "discord-rich-presence", "lofty", + "log", "parking_lot", "rtc", "thiserror 2.0.18", @@ -396,6 +466,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -453,6 +529,18 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -473,12 +561,49 @@ dependencies = [ "cipher", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "data-encoding" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "der-parser" version = "9.0.0" @@ -520,6 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -550,6 +676,41 @@ dependencies = [ "syn 3.0.2", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -592,6 +753,22 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "find-msvc-tools" version = "0.1.11" @@ -722,6 +899,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -747,6 +925,16 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "glob" version = "0.3.3" @@ -764,6 +952,17 @@ dependencies = [ "scroll", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -782,6 +981,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -911,6 +1119,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ + "block-padding", "generic-array", ] @@ -1158,6 +1367,36 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parking" version = "2.2.1" @@ -1203,6 +1442,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1215,12 +1463,45 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + [[package]] name = "potential_utf" version = "0.1.6" @@ -1236,6 +1517,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -1308,7 +1598,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "chacha20", + "chacha20 0.10.1", "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -1360,6 +1650,16 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -1406,15 +1706,16 @@ dependencies = [ [[package]] name = "rtc" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9005c36795ad076abd36db3ea9ae0275a60395944647d58c1f2bc3e118dddba" dependencies = [ "bytes", "hex", "log", - "pem", "rand", "rcgen", - "rtc-crypto", + "ring", "rtc-datachannel", "rtc-dtls", "rtc-ice", @@ -1433,31 +1734,16 @@ dependencies = [ "sansio", "serde", "serde_json", + "sha2", "unicase", "url", - "x509-parser 0.16.0", -] - -[[package]] -name = "rtc-crypto" -version = "0.21.0-beta.1" -dependencies = [ - "aes", - "ccm", - "ctr", - "hmac", - "md-5", - "rand", - "ring", - "sha1", - "subtle", - "thiserror 2.0.18", - "zeroize", ] [[package]] name = "rtc-datachannel" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b61c7b8e9892094cba8a6c7fb8120ae863d32d432b00e560177b3d7ae6d2c6" dependencies = [ "bytes", "log", @@ -1468,30 +1754,47 @@ dependencies = [ [[package]] name = "rtc-dtls" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c737b1dd17a0ff63884a2f466b9588f0cffadfce5a724c0c368764d7c27f9c74" dependencies = [ + "aes", "bytecheck", "byteorder", "bytes", + "cbc", + "ccm", + "chacha20poly1305", "der-parser 9.0.0", + "hmac", "log", - "pem", + "p256", + "p384", + "rand", + "rand_core 0.6.4", "rcgen", + "ring", "rkyv", - "rtc-crypto", "rtc-shared", "rustls", + "sec1", + "sha1", + "sha2", + "subtle", + "x25519-dalek", "x509-parser 0.16.0", ] [[package]] name = "rtc-ice" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c06eeabd250a7693e1e8b28222b78c4a81a7c6ca7fe3cb99bbdff2f6c0ff0ab" dependencies = [ "bytes", "crc", "log", - "rtc-crypto", + "rand", "rtc-mdns", "rtc-shared", "rtc-stun", @@ -1503,19 +1806,35 @@ dependencies = [ [[package]] name = "rtc-interceptor" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec2776ab86c0c03c3de8ec742aa13ccc3b2c82317590d0624f251bd37eae3b9" dependencies = [ "log", "rand", + "rtc-interceptor-derive", "rtc-rtcp", "rtc-rtp", "rtc-shared", "sansio", ] +[[package]] +name = "rtc-interceptor-derive" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc31da3875839bc18e00997354a582e6decacdb23d39f8c004fc4fe2fd3fcd8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "rtc-mdns" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cd53120b83321c8b8310cce9512c685d2d6356acef34647a99ea420e6f2249" dependencies = [ "bytes", "log", @@ -1526,7 +1845,9 @@ dependencies = [ [[package]] name = "rtc-media" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0411e44fcdc1363487ae0c6a4612ec908b9b09175d05499c5de0b3c81f0b5e5" dependencies = [ "byteorder", "bytes", @@ -1538,7 +1859,9 @@ dependencies = [ [[package]] name = "rtc-rtcp" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fceaadac17b114140368dd68478d186ccfc293970f79cb8dd28f94dbbc0300be" dependencies = [ "bytes", "rtc-shared", @@ -1546,7 +1869,9 @@ dependencies = [ [[package]] name = "rtc-rtp" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "babb45ac2263340e2bb412d1921aa07ca441ae9b5589477221d1a50d98750ba3" dependencies = [ "bytes", "memchr", @@ -1557,7 +1882,9 @@ dependencies = [ [[package]] name = "rtc-sctp" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2513391b524b88b041277faba617e0531ad726729861ea8933015393fd68ab05" dependencies = [ "bytes", "crc32c", @@ -1571,7 +1898,9 @@ dependencies = [ [[package]] name = "rtc-sdp" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d136a422965289e3d32d8e110789d8fa2ac669a4474a4084fa1eeac32758ee" dependencies = [ "rand", "rtc-shared", @@ -1580,12 +1909,19 @@ dependencies = [ [[package]] name = "rtc-shared" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce81c72adbce3a2f2ad8e2b97674d2482be83cb3bfd9a153341b04b1a87ca24" dependencies = [ + "aes", + "aes-gcm", "bitflags 1.3.2", "bytes", "nix", + "p256", "rand", + "rcgen", + "sec1", "serde", "substring", "thiserror 2.0.18", @@ -1595,38 +1931,50 @@ dependencies = [ [[package]] name = "rtc-srtp" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b880d5f6d436b3215c7bcfd3fb5ffe2a752fea0236440ccd98b6bf1c3561df8" dependencies = [ + "aes", "byteorder", "bytes", - "rtc-crypto", + "ctr", + "hmac", + "ring", "rtc-rtcp", "rtc-rtp", "rtc-shared", + "sha1", + "subtle", ] [[package]] name = "rtc-stun" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06b19c36a200df6071b92a25583a19ab0f9c6d5ad036d8c3ff5d392802cc926e" dependencies = [ "base64", "bytes", "crc", "lazy_static", + "md-5", "rand", - "rtc-crypto", + "ring", "rtc-shared", "sansio", + "subtle", "url", ] [[package]] name = "rtc-turn" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf0b5fbb94085c86be7277c38ae8f1c21ec75ab47ba975be0984409732020dd" dependencies = [ "bytes", "log", - "rtc-crypto", "rtc-shared", "rtc-stun", "sansio", @@ -1741,6 +2089,20 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.28" @@ -1816,12 +2178,33 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.10" @@ -1868,6 +2251,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -2217,6 +2610,16 @@ dependencies = [ "weedle2", ] +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2320,7 +2723,9 @@ dependencies = [ [[package]] name = "webrtc" -version = "0.21.0-beta.1" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3daa8f2f6366331ae3275a6c02a855c6fb3faa1d16960498d7daaf61c96e76bd" dependencies = [ "async-broadcast", "async-channel", @@ -2468,6 +2873,18 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "x509-parser" version = "0.16.0" @@ -2562,6 +2979,20 @@ name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] name = "zerotrie" diff --git a/composeApp/Cargo.toml b/composeApp/Cargo.toml index 68dbc246..900cd117 100644 --- a/composeApp/Cargo.toml +++ b/composeApp/Cargo.toml @@ -9,8 +9,9 @@ lofty = "0.24.0" discord-rich-presence = "1.1.0" thiserror = "2.0" parking_lot = "0.12" -webrtc = { path = "../build/webrtc-rs" } -rtc = { path = "../build/webrtc-rs/rtc" } +log = "0.4" +webrtc = "0.20.4" +rtc = "0.20.4" async-trait = "0.1" bytes = "1" tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/jam/JamSessionService.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/jam/JamSessionService.kt index c85db931..bfcde591 100644 --- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/jam/JamSessionService.kt +++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/jam/JamSessionService.kt @@ -121,7 +121,7 @@ class JamSessionService( log.i { "Generating invite $inviteId" } val pc = createWebrtcPeerConnection( - iceServers = listOf(defaultIceServer()), + iceServers = defaultIceServers(), handler = guestEventHandler(inviteId), ) @@ -179,7 +179,7 @@ class JamSessionService( val participantName = resolveParticipantName(defaultPrefix = "Guest") val pc = createWebrtcPeerConnection( - iceServers = listOf(defaultIceServer()), + iceServers = defaultIceServers(), handler = eventHandler, ) @@ -254,10 +254,28 @@ class JamSessionService( sendMessage(JamMessage.SuggestPlaylist(tracks)) } - private fun defaultIceServer() = IceServerConfig( - urls = listOf("stun:stun.l.google.com:19302"), - username = "", - credential = "", + /** + * ICE servers for global peer-to-peer jam sessions: multiple STUN servers for + * NAT traversal plus a TURN relay for symmetric NATs and strict firewalls. + * Unreachable servers no longer stall offer/answer creation — the webrtc + * driver completes gathering once every STUN client has answered or timed out, + * and [WebrtcPeerConnection] bounds the wait anyway. + */ + private fun defaultIceServers(): List = listOf( + IceServerConfig( + urls = listOf( + "stun:stun.cloudflare.com:3478", + "stun:stun1.l.google.com:19302", + "stun:stun.l.google.com:19302", + ), + username = "", + credential = "", + ), + IceServerConfig( + urls = listOf("turn:openrelay.metered.ca:80"), + username = "openrelayproject", + credential = "openrelayproject", + ), ) private suspend fun resolveParticipantName(defaultPrefix: String): String { @@ -271,10 +289,12 @@ class JamSessionService( * attributed back to that guest (needed for kick-on-leave and targeted sends). */ private fun guestEventHandler(guestId: String) = object : WebrtcEventHandler { - override fun onIceCandidate(candidate: String) {} + override fun onIceCandidate(candidate: String) { + log.i { "[$guestId] ICE candidate: $candidate" } + } override fun onIceGatheringStateChange(state: String) { - log.d { "[$guestId] ICE gathering state: $state" } + log.i { "[$guestId] ICE gathering state: $state" } } override fun onConnectionStateChange(state: String) { @@ -295,10 +315,12 @@ class JamSessionService( } private val eventHandler = object : WebrtcEventHandler { - override fun onIceCandidate(candidate: String) {} + override fun onIceCandidate(candidate: String) { + log.i { "ICE candidate: $candidate" } + } override fun onIceGatheringStateChange(state: String) { - log.d { "ICE gathering state: $state" } + log.i { "ICE gathering state: $state" } } override fun onConnectionStateChange(state: String) { diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/home/HomeScreen.kt index 012e6947..67924aaf 100644 --- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/home/HomeScreen.kt @@ -128,17 +128,19 @@ fun HomeScreen(viewModel: HomeScreenViewModel) { Text("Browse") }, actions = { - IconButton(onClick = { navigationCommands.navigateTo(Routes.Devices) }) { - Icon( - imageVector = Iconsax.IconsaxMirroringScreen, - contentDescription = "Devices", - ) - } - IconButton(onClick = { navigationCommands.navigateTo(Routes.Jam) }) { - Icon( - imageVector = Iconsax.User, - contentDescription = "Group Jam", - ) + if (!isDesktop) { + IconButton(onClick = { navigationCommands.navigateTo(Routes.Devices) }) { + Icon( + imageVector = Iconsax.IconsaxMirroringScreen, + contentDescription = "Devices", + ) + } + IconButton(onClick = { navigationCommands.navigateTo(Routes.Jam) }) { + Icon( + imageVector = Iconsax.User, + contentDescription = "Group Jam", + ) + } } }, ) @@ -355,7 +357,7 @@ private fun HomeSection( if (!subtitle.isNullOrEmpty()) Text( text = subtitle, style = MaterialTheme.typography.labelMedium.copy( - color = MaterialTheme.colorScheme.secondary, + color = MaterialTheme.colorScheme.secondary, fontWeight = FontWeight.Medium, ), modifier = Modifier.padding(horizontal = 16.dp), diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/jam/JamScreen.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/jam/JamScreen.kt index 26280783..bb3cc055 100644 --- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/jam/JamScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/jam/JamScreen.kt @@ -53,6 +53,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import dev.krtirtho.spotube.core.jam.JamRole import dev.krtirtho.spotube.core.navigation.NavigationCommands import dev.krtirtho.spotube.core.ui.component.ApplicationMainBar +import dev.krtirtho.spotube.modules.shell.LocalAppShellBottomInset import org.koin.compose.viewmodel.koinViewModel @Composable @@ -61,6 +62,7 @@ fun JamScreen( ) { val viewModel = koinViewModel() val state by viewModel.uiState.collectAsStateWithLifecycle() + val shellBottomInset = LocalAppShellBottomInset.current Scaffold( topBar = { @@ -75,6 +77,7 @@ fun JamScreen( .fillMaxSize() .padding(innerPadding) .padding(16.dp) + .padding(bottom = shellBottomInset) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(16.dp), ) { diff --git a/composeApp/src/commonMain/rust/webrtc_p2p.rs b/composeApp/src/commonMain/rust/webrtc_p2p.rs index ba3ed9d9..3b60d756 100644 --- a/composeApp/src/commonMain/rust/webrtc_p2p.rs +++ b/composeApp/src/commonMain/rust/webrtc_p2p.rs @@ -16,9 +16,12 @@ */ use std::sync::Arc; +use std::time::Duration; use parking_lot::Mutex; +use rtc::ice::mdns::MulticastDnsMode; use rtc::peer_connection::configuration::interceptor_registry::register_default_interceptors; +use rtc::peer_connection::configuration::setting_engine::SettingEngine; use webrtc::data_channel::{DataChannel, DataChannelEvent, RTCDataChannelInit}; use webrtc::peer_connection::{ MediaEngine, PeerConnection, PeerConnectionBuilder, PeerConnectionEventHandler, @@ -111,6 +114,13 @@ pub async fn create_webrtc_peer_connection( ) .build(); + // mDNS adds a multicast UDP socket per peer connection. On some platforms + // (notably Android) that socket can stall and ICE gathering then never + // completes. Real-IP host candidates (no mDNS) work fine alongside STUN/TURN, + // so mDNS is disabled. + let mut setting_engine = SettingEngine::default(); + setting_engine.set_multicast_dns_mode(MulticastDnsMode::Disabled); + let (gather_tx, gather_rx) = channel::<()>(1); let pc_handler = Arc::new(PeerHandlerBridge { handler: Arc::clone(&handler), @@ -119,6 +129,7 @@ pub async fn create_webrtc_peer_connection( let pc = PeerConnectionBuilder::new() .with_configuration(config) + .with_setting_engine(setting_engine) .with_media_engine(media_engine) .with_interceptor_registry(registry) .with_handler(pc_handler) @@ -138,9 +149,20 @@ impl WebrtcPeerConnection { /// Waits for ICE gathering to reach `Complete` so the local SDP includes all /// candidates (non-trickle exchange). Must be called after `set_local_description`, /// which is what starts gathering. + /// + /// Bounded by a timeout so a stalled gatherer (e.g. a platform that never reports + /// completion) can never hang `create_offer`/`create_answer` forever — the SDP + /// with the candidates gathered so far is returned instead. async fn wait_for_ice_gathering(&self) { let mut gather_rx = self.gather_rx.lock().clone(); - let _ = gather_rx.recv().await; + match tokio::time::timeout(Duration::from_secs(5), gather_rx.recv()).await { + Ok(_) => {} + Err(_) => { + log::warn!( + "ICE gathering did not complete within 5s; returning SDP with the candidates gathered so far" + ); + } + } } }