cheogram-www

created pr with cheogram-www/xmpp-proxy.1 on 2026-11-03T05:59:15Z · by 9e834e0d
commented on 2026-11-09T15:39:12Z · by 3c31bc8c
lgtm
cmds
checkout latest patchset:
ssh pr.pico.sh pull cheogram-www:xmpp-proxy | git am -3
checkout specific patchset revision:
ssh pr.pico.sh pull cheogram-www:xmpp-proxy [rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh cheogram-www:xmpp-proxy
add comment to patch request:
ssh pr.pico.sh comment cheogram-www:xmpp-proxy "lgtm!"

Patchset cheogram-www/xmpp-proxy.1 on 2026-11-03T05:59:15Z · commit 7cc03ca

Use xmpp-proxy as an xmpp.js Connection backend
Stephen Paul Weber 2026-11-03T05:57:12Z
Instead of doing any networking from JS land, do it in Rust lang with
xmpp-proxy, and just shuttle the stanzas back and forth using invokes
and a binary Channel.

This allows connecting using standard STARTTLS as well as exotic things
like WebTransport.
Semantic diff summary
26 added, 4 modified, 0 signature changed, 0 removed across 6 analyzed files (2 files skipped: unsupported file type)
+848 -34 src-tauri/Cargo.lock #
......@@ -88,6 +88,18 @@ dependencies = [
8888 "pin-project-lite",
8989 ]
9090
91+[[package]]
92+name = "async-compression"
93+version = "0.4.52"
94+source = "registry+https://github.com/rust-lang/crates.io-index"
95+checksum = "6ad47a740fb906fffdd891e8b6d5fde2511600f7bfaebd68939fa08a14999459"
96+dependencies = [
97+ "compression-codecs",
98+ "compression-core",
99+ "pin-project-lite",
100+ "tokio",
101+]
102+
91103 [[package]]
92104 name = "async-executor"
93105 version = "1.14.0"
......@@ -230,6 +242,29 @@ version = "1.5.1"
230242 source = "registry+https://github.com/rust-lang/crates.io-index"
231243 checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
232244
245+[[package]]
246+name = "aws-lc-rs"
247+version = "1.19.0"
248+source = "registry+https://github.com/rust-lang/crates.io-index"
249+checksum = "048006790404103c488e6c5616b3e7e702a71292aadda08e8f7698a9e0d2eb53"
250+dependencies = [
251+ "aws-lc-sys",
252+ "zeroize",
253+]
254+
255+[[package]]
256+name = "aws-lc-sys"
257+version = "0.47.0"
258+source = "registry+https://github.com/rust-lang/crates.io-index"
259+checksum = "8bfbe32ac36b3c428696ce315464181bc4029d689fd58e3f2a4e58c252242f52"
260+dependencies = [
261+ "cc",
262+ "cmake",
263+ "dunce",
264+ "fs_extra",
265+ "pkg-config",
266+]
267+
233268 [[package]]
234269 name = "base64"
235270 version = "0.21.7"
......@@ -441,6 +476,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
441476 checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0"
442477 dependencies = [
443478 "find-msvc-tools",
479+ "jobserver",
480+ "libc",
444481 "shlex",
445482 ]
446483
......@@ -477,10 +514,28 @@ version = "1.0.5"
477514 source = "registry+https://github.com/rust-lang/crates.io-index"
478515 checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
479516
517+[[package]]
518+name = "cfg_aliases"
519+version = "0.2.2"
520+source = "registry+https://github.com/rust-lang/crates.io-index"
521+checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
522+
523+[[package]]
524+name = "chacha20"
525+version = "0.10.2"
526+source = "registry+https://github.com/rust-lang/crates.io-index"
527+checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
528+dependencies = [
529+ "cfg-if",
530+ "cpufeatures 0.3.1",
531+ "rand_core 0.10.1",
532+]
533+
480534 [[package]]
481535 name = "cheogram-www"
482536 version = "0.0.1"
483537 dependencies = [
538+ "anyhow",
484539 "base64 0.22.1",
485540 "hex",
486541 "infer",
......@@ -499,6 +554,7 @@ dependencies = [
499554 "tempfile",
500555 "tokio",
501556 "uuid",
557+ "xmpp-proxy",
502558 ]
503559
504560 [[package]]
......@@ -513,6 +569,15 @@ dependencies = [
513569 "windows-link",
514570 ]
515571
572+[[package]]
573+name = "cmake"
574+version = "0.1.58"
575+source = "registry+https://github.com/rust-lang/crates.io-index"
576+checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
577+dependencies = [
578+ "cc",
579+]
580+
516581 [[package]]
517582 name = "combine"
518583 version = "4.6.9"
......@@ -523,6 +588,23 @@ dependencies = [
523588 "memchr",
524589 ]
525590
591+[[package]]
592+name = "compression-codecs"
593+version = "0.4.47"
594+source = "registry+https://github.com/rust-lang/crates.io-index"
595+checksum = "84f840cff84d10085260e460023934d0af699e71212b09b2a41452e8bd9cda43"
596+dependencies = [
597+ "compression-core",
598+ "flate2",
599+ "memchr",
600+]
601+
602+[[package]]
603+name = "compression-core"
604+version = "0.4.34"
605+source = "registry+https://github.com/rust-lang/crates.io-index"
606+checksum = "2ebdda89edc534bf8d5dd2857562633b6495557e5846552ade994b99ed13c36a"
607+
526608 [[package]]
527609 name = "concurrent-queue"
528610 version = "2.5.0"
......@@ -591,6 +673,15 @@ dependencies = [
591673 "libc",
592674 ]
593675
676+[[package]]
677+name = "cpufeatures"
678+version = "0.3.1"
679+source = "registry+https://github.com/rust-lang/crates.io-index"
680+checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
681+dependencies = [
682+ "libc",
683+]
684+
594685 [[package]]
595686 name = "crc32fast"
596687 version = "1.5.3"
......@@ -600,6 +691,12 @@ dependencies = [
600691 "cfg-if",
601692 ]
602693
694+[[package]]
695+name = "critical-section"
696+version = "1.2.0"
697+source = "registry+https://github.com/rust-lang/crates.io-index"
698+checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
699+
603700 [[package]]
604701 name = "crossbeam-channel"
605702 version = "0.5.17"
......@@ -609,6 +706,15 @@ dependencies = [
609706 "crossbeam-utils",
610707 ]
611708
709+[[package]]
710+name = "crossbeam-epoch"
711+version = "0.9.21"
712+source = "registry+https://github.com/rust-lang/crates.io-index"
713+checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d"
714+dependencies = [
715+ "crossbeam-utils",
716+]
717+
612718 [[package]]
613719 name = "crossbeam-utils"
614720 version = "0.8.23"
......@@ -688,6 +794,12 @@ dependencies = [
688794 "syn 3.0.9",
689795 ]
690796
797+[[package]]
798+name = "data-encoding"
799+version = "2.11.1"
800+source = "registry+https://github.com/rust-lang/crates.io-index"
801+checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
802+
691803 [[package]]
692804 name = "dbus"
693805 version = "0.9.12"
......@@ -760,6 +872,12 @@ dependencies = [
760872 "syn 2.0.119",
761873 ]
762874
875+[[package]]
876+name = "die"
877+version = "0.2.0"
878+source = "registry+https://github.com/rust-lang/crates.io-index"
879+checksum = "f8634d5e6139f7364a4e99bd718b2f511f2f25863146360e70909bc45a016290"
880+
763881 [[package]]
764882 name = "digest"
765883 version = "0.10.7"
......@@ -914,6 +1032,18 @@ version = "1.1.1"
9141032 source = "registry+https://github.com/rust-lang/crates.io-index"
9151033 checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
9161034
1035+[[package]]
1036+name = "enum-as-inner"
1037+version = "0.6.1"
1038+source = "registry+https://github.com/rust-lang/crates.io-index"
1039+checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
1040+dependencies = [
1041+ "heck 0.5.0",
1042+ "proc-macro2",
1043+ "quote",
1044+ "syn 2.0.119",
1045+]
1046+
9171047 [[package]]
9181048 name = "enumflags2"
9191049 version = "0.7.12"
......@@ -992,6 +1122,18 @@ dependencies = [
9921122 "pin-project-lite",
9931123 ]
9941124
1125+[[package]]
1126+name = "fastbloom"
1127+version = "0.17.0"
1128+source = "registry+https://github.com/rust-lang/crates.io-index"
1129+checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8"
1130+dependencies = [
1131+ "foldhash",
1132+ "libm",
1133+ "portable-atomic",
1134+ "siphasher",
1135+]
1136+
9951137 [[package]]
9961138 name = "fastrand"
9971139 version = "2.5.0"
......@@ -1091,6 +1233,27 @@ dependencies = [
10911233 "percent-encoding",
10921234 ]
10931235
1236+[[package]]
1237+name = "fs_extra"
1238+version = "1.3.0"
1239+source = "registry+https://github.com/rust-lang/crates.io-index"
1240+checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
1241+
1242+[[package]]
1243+name = "futures"
1244+version = "0.3.34"
1245+source = "registry+https://github.com/rust-lang/crates.io-index"
1246+checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3"
1247+dependencies = [
1248+ "futures-channel",
1249+ "futures-core",
1250+ "futures-executor",
1251+ "futures-io",
1252+ "futures-sink",
1253+ "futures-task",
1254+ "futures-util",
1255+]
1256+
10941257 [[package]]
10951258 name = "futures-channel"
10961259 version = "0.3.34"
......@@ -1098,6 +1261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
10981261 checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
10991262 dependencies = [
11001263 "futures-core",
1264+ "futures-sink",
11011265 ]
11021266
11031267 [[package]]
......@@ -1165,6 +1329,7 @@ version = "0.3.34"
11651329 source = "registry+https://github.com/rust-lang/crates.io-index"
11661330 checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
11671331 dependencies = [
1332+ "futures-channel",
11681333 "futures-core",
11691334 "futures-io",
11701335 "futures-macro",
......@@ -1284,6 +1449,19 @@ dependencies = [
12841449 "version_check",
12851450 ]
12861451
1452+[[package]]
1453+name = "getrandom"
1454+version = "0.2.17"
1455+source = "registry+https://github.com/rust-lang/crates.io-index"
1456+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
1457+dependencies = [
1458+ "cfg-if",
1459+ "js-sys",
1460+ "libc",
1461+ "wasi",
1462+ "wasm-bindgen",
1463+]
1464+
12871465 [[package]]
12881466 name = "getrandom"
12891467 version = "0.3.4"
......@@ -1303,8 +1481,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
13031481 checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
13041482 dependencies = [
13051483 "cfg-if",
1484+ "js-sys",
13061485 "libc",
13071486 "r-efi 6.0.0",
1487+ "rand_core 0.10.1",
1488+ "wasm-bindgen",
13081489 ]
13091490
13101491 [[package]]
......@@ -1491,6 +1672,55 @@ version = "0.4.3"
14911672 source = "registry+https://github.com/rust-lang/crates.io-index"
14921673 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
14931674
1675+[[package]]
1676+name = "hickory-proto"
1677+version = "0.25.2"
1678+source = "registry+https://github.com/rust-lang/crates.io-index"
1679+checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
1680+dependencies = [
1681+ "async-trait",
1682+ "bitflags 2.13.2",
1683+ "cfg-if",
1684+ "data-encoding",
1685+ "enum-as-inner",
1686+ "futures-channel",
1687+ "futures-io",
1688+ "futures-util",
1689+ "idna",
1690+ "ipnet",
1691+ "once_cell",
1692+ "rand 0.9.5",
1693+ "ring",
1694+ "rustls-pki-types",
1695+ "thiserror 2.0.21",
1696+ "time",
1697+ "tinyvec",
1698+ "tokio",
1699+ "tracing",
1700+ "url",
1701+]
1702+
1703+[[package]]
1704+name = "hickory-resolver"
1705+version = "0.25.2"
1706+source = "registry+https://github.com/rust-lang/crates.io-index"
1707+checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a"
1708+dependencies = [
1709+ "cfg-if",
1710+ "futures-util",
1711+ "hickory-proto",
1712+ "ipconfig",
1713+ "moka",
1714+ "once_cell",
1715+ "parking_lot",
1716+ "rand 0.9.5",
1717+ "resolv-conf",
1718+ "smallvec",
1719+ "thiserror 2.0.21",
1720+ "tokio",
1721+ "tracing",
1722+]
1723+
14941724 [[package]]
14951725 name = "html5ever"
14961726 version = "0.39.0"
......@@ -1560,6 +1790,21 @@ dependencies = [
15601790 "want",
15611791 ]
15621792
1793+[[package]]
1794+name = "hyper-rustls"
1795+version = "0.27.10"
1796+source = "registry+https://github.com/rust-lang/crates.io-index"
1797+checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53"
1798+dependencies = [
1799+ "http",
1800+ "hyper",
1801+ "hyper-util",
1802+ "rustls",
1803+ "tokio",
1804+ "tokio-rustls",
1805+ "tower-service",
1806+]
1807+
15631808 [[package]]
15641809 name = "hyper-util"
15651810 version = "0.1.20"
......@@ -1759,6 +2004,19 @@ dependencies = [
17592004 "cfb",
17602005 ]
17612006
2007+[[package]]
2008+name = "ipconfig"
2009+version = "0.3.4"
2010+source = "registry+https://github.com/rust-lang/crates.io-index"
2011+checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222"
2012+dependencies = [
2013+ "socket2",
2014+ "widestring",
2015+ "windows-registry",
2016+ "windows-result",
2017+ "windows-sys 0.61.2",
2018+]
2019+
17622020 [[package]]
17632021 name = "ipnet"
17642022 version = "2.12.0"
......@@ -1883,6 +2141,36 @@ dependencies = [
18832141 "windows-sys 0.45.0",
18842142 ]
18852143
2144+[[package]]
2145+name = "jni"
2146+version = "0.22.4"
2147+source = "registry+https://github.com/rust-lang/crates.io-index"
2148+checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
2149+dependencies = [
2150+ "cfg-if",
2151+ "combine",
2152+ "jni-macros",
2153+ "jni-sys 0.4.1",
2154+ "log",
2155+ "simd_cesu8",
2156+ "thiserror 2.0.21",
2157+ "walkdir",
2158+ "windows-link",
2159+]
2160+
2161+[[package]]
2162+name = "jni-macros"
2163+version = "0.22.4"
2164+source = "registry+https://github.com/rust-lang/crates.io-index"
2165+checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
2166+dependencies = [
2167+ "proc-macro2",
2168+ "quote",
2169+ "rustc_version",
2170+ "simd_cesu8",
2171+ "syn 2.0.119",
2172+]
2173+
18862174 [[package]]
18872175 name = "jni-sys"
18882176 version = "0.3.1"
......@@ -1911,6 +2199,16 @@ dependencies = [
19112199 "syn 2.0.119",
19122200 ]
19132201
2202+[[package]]
2203+name = "jobserver"
2204+version = "0.1.35"
2205+source = "registry+https://github.com/rust-lang/crates.io-index"
2206+checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
2207+dependencies = [
2208+ "getrandom 0.4.3",
2209+ "libc",
2210+]
2211+
19142212 [[package]]
19152213 name = "js-sys"
19162214 version = "0.3.106"
......@@ -2003,6 +2301,12 @@ dependencies = [
20032301 "winapi",
20042302 ]
20052303
2304+[[package]]
2305+name = "libm"
2306+version = "0.2.16"
2307+source = "registry+https://github.com/rust-lang/crates.io-index"
2308+checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
2309+
20062310 [[package]]
20072311 name = "libredox"
20082312 version = "0.1.25"
......@@ -2039,6 +2343,12 @@ version = "0.4.34"
20392343 source = "registry+https://github.com/rust-lang/crates.io-index"
20402344 checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
20412345
2346+[[package]]
2347+name = "lru-slab"
2348+version = "0.1.3"
2349+source = "registry+https://github.com/rust-lang/crates.io-index"
2350+checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f"
2351+
20422352 [[package]]
20432353 name = "mac-notification-sys"
20442354 version = "0.6.15"
......@@ -2122,6 +2432,23 @@ dependencies = [
21222432 "windows-sys 0.61.2",
21232433 ]
21242434
2435+[[package]]
2436+name = "moka"
2437+version = "0.12.16"
2438+source = "registry+https://github.com/rust-lang/crates.io-index"
2439+checksum = "4293f18e7567a1caf3c584855554377025c65e0aa445344d04171f5ad63d19b9"
2440+dependencies = [
2441+ "crossbeam-channel",
2442+ "crossbeam-epoch",
2443+ "crossbeam-utils",
2444+ "equivalent",
2445+ "parking_lot",
2446+ "portable-atomic",
2447+ "smallvec",
2448+ "tagptr",
2449+ "uuid",
2450+]
2451+
21252452 [[package]]
21262453 name = "muda"
21272454 version = "0.20.0"
......@@ -2440,6 +2767,10 @@ name = "once_cell"
24402767 version = "1.21.4"
24412768 source = "registry+https://github.com/rust-lang/crates.io-index"
24422769 checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
2770+dependencies = [
2771+ "critical-section",
2772+ "portable-atomic",
2773+]
24432774
24442775 [[package]]
24452776 name = "open"
......@@ -2452,6 +2783,12 @@ dependencies = [
24522783 "libc",
24532784 ]
24542785
2786+[[package]]
2787+name = "openssl-probe"
2788+version = "0.2.2"
2789+source = "registry+https://github.com/rust-lang/crates.io-index"
2790+checksum = "7e036b411754132fd6b74e94b74e9a13c5cf606fa93d1885c35860d3060820b1"
2791+
24552792 [[package]]
24562793 name = "option-ext"
24572794 version = "0.2.0"
......@@ -2760,34 +3097,103 @@ dependencies = [
27603097 ]
27613098
27623099 [[package]]
2763-name = "quote"
2764-version = "1.0.47"
3100+name = "quinn"
3101+version = "0.11.12"
27653102 source = "registry+https://github.com/rust-lang/crates.io-index"
2766-checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
3103+checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11"
27673104 dependencies = [
2768- "proc-macro2",
3105+ "bytes",
3106+ "cfg_aliases",
3107+ "pin-project-lite",
3108+ "quinn-proto",
3109+ "quinn-udp",
3110+ "rustc-hash",
3111+ "rustls",
3112+ "socket2",
3113+ "thiserror 2.0.21",
3114+ "tokio",
3115+ "tracing",
3116+ "web-time",
27693117 ]
27703118
27713119 [[package]]
2772-name = "r-efi"
2773-version = "5.3.0"
2774-source = "registry+https://github.com/rust-lang/crates.io-index"
2775-checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
2776-
2777-[[package]]
2778-name = "r-efi"
2779-version = "6.0.0"
3120+name = "quinn-proto"
3121+version = "0.11.19"
27803122 source = "registry+https://github.com/rust-lang/crates.io-index"
2781-checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
2782-
2783-[[package]]
2784-name = "rand"
3123+checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe"
3124+dependencies = [
3125+ "bytes",
3126+ "fastbloom",
3127+ "getrandom 0.4.3",
3128+ "lru-slab",
3129+ "rand 0.10.3",
3130+ "rand_pcg",
3131+ "ring",
3132+ "rustc-hash",
3133+ "rustls",
3134+ "rustls-pki-types",
3135+ "rustls-platform-verifier",
3136+ "slab",
3137+ "thiserror 2.0.21",
3138+ "tinyvec",
3139+ "tracing",
3140+ "web-time",
3141+]
3142+
3143+[[package]]
3144+name = "quinn-udp"
3145+version = "0.5.16"
3146+source = "registry+https://github.com/rust-lang/crates.io-index"
3147+checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016"
3148+dependencies = [
3149+ "cfg_aliases",
3150+ "libc",
3151+ "once_cell",
3152+ "socket2",
3153+ "tracing",
3154+ "windows-sys 0.61.2",
3155+]
3156+
3157+[[package]]
3158+name = "quote"
3159+version = "1.0.47"
3160+source = "registry+https://github.com/rust-lang/crates.io-index"
3161+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
3162+dependencies = [
3163+ "proc-macro2",
3164+]
3165+
3166+[[package]]
3167+name = "r-efi"
3168+version = "5.3.0"
3169+source = "registry+https://github.com/rust-lang/crates.io-index"
3170+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
3171+
3172+[[package]]
3173+name = "r-efi"
3174+version = "6.0.0"
3175+source = "registry+https://github.com/rust-lang/crates.io-index"
3176+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
3177+
3178+[[package]]
3179+name = "rand"
27853180 version = "0.9.5"
27863181 source = "registry+https://github.com/rust-lang/crates.io-index"
27873182 checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
27883183 dependencies = [
27893184 "rand_chacha",
2790- "rand_core",
3185+ "rand_core 0.9.5",
3186+]
3187+
3188+[[package]]
3189+name = "rand"
3190+version = "0.10.3"
3191+source = "registry+https://github.com/rust-lang/crates.io-index"
3192+checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
3193+dependencies = [
3194+ "chacha20",
3195+ "getrandom 0.4.3",
3196+ "rand_core 0.10.1",
27913197 ]
27923198
27933199 [[package]]
......@@ -2797,7 +3203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
27973203 checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
27983204 dependencies = [
27993205 "ppv-lite86",
2800- "rand_core",
3206+ "rand_core 0.9.5",
28013207 ]
28023208
28033209 [[package]]
......@@ -2809,6 +3215,21 @@ dependencies = [
28093215 "getrandom 0.3.4",
28103216 ]
28113217
3218+[[package]]
3219+name = "rand_core"
3220+version = "0.10.1"
3221+source = "registry+https://github.com/rust-lang/crates.io-index"
3222+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
3223+
3224+[[package]]
3225+name = "rand_pcg"
3226+version = "0.10.2"
3227+source = "registry+https://github.com/rust-lang/crates.io-index"
3228+checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
3229+dependencies = [
3230+ "rand_core 0.10.1",
3231+]
3232+
28123233 [[package]]
28133234 name = "raw-window-handle"
28143235 version = "0.6.2"
......@@ -2897,15 +3318,20 @@ dependencies = [
28973318 "http-body",
28983319 "http-body-util",
28993320 "hyper",
3321+ "hyper-rustls",
29003322 "hyper-util",
29013323 "js-sys",
29023324 "log",
29033325 "percent-encoding",
29043326 "pin-project-lite",
3327+ "rustls",
3328+ "rustls-pki-types",
3329+ "rustls-platform-verifier",
29053330 "serde",
29063331 "serde_json",
29073332 "sync_wrapper",
29083333 "tokio",
3334+ "tokio-rustls",
29093335 "tokio-util",
29103336 "tower",
29113337 "tower-http",
......@@ -2917,6 +3343,26 @@ dependencies = [
29173343 "web-sys",
29183344 ]
29193345
3346+[[package]]
3347+name = "resolv-conf"
3348+version = "0.7.6"
3349+source = "registry+https://github.com/rust-lang/crates.io-index"
3350+checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7"
3351+
3352+[[package]]
3353+name = "ring"
3354+version = "0.17.14"
3355+source = "registry+https://github.com/rust-lang/crates.io-index"
3356+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
3357+dependencies = [
3358+ "cc",
3359+ "cfg-if",
3360+ "getrandom 0.2.17",
3361+ "libc",
3362+ "untrusted",
3363+ "windows-sys 0.52.0",
3364+]
3365+
29203366 [[package]]
29213367 name = "rustc-hash"
29223368 version = "2.1.3"
......@@ -2945,6 +3391,83 @@ dependencies = [
29453391 "windows-sys 0.61.2",
29463392 ]
29473393
3394+[[package]]
3395+name = "rustls"
3396+version = "0.23.46"
3397+source = "registry+https://github.com/rust-lang/crates.io-index"
3398+checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
3399+dependencies = [
3400+ "aws-lc-rs",
3401+ "log",
3402+ "once_cell",
3403+ "ring",
3404+ "rustls-pki-types",
3405+ "rustls-webpki",
3406+ "subtle",
3407+ "zeroize",
3408+]
3409+
3410+[[package]]
3411+name = "rustls-native-certs"
3412+version = "0.8.5"
3413+source = "registry+https://github.com/rust-lang/crates.io-index"
3414+checksum = "4a073f5dc7469f984c52ad2752b63b0807745133b6de880b7b64c1ac4c48aec4"
3415+dependencies = [
3416+ "openssl-probe",
3417+ "rustls-pki-types",
3418+ "schannel",
3419+ "security-framework",
3420+]
3421+
3422+[[package]]
3423+name = "rustls-pki-types"
3424+version = "1.15.1"
3425+source = "registry+https://github.com/rust-lang/crates.io-index"
3426+checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
3427+dependencies = [
3428+ "web-time",
3429+ "zeroize",
3430+]
3431+
3432+[[package]]
3433+name = "rustls-platform-verifier"
3434+version = "0.7.1"
3435+source = "registry+https://github.com/rust-lang/crates.io-index"
3436+checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98"
3437+dependencies = [
3438+ "core-foundation",
3439+ "core-foundation-sys",
3440+ "jni 0.22.4",
3441+ "log",
3442+ "once_cell",
3443+ "rustls",
3444+ "rustls-native-certs",
3445+ "rustls-platform-verifier-android",
3446+ "rustls-webpki",
3447+ "security-framework",
3448+ "security-framework-sys",
3449+ "webpki-root-certs",
3450+ "windows-sys 0.61.2",
3451+]
3452+
3453+[[package]]
3454+name = "rustls-platform-verifier-android"
3455+version = "0.2.0"
3456+source = "registry+https://github.com/rust-lang/crates.io-index"
3457+checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
3458+
3459+[[package]]
3460+name = "rustls-webpki"
3461+version = "0.103.16"
3462+source = "registry+https://github.com/rust-lang/crates.io-index"
3463+checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
3464+dependencies = [
3465+ "aws-lc-rs",
3466+ "ring",
3467+ "rustls-pki-types",
3468+ "untrusted",
3469+]
3470+
29483471 [[package]]
29493472 name = "rustversion"
29503473 version = "1.0.23"
......@@ -2969,6 +3492,15 @@ dependencies = [
29693492 "regex",
29703493 ]
29713494
3495+[[package]]
3496+name = "schannel"
3497+version = "0.1.30"
3498+source = "registry+https://github.com/rust-lang/crates.io-index"
3499+checksum = "9cb23c424d8ee841bb4d813677ca237e2a610067d594fec130f87d6093495ab5"
3500+dependencies = [
3501+ "windows-sys 0.61.2",
3502+]
3503+
29723504 [[package]]
29733505 name = "schemars"
29743506 version = "0.8.22"
......@@ -3026,6 +3558,29 @@ version = "1.2.0"
30263558 source = "registry+https://github.com/rust-lang/crates.io-index"
30273559 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
30283560
3561+[[package]]
3562+name = "security-framework"
3563+version = "3.7.0"
3564+source = "registry+https://github.com/rust-lang/crates.io-index"
3565+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
3566+dependencies = [
3567+ "bitflags 2.13.2",
3568+ "core-foundation",
3569+ "core-foundation-sys",
3570+ "libc",
3571+ "security-framework-sys",
3572+]
3573+
3574+[[package]]
3575+name = "security-framework-sys"
3576+version = "2.17.0"
3577+source = "registry+https://github.com/rust-lang/crates.io-index"
3578+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
3579+dependencies = [
3580+ "core-foundation-sys",
3581+ "libc",
3582+]
3583+
30293584 [[package]]
30303585 name = "selectors"
30313586 version = "0.38.0"
......@@ -3221,7 +3776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
32213776 checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
32223777 dependencies = [
32233778 "cfg-if",
3224- "cpufeatures",
3779+ "cpufeatures 0.2.17",
32253780 "digest",
32263781 ]
32273782
......@@ -3232,7 +3787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
32323787 checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
32333788 dependencies = [
32343789 "cfg-if",
3235- "cpufeatures",
3790+ "cpufeatures 0.2.17",
32363791 "digest",
32373792 ]
32383793
......@@ -3258,6 +3813,22 @@ version = "0.3.10"
32583813 source = "registry+https://github.com/rust-lang/crates.io-index"
32593814 checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
32603815
3816+[[package]]
3817+name = "simd_cesu8"
3818+version = "1.2.0"
3819+source = "registry+https://github.com/rust-lang/crates.io-index"
3820+checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
3821+dependencies = [
3822+ "rustc_version",
3823+ "simdutf8",
3824+]
3825+
3826+[[package]]
3827+name = "simdutf8"
3828+version = "0.1.5"
3829+source = "registry+https://github.com/rust-lang/crates.io-index"
3830+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
3831+
32613832 [[package]]
32623833 name = "siphasher"
32633834 version = "1.0.4"
......@@ -3376,6 +3947,12 @@ version = "0.11.1"
33763947 source = "registry+https://github.com/rust-lang/crates.io-index"
33773948 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
33783949
3950+[[package]]
3951+name = "subtle"
3952+version = "2.6.1"
3953+source = "registry+https://github.com/rust-lang/crates.io-index"
3954+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
3955+
33793956 [[package]]
33803957 name = "swift-rs"
33813958 version = "1.0.9"
......@@ -3452,6 +4029,12 @@ dependencies = [
34524029 "version-compare",
34534030 ]
34544031
4032+[[package]]
4033+name = "tagptr"
4034+version = "0.2.0"
4035+source = "registry+https://github.com/rust-lang/crates.io-index"
4036+checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
4037+
34554038 [[package]]
34564039 name = "tao"
34574040 version = "0.37.2"
......@@ -3470,7 +4053,7 @@ dependencies = [
34704053 "gdkwayland-sys",
34714054 "gdkx11-sys",
34724055 "gtk",
3473- "jni",
4056+ "jni 0.21.1",
34744057 "libc",
34754058 "log",
34764059 "ndk",
......@@ -3526,7 +4109,7 @@ dependencies = [
35264109 "gtk",
35274110 "heck 0.5.0",
35284111 "http",
3529- "jni",
4112+ "jni 0.21.1",
35304113 "libc",
35314114 "log",
35324115 "mime",
......@@ -3669,7 +4252,7 @@ checksum = "b939d7b19c8af1381a72ef8474b3aba2b56c1ddac2c23f0c8e96abbcf86b198b"
36694252 dependencies = [
36704253 "log",
36714254 "notify-rust",
3672- "rand",
4255+ "rand 0.9.5",
36734256 "serde",
36744257 "serde_json",
36754258 "serde_repr",
......@@ -3712,7 +4295,7 @@ dependencies = [
37124295 "dpi",
37134296 "gtk",
37144297 "http",
3715- "jni",
4298+ "jni 0.21.1",
37164299 "objc2",
37174300 "objc2-ui-kit",
37184301 "objc2-web-kit",
......@@ -3735,7 +4318,7 @@ checksum = "e1aa9d8b7a120f879f44fdc1053f7b7dbf416bf0bbc6a72b714dec46b782b52f"
37354318 dependencies = [
37364319 "gtk",
37374320 "http",
3738- "jni",
4321+ "jni 0.21.1",
37394322 "log",
37404323 "objc2",
37414324 "objc2-app-kit",
......@@ -3932,10 +4515,33 @@ dependencies = [
39324515 "libc",
39334516 "mio",
39344517 "pin-project-lite",
4518+ "signal-hook-registry",
39354519 "socket2",
4520+ "tokio-macros",
39364521 "windows-sys 0.61.2",
39374522 ]
39384523
4524+[[package]]
4525+name = "tokio-macros"
4526+version = "2.7.2"
4527+source = "registry+https://github.com/rust-lang/crates.io-index"
4528+checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
4529+dependencies = [
4530+ "proc-macro2",
4531+ "quote",
4532+ "syn 3.0.9",
4533+]
4534+
4535+[[package]]
4536+name = "tokio-rustls"
4537+version = "0.26.6"
4538+source = "registry+https://github.com/rust-lang/crates.io-index"
4539+checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db"
4540+dependencies = [
4541+ "rustls",
4542+ "tokio",
4543+]
4544+
39394545 [[package]]
39404546 name = "tokio-util"
39414547 version = "0.7.18"
......@@ -3961,6 +4567,21 @@ dependencies = [
39614567 "toml_edit 0.22.27",
39624568 ]
39634569
4570+[[package]]
4571+name = "toml"
4572+version = "0.9.12+spec-1.1.0"
4573+source = "registry+https://github.com/rust-lang/crates.io-index"
4574+checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
4575+dependencies = [
4576+ "indexmap 2.14.2",
4577+ "serde_core",
4578+ "serde_spanned 1.1.2",
4579+ "toml_datetime 0.7.5+spec-1.1.0",
4580+ "toml_parser",
4581+ "toml_writer",
4582+ "winnow 0.7.15",
4583+]
4584+
39644585 [[package]]
39654586 name = "toml"
39664587 version = "1.1.8+spec-1.1.0"
......@@ -3985,6 +4606,15 @@ dependencies = [
39854606 "serde",
39864607 ]
39874608
4609+[[package]]
4610+name = "toml_datetime"
4611+version = "0.7.5+spec-1.1.0"
4612+source = "registry+https://github.com/rust-lang/crates.io-index"
4613+checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
4614+dependencies = [
4615+ "serde_core",
4616+]
4617+
39884618 [[package]]
39894619 name = "toml_datetime"
39904620 version = "1.1.2+spec-1.1.0"
......@@ -4077,12 +4707,17 @@ version = "0.6.11"
40774707 source = "registry+https://github.com/rust-lang/crates.io-index"
40784708 checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
40794709 dependencies = [
4710+ "async-compression",
40804711 "bitflags 2.13.2",
40814712 "bytes",
4713+ "futures-core",
40824714 "futures-util",
40834715 "http",
40844716 "http-body",
4717+ "http-body-util",
40854718 "pin-project-lite",
4719+ "tokio",
4720+ "tokio-util",
40864721 "tower",
40874722 "tower-layer",
40884723 "tower-service",
......@@ -4195,6 +4830,12 @@ version = "1.13.3"
41954830 source = "registry+https://github.com/rust-lang/crates.io-index"
41964831 checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
41974832
4833+[[package]]
4834+name = "untrusted"
4835+version = "0.9.0"
4836+source = "registry+https://github.com/rust-lang/crates.io-index"
4837+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
4838+
41984839 [[package]]
41994840 name = "url"
42004841 version = "2.5.8"
......@@ -4393,6 +5034,48 @@ dependencies = [
43935034 "wasm-bindgen",
43945035 ]
43955036
5037+[[package]]
5038+name = "web-transport-proto"
5039+version = "0.3.1"
5040+source = "registry+https://github.com/rust-lang/crates.io-index"
5041+checksum = "660175a6d1643adb93b71c4f853d4f20f0fce47f53ae579afe9f7711fe84870d"
5042+dependencies = [
5043+ "bytes",
5044+ "http",
5045+ "thiserror 2.0.21",
5046+ "tokio",
5047+ "url",
5048+]
5049+
5050+[[package]]
5051+name = "web-transport-quinn"
5052+version = "0.10.2"
5053+source = "registry+https://github.com/rust-lang/crates.io-index"
5054+checksum = "b1f44b4e68a3e7adb790793e24ec8b5923a610a8c2df1d6cd58849f9e4759d04"
5055+dependencies = [
5056+ "bytes",
5057+ "futures",
5058+ "http",
5059+ "quinn",
5060+ "rustls",
5061+ "rustls-native-certs",
5062+ "thiserror 2.0.21",
5063+ "tokio",
5064+ "tracing",
5065+ "url",
5066+ "web-transport-proto",
5067+ "web-transport-trait",
5068+]
5069+
5070+[[package]]
5071+name = "web-transport-trait"
5072+version = "0.3.7"
5073+source = "registry+https://github.com/rust-lang/crates.io-index"
5074+checksum = "6394e09415ddc1e7c88d605443a3d2f333bf278f74c17020a2b6c44e97507883"
5075+dependencies = [
5076+ "bytes",
5077+]
5078+
43965079 [[package]]
43975080 name = "web_atoms"
43985081 version = "0.2.6"
......@@ -4449,6 +5132,15 @@ dependencies = [
44495132 "system-deps",
44505133 ]
44515134
5135+[[package]]
5136+name = "webpki-root-certs"
5137+version = "1.0.11"
5138+source = "registry+https://github.com/rust-lang/crates.io-index"
5139+checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a"
5140+dependencies = [
5141+ "rustls-pki-types",
5142+]
5143+
44525144 [[package]]
44535145 name = "webview2-com"
44545146 version = "0.39.1"
......@@ -4483,6 +5175,12 @@ dependencies = [
44835175 "windows-core",
44845176 ]
44855177
5178+[[package]]
5179+name = "widestring"
5180+version = "1.2.1"
5181+source = "registry+https://github.com/rust-lang/crates.io-index"
5182+checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
5183+
44865184 [[package]]
44875185 name = "winapi"
44885186 version = "0.3.9"
......@@ -4613,6 +5311,17 @@ dependencies = [
46135311 "windows-link",
46145312 ]
46155313
5314+[[package]]
5315+name = "windows-registry"
5316+version = "0.6.1"
5317+source = "registry+https://github.com/rust-lang/crates.io-index"
5318+checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
5319+dependencies = [
5320+ "windows-link",
5321+ "windows-result",
5322+ "windows-strings",
5323+]
5324+
46165325 [[package]]
46175326 name = "windows-result"
46185327 version = "0.4.1"
......@@ -4637,7 +5346,16 @@ version = "0.45.0"
46375346 source = "registry+https://github.com/rust-lang/crates.io-index"
46385347 checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
46395348 dependencies = [
4640- "windows-targets",
5349+ "windows-targets 0.42.2",
5350+]
5351+
5352+[[package]]
5353+name = "windows-sys"
5354+version = "0.52.0"
5355+source = "registry+https://github.com/rust-lang/crates.io-index"
5356+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
5357+dependencies = [
5358+ "windows-targets 0.52.6",
46415359 ]
46425360
46435361 [[package]]
......@@ -4655,13 +5373,29 @@ version = "0.42.2"
46555373 source = "registry+https://github.com/rust-lang/crates.io-index"
46565374 checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
46575375 dependencies = [
4658- "windows_aarch64_gnullvm",
4659- "windows_aarch64_msvc",
4660- "windows_i686_gnu",
4661- "windows_i686_msvc",
4662- "windows_x86_64_gnu",
4663- "windows_x86_64_gnullvm",
4664- "windows_x86_64_msvc",
5376+ "windows_aarch64_gnullvm 0.42.2",
5377+ "windows_aarch64_msvc 0.42.2",
5378+ "windows_i686_gnu 0.42.2",
5379+ "windows_i686_msvc 0.42.2",
5380+ "windows_x86_64_gnu 0.42.2",
5381+ "windows_x86_64_gnullvm 0.42.2",
5382+ "windows_x86_64_msvc 0.42.2",
5383+]
5384+
5385+[[package]]
5386+name = "windows-targets"
5387+version = "0.52.6"
5388+source = "registry+https://github.com/rust-lang/crates.io-index"
5389+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
5390+dependencies = [
5391+ "windows_aarch64_gnullvm 0.52.6",
5392+ "windows_aarch64_msvc 0.52.6",
5393+ "windows_i686_gnu 0.52.6",
5394+ "windows_i686_gnullvm",
5395+ "windows_i686_msvc 0.52.6",
5396+ "windows_x86_64_gnu 0.52.6",
5397+ "windows_x86_64_gnullvm 0.52.6",
5398+ "windows_x86_64_msvc 0.52.6",
46655399 ]
46665400
46675401 [[package]]
......@@ -4688,42 +5422,90 @@ version = "0.42.2"
46885422 source = "registry+https://github.com/rust-lang/crates.io-index"
46895423 checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
46905424
5425+[[package]]
5426+name = "windows_aarch64_gnullvm"
5427+version = "0.52.6"
5428+source = "registry+https://github.com/rust-lang/crates.io-index"
5429+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
5430+
46915431 [[package]]
46925432 name = "windows_aarch64_msvc"
46935433 version = "0.42.2"
46945434 source = "registry+https://github.com/rust-lang/crates.io-index"
46955435 checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
46965436
5437+[[package]]
5438+name = "windows_aarch64_msvc"
5439+version = "0.52.6"
5440+source = "registry+https://github.com/rust-lang/crates.io-index"
5441+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
5442+
46975443 [[package]]
46985444 name = "windows_i686_gnu"
46995445 version = "0.42.2"
47005446 source = "registry+https://github.com/rust-lang/crates.io-index"
47015447 checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
47025448
5449+[[package]]
5450+name = "windows_i686_gnu"
5451+version = "0.52.6"
5452+source = "registry+https://github.com/rust-lang/crates.io-index"
5453+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
5454+
5455+[[package]]
5456+name = "windows_i686_gnullvm"
5457+version = "0.52.6"
5458+source = "registry+https://github.com/rust-lang/crates.io-index"
5459+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
5460+
47035461 [[package]]
47045462 name = "windows_i686_msvc"
47055463 version = "0.42.2"
47065464 source = "registry+https://github.com/rust-lang/crates.io-index"
47075465 checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
47085466
5467+[[package]]
5468+name = "windows_i686_msvc"
5469+version = "0.52.6"
5470+source = "registry+https://github.com/rust-lang/crates.io-index"
5471+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
5472+
47095473 [[package]]
47105474 name = "windows_x86_64_gnu"
47115475 version = "0.42.2"
47125476 source = "registry+https://github.com/rust-lang/crates.io-index"
47135477 checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
47145478
5479+[[package]]
5480+name = "windows_x86_64_gnu"
5481+version = "0.52.6"
5482+source = "registry+https://github.com/rust-lang/crates.io-index"
5483+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
5484+
47155485 [[package]]
47165486 name = "windows_x86_64_gnullvm"
47175487 version = "0.42.2"
47185488 source = "registry+https://github.com/rust-lang/crates.io-index"
47195489 checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
47205490
5491+[[package]]
5492+name = "windows_x86_64_gnullvm"
5493+version = "0.52.6"
5494+source = "registry+https://github.com/rust-lang/crates.io-index"
5495+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
5496+
47215497 [[package]]
47225498 name = "windows_x86_64_msvc"
47235499 version = "0.42.2"
47245500 source = "registry+https://github.com/rust-lang/crates.io-index"
47255501 checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
47265502
5503+[[package]]
5504+name = "windows_x86_64_msvc"
5505+version = "0.52.6"
5506+source = "registry+https://github.com/rust-lang/crates.io-index"
5507+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
5508+
47275509 [[package]]
47285510 name = "winnow"
47295511 version = "0.5.40"
......@@ -4791,7 +5573,7 @@ dependencies = [
47915573 "gtk",
47925574 "http",
47935575 "javascriptcore-rs",
4794- "jni",
5576+ "jni 0.21.1",
47955577 "libc",
47965578 "ndk",
47975579 "objc2",
......@@ -4837,6 +5619,32 @@ dependencies = [
48375619 "pkg-config",
48385620 ]
48395621
5622+[[package]]
5623+name = "xmpp-proxy"
5624+version = "1.1.0"
5625+source = "git+https://github.com/moparisthebest/xmpp-proxy.git?branch=master#af04d64c00c1f7d971b3a8e9405ea5cf55ddb002"
5626+dependencies = [
5627+ "anyhow",
5628+ "async-trait",
5629+ "data-encoding",
5630+ "die",
5631+ "futures",
5632+ "hickory-resolver",
5633+ "log",
5634+ "pin-project-lite",
5635+ "quinn",
5636+ "reqwest",
5637+ "ring",
5638+ "rustls",
5639+ "rustls-native-certs",
5640+ "rustls-webpki",
5641+ "serde",
5642+ "tokio",
5643+ "tokio-rustls",
5644+ "toml 0.9.12+spec-1.1.0",
5645+ "web-transport-quinn",
5646+]
5647+
48405648 [[package]]
48415649 name = "yoke"
48425650 version = "0.8.4"
......@@ -4971,6 +5779,12 @@ dependencies = [
49715779 "synstructure",
49725780 ]
49735781
5782+[[package]]
5783+name = "zeroize"
5784+version = "1.9.1"
5785+source = "registry+https://github.com/rust-lang/crates.io-index"
5786+checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879"
5787+
49745788 [[package]]
49755789 name = "zerotrie"
49765790 version = "0.2.5"
+4 -1 src-tauri/Cargo.toml #
......@@ -26,7 +26,7 @@ tauri-plugin-opener = { git = "https://github.com/tauri-apps/plugins-workspace",
2626 base64 = "0.22"
2727 hex = "0.4.3"
2828 mime2ext = "0.1.54"
29-tokio = { version = "1", features = ["time"] }
29+tokio = { version = "1", features = ["time", "io-util", "rt", "sync"] }
3030 sha1 = "0.10"
3131 sha2 = "0.10"
3232 uuid = { version = "1", features = ["v4"] }
......@@ -36,5 +36,8 @@ tempfile = "3.27.0"
3636
3737 sanitize-filename = "0.6"
3838
39+anyhow = "1"
40+xmpp-proxy = { git = "https://github.com/moparisthebest/xmpp-proxy.git", branch = "master", default-features = false, features = ["c2s-outgoing", "tls", "webtransport", "tls-ca-roots-native", "tls-ring"] }
41+
3942 [patch.crates-io]
4043 notify-rust = { git = "https://github.com/hoodie/notify-rust", branch = "main" }
+8 -1 src-tauri/src/lib.rs #
......@@ -1,18 +1,25 @@
11 mod media;
2+mod xmpp;
23
34 use tauri::Manager;
5+use xmpp::{XmppState, xmpp_disconnect, xmpp_open, xmpp_write};
46
57 #[cfg_attr(mobile, tauri::mobile_entry_point)]
68 pub fn run() {
9+ xmpp_proxy::install_default_rustls_provider().expect("invalid crypto provider");
710 tauri::Builder::default()
811 .plugin(tauri_plugin_opener::init())
912 .plugin(tauri_plugin_notification::init())
13+ .manage(XmppState::default())
1014 .invoke_handler(tauri::generate_handler![
1115 media::begin_media,
1216 media::write_media,
1317 media::finish_media,
1418 media::has_media,
15- media::remove_media
19+ media::remove_media,
20+ xmpp_open,
21+ xmpp_write,
22+ xmpp_disconnect,
1623 ])
1724 .register_asynchronous_uri_scheme_protocol("tauri", media::protocol)
1825 .setup(|app| {
+203 -0 src-tauri/src/xmpp.rs #
......@@ -0,0 +1,203 @@
1+use std::collections::HashMap;
2+use std::sync::Arc;
3+use std::sync::atomic::{AtomicU64, Ordering};
4+
5+use anyhow::anyhow;
6+use tauri::ipc::{Channel, InvokeResponseBody};
7+use tokio::sync::Mutex;
8+use xmpp_proxy::common::certs_key::CertsKey;
9+use xmpp_proxy::common::outgoing::OutgoingConfig;
10+use xmpp_proxy::context::Context;
11+use xmpp_proxy::in_out::{StanzaRead, StanzaWrite};
12+use xmpp_proxy::srv::srv_connect;
13+use xmpp_proxy::stanzafilter::StanzaFilter;
14+
15+const MAX_STANZA_SIZE_BYTES: usize = 262_144;
16+
17+const FRAME_DATA: u8 = 0;
18+const FRAME_ERROR: u8 = 1;
19+const FRAME_CLOSE: u8 = 2;
20+
21+fn send_frame(
22+ events: &Channel<InvokeResponseBody>,
23+ kind: u8,
24+ payload: &[u8],
25+) -> Result<(), String> {
26+ let mut frame = Vec::with_capacity(payload.len() + 1);
27+ frame.push(kind);
28+ frame.extend_from_slice(payload);
29+ events
30+ .send(InvokeResponseBody::Raw(frame))
31+ .map_err(|e| e.to_string())
32+}
33+
34+fn send_close(events: &Channel<InvokeResponseBody>, clean: bool) -> Result<(), String> {
35+ send_frame(events, FRAME_CLOSE, &[u8::from(clean)])
36+}
37+
38+struct Session {
39+ domain: String,
40+ write: Option<StanzaWrite>,
41+ reader: Option<tauri::async_runtime::JoinHandle<()>>,
42+ events: Channel<InvokeResponseBody>,
43+}
44+
45+#[derive(Default)]
46+pub struct XmppState {
47+ next_id: AtomicU64,
48+ sessions: Mutex<HashMap<u64, Arc<Mutex<Session>>>>,
49+}
50+
51+fn normalize_domain(service: &str) -> String {
52+ let service = service
53+ .strip_prefix("xmpps://")
54+ .or_else(|| service.strip_prefix("xmpp://"))
55+ .or_else(|| service.strip_prefix("xmpp:"))
56+ .unwrap_or(service);
57+
58+ service
59+ .split('/')
60+ .next()
61+ .unwrap_or(service)
62+ .trim_end_matches('.')
63+ .to_string()
64+}
65+
66+async fn session(state: &XmppState, id: u64) -> Result<Arc<Mutex<Session>>, String> {
67+ state
68+ .sessions
69+ .lock()
70+ .await
71+ .get(&id)
72+ .cloned()
73+ .ok_or_else(|| format!("unknown xmpp session {id}"))
74+}
75+
76+#[tauri::command]
77+pub async fn xmpp_open(
78+ state: tauri::State<'_, XmppState>,
79+ service: String,
80+ stream_open: String,
81+ on_event: Channel<InvokeResponseBody>,
82+) -> Result<u64, String> {
83+ let domain = normalize_domain(&service);
84+ if domain.is_empty() {
85+ return Err("empty xmpp domain".into());
86+ }
87+
88+ let id = state.next_id.fetch_add(1, Ordering::Relaxed);
89+ let session = Arc::new(Mutex::new(Session {
90+ domain,
91+ write: None,
92+ reader: None,
93+ events: on_event,
94+ }));
95+ state.sessions.lock().await.insert(id, session.clone());
96+
97+ if let Err(e) = open_session(&session, stream_open).await {
98+ state.sessions.lock().await.remove(&id);
99+ return Err(e);
100+ }
101+
102+ Ok(id)
103+}
104+
105+async fn open_session(session: &Arc<Mutex<Session>>, stream_open: String) -> Result<(), String> {
106+ let mut session = session.lock().await;
107+ let mut filter = StanzaFilter::new(MAX_STANZA_SIZE_BYTES);
108+ let mut ctx = Context::new(
109+ "tauri",
110+ "0.0.0.0:0"
111+ .parse()
112+ .map_err(|e| format!("invalid local address: {e}"))?,
113+ );
114+ ctx.set_c2s_stream_open(true, stream_open.as_bytes());
115+
116+ let config = OutgoingConfig {
117+ max_stanza_size_bytes: MAX_STANZA_SIZE_BYTES,
118+ certs_key: Arc::new(CertsKey::new(Err(anyhow!(
119+ "no client certificate configured"
120+ )))),
121+ };
122+
123+ let (write, read, server_open) = srv_connect(
124+ &session.domain,
125+ true,
126+ stream_open.as_bytes(),
127+ &mut filter,
128+ &mut ctx,
129+ config,
130+ )
131+ .await
132+ .map_err(|e| e.to_string())?;
133+
134+ session.write = Some(write);
135+
136+ send_frame(&session.events, FRAME_DATA, &server_open)?;
137+
138+ let events = session.events.clone();
139+ session.reader = Some(tauri::async_runtime::spawn(read_loop(read, events)));
140+
141+ Ok(())
142+}
143+
144+#[tauri::command]
145+pub async fn xmpp_write(
146+ state: tauri::State<'_, XmppState>,
147+ id: u64,
148+ data: String,
149+) -> Result<(), String> {
150+ let session = session(&state, id).await?;
151+ let mut session = session.lock().await;
152+ let write = session
153+ .write
154+ .as_mut()
155+ .ok_or_else(|| format!("xmpp session {id} is not open"))?;
156+
157+ write
158+ .write_all(true, data.as_bytes(), 0, "tauri")
159+ .await
160+ .map_err(|e| e.to_string())?;
161+ write.flush().await.map_err(|e| e.to_string())
162+}
163+
164+#[tauri::command]
165+pub async fn xmpp_disconnect(state: tauri::State<'_, XmppState>, id: u64) -> Result<(), String> {
166+ let session = state.sessions.lock().await.remove(&id);
167+
168+ if let Some(session) = session {
169+ let mut session = session.lock().await;
170+ if let Some(reader) = session.reader.take() {
171+ reader.abort();
172+ }
173+ session.write = None;
174+ }
175+
176+ Ok(())
177+}
178+
179+async fn read_loop(mut read: StanzaRead, events: Channel<InvokeResponseBody>) {
180+ let mut filter = StanzaFilter::new(MAX_STANZA_SIZE_BYTES);
181+ // Hack to work around the API needing this for websocket
182+ // We don't use websocket so this works
183+ let mut unused_write = StanzaWrite::new(tokio::io::sink());
184+
185+ loop {
186+ match read.next(&mut filter, "tauri", &mut unused_write).await {
187+ Ok(Some((data, _end_of_first_tag))) => {
188+ if send_frame(&events, FRAME_DATA, data).is_err() {
189+ return;
190+ }
191+ }
192+ Ok(None) => {
193+ let _ = send_close(&events, true);
194+ return;
195+ }
196+ Err(e) => {
197+ let _ = send_frame(&events, FRAME_ERROR, e.to_string().as_bytes());
198+ let _ = send_close(&events, false);
199+ return;
200+ }
201+ }
202+ }
203+}
+3 -0 src/components/Login.tsx #
......@@ -4,6 +4,8 @@ import { Link, Navigate, useOutletContext } from "react-router";
44 import { Context } from "../App";
55 import { useEffect, useRef, useState } from "react";
66 import { Alert, CircularProgress } from "@mui/material";
7+import { isTauri } from "@tauri-apps/api/core";
8+import { installTauriXmppTransport } from "../tauri-xmpp";
79
810 const registerPush = (
911 client: borogove.Client,
......@@ -83,6 +85,7 @@ export const newAccount = (
8385 persistence: borogove.Persistence,
8486 ) => {
8587 const client = new borogove.Client(accountId, persistence);
88+ if (isTauri()) installTauriXmppTransport(client);
8689 registerPush(client, idbp);
8790 setTimeout(() => client.start(), 0);
8891
+12 -0 src/tauri-xmpp.test.ts #
......@@ -0,0 +1,12 @@
1+import { describe, expect, it } from "vitest";
2+
3+import { createTauriXmppClient } from "./tauri-xmpp";
4+
5+describe("createTauriXmppClient", () => {
6+ it("uses the Tauri transport without the xmpp.js resolver", () => {
7+ const xmpp = createTauriXmppClient({ service: "example.org" });
8+
9+ expect(xmpp.transports).toHaveLength(1);
10+ expect(xmpp.connect.toString()).not.toContain("fetchURIs");
11+ });
12+});
+178 -0 src/tauri-xmpp.ts #
......@@ -0,0 +1,178 @@
1+import * as borogove from "borogove";
2+import { Channel, invoke } from "@tauri-apps/api/core";
3+import { client as xmppClient } from "@xmpp/client";
4+import { Client as XmppClientCore } from "@xmpp/client-core";
5+import Connection from "@xmpp/connection";
6+import { EventEmitter } from "@xmpp/events";
7+import { Parser } from "@xmpp/xml";
8+
9+const NS_STREAM = "http://etherx.jabber.org/streams";
10+
11+const FRAME_DATA = 0;
12+const FRAME_ERROR = 1;
13+const FRAME_CLOSE = 2;
14+
15+const UTF8 = new TextDecoder("utf-8", { fatal: true });
16+
17+class TauriSocket extends EventEmitter {
18+ secure = true;
19+ id: number | null = null;
20+ closed = false;
21+ service: string | null = null;
22+ events: Channel<ArrayBuffer> | null = null;
23+ opening: Promise<number> | null = null;
24+
25+ async connect(service: string) {
26+ this.service = service;
27+ this.id = null;
28+ this.closed = false;
29+ this.opening = null;
30+
31+ this.events = new Channel<ArrayBuffer>();
32+ this.events.onmessage = (buffer) => {
33+ if (this.closed) return;
34+
35+ const frame = new Uint8Array(buffer);
36+ const kind = frame[0];
37+ const payload = frame.subarray(1);
38+ switch (kind) {
39+ case FRAME_DATA:
40+ this.emit("data", UTF8.decode(payload));
41+ break;
42+ case FRAME_ERROR:
43+ this.emit("error", new Error(UTF8.decode(payload)));
44+ break;
45+ case FRAME_CLOSE:
46+ this.#close(payload[0] === 1);
47+ break;
48+ default:
49+ this.emit("error", new Error(`unknown xmpp frame type ${kind}`));
50+ }
51+ };
52+
53+ // Connection.connect attaches its "connect" listener after this method
54+ // returns, so don't emit synchronously.
55+ await Promise.resolve();
56+ this.emit("connect");
57+ }
58+
59+ write(data: string, fn?: (err?: Error) => void) {
60+ if (this.closed) {
61+ fn?.(new Error("xmpp transport is closed"));
62+ return;
63+ }
64+
65+ const fail = (e: unknown) => {
66+ const error = e instanceof Error ? e : new Error(String(e));
67+ this.emit("error", error);
68+ fn?.(error);
69+ };
70+
71+ if (this.opening) {
72+ this.opening.then(() => this.write(data, fn), fail);
73+ return;
74+ }
75+
76+ const events = this.events;
77+ const service = this.service;
78+ if (!events || !service) {
79+ fail(new Error("xmpp transport is not connected"));
80+ return;
81+ }
82+
83+ if (this.id != null) {
84+ invoke("xmpp_write", { id: this.id, data }).then(() => fn?.(), fail);
85+ } else {
86+ const opening = invoke<number>("xmpp_open", {
87+ service,
88+ streamOpen: data,
89+ onEvent: events,
90+ });
91+ this.opening = opening;
92+ opening.then(
93+ (id) => {
94+ this.id = id;
95+ this.opening = null;
96+ if (this.closed) {
97+ invoke("xmpp_disconnect", { id }).catch(() => {});
98+ }
99+ fn?.();
100+ },
101+ (e) => {
102+ this.opening = null;
103+ fail(e);
104+ },
105+ );
106+ }
107+ }
108+
109+ end() {
110+ const disconnect = (id: number) =>
111+ invoke("xmpp_disconnect", { id })
112+ .catch(() => {})
113+ .finally(() => this.#close(true));
114+
115+ if (this.id != null) {
116+ disconnect(this.id);
117+ } else if (this.opening) {
118+ this.opening.then(disconnect, () => this.#close(true));
119+ } else {
120+ this.#close(true);
121+ }
122+ }
123+
124+ #close(clean: boolean) {
125+ if (this.closed) return;
126+ this.closed = true;
127+ this.events = null;
128+ this.emit("close", !clean, {});
129+ }
130+}
131+
132+class TauriConnection extends Connection {
133+ socketParameters(service: string) {
134+ return service;
135+ }
136+
137+ headerElement() {
138+ const el = super.headerElement();
139+ el.name = "stream:stream";
140+ el.attrs.xmlns = "jabber:client";
141+ el.attrs["xmlns:stream"] = NS_STREAM;
142+ return el;
143+ }
144+
145+ header(el: { toString(): string }) {
146+ return `<?xml version='1.0'?>${el.toString().slice(0, -2)}>`;
147+ }
148+
149+ footer() {
150+ return "</stream:stream>";
151+ }
152+}
153+
154+Object.assign(TauriConnection.prototype, {
155+ Socket: TauriSocket,
156+ Parser,
157+});
158+
159+export const createTauriXmppClient = (options: Record<string, unknown>) => {
160+ const xmpp = xmppClient(options);
161+ xmpp.transports = [TauriConnection];
162+
163+ // @xmpp/client installs @xmpp/resolve, which replaces connect() and does
164+ // SRV/TXT/host-meta lookups in the webview. xmpp-proxy does discovery on the
165+ // Rust side, so restore the plain transport-selecting connect() method.
166+ xmpp.connect = (service: string) =>
167+ XmppClientCore.prototype.connect.call(xmpp, service);
168+
169+ return xmpp;
170+};
171+
172+export const installTauriXmppTransport = (client: borogove.Client) => {
173+ (
174+ client as unknown as {
175+ stream: { createClient: typeof createTauriXmppClient };
176+ }
177+ ).stream.createClient = createTauriXmppClient;
178+};
+75 -0 src/types/xmpp.d.ts #
......@@ -0,0 +1,75 @@
1+declare module "@xmpp/client" {
2+ import type { XmppClient } from "@xmpp/client-core";
3+
4+ export function client(options?: Record<string, unknown>): XmppClient;
5+}
6+
7+declare module "@xmpp/client-core" {
8+ export interface XmppClient {
9+ transports: unknown[];
10+ connect(service: string): Promise<void>;
11+ [key: string]: unknown;
12+ }
13+
14+ export class Client {
15+ constructor(options?: Record<string, unknown>);
16+ connect(service: string): Promise<void>;
17+ [key: string]: unknown;
18+ }
19+}
20+
21+declare module "@xmpp/connection" {
22+ import { EventEmitter } from "@xmpp/events";
23+
24+ export interface XmppElement {
25+ name: string;
26+ attrs: Record<string, string | undefined>;
27+ toString(): string;
28+ }
29+
30+ export default class Connection extends EventEmitter {
31+ constructor(options?: Record<string, unknown>);
32+ jid: unknown;
33+ status: string;
34+ timeout: number;
35+ root: XmppElement | null;
36+ socket: EventEmitter | null;
37+ parser: EventEmitter | null;
38+ Parser: new (...args: unknown[]) => EventEmitter;
39+ _status(status: string, ...args: unknown[]): void;
40+ _attachParser(parser: EventEmitter): void;
41+ _detachParser(): void;
42+ headerElement(): XmppElement;
43+ header(el: XmppElement): string;
44+ footer(el?: XmppElement): string;
45+ footerElement(): XmppElement | undefined;
46+ write(data: string): Promise<void>;
47+ connect(service: string): Promise<void>;
48+ open(options: { domain: string; lang?: string }): Promise<unknown>;
49+ _closeStream(timeout?: number): Promise<unknown>;
50+ [key: string]: unknown;
51+ }
52+}
53+
54+declare module "@xmpp/events" {
55+ export class EventEmitter {
56+ constructor(...args: unknown[]);
57+ on(event: string, listener: (...args: unknown[]) => void): void;
58+ once(event: string, listener: (...args: unknown[]) => void): void;
59+ off(event: string, listener: (...args: unknown[]) => void): void;
60+ emit(event: string, ...args: unknown[]): void;
61+ }
62+
63+ export function promise(
64+ target: EventEmitter,
65+ event: string,
66+ rejectEvent?: string,
67+ timeout?: number,
68+ ): Promise<unknown>;
69+}
70+
71+declare module "@xmpp/xml" {
72+ export class Parser extends import("@xmpp/events").EventEmitter {
73+ constructor(...args: unknown[]);
74+ }
75+}
Back to top