diff --git a/.config/nextest.toml b/.config/nextest.toml index 37328a3..1e11d97 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -17,11 +17,12 @@ test-threads = 1 [[profile.default.overrides]] filter = 'test(test_replicate_group) | test(test_join_group)' retries = { backoff = "exponential", count = 4, delay = "8s", max-delay = "45s", jitter = true } +slow-timeout = { period = "60s", terminate-after = 6 } [[profile.default.overrides]] -filter = 'test(test_refresh_joined_group)' +filter = 'test(test_refresh_joined_group) | test(test_refresh_member_joined_before_owner_uploads)' retries = { backoff = "exponential", count = 2, delay = "8s", max-delay = "30s", jitter = true } -slow-timeout = { period = "60s", terminate-after = 5 } +slow-timeout = { period = "60s", terminate-after = 8 } # Faster CI profile used for PR runs. [profile.ci-virtual] @@ -32,9 +33,9 @@ test-threads = 1 [[profile.ci-virtual.overrides]] filter = 'test(test_replicate_group) | test(test_join_group)' retries = { backoff = "exponential", count = 2, delay = "5s", max-delay = "20s", jitter = true } -slow-timeout = { period = "45s", terminate-after = 4 } +slow-timeout = { period = "60s", terminate-after = 6 } [[profile.ci-virtual.overrides]] -filter = 'test(test_refresh_joined_group)' +filter = 'test(test_refresh_joined_group) | test(test_refresh_member_joined_before_owner_uploads)' retries = { backoff = "exponential", count = 1, delay = "5s", max-delay = "15s", jitter = true } -slow-timeout = { period = "45s", terminate-after = 4 } +slow-timeout = { period = "60s", terminate-after = 8 } diff --git a/Cargo.lock b/Cargo.lock index fc4bbf6..24eff73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,8 +8,8 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.10.0", - "bytes 1.11.1", + "bitflags 2.11.1", + "bytes", "futures-core", "futures-sink", "memchr", @@ -30,9 +30,9 @@ dependencies = [ "actix-service", "actix-utils", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.1", "brotli", - "bytes 1.11.1", + "bytes", "bytestring", "derive_more 2.1.1", "encoding_rs", @@ -49,7 +49,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand 0.9.2", + "rand 0.9.4", "sha1", "smallvec", "tokio", @@ -145,7 +145,7 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "bytes 1.11.1", + "bytes", "bytestring", "cfg-if 1.0.4", "cookie", @@ -220,21 +220,31 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "bytes 1.11.1", - "crypto-common", + "bytes", + "crypto-common 0.1.7", "generic-array", ] +[[package]] +name = "aead" +version = "0.6.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b657e772794c6b04730ea897b66a058ccd866c16d1967da05eeeecec39043fe" +dependencies = [ + "bytes", + "crypto-common 0.2.1", + "inout 0.2.2", +] + [[package]] name = "aes" -version = "0.7.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if 1.0.4", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug", + "cipher 0.4.4", + "cpufeatures 0.2.17", ] [[package]] @@ -279,12 +289,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android_log-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" - [[package]] name = "android_log-sys" version = "0.3.2" @@ -293,26 +297,13 @@ checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" [[package]] name = "android_logger" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8619b80c242aa7bd638b5c7ddd952addeecb71f69c75e33f1d47b2804f8f883a" -dependencies = [ - "android_log-sys 0.2.0", - "env_logger", - "log", - "once_cell", -] - -[[package]] -name = "android_logger" -version = "0.13.3" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" dependencies = [ - "android_log-sys 0.3.2", - "env_logger", + "android_log-sys", + "env_filter", "log", - "once_cell", ] [[package]] @@ -389,6 +380,12 @@ dependencies = [ "rustversion", ] +[[package]] +name = "archery" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e0a5f99dfebb87bb342d0f53bb92c81842e100bbb915223e38349580e5441d" + [[package]] name = "argon2" version = "0.5.3" @@ -397,7 +394,7 @@ checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", - "cpufeatures", + "cpufeatures 0.2.17", "password-hash", ] @@ -452,6 +449,18 @@ dependencies = [ "syn 2.0.115", ] +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -477,31 +486,20 @@ dependencies = [ [[package]] name = "async-io" -version = "1.13.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock 2.8.0", "autocfg", "cfg-if 1.0.4", "concurrent-queue", - "futures-lite 1.13.0", - "log", + "futures-io", + "futures-lite", "parking", "polling", - "rustix 0.37.28", + "rustix", "slab", - "socket2 0.4.10", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.61.2", ] [[package]] @@ -515,11 +513,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.115", +] + [[package]] name = "async-sqlite" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556a4163d701c7d3e28c89917294cea8d2a05092c92a50307c0f2d1742058ced" +checksum = "b6037310bc3258a157bc12e9bba372420ad69143ecc24d986a3b1218d6d97b01" dependencies = [ "crossbeam-channel", "futures-channel", @@ -575,16 +584,19 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.27.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5359381fd414fbdb272c48f2111c16cb0bb3447bfacd59311ff3736da9f6664" +checksum = "f3b465d66478a9bb84abed46695c44a58e34f3e8d0abfb2e958218d420969049" dependencies = [ "async-tls", + "atomic-waker", + "futures-core", "futures-io", + "futures-task", "futures-util", "log", "pin-project-lite", - "tungstenite 0.23.0", + "tungstenite 0.28.0", ] [[package]] @@ -598,7 +610,7 @@ dependencies = [ "futures-task", "futures-timer", "futures-util", - "pin-project 1.1.10", + "pin-project", "rustc_version", "tokio", "wasm-bindgen-futures", @@ -634,11 +646,13 @@ dependencies = [ [[package]] name = "attribute-derive" -version = "0.6.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c124f12ade4e670107b132722d0ad1a5c9790bcbc1b265336369ea05626b4498" +checksum = "05832cdddc8f2650cc2cc187cc2e952b8c133a48eb055f35211f61ee81502d77" dependencies = [ "attribute-derive-macro", + "derive-where", + "manyhow", "proc-macro2", "quote", "syn 2.0.115", @@ -646,13 +660,13 @@ dependencies = [ [[package]] name = "attribute-derive-macro" -version = "0.6.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b217a07446e0fb086f83401a98297e2d81492122f5874db5391bd270a185f88" +checksum = "0a7cdbbd4bd005c5d3e2e9c885e6fa575db4f4a3572335b974d8db853b6beb61" dependencies = [ "collection_literals", "interpolator", - "proc-macro-error 1.0.4", + "manyhow", "proc-macro-utils", "proc-macro2", "quote", @@ -674,7 +688,7 @@ checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "getrandom 0.2.17", "instant", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -698,8 +712,8 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1f7a89a8ee5889d2593ae422ce6e1bb03e48a0e8a16e4fa0882dfcbe7e182ef" dependencies = [ - "bytes 1.11.1", - "futures-lite 2.6.1", + "bytes", + "futures-lite", "genawaiter", "iroh-blake3", "iroh-io", @@ -765,9 +779,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitmaps" @@ -781,7 +795,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -795,7 +809,7 @@ dependencies = [ "cc", "cfg-if 1.0.4", "constant_time_eq 0.4.2", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -809,15 +823,6 @@ dependencies = [ "syn 2.0.115", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -828,20 +833,22 @@ dependencies = [ ] [[package]] -name = "block-modes" -version = "0.8.1" +name = "block-buffer" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ - "block-padding", - "cipher 0.3.0", + "hybrid-array", ] [[package]] name = "block-padding" -version = "0.2.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] [[package]] name = "block2" @@ -854,9 +861,9 @@ dependencies = [ [[package]] name = "bosion" -version = "1.1.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812324ec2142bc1152978f22772cedd56cc617094d9d24fab05643149b4f185f" +checksum = "092fa5f40ea295acd5e514c51b73696511f3815a540f634e7ba32ea6ad8bc23c" dependencies = [ "time", ] @@ -895,16 +902,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] -name = "byteorder" -version = "1.5.0" +name = "bytemuck" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] -name = "bytes" -version = "0.5.6" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -915,33 +922,48 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" + [[package]] name = "bytestring" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289" dependencies = [ - "bytes 1.11.1", + "bytes", ] [[package]] name = "capnp" -version = "0.21.7" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e92edec8974fcd7ece90bb021db782abe14a61c10c817f197f700fef7430eb8" +checksum = "63da65e5e9ffc3b8f993d4ad222a548152549351a643f6b850a7773cb6ff2809" dependencies = [ - "embedded-io 0.6.1", + "embedded-io 0.7.1", ] [[package]] name = "capnpc" -version = "0.21.4" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da96dcb0a0e0c526daf42bac55e1550f18ad973df9ef9ba75204f332c80ad16" +checksum = "fca02be865c8c5a78bfc24b9819006ab6b59bef238467203928e26459557af93" dependencies = [ "capnp", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher 0.4.4", +] + [[package]] name = "cc" version = "1.2.55" @@ -986,19 +1008,31 @@ checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if 1.0.4", "cipher 0.4.4", - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if 1.0.4", + "cipher 0.5.1", + "cpufeatures 0.3.0", + "zeroize", ] [[package]] name = "chacha20poly1305" -version = "0.10.1" +version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "1c9ed179664f12fd6f155f6dd632edf5f3806d48c228c67ff78366f2a0eb6b5e" dependencies = [ - "aead", - "chacha20", - "cipher 0.4.4", - "poly1305", + "aead 0.6.0-rc.10", + "chacha20 0.10.0", + "cipher 0.5.1", + "poly1305 0.9.0", "zeroize", ] @@ -1018,22 +1052,24 @@ dependencies = [ [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common 0.1.7", + "inout 0.1.4", + "zeroize", ] [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" dependencies = [ - "crypto-common", - "inout", - "zeroize", + "block-buffer 0.12.0", + "crypto-common 0.2.1", + "inout 0.2.2", ] [[package]] @@ -1055,7 +1091,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -1076,6 +1112,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "cobs" version = "0.3.0" @@ -1103,7 +1145,7 @@ version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "bytes 1.11.1", + "bytes", "memchr", ] @@ -1199,6 +1241,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -1238,6 +1289,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -1277,13 +1338,14 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.11.0" +name = "crypto-common" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ - "generic-array", - "subtle", + "getrandom 0.4.1", + "hybrid-array", + "rand_core 0.10.1", ] [[package]] @@ -1292,8 +1354,8 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" dependencies = [ - "aead", - "chacha20", + "aead 0.5.2", + "chacha20 0.9.1", "crypto_secretbox", "curve25519-dalek", "salsa20", @@ -1308,11 +1370,11 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" dependencies = [ - "aead", - "chacha20", + "aead 0.5.2", + "chacha20 0.9.1", "cipher 0.4.4", "generic-array", - "poly1305", + "poly1305 0.8.0", "salsa20", "subtle", "zeroize", @@ -1329,6 +1391,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1336,9 +1407,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if 1.0.4", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", - "digest 0.10.7", + "digest", "fiat-crypto", "rustc_version", "subtle", @@ -1356,38 +1427,14 @@ dependencies = [ "syn 2.0.115", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1400,28 +1447,17 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn 2.0.115", ] -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core 0.21.3", + "darling_core", "quote", "syn 2.0.115", ] @@ -1491,17 +1527,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive-where" version = "1.6.0" @@ -1563,15 +1588,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" @@ -1580,29 +1596,29 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.7", "subtle", ] [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -1611,7 +1627,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "block2", "libc", "objc2", @@ -1679,7 +1695,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest 0.10.7", + "digest", "elliptic-curve", "rfc6979", "signature", @@ -1707,7 +1723,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2 0.10.9", + "sha2", "signature", "subtle", "zeroize", @@ -1739,7 +1755,7 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.7", + "digest", "ff", "generic-array", "group", @@ -1762,6 +1778,12 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -1771,6 +1793,12 @@ dependencies = [ "cfg-if 1.0.4", ] +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + [[package]] name = "enum-as-inner" version = "0.6.1" @@ -1796,34 +1824,14 @@ dependencies = [ "syn 2.0.115", ] -[[package]] -name = "enumflags2" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0" -dependencies = [ - "enumflags2_derive 0.6.4", - "serde", -] - [[package]] name = "enumflags2" version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ - "enumflags2_derive 0.7.12", -] - -[[package]] -name = "enumflags2_derive" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "enumflags2_derive", + "serde", ] [[package]] @@ -1853,12 +1861,22 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" dependencies = [ - "darling 0.21.3", + "darling", "proc-macro2", "quote", "syn 2.0.115", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" version = "0.10.2" @@ -1900,7 +1918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1965,19 +1983,13 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.9.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" dependencies = [ - "instant", + "getrandom 0.2.17", ] -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "ff" version = "0.13.1" @@ -2028,6 +2040,18 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "fastrand", + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fn_name" version = "0.1.0" @@ -2063,12 +2087,12 @@ dependencies = [ [[package]] name = "fs4" -version = "0.6.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" +checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" dependencies = [ - "rustix 0.38.44", - "windows-sys 0.48.0", + "rustix", + "windows-sys 0.59.0", ] [[package]] @@ -2117,8 +2141,8 @@ checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" dependencies = [ "fixedbitset", "futures-core", - "futures-lite 2.6.1", - "pin-project 1.1.10", + "futures-lite", + "pin-project", "smallvec", ] @@ -2145,28 +2169,13 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-lite" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand 2.3.0", + "fastrand", "futures-core", "futures-io", "parking", @@ -2184,6 +2193,17 @@ dependencies = [ "syn 2.0.115", ] +[[package]] +name = "futures-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" +dependencies = [ + "futures-io", + "rustls 0.23.36", + "rustls-pki-types", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -2226,14 +2246,15 @@ dependencies = [ [[package]] name = "futures_codec" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" +checksum = "ad004dd81205978a2bba6c566ed70535ccf88c0be34649e628186474603f43ca" dependencies = [ - "bytes 0.5.6", - "futures", + "bytes", + "futures-sink", + "futures-util", "memchr", - "pin-project 0.4.30", + "pin-project-lite", ] [[package]] @@ -2266,7 +2287,7 @@ version = "0.99.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" dependencies = [ - "proc-macro-error 0.4.12", + "proc-macro-error", "proc-macro-hack", "proc-macro2", "quote", @@ -2300,23 +2321,23 @@ dependencies = [ ] [[package]] -name = "get-size" -version = "0.1.4" +name = "get-size-derive2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b61e2dab7eedce93a83ab3468b919873ff16bac5a3e704011ff836d22b2120" +checksum = "f2b6d1e2f75c16bfbcd0f95d84f99858a6e2f885c2287d1f5c3a96e8444a34b4" dependencies = [ - "get-size-derive", + "attribute-derive", + "quote", + "syn 2.0.115", ] [[package]] -name = "get-size-derive" -version = "0.1.3" +name = "get-size2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a1bcfb855c1f340d5913ab542e36f25a1c56f57de79022928297632435dec2" +checksum = "49cf31a6d70300cf81461098f7797571362387ef4bf85d32ac47eaa59b3a5a1a" dependencies = [ - "attribute-derive", - "quote", - "syn 2.0.115", + "get-size-derive2", ] [[package]] @@ -2353,10 +2374,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" dependencies = [ "cfg-if 1.0.4", + "js-sys", "libc", "r-efi", + "rand_core 0.10.1", "wasip2", "wasip3", + "wasm-bindgen", ] [[package]] @@ -2411,7 +2435,7 @@ dependencies = [ "parking_lot", "portable-atomic", "quanta", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "spinning_top", ] @@ -2433,7 +2457,7 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "bytes 1.11.1", + "bytes", "fnv", "futures-core", "futures-sink", @@ -2498,11 +2522,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2517,12 +2541,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.5.2" @@ -2551,7 +2569,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.8.5", + "rand 0.8.6", "thiserror 1.0.69", "tinyvec", "tokio", @@ -2575,7 +2593,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.2", + "rand 0.9.4", "ring", "thiserror 2.0.18", "tinyvec", @@ -2597,7 +2615,7 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.9.4", "resolv-conf", "smallvec", "thiserror 2.0.18", @@ -2607,22 +2625,11 @@ dependencies = [ [[package]] name = "hkdf" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" -dependencies = [ - "digest 0.9.0", - "hmac 0.11.0", -] - -[[package]] -name = "hmac" -version = "0.11.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "crypto-mac", - "digest 0.9.0", + "hmac", ] [[package]] @@ -2631,7 +2638,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -2640,7 +2647,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b05da5b9e5d4720bfb691eebb2b9d42da3570745da71eac8a1f5bb7e59aab88" dependencies = [ - "hmac 0.12.1", + "hmac", "sha1", ] @@ -2673,7 +2680,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.11.1", + "bytes", "fnv", "itoa", ] @@ -2684,7 +2691,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ - "bytes 1.11.1", + "bytes", "itoa", ] @@ -2694,7 +2701,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.11.1", + "bytes", "http 0.2.12", "pin-project-lite", ] @@ -2705,7 +2712,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.11.1", + "bytes", "http 1.4.0", ] @@ -2715,7 +2722,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ - "bytes 1.11.1", + "bytes", "futures-core", "http 1.4.0", "http-body 1.0.1", @@ -2740,13 +2747,22 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "bytes 1.11.1", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -2757,7 +2773,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2771,7 +2787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", - "bytes 1.11.1", + "bytes", "futures-channel", "futures-core", "http 1.4.0", @@ -2810,7 +2826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", - "bytes 1.11.1", + "bytes", "futures-channel", "futures-util", "http 1.4.0", @@ -2982,12 +2998,12 @@ checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ "async-trait", "attohttpc", - "bytes 1.11.1", + "bytes", "futures", "http 0.2.12", "hyper 0.14.32", "log", - "rand 0.8.5", + "rand 0.8.6", "tokio", "url", "xmltree", @@ -2995,16 +3011,18 @@ dependencies = [ [[package]] name = "imbl" -version = "3.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be8d8cd36f33a46b1849f31f837c44d9fa87223baee3b4bd96b8f11df81eb" +checksum = "e525189e5f603908d0c6e0d402cb5de9c4b2c8866151fabc4ebd771ed2630a2e" dependencies = [ + "archery", "bitmaps", "imbl-sized-chunks", - "rand_core 0.6.4", + "rand_core 0.9.5", "rand_xoshiro", - "serde", + "serde_core", "version_check", + "wide", ] [[package]] @@ -3063,9 +3081,19 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ + "block-padding", "generic-array", ] +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "hybrid-array", +] + [[package]] name = "inplace-vec-builder" version = "0.1.1" @@ -3090,17 +3118,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -3137,10 +3154,10 @@ dependencies = [ "anyhow", "async-channel 2.5.0", "bao-tree", - "bytes 1.11.1", + "bytes", "derive_more 1.0.0-beta.7", "futures-buffered", - "futures-lite 2.6.1", + "futures-lite", "futures-util", "genawaiter", "hex", @@ -3159,7 +3176,7 @@ dependencies = [ "postcard", "quic-rpc", "quic-rpc-derive", - "rand 0.8.5", + "rand 0.8.6", "ref-cast", "serde", "strum 0.25.0", @@ -3178,7 +3195,7 @@ name = "iroh-base" version = "0.24.0" source = "git+https://github.com/tripledoublev/iroh.git?rev=b3f52f6d8bba462eebd7e3991946d844c9a75039#b3f52f6d8bba462eebd7e3991946d844c9a75039" dependencies = [ - "aead", + "aead 0.5.2", "anyhow", "crypto_box", "data-encoding", @@ -3189,7 +3206,7 @@ dependencies = [ "iroh-blake3", "once_cell", "postcard", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "redb 2.6.3", "serde", @@ -3222,11 +3239,11 @@ dependencies = [ "anyhow", "async-channel 2.5.0", "bao-tree", - "bytes 1.11.1", + "bytes", "chrono", "derive_more 1.0.0-beta.7", "futures-buffered", - "futures-lite 2.6.1", + "futures-lite", "genawaiter", "hashlink 0.9.1", "hex", @@ -3238,9 +3255,9 @@ dependencies = [ "num_cpus", "oneshot", "parking_lot", - "pin-project 1.1.10", + "pin-project", "postcard", - "rand 0.8.5", + "rand 0.8.6", "range-collections", "redb 1.5.2", "redb 2.6.3", @@ -3263,11 +3280,11 @@ source = "git+https://github.com/tripledoublev/iroh.git?rev=b3f52f6d8bba462eebd7 dependencies = [ "anyhow", "async-channel 2.5.0", - "bytes 1.11.1", + "bytes", "derive_more 1.0.0-beta.7", "ed25519-dalek", "futures-buffered", - "futures-lite 2.6.1", + "futures-lite", "futures-util", "hex", "iroh-base", @@ -3277,9 +3294,9 @@ dependencies = [ "iroh-metrics", "iroh-net", "lru", - "num_enum 0.7.5", + "num_enum", "postcard", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "redb 1.5.2", "redb 2.6.3", @@ -3301,11 +3318,11 @@ source = "git+https://github.com/tripledoublev/iroh.git?rev=b3f52f6d8bba462eebd7 dependencies = [ "anyhow", "async-channel 2.5.0", - "bytes 1.11.1", + "bytes", "derive_more 1.0.0-beta.7", "ed25519-dalek", "futures-concurrency", - "futures-lite 2.6.1", + "futures-lite", "futures-util", "indexmap 2.13.0", "iroh-base", @@ -3313,7 +3330,7 @@ dependencies = [ "iroh-metrics", "iroh-net", "postcard", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "serde", "tokio", @@ -3327,9 +3344,9 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a5feb781017b983ff1b155cd1faf8174da2acafd807aa482876da2d7e6577a" dependencies = [ - "bytes 1.11.1", - "futures-lite 2.6.1", - "pin-project 1.1.10", + "bytes", + "futures-lite", + "pin-project", "smallvec", "tokio", ] @@ -3362,13 +3379,13 @@ dependencies = [ "anyhow", "backoff", "base64 0.22.1", - "bytes 1.11.1", + "bytes", "der", "derive_more 1.0.0-beta.7", "duct", "futures-buffered", "futures-concurrency", - "futures-lite 2.6.1", + "futures-lite", "futures-sink", "futures-util", "genawaiter", @@ -3389,21 +3406,21 @@ dependencies = [ "iroh-quinn-udp", "libc", "netdev", - "netlink-packet-core", - "netlink-packet-route", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", "netlink-sys", - "num_enum 0.7.5", + "num_enum", "once_cell", "parking_lot", - "pin-project 1.1.10", + "pin-project", "pkarr", "postcard", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "rcgen", "reqwest", "ring", - "rtnetlink", + "rtnetlink 0.13.1", "rustls 0.23.36", "rustls-webpki 0.102.8", "serde", @@ -3438,7 +3455,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fd590a39a14cfc168efa4d894de5039d65641e62d8da4a80733018ababe3c33" dependencies = [ - "bytes 1.11.1", + "bytes", "iroh-quinn-proto", "iroh-quinn-udp", "pin-project-lite", @@ -3456,8 +3473,8 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd0538ff12efe3d61ea1deda2d7913f4270873a519d43e6995c6e87a1558538" dependencies = [ - "bytes 1.11.1", - "rand 0.8.5", + "bytes", + "rand 0.8.6", "ring", "rustc-hash", "rustls 0.23.36", @@ -3488,9 +3505,9 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.5.2", + "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3501,9 +3518,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -3522,7 +3539,7 @@ checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" dependencies = [ "cesu8", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.69", "walkdir", @@ -3537,19 +3554,68 @@ dependencies = [ "cesu8", "cfg-if 1.0.4", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if 1.0.4", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.115", +] + [[package]] name = "jni-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.115", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -3570,30 +3636,20 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" - [[package]] name = "keyring-manager" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7118537d59e34bd487248fb745ec6c21625d216a4722712c8fc581f6ec6bd68e" +checksum = "524fc930c46e87a7ac9e717507b2a9dfc344aaa3c2a54542180cca85229222fa" dependencies = [ "byteorder", "cfg-if 1.0.4", "directories", "fs4", - "jni 0.21.1", - "lazy_static", + "jni 0.22.4", "log", - "ndk", - "ndk-glue", "secret-service", - "security-framework 2.11.1", - "security-framework 3.5.1", + "security-framework 3.7.0", "serde", "serde_cbor", "unicode_categories", @@ -3602,18 +3658,15 @@ dependencies = [ [[package]] name = "keyvaluedb" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00311e7a7a584e68bb60d5779cc1e0ed94a23aced561ab822bbe3f6d74ec8195" -dependencies = [ - "smallvec", -] +checksum = "af169814b635a232e38be1f9bcac8ce5a8e665f764e805ed65fdb7505448132b" [[package]] name = "keyvaluedb-memorydb" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3070865865c42b96c4a86758d15c8de4c5590fb6f20b33eb4b55531a1efc16" +checksum = "699f9bfbb7b0f8e3caa94c9eff0c5b5e70db0bc4acecaa54cef08f13dacff06e" dependencies = [ "keyvaluedb", "parking_lot", @@ -3621,24 +3674,22 @@ dependencies = [ [[package]] name = "keyvaluedb-sqlite" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91f07cd53c582fd8eec2a59926420df419ed5b239babb0444c4a57693ec9ac68" +checksum = "0b0ccccf41de069f93bb6c5ae3bfe12e6a1e742c3405843174d817ba7ed37663" dependencies = [ "async-sqlite", - "hex", "keyvaluedb", - "log", "parking_lot", ] [[package]] name = "keyvaluedb-web" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3c88ac3ab6a0b36545339fc026468a3495078b726f31f43b9b3181a094f09f" +checksum = "08a74fe713c6ab20d6c653d594a6b8d905061c33352dd57b45639e7fb393a687" dependencies = [ - "flume", + "flume 0.12.0", "futures", "js-sys", "keyvaluedb", @@ -3646,7 +3697,6 @@ dependencies = [ "log", "send_wrapper 0.6.0", "wasm-bindgen", - "wasm-bindgen-derive", "web-sys", ] @@ -3673,9 +3723,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.181" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" @@ -3689,15 +3739,15 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "libc", ] [[package]] name = "libsqlite3-sys" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a" dependencies = [ "cc", "pkg-config", @@ -3710,18 +3760,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -3764,6 +3802,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", + "serde", ] [[package]] @@ -3802,9 +3841,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lz4_flex" -version = "0.11.5" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +checksum = "90071f8077f8e40adfc4b7fe9cd495ce316263f19e75c2211eeff3fdf475a3d9" [[package]] name = "macro_rules_attribute" @@ -3828,12 +3867,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b751ffb57303217bcae8f490eee6044a5b40eadf6ca05ff476cad37e7b7970d" dependencies = [ - "bytes 1.11.1", + "bytes", "crc", "ed25519-dalek", - "flume", + "flume 0.11.1", "lru", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_bencode", "serde_bytes", @@ -3842,6 +3881,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 2.0.115", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -3877,9 +3939,9 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] @@ -3944,82 +4006,13 @@ dependencies = [ "getrandom 0.2.17", ] -[[package]] -name = "nb-connect" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb540dc6ef51cfe1916ec038ce7a620daf3a111e2502d745197cd53d6bca15" -dependencies = [ - "libc", - "socket2 0.4.10", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum 0.5.11", - "raw-window-handle", - "thiserror 1.0.69", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-glue" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" -dependencies = [ - "android_logger 0.11.3", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", - "once_cell", - "parking_lot", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling 0.13.4", - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - [[package]] name = "nested_enum_utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f256ef99e7ac37428ef98c89bef9d84b590172de4bbfbe81b68a4cd3abadb32" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -4034,8 +4027,8 @@ dependencies = [ "dlopen2", "libc", "memalloc", - "netlink-packet-core", - "netlink-packet-route", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", "netlink-sys", "once_cell", "system-configuration", @@ -4053,6 +4046,15 @@ dependencies = [ "netlink-packet-utils", ] +[[package]] +name = "netlink-packet-core" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" +dependencies = [ + "paste", +] + [[package]] name = "netlink-packet-route" version = "0.17.1" @@ -4063,10 +4065,22 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "libc", - "netlink-packet-core", + "netlink-packet-core 0.7.0", "netlink-packet-utils", ] +[[package]] +name = "netlink-packet-route" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" +dependencies = [ + "bitflags 2.11.1", + "libc", + "log", + "netlink-packet-core 0.8.1", +] + [[package]] name = "netlink-packet-utils" version = "0.5.2" @@ -4085,38 +4099,39 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" dependencies = [ - "bytes 1.11.1", + "bytes", "futures", "log", - "netlink-packet-core", + "netlink-packet-core 0.7.0", "netlink-sys", "thiserror 2.0.18", ] [[package]] -name = "netlink-sys" -version = "0.8.5" +name = "netlink-proto" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" dependencies = [ - "bytes 1.11.1", + "bytes", "futures", - "libc", "log", - "tokio", + "netlink-packet-core 0.8.1", + "netlink-sys", + "thiserror 2.0.18", ] [[package]] -name = "nix" -version = "0.22.3" +name = "netlink-sys" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" +checksum = "cd6c30ed10fa69cc491d491b85cc971f6bdeb8e7367b7cde2ee6cc878d583fae" dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.4", + "bytes", + "futures-util", "libc", - "memoffset", + "log", + "tokio", ] [[package]] @@ -4132,22 +4147,23 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg-if 1.0.4", + "cfg_aliases", "libc", ] [[package]] name = "nix" -version = "0.30.1" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -4196,7 +4212,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4234,7 +4250,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -4301,48 +4317,27 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.5.2", + "hermit-abi", "libc", ] -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - [[package]] name = "num_enum" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ - "num_enum_derive 0.7.5", + "num_enum_derive", "rustversion", ] -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "num_enum_derive" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.115", @@ -4357,12 +4352,31 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "object" version = "0.37.3" @@ -4421,6 +4435,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_pipe" version = "1.2.3" @@ -4428,7 +4452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.45.0", + "windows-sys 0.61.2", ] [[package]] @@ -4440,7 +4464,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -4452,7 +4476,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -4466,7 +4490,7 @@ dependencies = [ "elliptic-curve", "primeorder", "rand_core 0.6.4", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -4515,6 +4539,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" + [[package]] name = "pem" version = "3.0.6" @@ -4580,7 +4610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -4593,33 +4623,13 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "pin-project" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a" -dependencies = [ - "pin-project-internal 0.4.30", -] - [[package]] name = "pin-project" version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ - "pin-project-internal 1.1.10", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "pin-project-internal", ] [[package]] @@ -4651,11 +4661,11 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92eff194c72f00f3076855b413ad2d940e3a6e307fa697e5c7733e738341aed4" dependencies = [ - "bytes 1.11.1", + "bytes", "document-features", "dyn-clone", "ed25519-dalek", - "flume", + "flume 0.11.1", "futures", "js-sys", "lru", @@ -4742,18 +4752,16 @@ dependencies = [ [[package]] name = "polling" -version = "2.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ - "autocfg", - "bitflags 1.3.2", "cfg-if 1.0.4", "concurrent-queue", - "libc", - "log", + "hermit-abi", "pin-project-lite", - "windows-sys 0.48.0", + "rustix", + "windows-sys 0.61.2", ] [[package]] @@ -4762,9 +4770,19 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", - "universal-hash", + "universal-hash 0.5.1", +] + +[[package]] +name = "poly1305" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00baa632505d05512f48a963e16051c54fda9a95cc9acea1a4e3c90991c4a2e" +dependencies = [ + "cpufeatures 0.3.0", + "universal-hash 0.6.1", ] [[package]] @@ -4884,32 +4902,13 @@ dependencies = [ "elliptic-curve", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - [[package]] name = "proc-macro-crate" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit", ] [[package]] @@ -4918,20 +4917,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" dependencies = [ - "proc-macro-error-attr 0.4.12", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr 1.0.4", + "proc-macro-error-attr", "proc-macro2", "quote", "syn 1.0.109", @@ -4951,17 +4937,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -4970,9 +4945,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-utils" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" dependencies = [ "proc-macro2", "quote", @@ -5036,13 +5011,13 @@ dependencies = [ "bincode", "derive_more 1.0.0-beta.7", "educe", - "flume", - "futures-lite 2.6.1", + "flume 0.11.1", + "futures-lite", "futures-sink", "futures-util", "hex", "iroh-quinn", - "pin-project 1.1.10", + "pin-project", "serde", "slab", "tokio", @@ -5069,7 +5044,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ - "bytes 1.11.1", + "bytes", "cfg_aliases", "pin-project-lite", "quinn-proto", @@ -5085,14 +5060,14 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ - "bytes 1.11.1", + "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls 0.23.36", @@ -5115,7 +5090,7 @@ dependencies = [ "once_cell", "socket2 0.6.2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5129,22 +5104,21 @@ dependencies = [ [[package]] name = "quote-use" -version = "0.7.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b5abe3fe82fdeeb93f44d66a7b444dedf2e4827defb0a8e69c437b2de2ef94" +checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" dependencies = [ "quote", "quote-use-macros", - "syn 2.0.115", ] [[package]] name = "quote-use-macros" -version = "0.7.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ea44c7e20f16017a76a245bb42188517e13d16dcb1aa18044bc406cdc3f4af" +checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" dependencies = [ - "derive-where", + "proc-macro-utils", "proc-macro2", "quote", "syn 2.0.115", @@ -5168,9 +5142,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5179,9 +5153,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -5225,13 +5199,19 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xoshiro" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ - "rand_core 0.6.4", + "rand_core 0.9.5", ] [[package]] @@ -5248,9 +5228,21 @@ dependencies = [ [[package]] name = "range-set-blaze" -version = "0.1.16" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2137da7c20957a8c1fc2d9a78952fe5989379f3472f2e4ceb908074d561ac5" +dependencies = [ + "gen_ops", + "itertools", + "num-integer", + "num-traits", +] + +[[package]] +name = "range-set-blaze" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8421b5d459262eabbe49048d362897ff3e3830b44eac6cfe341d6acb2f0f13d2" +checksum = "4dbaaf29990efce7efbdb301794fbacf9fcdbfb871e77f67c00b0ae3c08b665e" dependencies = [ "gen_ops", "itertools", @@ -5264,14 +5256,28 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] -name = "raw-window-handle" -version = "0.5.2" +name = "rayon" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] name = "rcgen" @@ -5309,18 +5315,18 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -5351,7 +5357,7 @@ checksum = "23bbed272e39c47a095a5242218a67412a220006842558b03fe2935e8f3d7b92" dependencies = [ "cfg-if 1.0.4", "libc", - "rustix 1.1.3", + "rustix", "windows 0.62.2", ] @@ -5397,7 +5403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", - "bytes 1.11.1", + "bytes", "futures-core", "http 1.4.0", "http-body 1.0.1", @@ -5440,7 +5446,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac 0.12.1", + "hmac", "subtle", ] @@ -5465,20 +5471,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", - "digest 0.10.7", + "digest", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", "rand_core 0.6.4", - "sha2 0.10.9", + "sha2", "signature", "spki", "subtle", "zeroize", ] +[[package]] +name = "rsqlite-vfs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" +dependencies = [ + "hashbrown 0.16.1", + "thiserror 2.0.18", +] + [[package]] name = "rtnetlink" version = "0.13.1" @@ -5487,28 +5503,47 @@ checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ "futures", "log", - "netlink-packet-core", - "netlink-packet-route", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", "netlink-packet-utils", - "netlink-proto", + "netlink-proto 0.11.5", "netlink-sys", "nix 0.26.4", "thiserror 1.0.69", "tokio", ] +[[package]] +name = "rtnetlink" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b960d5d873a75b5be9761b1e73b146f52dddcd27bac75263f40fba686d4d7b5" +dependencies = [ + "futures-channel", + "futures-util", + "log", + "netlink-packet-core 0.8.1", + "netlink-packet-route 0.28.0", + "netlink-proto 0.12.0", + "netlink-sys", + "nix 0.30.1", + "thiserror 1.0.69", + "tokio", +] + [[package]] name = "rusqlite" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "fallible-iterator", "fallible-streaming-iterator", - "hashlink 0.10.0", + "hashlink 0.11.0", "libsqlite3-sys", "smallvec", + "sqlite-wasm-rs", ] [[package]] @@ -5541,44 +5576,17 @@ dependencies = [ "nom", ] -[[package]] -name = "rustix" -version = "0.37.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "errno", "libc", - "linux-raw-sys 0.11.0", - "windows-sys 0.59.0", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] @@ -5603,7 +5611,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] @@ -5699,9 +5707,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -5720,6 +5728,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + [[package]] name = "salsa20" version = "0.10.2" @@ -5740,28 +5757,28 @@ dependencies = [ [[package]] name = "sanitize-filename" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ed72fbaf78e6f2d41744923916966c4fbe3d7c74e3037a8ee482f1115572603" +checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d" dependencies = [ - "lazy_static", "regex", ] [[package]] name = "save" -version = "0.2.1" +version = "0.2.3" dependencies = [ "actix-web", "anyhow", "async-trait", "base64-url", "blake3", - "bytes 1.11.1", + "bytes", "crossbeam-channel", "env_logger", "eyre", "futures", + "hickory-resolver", "iroh-blobs", "jni 0.21.1", "lazy_static", @@ -5781,21 +5798,22 @@ dependencies = [ [[package]] name = "save-dweb-backend" -version = "0.3.4" -source = "git+https://github.com/OpenArchive/save-dweb-backend?tag=v0.3.4#e997584efa0a6a2ad5af116045508e8b7eef75c6" +version = "0.3.6" +source = "git+https://github.com/OpenArchive/save-dweb-backend?tag=v0.3.6#1c0c3faf3a0620a52e91731e6cfd56f3fc6f7fe5" dependencies = [ "anyhow", "async-stream", "base64 0.22.1", - "bytes 1.11.1", + "bytes", "clap", "futures", "futures-core", "futures-util", "hex", + "hickory-resolver", "iroh", "iroh-blobs", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_cbor", "serial_test 3.3.1", @@ -5910,22 +5928,21 @@ dependencies = [ [[package]] name = "secret-service" -version = "2.0.2" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1da5c423b8783185fd3fecd1c8796c267d2c089d894ce5a93c280a5d3f780a2" +checksum = "9a62d7f86047af0077255a29494136b9aaaf697c76ff70b8e49cded4e2623c14" dependencies = [ "aes", - "block-modes", + "cbc", + "futures-util", + "generic-array", + "getrandom 0.2.17", "hkdf", - "lazy_static", "num", - "rand 0.8.5", + "once_cell", "serde", - "sha2 0.9.9", + "sha2", "zbus", - "zbus_macros", - "zvariant", - "zvariant_derive", ] [[package]] @@ -5934,7 +5951,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -5944,11 +5961,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -5957,9 +5974,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -6144,7 +6161,7 @@ version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ - "darling 0.21.3", + "darling", "proc-macro2", "quote", "syn 2.0.115", @@ -6218,8 +6235,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.4", - "cpufeatures", - "digest 0.10.7", + "cpufeatures 0.2.17", + "digest", ] [[package]] @@ -6228,19 +6245,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.4", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.9" @@ -6248,8 +6252,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if 1.0.4", - "cpufeatures", - "digest 0.10.7", + "cpufeatures 0.2.17", + "digest", ] [[package]] @@ -6321,7 +6325,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", + "digest", "rand_core 0.6.4", ] @@ -6331,13 +6335,29 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "simple-dns" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", ] [[package]] @@ -6361,16 +6381,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.10" @@ -6425,6 +6435,18 @@ dependencies = [ "der", ] +[[package]] +name = "sqlite-wasm-rs" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] + [[package]] name = "ssh-cipher" version = "0.2.0" @@ -6443,7 +6465,7 @@ checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" dependencies = [ "base64ct", "pem-rfc7468", - "sha2 0.10.9", + "sha2", ] [[package]] @@ -6459,7 +6481,7 @@ dependencies = [ "rand_core 0.6.4", "rsa", "sec1", - "sha2 0.10.9", + "sha2", "signature", "ssh-cipher", "ssh-encoding", @@ -6473,12 +6495,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stop-token" version = "0.7.0" @@ -6491,12 +6507,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -6586,7 +6596,7 @@ dependencies = [ "bounded-integer", "byteorder", "crc", - "enumflags2 0.7.12", + "enumflags2", "fallible-iterator", "hmac-sha1", "hmac-sha256", @@ -6597,7 +6607,7 @@ dependencies = [ "precis-core", "precis-profiles", "quoted-string-parser", - "rand 0.9.2", + "rand 0.9.4", ] [[package]] @@ -6615,7 +6625,7 @@ dependencies = [ "hex", "parking_lot", "pnet_packet", - "rand 0.9.2", + "rand 0.9.4", "socket2 0.6.2", "thiserror 1.0.69", "tokio", @@ -6631,7 +6641,7 @@ dependencies = [ "acto", "anyhow", "hickory-proto 0.24.4", - "rand 0.8.5", + "rand 0.8.6", "socket2 0.5.10", "tokio", "tracing", @@ -6692,16 +6702,16 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.13" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" dependencies = [ - "cfg-if 1.0.4", - "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", - "windows 0.52.0", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.62.2", ] [[package]] @@ -6710,7 +6720,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6737,11 +6747,11 @@ version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ - "fastrand 2.3.0", + "fastrand", "getrandom 0.4.1", "once_cell", - "rustix 1.1.3", - "windows-sys 0.59.0", + "rustix", + "windows-sys 0.61.2", ] [[package]] @@ -6865,7 +6875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4d51942bbd63241e665ca0cc613f56dfaee117b41d5288a6cb3fca5cdab2415" dependencies = [ "futures", - "rand 0.8.5", + "rand 0.8.6", "tokio", ] @@ -6875,7 +6885,7 @@ version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "bytes 1.11.1", + "bytes", "libc", "mio", "parking_lot", @@ -6915,11 +6925,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" dependencies = [ "bincode", - "bytes 1.11.1", + "bytes", "educe", "futures-core", "futures-sink", - "pin-project 1.1.10", + "pin-project", "serde", ] @@ -6971,7 +6981,7 @@ version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ - "bytes 1.11.1", + "bytes", "futures-core", "futures-io", "futures-sink", @@ -6980,21 +6990,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -7004,17 +6999,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.13.0", - "toml_datetime 0.6.11", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.23.10+spec-1.0.0" @@ -7022,7 +7006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime", "toml_parser", "winnow 0.7.14", ] @@ -7057,8 +7041,8 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", - "bytes 1.11.1", + "bitflags 2.11.1", + "bytes", "futures-util", "http 1.4.0", "http-body 1.0.1", @@ -7120,7 +7104,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.1.10", + "pin-project", "tracing", ] @@ -7202,12 +7186,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", - "bytes 1.11.1", + "bytes", "data-encoding", "http 1.4.0", "httparse", "log", - "rand 0.8.5", + "rand 0.8.6", "sha1", "thiserror 1.0.69", "url", @@ -7216,27 +7200,26 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ - "byteorder", - "bytes 1.11.1", + "bytes", "data-encoding", "http 1.4.0", "httparse", "log", - "rand 0.8.5", + "rand 0.9.4", "sha1", - "thiserror 1.0.69", + "thiserror 2.0.18", "utf-8", ] [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ucd-parse" @@ -7253,6 +7236,17 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + [[package]] name = "unicode-ident" version = "1.0.23" @@ -7292,10 +7286,20 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "universal-hash" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" +dependencies = [ + "crypto-common 0.2.1", + "ctutils", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -7356,6 +7360,7 @@ checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ "getrandom 0.4.1", "js-sys", + "serde_core", "wasm-bindgen", ] @@ -7373,40 +7378,40 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "veilid-core" -version = "0.5.2" -source = "git+https://gitlab.com/veilid/veilid.git?tag=v0.5.2#c7fdbc43326da464ccb9c814682053be48def195" +version = "0.5.3" +source = "git+https://gitlab.com/veilid/veilid.git?tag=v0.5.3#3dd2b67fbdbea62e77accd4990dd1e1a99ba7054" dependencies = [ "arc-swap", "argon2", - "async-sqlite", - "async-tls", "async-trait", "async-tungstenite", "backtrace", "blake2", "blake3", "bosion", - "bytes 1.11.1", + "bytesize", "capnp", "capnpc", "cfg-if 1.0.4", - "chacha20", + "chacha20 0.10.0", "chacha20poly1305", + "clap", "curve25519-dalek", "data-encoding", "directories", "ed25519-dalek", "enumset", "eyre", - "flume", + "flume 0.12.0", + "futures-rustls", "futures-util", - "get-size", + "get-size2", + "getrandom 0.4.1", "glob", "hex", "indent", - "jni 0.21.1", + "jni 0.22.4", "js-sys", - "json", "keyring-manager", "keyvaluedb", "keyvaluedb-sqlite", @@ -7415,12 +7420,8 @@ dependencies = [ "lz4_flex", "macro_rules_attribute", "num-traits", - "once_cell", - "parking_lot", - "paste", - "range-set-blaze", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", + "pastey", + "range-set-blaze 0.5.0", "sanitize-filename", "schemars 1.2.1", "send_wrapper 0.6.0", @@ -7429,11 +7430,11 @@ dependencies = [ "serde_bytes", "serde_json", "serde_with", - "sha2 0.10.9", + "sha2", "shell-words", "stop-token", "sysinfo", - "thiserror 1.0.69", + "thiserror 2.0.18", "tokio", "tracing", "tracing-subscriber", @@ -7467,19 +7468,19 @@ checksum = "ce2b3c073da0025538ff4cf5bea61a7a7a046c1bf060e2d0981c71800747551d" dependencies = [ "attohttpc", "log", - "rand 0.8.5", + "rand 0.8.6", "url", "xmltree", ] [[package]] name = "veilid-iroh-blobs" -version = "0.3.2" -source = "git+https://github.com/RangerMauve/veilid-iroh-blobs?tag=v0.3.2#9c58b16fde7c2a881dc057e0556b1ae66a51a2c2" +version = "0.3.4" +source = "git+https://github.com/RangerMauve/veilid-iroh-blobs?tag=v0.3.4#62c64886942f78ef0855fa97c529c240e809eca2" dependencies = [ "anyhow", - "bytes 1.11.1", - "futures-lite 2.6.1", + "bytes", + "futures-lite", "futures-util", "hex", "iroh-blobs", @@ -7494,18 +7495,19 @@ dependencies = [ [[package]] name = "veilid-tools" -version = "0.5.2" -source = "git+https://gitlab.com/veilid/veilid.git?tag=v0.5.2#c7fdbc43326da464ccb9c814682053be48def195" +version = "0.5.3" +source = "git+https://gitlab.com/veilid/veilid.git?tag=v0.5.3#3dd2b67fbdbea62e77accd4990dd1e1a99ba7054" dependencies = [ - "android_logger 0.13.3", + "android_logger", "async-io", - "async-lock 3.4.2", + "async-lock", "async_executors", "backtrace", + "bytes", "cfg-if 1.0.4", "chrono", "ctrlc", - "flume", + "flume 0.12.0", "fn_name", "futures-util", "futures_codec", @@ -7517,26 +7519,26 @@ dependencies = [ "js-sys", "libc", "log", - "netlink-packet-route", + "netlink-packet-route 0.28.0", "netlink-sys", - "nix 0.27.1", - "once_cell", + "nix 0.31.3", "parking_lot", - "rand 0.8.5", - "range-set-blaze", - "rtnetlink", + "rand 0.8.6", + "range-set-blaze 0.4.4", + "rayon", + "rtnetlink 0.20.0", "send_wrapper 0.6.0", "serde", - "socket2 0.5.10", + "socket2 0.6.2", "stop-token", - "thiserror 1.0.69", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", "tracing", "tracing-subscriber", "winapi", - "windows 0.51.1", + "windows 0.62.2", "ws_stream_wasm", ] @@ -7546,12 +7548,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - [[package]] name = "walkdir" version = "2.5.0" @@ -7704,7 +7700,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap 2.13.0", "semver", @@ -7785,6 +7781,16 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "widestring" version = "1.2.1" @@ -7813,7 +7819,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7832,16 +7838,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.58.0" @@ -7882,15 +7878,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.58.0" @@ -8333,18 +8320,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.5.40" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] name = "winnow" -version = "0.7.14" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -8417,7 +8404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.11.1", "indexmap 2.13.0", "log", "serde", @@ -8577,37 +8564,58 @@ checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f" [[package]] name = "zbus" -version = "1.9.3" +version = "5.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbeb2291cd7267a94489b71376eda33496c1b9881adf6b36f26cc2779f3fc49" +checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" dependencies = [ - "async-io", - "byteorder", - "derivative", - "enumflags2 0.6.4", - "fastrand 1.9.0", - "futures", - "nb-connect", - "nix 0.22.3", - "once_cell", - "polling", - "scoped-tls", + "async-broadcast", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener 5.4.1", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", "serde", "serde_repr", + "tokio", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.2", "zbus_macros", + "zbus_names", "zvariant", ] [[package]] name = "zbus_macros" -version = "1.9.3" +version = "5.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa3959a7847cf95e3d51e312856617c5b1b77191176c65a79a5f14d778bbe0a6" +checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" dependencies = [ - "proc-macro-crate 0.1.5", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.115", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" +dependencies = [ + "serde", + "winnow 1.0.2", + "zvariant", ] [[package]] @@ -8740,26 +8748,40 @@ dependencies = [ [[package]] name = "zvariant" -version = "2.10.0" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68c7b55f2074489b7e8e07d2d0a6ee6b4f233867a653c664d8020ba53692525" +checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" dependencies = [ - "byteorder", - "enumflags2 0.6.4", - "libc", + "endi", + "enumflags2", "serde", - "static_assertions", + "winnow 1.0.2", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "2.10.0" +version = "5.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9" +checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.115", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.115", + "winnow 1.0.2", ] diff --git a/Cargo.toml b/Cargo.toml index a3fd286..fec3127 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "save" -version = "0.2.1" +version = "0.2.3" authors = ["Richard Puckett JObject; @@ -110,14 +109,14 @@ pub extern "system" fn Java_net_opendasharchive_openarchive_services_snowbird_Sn // Create a runtime to handle async operations let runtime = tokio::runtime::Runtime::new().unwrap(); - + // Stop the backend server and clean up Veilid API let stop_result = runtime.block_on(async { // First stop the backend match server::stop().await { Ok(_) => { log_info!(TAG, "Backend stopped successfully"); - + // Get the backend to access Veilid API if let Ok(backend) = server::get_backend().await { // Shutdown Veilid API @@ -126,10 +125,10 @@ pub extern "system" fn Java_net_opendasharchive_openarchive_services_snowbird_Sn log_info!(TAG, "Veilid API shut down successfully"); } } - + // Add a small delay to ensure tasks complete tokio::time::sleep(Duration::from_millis(500)).await; - + Ok(()) } Err(e) => { diff --git a/src/constants.rs b/src/constants.rs index 09d5923..142aeb9 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,6 +2,4 @@ use once_cell::sync::Lazy; pub const TAG: &str = "SnowbirdBridge"; -pub static VERSION: Lazy = Lazy::new(|| { - env!("CARGO_PKG_VERSION").to_string() -}); \ No newline at end of file +pub static VERSION: Lazy = Lazy::new(|| env!("CARGO_PKG_VERSION").to_string()); diff --git a/src/error.rs b/src/error.rs index 7846787..520e7b9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,10 +1,10 @@ -use actix_web::{HttpResponse, ResponseError, error::BlockingError}; +use crate::constants::TAG; +use crate::log_error; +use actix_web::{error::BlockingError, HttpResponse, ResponseError}; use anyhow::anyhow; use anyhow::Error as AnyhowError; use base64_url::base64; use eyre::ErrReport; -use crate::log_error; -use crate::constants::TAG; pub struct AppError(pub AnyhowError); @@ -36,7 +36,8 @@ impl ResponseError for AppError { let legacy_body = format!("Something went wrong: {error_msg}"); if error_msg.contains("Backend not ready") || error_msg.contains("not initialized") - || error_msg.contains("Initialization") { + || error_msg.contains("Initialization") + { return HttpResponse::ServiceUnavailable().json(legacy_body); } diff --git a/src/groups.rs b/src/groups.rs index 46686d7..bce8683 100644 --- a/src/groups.rs +++ b/src/groups.rs @@ -1,10 +1,10 @@ -use actix_web::{web, delete, get, post, Responder, HttpResponse}; -use serde_json::json; +use crate::constants::TAG; use crate::error::AppResult; -use crate::{log_debug, log_error}; use crate::models::{IntoSnowbirdGroupsWithNames, RequestName, RequestUrl, SnowbirdGroup}; use crate::repos; -use crate::constants::{TAG}; +use crate::{log_debug, log_error}; +use actix_web::{delete, get, post, web, HttpResponse, Responder}; +use serde_json::json; use crate::server::get_backend; use crate::utils::create_veilid_cryptokey_from_base64; @@ -20,7 +20,7 @@ pub fn scope() -> actix_web::Scope { .service(delete_group) .service(get_group) .service(refresh_group) - .service(repos::scope()) + .service(repos::scope()), ) } @@ -30,7 +30,7 @@ async fn delete_group(group_id: web::Path) -> AppResult let backend = get_backend().await?; let group_id = group_id.into_inner(); let crypto_key = create_veilid_cryptokey_from_base64(&group_id)?; - + backend.close_group(crypto_key).await?; Ok(HttpResponse::Ok().json(json!({}))) @@ -175,28 +175,105 @@ async fn refresh_group(group_id: web::Path) -> AppResult let mut refreshed_files_vec = Vec::new(); let mut all_files_vec: Vec = Vec::new(); + if repo.can_write() { + match tokio::time::timeout(std::time::Duration::from_secs(2), repo.get_hash_from_dht()) + .await + { + Ok(Ok(repo_hash)) => { + repo_info["repo_hash"] = json!(repo_hash.to_string()); + } + Ok(Err(e)) => { + log_debug!(TAG, "Error getting repo hash for {}: {}", repo.id(), e); + repo_info["repo_hash_error"] = + json!(format!("Error getting repo hash from DHT: {}", e)); + } + Err(_) => { + log_debug!( + TAG, + "Timed out getting optional writable repo hash for {}", + repo.id() + ); + repo_info["repo_hash_error"] = + json!("Timed out getting optional writable repo hash from DHT"); + } + } + + match repo.list_files().await { + Ok(files) => { + log_debug!( + TAG, + "Writable repo {} lists local files: {:?}", + repo.id(), + files + ); + repo_info["all_files"] = json!(files); + } + Err(e) => { + log_debug!( + TAG, + "Error listing local writable repo {}: {}", + repo.id(), + e + ); + repo_info["error_listing_files"] = + json!(format!("Error listing local writable repo files: {}", e)); + } + } + refreshed_repos.push(repo_info); + continue; + } + // Get current repo hash and collection info - match repo.get_hash_from_dht().await { - Ok(repo_hash) => { + match tokio::time::timeout(std::time::Duration::from_secs(30), repo.get_hash_from_dht()) + .await + { + Ok(Ok(repo_hash)) => { repo_info["repo_hash"] = json!(repo_hash.to_string()); - + // Refresh collection hash if needed - log_debug!(TAG, "Repo {} has DHT hash {}. Checking if group has it locally.", repo.id(), repo_hash); + log_debug!( + TAG, + "Repo {} has DHT hash {}. Checking if group has it locally.", + repo.id(), + repo_hash + ); if !group.has_hash(&repo_hash).await? { - log_debug!(TAG, "Repo {} collection {} not found locally. Downloading...", repo.id(), repo_hash); + log_debug!( + TAG, + "Repo {} collection {} not found locally. Downloading...", + repo.id(), + repo_hash + ); match group.download_hash_from_peers(&repo_hash).await { Ok(_) => { - log_debug!(TAG, "Successfully downloaded collection hash {} for repo {}", repo_hash, repo.id()); + log_debug!( + TAG, + "Successfully downloaded collection hash {} for repo {}", + repo_hash, + repo.id() + ); } Err(e) => { - log_debug!(TAG, "Error downloading collection hash {} for repo {}: {}", repo_hash, repo.id(), e); - repo_info["error"] = json!(format!("Error downloading collection: {}", e)); + log_debug!( + TAG, + "Error downloading collection hash {} for repo {}: {}", + repo_hash, + repo.id(), + e + ); + repo_info["error"] = + json!(format!("Error downloading collection: {}", e)); refreshed_repos.push(repo_info); continue; // Skip to next repo if download fails } } } else { - log_debug!(TAG, "Repo {} collection {} already local.", repo.id(), repo_hash); + log_debug!( + TAG, + "Repo {} collection {} already local.", + repo.id(), + repo_hash + ); } // Now that the collection is ensured to be local, list all files in the repo @@ -209,25 +286,41 @@ async fn refresh_group(group_id: web::Path) -> AppResult log_debug!(TAG, "Error listing files for repo {} after ensuring collection download: {}", repo.id(), e); // Even if listing fails here, we might have a repo_hash, so continue with empty files. // Or, handle as a more significant error. For now, log and continue. - repo_info["error_listing_files"] = json!(format!("Error listing files post-download: {}", e)); + repo_info["error_listing_files"] = + json!(format!("Error listing files post-download: {}", e)); } }; repo_info["all_files"] = json!(all_files_vec.clone()); - // For each file, check if it needs to be refreshed for file_name in &all_files_vec { match repo.get_file_hash(file_name).await { Ok(file_hash) => { if !group.has_hash(&file_hash).await? { - log_debug!(TAG, "File {} hash {} not found locally. Downloading...", file_name, file_hash); + log_debug!( + TAG, + "File {} hash {} not found locally. Downloading...", + file_name, + file_hash + ); match group.download_hash_from_peers(&file_hash).await { Ok(_) => { - log_debug!(TAG, "Successfully downloaded file hash {} for {}", file_hash, file_name); + log_debug!( + TAG, + "Successfully downloaded file hash {} for {}", + file_hash, + file_name + ); refreshed_files_vec.push(file_name.clone()); } Err(e) => { - log_debug!(TAG, "Error downloading file {} hash {}: {}", file_name, file_hash, e); + log_debug!( + TAG, + "Error downloading file {} hash {}: {}", + file_name, + file_hash, + e + ); // Optionally add to a list of files that failed to download } } @@ -240,10 +333,14 @@ async fn refresh_group(group_id: web::Path) -> AppResult } repo_info["refreshed_files"] = json!(refreshed_files_vec); } - Err(e) => { + Ok(Err(e)) => { log_debug!(TAG, "Error getting repo hash for {}: {}", repo.id(), e); repo_info["error"] = json!(format!("Error getting repo hash from DHT: {}", e)); } + Err(_) => { + log_debug!(TAG, "Timed out getting repo hash for {}", repo.id()); + repo_info["error"] = json!("Timed out getting repo hash from DHT"); + } } refreshed_repos.push(repo_info); diff --git a/src/jni_globals.rs b/src/jni_globals.rs index 48aaa79..a3ff275 100644 --- a/src/jni_globals.rs +++ b/src/jni_globals.rs @@ -1,12 +1,12 @@ #![allow(clippy::result_large_err)] // Allows for larger error types in Result -use std::result::Result as StdResult; -use std::sync::{Arc, Mutex, Once}; -use jni::AttachGuard; -use jni::JavaVM; use jni::objects::{GlobalRef, JClass}; +use jni::AttachGuard; use jni::JNIEnv; +use jni::JavaVM; use once_cell::sync::Lazy; +use std::result::Result as StdResult; +use std::sync::{Arc, Mutex, Once}; use thiserror::Error; #[derive(Error, Debug)] @@ -35,7 +35,11 @@ static INIT: Once = Once::new(); pub fn get_java_vm() -> JniResult { let jvm_locked = JAVA_VM.lock(); let jvm = jvm_locked.as_ref().unwrap(); - let env = jvm.as_ref().unwrap().attach_current_thread_as_daemon().unwrap(); + let env = jvm + .as_ref() + .unwrap() + .attach_current_thread_as_daemon() + .unwrap(); let vm = env.get_java_vm(); return Ok(vm?); } @@ -52,15 +56,15 @@ pub fn init_jni(env: &JNIEnv, class: JClass) -> JniResult<()> { fn init_jni_inner(env: &JNIEnv, class: JClass) -> JniResult<()> { let java_vm = env.get_java_vm()?; let global_class = env.new_global_ref(class)?; - - *JAVA_VM.lock() - .map_err(|e| JniError::InitializationError(format!("Failed to acquire JavaVM lock: {e}")))? - = Some(java_vm); - - *CLASS.lock() - .map_err(|e| JniError::InitializationError(format!("Failed to acquire class lock: {e}")))? - = Some(global_class); - + + *JAVA_VM.lock().map_err(|e| { + JniError::InitializationError(format!("Failed to acquire JavaVM lock: {e}")) + })? = Some(java_vm); + + *CLASS.lock().map_err(|e| { + JniError::InitializationError(format!("Failed to acquire class lock: {e}")) + })? = Some(global_class); + Ok(()) } @@ -77,10 +81,12 @@ pub fn with_class(f: F) -> JniResult where F: FnOnce(&GlobalRef) -> JniResult, { - let class_guard = CLASS.lock() + let class_guard = CLASS + .lock() .map_err(|_| JniError::InitializationError("Failed to acquire class lock".into()))?; - - let class = class_guard.as_ref() + + let class = class_guard + .as_ref() .ok_or_else(|| JniError::InitializationError("Class not initialized".into()))?; f(class) @@ -99,14 +105,17 @@ pub fn with_env(f: F) -> JniResult where F: FnOnce(AttachGuard) -> JniResult, { - let vm_guard = JAVA_VM.lock() + let vm_guard = JAVA_VM + .lock() .map_err(|e| JniError::ThreadAttachError(format!("Failed to acquire JavaVM lock: {e}")))?; - - let vm = vm_guard.as_ref() + + let vm = vm_guard + .as_ref() .ok_or_else(|| JniError::InitializationError("JavaVM not initialized".into()))?; - let env = vm.attach_current_thread() + let env = vm + .attach_current_thread() .map_err(|e| JniError::ThreadAttachError(format!("Failed to attach thread: {e}")))?; f(env) -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index f971951..8d57264 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,20 +25,20 @@ mod tests { use super::*; use actix_web::{test, web, App}; use anyhow::Result; + use base64_url::base64; + use base64_url::base64::Engine; use models::{RequestName, RequestUrl, SnowbirdFile, SnowbirdGroup, SnowbirdRepo}; + use save_dweb_backend::backend::Backend; use save_dweb_backend::{common::DHTEntity, constants::TEST_GROUP_NAME}; use serde::{Deserialize, Serialize}; use serde_json::json; - use server::{status, health, set_backend, clear_backend}; - use tmpdir::TmpDir; - use base64_url::base64; - use base64_url::base64::Engine; - use save_dweb_backend::backend::Backend; - use veilid_core::VeilidConfig; - use veilid_core::VeilidUpdate; use serial_test::serial; + use server::{clear_backend, health, set_backend, status}; use std::sync::Arc; + use tmpdir::TmpDir; use tokio::sync::broadcast; + use veilid_core::VeilidConfig; + use veilid_core::VeilidUpdate; #[derive(Debug, Serialize, Deserialize)] struct GroupsResponse { @@ -92,6 +92,90 @@ mod tests { } } + fn deterministic_test_payload(size: usize) -> Vec { + (0..size) + .map(|index| ((index * 31 + 17) % 251) as u8) + .collect() + } + + fn parse_size_token(token: &str) -> Option { + let normalized = token.trim().to_ascii_lowercase(); + if normalized.is_empty() { + return None; + } + + let units = [ + ("kib", 1024usize), + ("kb", 1024usize), + ("k", 1024usize), + ("mib", 1024usize * 1024), + ("mb", 1024usize * 1024), + ("m", 1024usize * 1024), + ]; + + for (suffix, multiplier) in units { + if let Some(value) = normalized.strip_suffix(suffix) { + return value + .trim() + .parse::() + .ok() + .map(|size| size * multiplier); + } + } + + normalized.parse::().ok() + } + + fn diagnostic_file_size_sweep() -> Vec { + if let Ok(value) = env::var("SAVE_FILE_SIZE_SWEEP_BYTES") { + let sizes: Vec = value + .split(',') + .filter_map(parse_size_token) + .filter(|size| *size > 0) + .collect(); + if !sizes.is_empty() { + return sizes; + } + } + + vec![ + 16 * 1024, + 64 * 1024, + 128 * 1024, + 256 * 1024, + 320 * 1024, + 512 * 1024, + 1024 * 1024, + ] + } + + fn format_size(size: usize) -> String { + if size.is_multiple_of(1024 * 1024) { + format!("{}MiB", size / (1024 * 1024)) + } else if size.is_multiple_of(1024) { + format!("{}KiB", size / 1024) + } else { + format!("{size}B") + } + } + + fn classify_transfer_failure(body: &str) -> &'static str { + if body.contains("Timed out getting repo hash") + || body.contains("Unable to get DHT value for repo root hash") + { + "repo_hash_dht" + } else if body.contains("Error downloading collection") { + "collection_blob_transfer" + } else if body.contains("Unable to download hash") + || body.contains("Tunnel closed") + || body.contains("Unable to read Timeout") + { + "file_blob_transfer" + } else { + "unknown" + } + } + fn apply_test_network_overrides(config: &mut VeilidConfig) { if !env_flag("SAVE_VEILID_LOCAL_TEST_MODE") { return; @@ -121,7 +205,8 @@ mod tests { namespace: String, ready_timeout: Duration, ) -> anyhow::Result<(veilid_core::VeilidAPI, broadcast::Receiver)> { - let mut config = save_dweb_backend::common::config_for_dir(base_dir.to_path_buf(), namespace); + let mut config = + save_dweb_backend::common::config_for_dir(base_dir.to_path_buf(), namespace); apply_test_network_overrides(&mut config); let (tx, mut rx) = broadcast::channel(32); @@ -145,7 +230,9 @@ mod tests { } } } - Err(anyhow::anyhow!("Update channel closed before network ready")) + Err(anyhow::anyhow!( + "Update channel closed before network ready" + )) }) .await .map_err(|_| anyhow::anyhow!("Timeout waiting for Veilid network to become ready"))??; @@ -157,24 +244,19 @@ mod tests { async fn init_test_backend(test_name: &str) -> Result { // Clear any previous backend clear_backend()?; - + let (path, namespace) = get_test_config(test_name).await; let store = iroh_blobs::store::fs::Store::load(path.to_path_buf().join("iroh")).await?; let (veilid_api, update_rx) = init_veilid_for_tests(&path.to_path_buf(), namespace, Duration::from_secs(180)).await?; - let backend = Backend::from_dependencies( - &path.to_path_buf(), - veilid_api, - update_rx, - store, - ) - .await?; - + let backend = + Backend::from_dependencies(&path.to_path_buf(), veilid_api, update_rx, store).await?; + // Set the BACKEND static so routes can access it set_backend(Arc::new(backend))?; - + Ok(path) } @@ -205,7 +287,9 @@ mod tests { } } } - Err(anyhow::anyhow!("Update channel closed before readiness observed")) + Err(anyhow::anyhow!( + "Update channel closed before readiness observed" + )) }) .await { @@ -221,13 +305,13 @@ mod tests { if let Ok(backend) = get_backend().await { backend.stop().await?; } - + // Clear the backend static clear_backend()?; - + // Add a small delay to ensure everything is cleaned up tokio::time::sleep(Duration::from_millis(500)).await; - + Ok(()) } @@ -270,7 +354,8 @@ mod tests { break; } Err(e) => { - last_create_group_error = format!("invalid success payload: {e}; body={body:?}"); + last_create_group_error = + format!("invalid success payload: {e}; body={body:?}"); } } } else { @@ -377,8 +462,6 @@ mod tests { let list_files_resp: FilesResponse = test::call_and_read_body_json(&app, list_files_req).await; - - // Now check if the response is an array directly let files_array = list_files_resp.files; assert_eq!(files_array.len(), 1, "There should be one file in the repo"); @@ -450,17 +533,16 @@ mod tests { // Initialize secondary backend with unique namespace let (path2, namespace2) = get_test_config("test_join_group_secondary").await; let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; - let (veilid_api2, update_rx2) = - init_veilid_for_tests(path2.to_path_buf().as_path(), namespace2, Duration::from_secs(180)) - .await?; - let backend2 = Backend::from_dependencies( - &path2.to_path_buf(), - veilid_api2, - update_rx2, - store2, + let (veilid_api2, update_rx2) = init_veilid_for_tests( + path2.to_path_buf().as_path(), + namespace2, + Duration::from_secs(180), ) - .await - .unwrap(); + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); // Wait for backend2 (creator) to be ready wait_for_public_internet_ready(&backend2).await?; @@ -494,7 +576,10 @@ mod tests { // Group name may not have propagated via DHT yet — the refresh loop below validates it. if joined_group.name.as_deref() != Some(TEST_GROUP_NAME) { - log::warn!("Group name not yet propagated at join time (got {:?}), will verify after refresh", joined_group.name); + log::warn!( + "Group name not yet propagated at join time (got {:?}), will verify after refresh", + joined_group.name + ); } // Retry with refresh (cache-invalidating) until DHT propagation converges — @@ -517,10 +602,7 @@ mod tests { let writable_repos: Vec<_> = resp.repos.iter().filter(|r| r.can_write).collect(); let creator_ok = read_only_repos.iter().any(|r| r.name == TEST_GROUP_NAME); - if read_only_repos.len() == 1 - && writable_repos.len() == 1 - && creator_ok - { + if read_only_repos.len() == 1 && writable_repos.len() == 1 && creator_ok { break; } } @@ -548,17 +630,16 @@ mod tests { // Create secondary backend (creator) first let (path2, namespace2) = get_test_config("test_replicate_group_secondary").await; let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; - let (veilid_api2, update_rx2) = - init_veilid_for_tests(path2.to_path_buf().as_path(), namespace2, Duration::from_secs(180)) - .await?; - let backend2 = Backend::from_dependencies( - &path2.to_path_buf(), - veilid_api2, - update_rx2, - store2, + let (veilid_api2, update_rx2) = init_veilid_for_tests( + path2.to_path_buf().as_path(), + namespace2, + Duration::from_secs(180), ) - .await - .unwrap(); + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); // Initialize main backend (joiner) let _path = init_test_backend("test_replicate_group_main").await?; @@ -666,9 +747,7 @@ mod tests { download_retries -= 1; if download_retries == 0 { - panic!( - "File download did not converge after retries. last status: {resp_status}" - ); + panic!("File download did not converge after retries. last status: {resp_status}"); } tokio::time::sleep(Duration::from_secs(5)).await; } @@ -705,7 +784,10 @@ mod tests { .uri(&format!("/api/groups/{fake_group_id}/refresh")) .to_request(); let non_existent_resp = test::call_service(&app, non_existent_req).await; - assert!(non_existent_resp.status().is_client_error(), "Should return error for non-existent group"); + assert!( + non_existent_resp.status().is_client_error(), + "Should return error for non-existent group" + ); // Clean up cleanup_test_resources().await?; @@ -743,7 +825,10 @@ mod tests { .uri(&format!("/api/groups/{}/refresh", empty_group.id())) .to_request(); let empty_group_resp = test::call_service(&app, empty_group_req).await; - assert!(empty_group_resp.status().is_success(), "Should handle empty group"); + assert!( + empty_group_resp.status().is_success(), + "Should handle empty group" + ); let empty_group_data: serde_json::Value = test::read_body_json(empty_group_resp).await; assert_eq!(empty_group_data["status"], "success"); assert!(empty_group_data["repos"].as_array().unwrap().is_empty()); @@ -768,26 +853,27 @@ mod tests { let (group, repo, dummy_file_name, dummy_file_content) = { use server::get_backend; let backend = get_backend().await?; - + // Wait for public internet readiness log::info!("Waiting for public internet readiness..."); wait_for_public_internet_ready(&backend).await?; log::info!("Public internet is ready"); - + let mut group = backend.create_group().await?; group.set_name(TEST_GROUP_NAME).await?; log::info!("Created group with name: {TEST_GROUP_NAME}"); - + let repo = group.create_repo().await?; repo.set_name("Test Repo").await?; log::info!("Created repo with name: Test Repo"); - + // Upload a dummy file to ensure the repo has a collection/hash let dummy_file_name = "dummy.txt"; let dummy_file_content = b"dummy content".to_vec(); - repo.upload(dummy_file_name, dummy_file_content.clone()).await?; + repo.upload(dummy_file_name, dummy_file_content.clone()) + .await?; log::info!("Uploaded dummy file: {dummy_file_name}"); - + (group, repo, dummy_file_name, dummy_file_content) }; @@ -805,50 +891,80 @@ mod tests { .uri(&format!("/api/groups/{}/refresh", group.id())) .to_request(); let refresh_resp = test::call_service(&app, refresh_req).await; - + // Verify response status - assert!(refresh_resp.status().is_success(), - "Refresh should succeed, got status: {}", refresh_resp.status()); - + assert!( + refresh_resp.status().is_success(), + "Refresh should succeed, got status: {}", + refresh_resp.status() + ); + // Parse and verify response data let refresh_data: serde_json::Value = test::read_body_json(refresh_resp).await; log::info!("Refresh response: {refresh_data:?}"); - - assert_eq!(refresh_data["status"], "success", "Response should indicate success"); - + + assert_eq!( + refresh_data["status"], "success", + "Response should indicate success" + ); + // Verify repos array - let repos = refresh_data["repos"].as_array() + let repos = refresh_data["repos"] + .as_array() .expect("repos should be an array in response"); assert_eq!(repos.len(), 1, "Should have exactly one repo"); - + // Verify repo details let repo_data = &repos[0]; - assert!(repo_data["can_write"].as_bool().unwrap(), "repo should be writable"); - assert!(repo_data["repo_hash"].is_string(), "repo should have a hash"); + assert!( + repo_data["can_write"].as_bool().unwrap(), + "repo should be writable" + ); + assert!( + repo_data["repo_hash"].is_string(), + "repo should have a hash" + ); assert_eq!(repo_data["name"], "Test Repo", "repo name should match"); - + // Verify refreshed files - let refreshed_files = repo_data["refreshed_files"].as_array() + let refreshed_files = repo_data["refreshed_files"] + .as_array() .expect("refreshed_files should be an array"); - assert!(refreshed_files.is_empty(), "No files should be refreshed since all are present"); + assert!( + refreshed_files.is_empty(), + "No files should be refreshed since all are present" + ); // Verify all_files contains the uploaded file - let all_files = repo_data["all_files"].as_array().expect("all_files should be an array"); + let all_files = repo_data["all_files"] + .as_array() + .expect("all_files should be an array"); assert_eq!(all_files.len(), 1, "Should have one file in all_files"); - assert_eq!(all_files[0], dummy_file_name, "all_files should contain the uploaded file"); + assert_eq!( + all_files[0], dummy_file_name, + "all_files should contain the uploaded file" + ); // Verify file is accessible after refresh let get_file_req = test::TestRequest::get() .uri(&format!( "/api/groups/{}/repos/{}/media/{}", - group.id(), repo.id(), dummy_file_name + group.id(), + repo.id(), + dummy_file_name )) .to_request(); let get_file_resp = test::call_service(&app, get_file_req).await; - assert!(get_file_resp.status().is_success(), "File should be accessible after refresh"); + assert!( + get_file_resp.status().is_success(), + "File should be accessible after refresh" + ); let got_content = test::read_body(get_file_resp).await; - assert_eq!(got_content.to_vec(), dummy_file_content, - "File content should match after refresh"); + assert_eq!( + got_content.to_vec(), + dummy_file_content, + "File content should match after refresh" + ); // Clean up log::info!("Cleaning up test resources..."); @@ -899,26 +1015,47 @@ mod tests { assert!(refresh_resp.status().is_success(), "Refresh should succeed"); let refresh_data: serde_json::Value = test::read_body_json(refresh_resp).await; assert_eq!(refresh_data["status"], "success"); - let repos = refresh_data["repos"].as_array().expect("repos should be an array"); + let repos = refresh_data["repos"] + .as_array() + .expect("repos should be an array"); assert_eq!(repos.len(), 1, "Should have one repo"); let repo_data = &repos[0]; - let refreshed_files = repo_data["refreshed_files"].as_array().expect("refreshed_files should be an array"); - assert!(refreshed_files.is_empty(), "No files should be refreshed since all are present"); - let all_files = repo_data["all_files"].as_array().expect("all_files should be an array"); + let refreshed_files = repo_data["refreshed_files"] + .as_array() + .expect("refreshed_files should be an array"); + assert!( + refreshed_files.is_empty(), + "No files should be refreshed since all are present" + ); + let all_files = repo_data["all_files"] + .as_array() + .expect("all_files should be an array"); assert_eq!(all_files.len(), 1, "Should have one file in all_files"); - assert_eq!(all_files[0], file_name, "all_files should contain the uploaded file"); + assert_eq!( + all_files[0], file_name, + "all_files should contain the uploaded file" + ); // Verify file is accessible let get_file_req = test::TestRequest::get() .uri(&format!( "/api/groups/{}/repos/{}/media/{}", - group.id(), repo.id(), file_name + group.id(), + repo.id(), + file_name )) .to_request(); let get_file_resp = test::call_service(&app, get_file_req).await; - assert!(get_file_resp.status().is_success(), "File should be accessible"); + assert!( + get_file_resp.status().is_success(), + "File should be accessible" + ); let got_content = test::read_body(get_file_resp).await; - assert_eq!(got_content.to_vec(), file_content.to_vec(), "File content should match"); + assert_eq!( + got_content.to_vec(), + file_content.to_vec(), + "File content should match" + ); // Clean up cleanup_test_resources().await?; @@ -976,7 +1113,9 @@ mod tests { let refresh_data: serde_json::Value = test::read_body_json(refresh_resp).await; assert_eq!(refresh_data["status"], "success"); - let repos = refresh_data["repos"].as_array().expect("repos should be an array"); + let repos = refresh_data["repos"] + .as_array() + .expect("repos should be an array"); assert!(!repos.is_empty(), "Group B should have at least one repo"); // Aggregate all files reported by refresh for group B. @@ -1032,17 +1171,16 @@ mod tests { // Create secondary backend (creator) first let (path2, namespace2) = get_test_config("test_refresh_joined_secondary").await; let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; - let (veilid_api2, update_rx2) = - init_veilid_for_tests(path2.to_path_buf().as_path(), namespace2, Duration::from_secs(180)) - .await?; - let backend2 = Backend::from_dependencies( - &path2.to_path_buf(), - veilid_api2, - update_rx2, - store2, + let (veilid_api2, update_rx2) = init_veilid_for_tests( + path2.to_path_buf().as_path(), + namespace2, + Duration::from_secs(180), ) - .await - .unwrap(); + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); // Wait for backend2 (creator) to be network-ready log::info!("Waiting for backend2 (creator) public internet readiness..."); @@ -1186,10 +1324,18 @@ mod tests { tokio::time::sleep(Duration::from_secs(5)).await; }; - assert_eq!(refresh_data["status"], "success", "First refresh status should be success"); + assert_eq!( + refresh_data["status"], "success", + "First refresh status should be success" + ); - let repos = refresh_data["repos"].as_array().expect("repos should be an array"); - assert!(!repos.is_empty(), "Should have at least one repo after joining"); + let repos = refresh_data["repos"] + .as_array() + .expect("repos should be an array"); + assert!( + !repos.is_empty(), + "Should have at least one repo after joining" + ); let repo_data = repos .iter() @@ -1205,7 +1351,8 @@ mod tests { .expect("repo_id should be a string") .to_string(); - let refreshed_files = repo_data["refreshed_files"].as_array() + let refreshed_files = repo_data["refreshed_files"] + .as_array() .expect("refreshed_files should be an array"); assert!( refreshed_files.is_empty() @@ -1214,35 +1361,56 @@ mod tests { "First refresh should report either no-op or one refreshed expected file, got {refreshed_files:?}" ); - let all_files = repo_data["all_files"].as_array().expect("all_files should be an array"); + let all_files = repo_data["all_files"] + .as_array() + .expect("all_files should be an array"); assert_eq!(all_files.len(), 1, "Should have one file in all_files"); - assert_eq!(all_files[0].as_str().unwrap(), file_name, - "all_files should contain the uploaded file"); + assert_eq!( + all_files[0].as_str().unwrap(), + file_name, + "all_files should contain the uploaded file" + ); // Verify file is accessible after refresh let get_file_req = test::TestRequest::get() .uri(&format!( "/api/groups/{}/repos/{}/media/{}", - group.id(), refreshed_repo_id, file_name + group.id(), + refreshed_repo_id, + file_name )) .to_request(); let get_file_resp = test::call_service(&app, get_file_req).await; - assert!(get_file_resp.status().is_success(), "File should be accessible after refresh"); + assert!( + get_file_resp.status().is_success(), + "File should be accessible after refresh" + ); let got_content = test::read_body(get_file_resp).await; - assert_eq!(got_content.to_vec(), file_content.to_vec(), - "File content should match after refresh"); + assert_eq!( + got_content.to_vec(), + file_content.to_vec(), + "File content should match after refresh" + ); // Test second refresh - should be no-op since all files are present let refresh_req2 = test::TestRequest::post() .uri(&format!("/api/groups/{}/refresh", group.id())) .to_request(); let refresh_resp2 = test::call_service(&app, refresh_req2).await; - assert!(refresh_resp2.status().is_success(), "Second refresh should succeed"); - + assert!( + refresh_resp2.status().is_success(), + "Second refresh should succeed" + ); + let refresh_data2: serde_json::Value = test::read_body_json(refresh_resp2).await; - assert_eq!(refresh_data2["status"], "success", "Second refresh status should be success"); - - let repos2 = refresh_data2["repos"].as_array().expect("repos should be an array"); + assert_eq!( + refresh_data2["status"], "success", + "Second refresh status should be success" + ); + + let repos2 = refresh_data2["repos"] + .as_array() + .expect("repos should be an array"); assert!(!repos2.is_empty(), "Should still have repos"); let repo_data2 = repos2 @@ -1254,10 +1422,13 @@ mod tests { .unwrap_or(false) }) .expect("Should still find the repo containing the uploaded file on second refresh"); - let refreshed_files2 = repo_data2["refreshed_files"].as_array() + let refreshed_files2 = repo_data2["refreshed_files"] + .as_array() .expect("refreshed_files should be an array"); - assert!(refreshed_files2.is_empty(), - "No files should be refreshed on second call since all are present"); + assert!( + refreshed_files2.is_empty(), + "No files should be refreshed on second call since all are present" + ); // Clean up both backends - secondary first, then main backend2.stop().await?; @@ -1266,6 +1437,451 @@ mod tests { Ok(()) } + + async fn assert_member_refreshes_owner_upload_after_join( + test_name: &str, + file_name: &str, + file_content: Vec, + ) -> Result<()> { + let _ = env_logger::try_init(); + log::info!("Testing refresh when member joins before owner upload: {test_name}"); + + // Create secondary backend (creator) first. + let (path2, namespace2) = get_test_config(&format!("{test_name}_secondary")).await; + let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; + let (veilid_api2, update_rx2) = init_veilid_for_tests( + path2.to_path_buf().as_path(), + namespace2, + Duration::from_secs(180), + ) + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); + wait_for_public_internet_ready(&backend2).await?; + + // Initialize main backend (joiner). + let _path = init_test_backend(&format!("{test_name}_main")).await?; + { + use server::get_backend; + let backend = get_backend().await?; + wait_for_public_internet_ready(&backend).await?; + } + + // Owner creates a group and repo, but does not upload until after the member joins. + let mut group = backend2.create_group().await?; + let join_url = group.get_url()?; + group.set_name(TEST_GROUP_NAME).await?; + let repo = group.create_repo().await?; + repo.set_name(TEST_GROUP_NAME).await?; + + let app = test::init_service( + App::new() + .service(status) + .service(web::scope("/api").service(groups::scope())), + ) + .await; + + { + use server::get_backend; + let backend = get_backend().await?; + backend.join_from_url(join_url.as_str()).await?; + } + + // Wait until the joiner can see the joined group and at least one repo before upload. + let mut metadata_retries = 20; + loop { + let groups_req = test::TestRequest::get().uri("/api/groups").to_request(); + let groups_resp: GroupsResponse = test::call_and_read_body_json(&app, groups_req).await; + let repos_req = test::TestRequest::get() + .uri(&format!("/api/groups/{}/repos", group.id())) + .to_request(); + let repos_resp: ReposResponse = test::call_and_read_body_json(&app, repos_req).await; + + let has_group = groups_resp + .groups + .iter() + .any(|g| g.key == group.id().to_string()); + if has_group && !repos_resp.repos.is_empty() { + break; + } + + metadata_retries -= 1; + if metadata_retries == 0 { + panic!( + "Member did not converge on joined group metadata before upload. groups: {}, repos: {}", + groups_resp.groups.len(), + repos_resp.repos.len(), + ); + } + tokio::time::sleep(Duration::from_secs(5)).await; + } + + repo.upload(file_name, file_content.clone()).await?; + tokio::time::sleep(Duration::from_secs(4)).await; + + let mut refresh_retries = 20; + loop { + let refresh_req = test::TestRequest::post() + .uri(&format!("/api/groups/{}/refresh", group.id())) + .to_request(); + let refresh_resp = test::call_service(&app, refresh_req).await; + let refresh_status = refresh_resp.status(); + + if refresh_status.is_success() { + let refresh_data: serde_json::Value = test::read_body_json(refresh_resp).await; + let repo_id_with_file = refresh_data["repos"].as_array().and_then(|repos| { + repos.iter().find_map(|repo| { + let has_file = repo["all_files"] + .as_array() + .map(|files| files.iter().any(|f| f.as_str() == Some(file_name))) + .unwrap_or(false); + if has_file { + repo["repo_id"].as_str().map(ToOwned::to_owned) + } else { + None + } + }) + }); + + if let Some(repo_id) = repo_id_with_file { + let get_file_req = test::TestRequest::get() + .uri(&format!( + "/api/groups/{}/repos/{}/media/{}", + group.id(), + repo_id, + file_name + )) + .to_request(); + let get_file_resp = test::call_service(&app, get_file_req).await; + if get_file_resp.status().is_success() { + let got_content = test::read_body(get_file_resp).await; + assert_eq!( + got_content.to_vec(), + file_content, + "Downloaded file should match uploaded bytes" + ); + break; + } + } + } else { + let body = test::read_body(refresh_resp).await; + let body_text = String::from_utf8_lossy(&body).to_string(); + let is_retryable = body_text.contains("couldn't look up relay") + || body_text.contains("Unable to open group DHT record") + || body_text.contains("Group not found:") + || body_text.contains("Unable to download hash"); + if !is_retryable { + panic!( + "Refresh failed with non-retryable error. status={refresh_status}, body={body_text}" + ); + } + } + + refresh_retries -= 1; + if refresh_retries == 0 { + panic!("Member did not refresh and download owner upload after 20 attempts."); + } + tokio::time::sleep(Duration::from_secs(5)).await; + } + + backend2.stop().await?; + tokio::time::sleep(Duration::from_millis(500)).await; + cleanup_test_resources().await?; + + Ok(()) + } + + #[actix_web::test] + #[serial] + async fn test_refresh_member_joined_before_owner_uploads() -> Result<()> { + assert_member_refreshes_owner_upload_after_join( + "test_refresh_member_joined_before_upload", + "member-joined-before-upload-16k.bin", + deterministic_test_payload(16 * 1024), + ) + .await + } + + #[actix_web::test] + #[serial] + #[ignore = "manual large-transfer coverage; 320 KiB is currently flaky on local Veilid/Iroh tunnels"] + async fn test_refresh_member_joined_before_owner_uploads_320k_file() -> Result<()> { + assert_member_refreshes_owner_upload_after_join( + "test_refresh_member_joined_before_upload_320k", + "member-joined-before-upload-320k.bin", + deterministic_test_payload(320 * 1024), + ) + .await + } + + #[actix_web::test] + #[serial] + #[ignore = "manual diagnostic; run with --ignored --nocapture to print file-size stability data"] + async fn test_diagnostic_member_refresh_file_size_sweep() -> Result<()> { + let _ = env_logger::try_init(); + let sizes = diagnostic_file_size_sweep(); + let attempts = env::var("SAVE_FILE_SIZE_SWEEP_ATTEMPTS") + .ok() + .and_then(|value| value.parse::().ok()) + .filter(|value| *value > 0) + .unwrap_or(3); + let continue_after_failure = env_flag("SAVE_FILE_SIZE_SWEEP_CONTINUE"); + + println!( + "FILE_SIZE_SWEEP start sizes={} attempts={} continue_after_failure={}", + sizes + .iter() + .map(|size| format_size(*size)) + .collect::>() + .join(","), + attempts, + continue_after_failure + ); + + // Create secondary backend (creator) first. + let (path2, namespace2) = get_test_config("test_file_size_sweep_secondary").await; + let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; + let (veilid_api2, update_rx2) = init_veilid_for_tests( + path2.to_path_buf().as_path(), + namespace2, + Duration::from_secs(180), + ) + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); + wait_for_public_internet_ready(&backend2).await?; + + // Initialize main backend (joiner). + let _path = init_test_backend("test_file_size_sweep_main").await?; + { + use server::get_backend; + let backend = get_backend().await?; + wait_for_public_internet_ready(&backend).await?; + } + + let mut group = backend2.create_group().await?; + let join_url = group.get_url()?; + group.set_name(TEST_GROUP_NAME).await?; + let repo = group.create_repo().await?; + repo.set_name(TEST_GROUP_NAME).await?; + + let app = test::init_service( + App::new() + .service(status) + .service(web::scope("/api").service(groups::scope())), + ) + .await; + + { + use server::get_backend; + let backend = get_backend().await?; + backend.join_from_url(join_url.as_str()).await?; + } + + let mut metadata_retries = 20; + loop { + let groups_req = test::TestRequest::get().uri("/api/groups").to_request(); + let groups_resp: GroupsResponse = test::call_and_read_body_json(&app, groups_req).await; + let repos_req = test::TestRequest::get() + .uri(&format!("/api/groups/{}/repos", group.id())) + .to_request(); + let repos_resp: ReposResponse = test::call_and_read_body_json(&app, repos_req).await; + + let has_group = groups_resp + .groups + .iter() + .any(|g| g.key == group.id().to_string()); + if has_group && !repos_resp.repos.is_empty() { + break; + } + + metadata_retries -= 1; + if metadata_retries == 0 { + println!( + "FILE_SIZE_SWEEP setup_result=fail stage=metadata detail=\"groups={}, repos={}\"", + groups_resp.groups.len(), + repos_resp.repos.len() + ); + backend2.stop().await?; + tokio::time::sleep(Duration::from_millis(500)).await; + cleanup_test_resources().await?; + return Ok(()); + } + tokio::time::sleep(Duration::from_secs(5)).await; + } + + for size in sizes { + let file_name = format!("sweep-{size}.bin"); + let file_content = deterministic_test_payload(size); + let upload_started = std::time::Instant::now(); + match repo.upload(&file_name, file_content.clone()).await { + Ok(_) => {} + Err(e) => { + println!( + "FILE_SIZE_SWEEP size={} bytes={} result=fail stage=upload attempts=0 upload_ms={} detail=\"{}\"", + format_size(size), + size, + upload_started.elapsed().as_millis(), + e + ); + if !continue_after_failure { + break; + } + continue; + } + } + let upload_ms = upload_started.elapsed().as_millis(); + tokio::time::sleep(Duration::from_secs(4)).await; + + let mut last_stage = "not_attempted"; + let mut last_detail = String::new(); + let mut last_refresh_ms = 0; + let mut last_download_ms = 0; + let mut passed = false; + + for attempt in 1..=attempts { + let refresh_started = std::time::Instant::now(); + let refresh_req = test::TestRequest::post() + .uri(&format!("/api/groups/{}/refresh", group.id())) + .to_request(); + let refresh_resp = test::call_service(&app, refresh_req).await; + last_refresh_ms = refresh_started.elapsed().as_millis(); + let refresh_status = refresh_resp.status(); + + if !refresh_status.is_success() { + let body = test::read_body(refresh_resp).await; + let body_text = String::from_utf8_lossy(&body).to_string(); + last_stage = classify_transfer_failure(&body_text); + last_detail = format!("refresh status={refresh_status}, body={body_text}"); + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + + let refresh_data: serde_json::Value = test::read_body_json(refresh_resp).await; + let repo_errors = refresh_data["repos"] + .as_array() + .map(|repos| { + repos + .iter() + .flat_map(|repo| { + ["error", "repo_hash_error", "error_listing_files"] + .into_iter() + .filter_map(|key| repo[key].as_str()) + .map(ToOwned::to_owned) + .collect::>() + }) + .collect::>() + }) + .unwrap_or_default(); + let repo_id_with_file = refresh_data["repos"].as_array().and_then(|repos| { + repos.iter().find_map(|repo| { + let has_file = repo["all_files"] + .as_array() + .map(|files| files.iter().any(|f| f.as_str() == Some(&file_name))) + .unwrap_or(false); + if has_file { + repo["repo_id"].as_str().map(ToOwned::to_owned) + } else { + None + } + }) + }); + + let Some(repo_id) = repo_id_with_file else { + last_stage = if repo_errors.iter().any(|error| error.contains("repo hash")) { + "repo_hash_dht" + } else if repo_errors + .iter() + .any(|error| error.contains("downloading collection")) + { + "collection_blob_transfer" + } else { + "refresh_visible" + }; + last_detail = if repo_errors.is_empty() { + "refresh succeeded but file was not visible".to_string() + } else { + repo_errors.join(" | ") + }; + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + }; + + let download_started = std::time::Instant::now(); + let get_file_req = test::TestRequest::get() + .uri(&format!( + "/api/groups/{}/repos/{}/media/{}", + group.id(), + repo_id, + file_name + )) + .to_request(); + let get_file_resp = test::call_service(&app, get_file_req).await; + last_download_ms = download_started.elapsed().as_millis(); + let download_status = get_file_resp.status(); + + if !download_status.is_success() { + let body = test::read_body(get_file_resp).await; + let body_text = String::from_utf8_lossy(&body).to_string(); + last_stage = classify_transfer_failure(&body_text); + last_detail = format!("download status={download_status}, body={body_text}"); + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + + let got_content = test::read_body(get_file_resp).await; + if got_content.to_vec() == file_content { + println!( + "FILE_SIZE_SWEEP size={} bytes={} result=ok attempts={} upload_ms={} refresh_ms={} download_ms={}", + format_size(size), + size, + attempt, + upload_ms, + last_refresh_ms, + last_download_ms + ); + passed = true; + break; + } + + last_stage = "download_bytes"; + last_detail = format!( + "downloaded {} bytes, expected {} bytes", + got_content.len(), + size + ); + tokio::time::sleep(Duration::from_secs(5)).await; + } + + if !passed { + println!( + "FILE_SIZE_SWEEP size={} bytes={} result=fail attempts={} upload_ms={} refresh_ms={} download_ms={} stage={} detail=\"{}\"", + format_size(size), + size, + attempts, + upload_ms, + last_refresh_ms, + last_download_ms, + last_stage, + last_detail.replace('"', "'") + ); + if !continue_after_failure { + break; + } + } + } + + backend2.stop().await?; + tokio::time::sleep(Duration::from_millis(500)).await; + cleanup_test_resources().await?; + + Ok(()) + } + #[actix_web::test] #[serial] async fn test_health_endpoint() -> Result<()> { @@ -1283,13 +1899,19 @@ mod tests { // Test the health endpoint let health_req = test::TestRequest::get().uri("/health").to_request(); let health_resp = test::call_service(&app, health_req).await; - + // Verify response status is 200 OK - assert!(health_resp.status().is_success(), "Health endpoint should return 200 OK"); - + assert!( + health_resp.status().is_success(), + "Health endpoint should return 200 OK" + ); + // Verify response body let health_data: serde_json::Value = test::read_body_json(health_resp).await; - assert_eq!(health_data["status"], "OK", "Health endpoint should return status OK"); + assert_eq!( + health_data["status"], "OK", + "Health endpoint should return status OK" + ); // Clean up cleanup_test_resources().await?; @@ -1318,19 +1940,13 @@ mod tests { // Create secondary backend (creator) with unique namespace let (path2, namespace2) = get_test_config("test_idempotent_create_repo_secondary").await; let store2 = iroh_blobs::store::fs::Store::load(path2.to_path_buf().join("iroh2")).await?; - let (veilid_api2, update_rx2) = save_dweb_backend::common::init_veilid( - path2.to_path_buf().as_path(), - namespace2, - ) - .await?; - let backend2 = Backend::from_dependencies( - &path2.to_path_buf(), - veilid_api2, - update_rx2, - store2, - ) - .await - .unwrap(); + let (veilid_api2, update_rx2) = + save_dweb_backend::common::init_veilid(path2.to_path_buf().as_path(), namespace2) + .await?; + let backend2 = + Backend::from_dependencies(&path2.to_path_buf(), veilid_api2, update_rx2, store2) + .await + .unwrap(); // Create a group on backend2 (creator) let group2 = backend2.create_group().await?; diff --git a/src/media.rs b/src/media.rs index e00ab27..3407fc1 100644 --- a/src/media.rs +++ b/src/media.rs @@ -1,11 +1,13 @@ use crate::constants::TAG; use crate::error::{AppError, AppResult}; +use crate::log_info; use crate::models::{GroupRepoMediaPath, GroupRepoPath}; use crate::server::get_backend; use crate::utils::create_veilid_cryptokey_from_base64; -use crate::log_info; -use actix_web::{delete, get, post, web, HttpResponse, Responder, Scope, http::header, error::BlockingError}; -use bytes::{BytesMut, Bytes}; +use actix_web::{ + delete, error::BlockingError, get, http::header, post, web, HttpResponse, Responder, Scope, +}; +use bytes::{Bytes, BytesMut}; use futures::Stream; use futures::StreamExt; use serde_json::json; @@ -23,7 +25,9 @@ pub fn from_blocking(result: Result) -> AppResult { result.map_err(AppError::from) } -async fn handle_file_stream(mut file_data: impl Stream> + Unpin) -> AppResult<(usize, Bytes)> { +async fn handle_file_stream( + mut file_data: impl Stream> + Unpin, +) -> AppResult<(usize, Bytes)> { let mut buffer = BytesMut::new(); let mut length = 0; @@ -33,9 +37,7 @@ async fn handle_file_stream(mut file_data: impl Stream) -> AppResult Scope { web::scope("/repos") @@ -91,7 +91,10 @@ async fn create_repo( // The Android UI may still call this endpoint after joining; make it idempotent. // Check for existing repo FIRST to avoid error-path issues with get_group cache. let repo = if let Some(existing) = group.get_own_repo().await { - log_debug!(TAG, "Own repo already exists, returning existing (idempotent)"); + log_debug!( + TAG, + "Own repo already exists, returning existing (idempotent)" + ); existing } else { group.create_repo().await? diff --git a/src/server.rs b/src/server.rs index 562ab32..275ea26 100644 --- a/src/server.rs +++ b/src/server.rs @@ -14,17 +14,17 @@ use save_dweb_backend::backend::Backend; use serde::Deserialize; use serde_json::json; use std::net::Ipv4Addr; -use std::time::{Duration, Instant}; use std::path::Path; use std::sync::Arc; +use std::time::{Duration, Instant}; use std::{env, panic}; use thiserror::Error; +use crate::actix_route_dumper::RouteDumper; +use crate::models::SnowbirdGroup; #[cfg(test)] use std::sync::RwLock; use veilid_core::VeilidUpdate; -use crate::actix_route_dumper::RouteDumper; -use crate::models::SnowbirdGroup; #[derive(Error, Debug)] pub enum BackendError { @@ -53,7 +53,9 @@ pub async fn get_backend() -> Result, anyhow::Error> { } #[cfg(test)] { - let backend_lock = BACKEND.read().map_err(|e| anyhow!("Failed to read backend lock: {e}"))?; + let backend_lock = BACKEND + .read() + .map_err(|e| anyhow!("Failed to read backend lock: {e}"))?; match backend_lock.as_ref() { Some(backend) => Ok(Arc::clone(backend)), None => Err(anyhow!("Backend not initialized")), @@ -63,14 +65,18 @@ pub async fn get_backend() -> Result, anyhow::Error> { #[cfg(test)] pub fn set_backend(backend: Arc) -> Result<()> { - let mut backend_lock = BACKEND.write().map_err(|e| anyhow!("Failed to write backend lock: {e}"))?; + let mut backend_lock = BACKEND + .write() + .map_err(|e| anyhow!("Failed to write backend lock: {e}"))?; *backend_lock = Some(backend); Ok(()) } #[cfg(test)] pub fn clear_backend() -> Result<()> { - let mut backend_lock = BACKEND.write().map_err(|e| anyhow!("Failed to write backend lock: {e}"))?; + let mut backend_lock = BACKEND + .write() + .map_err(|e| anyhow!("Failed to write backend lock: {e}"))?; *backend_lock = None; Ok(()) } @@ -125,16 +131,16 @@ async fn health_ready() -> AppResult { #[derive(Deserialize)] struct JoinGroupRequest { - uri: String + uri: String, } #[post("memberships")] async fn join_group(body: web::Json) -> AppResult { let join_request_data = body.into_inner(); - + // Ensure backend is fully initialized before proceeding ensure_backend_ready().await?; - + let backend = get_backend().await?; let boxed_group = backend.join_from_url(&join_request_data.uri).await?; let snowbird_group: SnowbirdGroup = boxed_group.as_ref().into(); @@ -162,7 +168,11 @@ fn get_optimal_worker_count() -> usize { log_info!(TAG, "Using SAVE_WORKER_COUNT={} (override)", worker_count); return worker_count; } else { - log_error!(TAG, "Invalid SAVE_WORKER_COUNT value: {}, using default", worker_count_str); + log_error!( + TAG, + "Invalid SAVE_WORKER_COUNT value: {}, using default", + worker_count_str + ); } } @@ -173,7 +183,11 @@ fn get_optimal_worker_count() -> usize { } pub async fn start(backend_base_directory: &str, server_socket_path: &str) -> anyhow::Result<()> { - log_debug!(TAG, "start_server: Using socket path: {:?}", server_socket_path); + log_debug!( + TAG, + "start_server: Using socket path: {:?}", + server_socket_path + ); let worker_count = get_optimal_worker_count(); @@ -231,15 +245,15 @@ pub async fn start(backend_base_directory: &str, server_socket_path: &str) -> an let web_server = HttpServer::new(move || { let app_start = Instant::now(); let app = App::new() - .wrap(RouteDumper::new(actix_log)) - .service(status) - .service(health) - .service(health_ready) - .service( - web::scope("/api") - .service(join_group) - .service(groups::scope()) - ); + .wrap(RouteDumper::new(actix_log)) + .service(status) + .service(health) + .service(health_ready) + .service( + web::scope("/api") + .service(join_group) + .service(groups::scope()), + ); log_perf("Web server app created", app_start.elapsed()); app }) @@ -250,7 +264,7 @@ pub async fn start(backend_base_directory: &str, server_socket_path: &str) -> an log_perf("Web server initialized", start_instant.elapsed()); log_info!(TAG, "Starting web server..."); - + let server_future = web_server.run(); log_perf("Web server started", start_instant.elapsed()); diff --git a/src/utils.rs b/src/utils.rs index 89434c2..1ae9931 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ +use crate::error::AppResult; use base64_url; use std::convert::TryInto; -use veilid_core::{RecordKey, BareRecordKey, BareOpaqueRecordKey, CRYPTO_KIND_VLD0}; -use crate::error::AppResult; +use veilid_core::{BareOpaqueRecordKey, BareRecordKey, RecordKey, CRYPTO_KIND_VLD0}; /// Parse a RecordKey from either: /// - Typed format: "VLD0:base64_key:base64_hash" (from RecordKey::to_string()) @@ -18,12 +18,12 @@ pub fn create_veilid_cryptokey_from_base64(key_string: &str) -> AppResult