diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20c2566545..7b4b7a56b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,9 +82,9 @@ jobs: - os: macos-latest rust: 1.75.0 - # Minimum Supported Rust Version = 1.70.0 + # Minimum Supported Rust Version = 1.72.0 - os: ubuntu-latest - rust: 1.70.0 + rust: 1.72.0 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index 6937a5711f..f013f659a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,6 +30,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "bytes", + "crypto-common", + "generic-array", +] + [[package]] name = "aes" version = "0.8.3" @@ -307,6 +318,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "attohttpc" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247" +dependencies = [ + "http 0.2.11", + "log", + "url", + "wildmatch", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -340,7 +363,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sha1", + "sha1 0.10.6", "sync_wrapper", "tokio", "tokio-tungstenite", @@ -371,6 +394,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom 0.2.11", + "instant", + "rand 0.8.5", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -386,6 +420,29 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bao-tree" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155e7e0c896695a9049badd7bf2b915d29230e24dc82a7c7ef065eded072404f" +dependencies = [ + "bytes", + "futures", + "iroh-blake3", + "iroh-io", + "positioned-io", + "range-collections", + "self_cell", + "smallvec", + "tokio", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base16ct" version = "0.1.1" @@ -428,6 +485,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "binary-merge" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" + [[package]] name = "bincode" version = "1.3.3" @@ -505,6 +568,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "bounded-integer" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a6932c88f1d2c29533a3b8a5f5a2f84cc19c3339b431677c3160c5c2e6ca85" + [[package]] name = "brotli" version = "3.4.0" @@ -569,6 +638,9 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "camellia" @@ -650,6 +722,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "charset" version = "0.1.3" @@ -670,6 +753,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-targets 0.48.5", ] @@ -709,6 +793,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -835,6 +920,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc24" version = "0.1.6" @@ -950,9 +1050,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "crypto_box" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" +dependencies = [ + "aead", + "chacha20", + "crypto_secretbox", + "curve25519-dalek 4.1.1", + "salsa20", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "chacha20", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -1064,27 +1197,77 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "data-encoding-macro" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +dependencies = [ + "data-encoding", + "syn 1.0.109", +] + [[package]] name = "default-net" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4898b43aed56499fad6b294d15b3e76a51df68079bf492e5daae38ca084e003" dependencies = [ - "dlopen2", + "dlopen2 0.4.1", + "libc", + "memalloc", + "netlink-packet-core 0.5.0", + "netlink-packet-route 0.15.0", + "netlink-sys", + "once_cell", + "system-configuration", + "windows 0.32.0", +] + +[[package]] +name = "default-net" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba429d84a27fa854c66fd2e29eb1cdf6d38bbfd4495bd9f522f12a7f21e05bf" +dependencies = [ + "dlopen2 0.5.0", "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", - "windows", + "windows 0.48.0", ] [[package]] @@ -1117,6 +1300,9 @@ dependencies = [ "humansize", "image", "iroh", + "iroh-base", + "iroh-gossip", + "iroh-net", "kamadak-exif", "lettre_email", "libc", @@ -1136,6 +1322,7 @@ dependencies = [ "proptest", "qrcodegen", "quick-xml", + "quinn", "quoted_printable", "rand 0.8.5", "ratelimit", @@ -1255,7 +1442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" dependencies = [ "const-oid", - "der_derive", + "der_derive 0.6.1", "pem-rfc7468 0.6.0", "zeroize", ] @@ -1267,6 +1454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", + "der_derive 0.7.2", "pem-rfc7468 0.7.0", "zeroize", ] @@ -1297,6 +1485,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "der_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1304,6 +1503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -1350,6 +1550,27 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", + "unicode-xid", +] + [[package]] name = "des" version = "0.8.1" @@ -1451,6 +1672,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "libc", + "once_cell", + "winapi", +] + [[package]] name = "dlopen2_derive" version = "0.2.0" @@ -1462,6 +1694,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + [[package]] name = "dyn-clone" version = "1.0.16" @@ -1511,6 +1761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8 0.10.2", + "serde", "signature 2.2.0", ] @@ -1537,6 +1788,7 @@ checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek 4.1.1", "ed25519 2.2.3", + "rand_core 0.6.4", "serde", "sha2 0.10.8", "subtle", @@ -1764,6 +2016,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +dependencies = [ + "serde", +] + +[[package]] +name = "erased_set" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5aa24577083f8190ad401e376b55887c7cd9083ae95d83ceec5d28ea78125" + [[package]] name = "errno" version = "0.3.8" @@ -1938,6 +2205,18 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2056,6 +2335,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.30" @@ -2074,6 +2359,22 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "futures-core", + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generic-array" version = "0.14.7" @@ -2125,6 +2426,30 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "governor" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "821239e5672ff23e2a7060901fa622950bbd80b649cdaadd78d1c1767ed14eb4" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "quanta", + "rand 0.8.5", + "smallvec", +] + [[package]] name = "group" version = "0.12.1" @@ -2291,6 +2616,21 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac-sha1" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1333fad8d94b82cab989da428b0b36a3435db3870d85e971a1d6dc0a8576722" +dependencies = [ + "sha1 0.2.0", +] + +[[package]] +name = "hmac-sha256" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" + [[package]] name = "home" version = "0.5.9" @@ -2311,6 +2651,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "hostname-validator" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" + [[package]] name = "http" version = "0.2.11" @@ -2449,6 +2795,21 @@ dependencies = [ "itoa", "pin-project-lite", "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.11", + "hyper 0.14.28", + "rustls", + "tokio", + "tokio-rustls", ] [[package]] @@ -2493,7 +2854,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2541,14 +2902,32 @@ dependencies = [ ] [[package]] -name = "image" -version = "0.24.7" +name = "igd" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "556b5a75cd4adb7c4ea21c64af1c48cefb2ce7d43dc4352c720a1fe47c21f355" dependencies = [ - "bytemuck", - "byteorder", - "color_quant", + "attohttpc", + "bytes", + "futures", + "http 0.2.11", + "hyper 0.14.28", + "log", + "rand 0.8.5", + "tokio", + "url", + "xmltree", +] + +[[package]] +name = "image" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", "gif", "jpeg-decoder", "num-rational", @@ -2583,6 +2962,24 @@ dependencies = [ "generic-array", ] +[[package]] +name = "inplace-vec-builder" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" +dependencies = [ + "smallvec", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipconfig" version = "0.3.2" @@ -2603,18 +3000,17 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "iroh" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85075391dcb8491a4939266334b28601052d418b37d20b33c58ffb5776adc912" +version = "0.4.1" +source = "git+https://github.com/deltachat/iroh?branch=0.4-update-quic#36ca9ca017a101c00dfdf74a917b92bdc505ddbd" dependencies = [ "abao", "anyhow", "base64 0.21.5", "blake3", "bytes", - "default-net", + "default-net 0.14.1", "der 0.6.1", - "derive_more", + "derive_more 0.99.17", "dirs-next", "ed25519-dalek 1.0.1", "futures", @@ -2625,13 +3021,13 @@ dependencies = [ "quic-rpc", "quinn", "rand 0.7.3", - "rcgen", + "rcgen 0.10.0", "ring 0.16.20", "rustls", "rustls-webpki", "serde", "serde-error", - "ssh-key", + "ssh-key 0.5.1", "tempfile", "thiserror", "tokio", @@ -2641,7 +3037,171 @@ dependencies = [ "tracing-futures", "tracing-subscriber", "walkdir", - "x509-parser", + "x509-parser 0.14.0", + "zeroize", +] + +[[package]] +name = "iroh-base" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" +dependencies = [ + "anyhow", + "bao-tree", + "data-encoding", + "hex", + "multibase", + "postcard", + "serde", + "serde-error", + "thiserror", +] + +[[package]] +name = "iroh-blake3" +version = "1.4.4" +source = "git+https://github.com/n0-computer/iroh-blake3.git?branch=master#c94bc3e3b9f88764ecba4e76103a9c393145329f" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "iroh-gossip" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" +dependencies = [ + "anyhow", + "bytes", + "data-encoding", + "derive_more 1.0.0-beta.6", + "ed25519-dalek 2.1.0", + "futures", + "genawaiter", + "indexmap", + "iroh-base", + "iroh-blake3", + "iroh-metrics", + "iroh-net", + "once_cell", + "postcard", + "quinn", + "rand 0.8.5", + "rand_core 0.6.4", + "serde", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "iroh-io" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ace4f69567bfeb726672bab901d3e81be0c01119d860b2a10b7efb1553b880" +dependencies = [ + "bytes", + "futures", + "pin-project", + "smallvec", + "tokio", +] + +[[package]] +name = "iroh-metrics" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" +dependencies = [ + "anyhow", + "erased_set", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "once_cell", + "prometheus-client", + "reqwest", + "serde", + "struct_iterable", + "time 0.3.31", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-net" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" +dependencies = [ + "aead", + "anyhow", + "backoff", + "bytes", + "crypto_box", + "curve25519-dalek 4.1.1", + "data-encoding", + "default-net 0.20.0", + "der 0.7.8", + "derive_more 1.0.0-beta.6", + "duct", + "ed25519-dalek 2.1.0", + "flume 0.11.0", + "futures", + "governor", + "hex", + "hostname", + "http 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "igd", + "iroh-base", + "iroh-metrics", + "libc", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", + "netlink-sys", + "num_enum", + "once_cell", + "parking_lot", + "postcard", + "quinn", + "quinn-proto", + "quinn-udp", + "rand 0.8.5", + "rand_core 0.6.4", + "rcgen 0.11.3", + "reqwest", + "ring 0.17.7", + "rtnetlink", + "rustls", + "rustls-webpki", + "serde", + "serde_bytes", + "serdect", + "smallvec", + "socket2", + "ssh-key 0.6.4", + "strum", + "stun-rs", + "surge-ping", + "thiserror", + "time 0.3.31", + "tokio", + "tokio-rustls", + "tokio-rustls-acme", + "tokio-util", + "tracing", + "trust-dns-resolver", + "ttl_cache", + "url", + "watchable", + "webpki-roots", + "windows 0.51.1", + "wmi", + "x509-parser 0.15.1", "zeroize", ] @@ -2809,6 +3369,15 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "mailparse" version = "0.14.1" @@ -2851,6 +3420,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memalloc" version = "0.1.0" @@ -2896,6 +3471,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + [[package]] name = "mutate_once" version = "0.1.1" @@ -2941,6 +3527,17 @@ dependencies = [ "netlink-packet-utils", ] +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + [[package]] name = "netlink-packet-route" version = "0.15.0" @@ -2951,7 +3548,21 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "libc", - "netlink-packet-core", + "netlink-packet-core 0.5.0", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core 0.7.0", "netlink-packet-utils", ] @@ -2967,6 +3578,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "netlink-proto" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842c6770fc4bb33dd902f41829c61ef872b8e38de1405aa0b938b27b8fba12c3" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core 0.7.0", + "netlink-sys", + "thiserror", + "tokio", +] + [[package]] name = "netlink-sys" version = "0.8.5" @@ -2974,8 +3600,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "bytes", + "futures", "libc", "log", + "tokio", ] [[package]] @@ -2987,6 +3615,17 @@ dependencies = [ "smallvec", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nix" version = "0.27.1" @@ -2998,6 +3637,18 @@ dependencies = [ "libc", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "nom" version = "7.1.3" @@ -3008,6 +3659,12 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "ntapi" version = "0.4.1" @@ -3119,6 +3776,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "object" version = "0.32.2" @@ -3226,6 +3904,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "os_pipe" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "overload" version = "0.1.1" @@ -3278,6 +3966,20 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct 0.2.0", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "primeorder", + "rand_core 0.6.4", + "sha2 0.10.8", +] + [[package]] name = "parking" version = "2.2.0" @@ -3322,6 +4024,26 @@ dependencies = [ "base64 0.13.1", ] +[[package]] +name = "pem" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a" +dependencies = [ + "base64 0.21.5", + "serde", +] + +[[package]] +name = "pem" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +dependencies = [ + "base64 0.21.5", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.6.0" @@ -3346,6 +4068,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.46", +] + +[[package]] +name = "pest_meta" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + [[package]] name = "pgp" version = "0.10.2" @@ -3387,7 +4154,7 @@ dependencies = [ "rand 0.8.5", "ripemd", "rsa 0.9.6", - "sha1", + "sha1 0.10.6", "sha2 0.10.8", "sha3", "signature 2.2.0", @@ -3513,6 +4280,48 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pnet_base" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872e46346144ebf35219ccaa64b1dffacd9c6f188cd7d012bd6977a2a838f42e" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_macros" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a780e80005c2e463ec25a6e9f928630049a10b43945fea83207207d4a7606f4" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", +] + +[[package]] +name = "pnet_macros_support" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d932134f32efd7834eb8b16d42418dac87086347d1bc7d142370ef078582bc" +dependencies = [ + "pnet_base", +] + +[[package]] +name = "pnet_packet" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde678bbd85cb1c2d99dc9fc596e57f03aa725f84f3168b0eaf33eeccb41706" +dependencies = [ + "glob", + "pnet_base", + "pnet_macros", + "pnet_macros_support", +] + [[package]] name = "png" version = "0.17.10" @@ -3526,12 +4335,33 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +[[package]] +name = "positioned-io" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccabfeeb89c73adf4081f0dca7f8e28dbda90981a222ceea37f619e93ea6afe9" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "postcard" version = "1.0.8" @@ -3568,6 +4398,40 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precis-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73e9dd26361c32e7cd13d1032bb01c4e26a23287274e8a4e2f228cf2c9ff77b" +dependencies = [ + "precis-tools", + "ucd-parse", + "unicode-normalization", +] + +[[package]] +name = "precis-profiles" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688124d96df311c37d794fb574bb5f75cdc86d8c5e514d3816d770a3dd0e1568" +dependencies = [ + "lazy_static", + "precis-core", + "precis-tools", + "unicode-normalization", +] + +[[package]] +name = "precis-tools" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07ecadec70b0f560f09abf815ae0ee1a940d38d2354c938ba7229ac7c9f5f52" +dependencies = [ + "lazy_static", + "regex", + "ucd-parse", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -3597,6 +4461,15 @@ dependencies = [ "elliptic-curve 0.13.8", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3630,6 +4503,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prometheus-client" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510c4f1c9d81d556458f94c98f857748130ea9737bbd6053da497503b26ea63c" +dependencies = [ + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "proptest" version = "1.4.0" @@ -3652,6 +4548,22 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" +[[package]] +name = "quanta" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +dependencies = [ + "crossbeam-utils", + "libc", + "mach2", + "once_cell", + "raw-cpuid", + "wasi 0.11.0+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + [[package]] name = "quic-rpc" version = "0.6.1" @@ -3660,7 +4572,7 @@ checksum = "6d60c2fc2390baad4b9d41ae9957ae88c3095496f88e252ef50722df8b5b78d7" dependencies = [ "bincode", "educe", - "flume", + "flume 0.10.14", "futures", "pin-project", "quinn", @@ -3743,6 +4655,16 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quoted-string-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc75379cdb451d001f1cb667a9f74e8b355e9df84cc5193513cbe62b96fc5e9" +dependencies = [ + "pest", + "pest_derive", +] + [[package]] name = "quoted_printable" version = "0.5.0" @@ -3839,10 +4761,31 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "range-collections" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca9edd21e2db51000ac63eccddabba622f826e631a60be7bade9bd6a76b69537" +dependencies = [ + "binary-merge", + "inplace-vec-builder", + "ref-cast", + "smallvec", +] + [[package]] name = "ratelimit" version = "1.0.0" +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "rayon" version = "1.8.0" @@ -3869,7 +4812,19 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ - "pem", + "pem 1.1.1", + "ring 0.16.20", + "time 0.3.31", + "yasna", +] + +[[package]] +name = "rcgen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" +dependencies = [ + "pem 3.0.3", "ring 0.16.20", "time 0.3.31", "yasna", @@ -3904,6 +4859,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref-cast" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "regex" version = "1.10.2" @@ -3936,6 +4911,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -3963,6 +4944,7 @@ dependencies = [ "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -3972,17 +4954,21 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] @@ -4090,12 +5076,31 @@ dependencies = [ "pkcs1 0.7.5", "pkcs8 0.10.2", "rand_core 0.6.4", + "sha2 0.10.8", "signature 2.2.0", "spki 0.7.3", "subtle", "zeroize", ] +[[package]] +name = "rtnetlink" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" +dependencies = [ + "futures", + "log", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", + "netlink-packet-utils", + "netlink-proto", + "netlink-sys", + "nix 0.26.4", + "thiserror", + "tokio", +] + [[package]] name = "rusqlite" version = "0.30.0" @@ -4165,6 +5170,7 @@ version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ + "log", "ring 0.17.7", "rustls-webpki", "sct", @@ -4221,7 +5227,7 @@ dependencies = [ "libc", "log", "memchr", - "nix", + "nix 0.27.1", "radix_trie", "unicode-segmentation", "unicode-width", @@ -4241,6 +5247,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -4466,6 +5481,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct 0.2.0", + "serde", +] + [[package]] name = "sha-1" version = "0.10.1" @@ -4477,6 +5502,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" + [[package]] name = "sha1" version = "0.10.6" @@ -4531,6 +5562,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -4632,6 +5673,16 @@ dependencies = [ "der 0.7.8", ] +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher", + "ssh-encoding 0.2.0", +] + [[package]] name = "ssh-encoding" version = "0.1.0" @@ -4639,7 +5690,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19cfdc32e0199062113edf41f344fbf784b8205a94600233c84eb838f45191e1" dependencies = [ "base64ct", - "pem-rfc7468 0.6.0", + "pem-rfc7468 0.6.0", + "sha2 0.10.8", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "pem-rfc7468 0.7.0", "sha2 0.10.8", ] @@ -4657,7 +5719,28 @@ dependencies = [ "sec1 0.3.0", "sha2 0.10.8", "signature 1.6.4", - "ssh-encoding", + "ssh-encoding 0.1.0", + "zeroize", +] + +[[package]] +name = "ssh-key" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01f8f4ea73476c0aa5d5e6a75ce1e8634e2c3f82005ef3bbed21547ac57f2bf7" +dependencies = [ + "ed25519-dalek 2.1.0", + "p256 0.13.2", + "p384 0.13.0", + "p521", + "rand_core 0.6.4", + "rsa 0.9.6", + "sec1 0.7.3", + "sha2 0.10.8", + "signature 2.2.0", + "ssh-cipher", + "ssh-encoding 0.2.0", + "subtle", "zeroize", ] @@ -4679,11 +5762,43 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "struct_iterable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "849a064c6470a650b72e41fa6c057879b68f804d113af92900f27574828e7712" +dependencies = [ + "struct_iterable_derive", + "struct_iterable_internal", +] + +[[package]] +name = "struct_iterable_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb939ce88a43ea4e9d012f2f6b4cc789deb2db9d47bad697952a85d6978662c" +dependencies = [ + "erased-serde", + "proc-macro2", + "quote", + "struct_iterable_internal", + "syn 2.0.46", +] + +[[package]] +name = "struct_iterable_internal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9426b2a0c03e6cc2ea8dbc0168dbbf943f88755e409fb91bcb8f6a268305f4a" + [[package]] name = "strum" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] [[package]] name = "strum_macros" @@ -4698,12 +5813,50 @@ dependencies = [ "syn 2.0.46", ] +[[package]] +name = "stun-rs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78517bf347f802eba0204cdecf5ff10fb7056c914a3b2d9f2011f231cb1438b5" +dependencies = [ + "bounded-integer", + "byteorder", + "crc", + "fallible-iterator", + "hmac-sha1", + "hmac-sha256", + "hostname-validator", + "lazy_static", + "md5", + "paste", + "precis-core", + "precis-profiles", + "quoted-string-parser", + "rand 0.8.5", +] + [[package]] name = "subtle" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "surge-ping" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af341b2be485d647b5dc4cfb2da99efac35b5c95748a08fb7233480fedc5ead3" +dependencies = [ + "hex", + "parking_lot", + "pnet_packet", + "rand 0.8.5", + "socket2", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "syn" version = "1.0.109" @@ -4977,6 +6130,42 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-rustls-acme" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb6f50b5523d014ba161512c37457acb16fd8218c883c7152e0a67ab763f2d4" +dependencies = [ + "async-trait", + "base64 0.21.5", + "chrono", + "futures", + "log", + "pem 2.0.1", + "rcgen 0.11.3", + "reqwest", + "ring 0.16.20", + "rustls", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-rustls", + "url", + "webpki-roots", + "x509-parser 0.15.1", +] + [[package]] name = "tokio-serde" version = "0.8.0" @@ -5178,12 +6367,67 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trust-dns-proto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand 0.8.5", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "ttl_cache" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "tungstenite" version = "0.21.0" @@ -5197,7 +6441,7 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "sha1", + "sha1 0.10.6", "thiserror", "url", "utf-8", @@ -5242,6 +6486,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ucd-parse" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" +dependencies = [ + "regex-lite", +] + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unarray" version = "0.1.4" @@ -5293,6 +6552,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -5314,6 +6583,7 @@ dependencies = [ "form_urlencoded", "idna 0.5.0", "percent-encoding", + "serde", ] [[package]] @@ -5459,6 +6729,18 @@ version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +[[package]] +name = "watchable" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45b42a2f611916b5965120a9cde2b60f2db4454826dd9ad5e6f47c24a5b3b259" +dependencies = [ + "event-listener 4.0.2", + "futures-util", + "parking_lot", + "thiserror", +] + [[package]] name = "web-sys" version = "0.3.66" @@ -5469,6 +6751,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" + [[package]] name = "weezl" version = "0.1.7" @@ -5491,6 +6779,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +[[package]] +name = "wildmatch" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a" + [[package]] name = "winapi" version = "0.3.9" @@ -5535,6 +6829,46 @@ dependencies = [ "windows_x86_64_msvc 0.32.0", ] +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "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-implement", + "windows-interface", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -5544,6 +6878,28 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "windows-implement" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + +[[package]] +name = "windows-interface" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5725,6 +7081,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wmi" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff298e96fd8ef6bb55dcb2a7fd2f26969f962bf428ffa6b267457dd804d64d8" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror", + "windows 0.52.0", +] + [[package]] name = "x25519-dalek" version = "2.0.0" @@ -5755,6 +7125,23 @@ dependencies = [ "time 0.3.31", ] +[[package]] +name = "x509-parser" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time 0.3.31", +] + [[package]] name = "xattr" version = "1.2.0" @@ -5766,6 +7153,21 @@ dependencies = [ "rustix", ] +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index e246a7b36c..d08eecc977 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "deltachat" version = "1.133.1" edition = "2021" license = "MPL-2.0" -rust-version = "1.70" +rust-version = "1.72" [profile.dev] debug = 0 @@ -32,6 +32,7 @@ strip = true [patch.crates-io] imap-proto = { git = "https://github.com/djc/tokio-imap.git", rev = "01ff256a7e42a9f7d2732706f8b71a16ce93427e" } +"iroh-blake3" = { git = "https://github.com/n0-computer/iroh-blake3.git", branch = "master" } [dependencies] deltachat_derive = { path = "./deltachat_derive" } @@ -40,14 +41,26 @@ ratelimit = { path = "./deltachat-ratelimit" } anyhow = "1" async-channel = "2.0.0" -async-imap = { version = "0.9.5", default-features = false, features = ["runtime-tokio"] } -async-native-tls = { version = "0.5", default-features = false, features = ["runtime-tokio"] } -async-smtp = { version = "0.9", default-features = false, features = ["runtime-tokio"] } -async_zip = { version = "0.0.12", default-features = false, features = ["deflate", "fs"] } +async-imap = { version = "0.9.5", default-features = false, features = [ + "runtime-tokio", +] } +async-native-tls = { version = "0.5", default-features = false, features = [ + "runtime-tokio", +] } +async-smtp = { version = "0.9", default-features = false, features = [ + "runtime-tokio", +] } +async_zip = { version = "0.0.12", default-features = false, features = [ + "deflate", + "fs", +] } backtrace = "0.3" base64 = "0.21" -brotli = { version = "3.4", default-features=false, features = ["std"] } -chrono = { version = "0.4", default-features=false, features = ["clock", "std"] } +brotli = { version = "3.4", default-features = false, features = ["std"] } +chrono = { version = "0.4", default-features = false, features = [ + "clock", + "std", +] } email = { git = "https://github.com/deltachat/rust-email", branch = "master" } encoded-words = { git = "https://github.com/async-email/encoded-words", branch = "master" } escaper = "0.1" @@ -58,8 +71,22 @@ futures-lite = "2.0.0" hex = "0.4.0" hickory-resolver = "0.24" humansize = "2" -image = { version = "0.24.7", default-features=false, features = ["gif", "jpeg", "ico", "png", "pnm", "webp", "bmp"] } -iroh = { version = "0.4.2", default-features = false } +image = { version = "0.24.7", default-features = false, features = [ + "gif", + "jpeg", + "ico", + "png", + "pnm", + "webp", + "bmp", +] } +iroh = { git = "https://github.com/deltachat/iroh", branch = "0.4-update-quic", default-features = false } +iroh-net = { git = "https://github.com/n0-computer/iroh", branch = "main" } +iroh-base = { git = "https://github.com/n0-computer/iroh", branch = "main" } +iroh-gossip = { git = "https://github.com/n0-computer/iroh", branch = "main", features = [ + "net", +] } +quinn = "0.10" kamadak-exif = "0.5" lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" } libc = "0.2" @@ -93,7 +120,12 @@ strum_macros = "0.25" tagger = "4.3.4" textwrap = "0.16.0" thiserror = "1" -tokio = { version = "1", features = ["fs", "rt-multi-thread", "macros"] } +tokio = { version = "1", features = [ + "fs", + "rt-multi-thread", + "macros", + "time", +] } tokio-io-timeout = "1.2.0" tokio-stream = { version = "0.1.14", features = ["fs"] } tokio-tar = { version = "0.3" } # TODO: integrate tokio into async-tar @@ -104,7 +136,9 @@ uuid = { version = "1", features = ["serde", "v4"] } [dev-dependencies] ansi_term = "0.12.0" -anyhow = { version = "1", features = ["backtrace"] } # Enable `backtrace` feature in tests. +anyhow = { version = "1", features = [ + "backtrace", +] } # Enable `backtrace` feature in tests. criterion = { version = "0.5.1", features = ["async_tokio"] } futures-lite = "2.0.0" log = "0.4" @@ -112,7 +146,11 @@ pretty_env_logger = "0.5" proptest = { version = "1", default-features = false, features = ["std"] } tempfile = "3" testdir = "0.9.0" -tokio = { version = "1", features = ["parking_lot", "rt-multi-thread", "macros"] } +tokio = { version = "1", features = [ + "parking_lot", + "rt-multi-thread", + "macros", +] } pretty_assertions = "1.3.0" [workspace] @@ -160,5 +198,5 @@ internals = [] vendored = [ "async-native-tls/vendored", "rusqlite/bundled-sqlcipher-vendored-openssl", - "reqwest/native-tls-vendored" + "reqwest/native-tls-vendored", ] diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 3d4fbf422d..1972626972 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -15,7 +15,6 @@ use deltachat::constants::DC_MSG_ID_DAYMARKER; use deltachat::contact::{may_be_valid_addr, Contact, ContactId, Origin}; use deltachat::context::get_info; use deltachat::ephemeral::Timer; -use deltachat::imex; use deltachat::location; use deltachat::message::get_msg_read_receipts; use deltachat::message::{ @@ -28,6 +27,7 @@ use deltachat::reaction::{get_msg_reactions, send_reaction}; use deltachat::securejoin; use deltachat::stock_str::StockMessage; use deltachat::webxdc::StatusUpdateSerial; +use deltachat::{imex, webxdc}; use sanitize_filename::is_sanitized; use tokio::fs; use tokio::sync::{watch, Mutex, RwLock}; @@ -1675,6 +1675,16 @@ impl CommandApi { .await } + async fn join_gossip_topic( + &self, + account_id: u32, + instance_msg_id: u32, + topic: String, + ) -> Result<()> { + let ctx = self.get_context(account_id).await?; + webxdc::join_gossip_topic(&ctx, MsgId::new(instance_msg_id), &topic).await + } + async fn get_webxdc_status_updates( &self, account_id: u32, diff --git a/deny.toml b/deny.toml index ee800c2e95..183693240d 100644 --- a/deny.toml +++ b/deny.toml @@ -18,56 +18,58 @@ ignore = [ # when upgrading. # Please keep this list alphabetically sorted. skip = [ - { name = "async-channel", version = "1.9.0" }, - { name = "base16ct", version = "0.1.1" }, - { name = "base64", version = "<0.21" }, - { name = "bitflags", version = "1.3.2" }, - { name = "block-buffer", version = "<0.10" }, - { name = "convert_case", version = "0.4.0" }, - { name = "curve25519-dalek", version = "3.2.0" }, - { name = "darling_core", version = "<0.14" }, - { name = "darling_macro", version = "<0.14" }, - { name = "darling", version = "<0.14" }, - { name = "der", version = "0.6.1" }, - { name = "digest", version = "<0.10" }, - { name = "ed25519-dalek", version = "1.0.1" }, - { name = "ed25519", version = "1.5.3" }, - { name = "event-listener", version = "2.5.3" }, - { name = "getrandom", version = "<0.2" }, - { name = "h2", version = "0.3.22" }, - { name = "http-body", version = "0.4.5" }, - { name = "http", version = "0.2.11" }, - { name = "hyper", version = "0.14.27" }, - { name = "idna", version = "0.4.0" }, - { name = "pem-rfc7468", version = "0.6.0" }, - { name = "pkcs8", version = "0.9.0" }, - { name = "quick-error", version = "<2.0" }, - { name = "rand_chacha", version = "<0.3" }, - { name = "rand_core", version = "<0.6" }, - { name = "rand", version = "<0.8" }, - { name = "redox_syscall", version = "0.3.5" }, - { name = "regex-automata", version = "0.1.10" }, - { name = "regex-syntax", version = "0.6.29" }, - { name = "ring", version = "0.16.20" }, - { name = "sec1", version = "0.3.0" }, - { name = "sha2", version = "<0.10" }, - { name = "signature", version = "1.6.4" }, - { name = "spin", version = "<0.9.6" }, - { name = "spki", version = "0.6.0" }, - { name = "syn", version = "1.0.109" }, - { name = "time", version = "<0.3" }, - { name = "untrusted", version = "0.7.1" }, - { name = "wasi", version = "<0.11" }, - { name = "windows_aarch64_gnullvm", version = "<0.52" }, - { name = "windows_aarch64_msvc", version = "<0.52" }, - { name = "windows_i686_gnu", version = "<0.52" }, - { name = "windows_i686_msvc", version = "<0.52" }, - { name = "windows-sys", version = "<0.52" }, - { name = "windows-targets", version = "<0.52" }, - { name = "windows", version = "0.32.0" }, - { name = "windows_x86_64_gnullvm", version = "<0.52" }, - { name = "windows_x86_64_gnu", version = "<0.52" }, - { name = "windows_x86_64_msvc", version = "<0.52" }, + { name = "async-channel", version = "1.9.0" }, + { name = "base16ct", version = "0.1.1" }, + { name = "base64", version = "<0.21" }, + { name = "bitflags", version = "1.3.2" }, + { name = "block-buffer", version = "<0.10" }, + { name = "convert_case", version = "0.4.0" }, + { name = "curve25519-dalek", version = "3.2.0" }, + { name = "darling_core", version = "<0.14" }, + { name = "darling_macro", version = "<0.14" }, + { name = "darling", version = "<0.14" }, + { name = "der", version = "0.6.1" }, + { name = "digest", version = "<0.10" }, + { name = "ed25519-dalek", version = "1.0.1" }, + { name = "ed25519", version = "1.5.3" }, + { name = "event-listener", version = "2.5.3" }, + { name = "fd-lock", version = "3.0.13" }, + { name = "getrandom", version = "<0.2" }, + { name = "h2", version = "0.3.22" }, + { name = "http-body", version = "0.4.5" }, + { name = "http", version = "0.2.11" }, + { name = "hyper", version = "0.14.27" }, + { name = "idna", version = "0.4.0" }, + { name = "pem-rfc7468", version = "0.6.0" }, + { name = "pkcs8", version = "0.9.0" }, + { name = "quick-error", version = "<2.0" }, + { name = "rand_chacha", version = "<0.3" }, + { name = "rand_core", version = "<0.6" }, + { name = "rand", version = "<0.8" }, + { name = "redox_syscall", version = "0.3.5" }, + { name = "regex-automata", version = "0.1.10" }, + { name = "regex-syntax", version = "0.6.29" }, + { name = "ring", version = "0.16.20" }, + { name = "sec1", version = "0.3.0" }, + { name = "sha2", version = "<0.10" }, + { name = "signature", version = "1.6.4" }, + { name = "socket2", version = "0.4.9" }, + { name = "spin", version = "<0.9.6" }, + { name = "spki", version = "0.6.0" }, + { name = "syn", version = "1.0.109" }, + { name = "time", version = "<0.3" }, + { name = "untrusted", version = "0.7.1" }, + { name = "wasi", version = "<0.11" }, + { name = "windows_aarch64_gnullvm", version = "<0.52" }, + { name = "windows_aarch64_msvc", version = "<0.52" }, + { name = "windows_i686_gnu", version = "<0.52" }, + { name = "windows_i686_msvc", version = "<0.52" }, + { name = "windows-sys", version = "<0.52" }, + { name = "windows-targets", version = "<0.52" }, + { name = "windows", version = "0.32.0" }, + { name = "windows_x86_64_gnullvm", version = "<0.52" }, + { name = "windows_x86_64_gnu", version = "<0.52" }, + { name = "windows_x86_64_msvc", version = "<0.52" }, ] @@ -77,7 +79,7 @@ allow = [ "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", - "BSL-1.0", # Boost Software License 1.0 + "BSL-1.0", # Boost Software License 1.0 "CC0-1.0", "ISC", "MIT", @@ -90,14 +92,13 @@ allow = [ [[licenses.clarify]] name = "ring" expression = "MIT AND ISC AND OpenSSL" -license-files = [ - { path = "LICENSE", hash = 0xbd0eed23 }, -] +license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] [sources.allow-org] # Organisations which we allow git sources from. github = [ - "async-email", - "deltachat", - "djc", + "async-email", + "deltachat", + "djc", + "n0-computer", # iroh ] diff --git a/src/config.rs b/src/config.rs index 0594939e38..552ffa1536 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use std::str::FromStr; use anyhow::{ensure, Context as _, Result}; use serde::{Deserialize, Serialize}; use strum::{EnumProperty, IntoEnumIterator}; -use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString}; +use strum_macros::{AsRefStr, Display, EnumIter, EnumString}; use crate::blob::BlobObject; use crate::constants::DC_VERSION_STR; @@ -347,6 +347,9 @@ pub enum Config { /// Row ID of the key in the `keypairs` table /// used for signatures, encryption to self and included in `Autocrypt` header. KeyId, + + /// Iroh secret key. + IrohSecretKey, } impl Config { diff --git a/src/context.rs b/src/context.rs index ebadb60bf4..fbf0cf94b6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,6 +10,8 @@ use std::time::{Duration, Instant, SystemTime}; use anyhow::{bail, ensure, Context as _, Result}; use async_channel::{self as channel, Receiver, Sender}; +use iroh_gossip::net::Gossip; +use iroh_net::MagicEndpoint; use ratelimit::Ratelimit; use tokio::sync::{Mutex, Notify, RwLock}; @@ -244,6 +246,12 @@ pub struct InnerContext { /// Standard RwLock instead of [`tokio::sync::RwLock`] is used /// because the lock is used from synchronous [`Context::emit_event`]. pub(crate) debug_logging: std::sync::RwLock>, + + /// [MagicEndpoint] needed for iroh peer channels. + pub(crate) endpoint: Mutex>, + + /// [Gossip] needed for iroh peer channels. + pub(crate) gossip: Mutex>, } /// The state of ongoing process. @@ -388,6 +396,8 @@ impl Context { last_full_folder_scan: Mutex::new(None), last_error: std::sync::RwLock::new("".to_string()), debug_logging: std::sync::RwLock::new(None), + endpoint: Mutex::new(None), + gossip: Mutex::new(None), }; let ctx = Context { @@ -417,11 +427,17 @@ impl Context { *lock = Ratelimit::new(Duration::new(3, 0), 3.0); } } + + if let Err(e) = self.create_gossip().await { + warn!(self, "{e}"); + } self.scheduler.start(self.clone()).await; } /// Stops the IO scheduler. pub async fn stop_io(&self) { + self.endpoint.lock().await.take(); + self.gossip.lock().await.take(); self.scheduler.stop(self).await; } @@ -433,6 +449,9 @@ impl Context { /// Indicate that the network likely has come back. pub async fn maybe_network(&self) { + if let Some(ref mut endpoint) = *self.endpoint.lock().await { + endpoint.network_change().await; + } self.scheduler.maybe_network().await; } @@ -1319,6 +1338,7 @@ mod tests { "socks5_user", "socks5_password", "key_id", + "iroh_secret_key", ]; let t = TestContext::new().await; let info = t.get_info().await.unwrap(); @@ -1605,4 +1625,15 @@ mod tests { Ok(()) } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_keypair_saving() -> Result<()> { + let alice = TestContext::new_alice().await; + + let key = alice.get_or_generate_iroh_keypair().await?; + let loaded_key = alice.get_or_generate_iroh_keypair().await?; + assert_eq!(key.to_bytes(), loaded_key.to_bytes()); + + Ok(()) + } } diff --git a/src/debug_logging.rs b/src/debug_logging.rs index bcccaaf9f5..c1814ea028 100644 --- a/src/debug_logging.rs +++ b/src/debug_logging.rs @@ -63,6 +63,7 @@ pub async fn debug_logging_loop(context: &Context, events: Receiver { if let Some(serial) = serial { - if !matches!(event, EventType::WebxdcStatusUpdate { .. }) { - context.emit_event(EventType::WebxdcStatusUpdate { - msg_id, - status_update_serial: serial, - }); - } + context.emit_event(EventType::WebxdcStatusUpdate { + msg_id, + status_update_serial: serial, + }); } else { // This should not happen as the update has no `uid`. error!(context, "Debug logging update is not created."); diff --git a/src/headerdef.rs b/src/headerdef.rs index f65729c9a1..e85bd0e80f 100644 --- a/src/headerdef.rs +++ b/src/headerdef.rs @@ -88,6 +88,9 @@ pub enum HeaderDef { /// See AuthenticationResults, + /// Public key to join gossip network. + IrohPublicGossip, + #[cfg(test)] TestHeader, } diff --git a/src/lib.rs b/src/lib.rs index 20f15972c5..6e975fcb68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,6 +105,7 @@ pub mod receive_imf; pub mod tools; pub mod accounts; +pub mod peer_channels; pub mod reaction; /// If set IMAP/incoming and SMTP/outgoing MIME messages will be printed. diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 4c4a417c33..3424dbb065 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -18,6 +18,7 @@ use crate::contact::Contact; use crate::context::Context; use crate::e2ee::EncryptHelper; use crate::ephemeral::Timer as EphemeralTimer; +use crate::headerdef::HeaderDef; use crate::html::new_html_mimepart; use crate::location; use crate::message::{self, Message, MsgId, Viewtype}; @@ -1274,6 +1275,7 @@ impl<'a> MimeFactory<'a> { } } + println!("hiiiii"); // we do not piggyback sync-files to other self-sent-messages // to not risk files becoming too larger and being skipped by download-on-demand. if command == SystemMessage::MultiDeviceSync && self.is_e2ee_guaranteed() { @@ -1283,6 +1285,16 @@ impl<'a> MimeFactory<'a> { self.sync_ids_to_delete = Some(ids.to_string()); } else if command == SystemMessage::WebxdcStatusUpdate { let json = self.msg.param.get(Param::Arg).unwrap_or_default(); + if json.find("gossip_topic").is_some() { + if let Some(ref endpoint) = *context.endpoint.lock().await { + // Add iroh NodeAddr to headers so peers can connect to us. + let node_addr = endpoint.my_addr().await.unwrap(); + headers.protected.push(Header::new( + HeaderDef::IrohPublicGossip.get_headername().to_string(), + serde_json::to_string(&node_addr)?, + )); + } + } parts.push(context.build_status_update_part(json)); } else if self.msg.viewtype == Viewtype::Webxdc { if let Some(json) = context diff --git a/src/peer_channels.rs b/src/peer_channels.rs new file mode 100644 index 0000000000..ef390c3b65 --- /dev/null +++ b/src/peer_channels.rs @@ -0,0 +1,413 @@ +//! Peer channels for webxdc updates using iroh. + +use anyhow::{anyhow, Context as _, Result}; +use image::EncodableLayout; +use iroh_base::base32; +use iroh_gossip::net::{Gossip, GOSSIP_ALPN}; +use iroh_gossip::proto::{Event as IrohEvent, TopicId}; +use iroh_net::magic_endpoint::accept_conn; +use iroh_net::NodeId; +use iroh_net::{derp::DerpMode, key::SecretKey, MagicEndpoint}; + +use crate::config::Config; +use crate::contact::ContactId; +use crate::context::Context; +use crate::message::{Message, MsgId}; +use crate::tools::time; +use crate::webxdc::StatusUpdateItem; + +impl Context { + /// Create magic endpoint and gossip for the context. + pub async fn create_gossip(&self) -> Result<()> { + let secret_key: SecretKey = self.get_or_generate_iroh_keypair().await?; + println!("> our secret key: {}", base32::fmt(secret_key.to_bytes())); + + if self.endpoint.lock().await.is_some() { + warn!( + self, + "Tried to create endpoint even though there is already one." + ); + return Ok(()); + } + + // build magic endpoint + let endpoint = MagicEndpoint::builder() + .secret_key(secret_key) + .alpns(vec![GOSSIP_ALPN.to_vec()]) + .derp_mode(DerpMode::Default) + .bind(0) + .await?; + + // create gossip + let my_addr = endpoint.my_addr().await?; + let gossip = Gossip::from_endpoint(endpoint.clone(), Default::default(), &my_addr.info); + + // spawn endpoint loop that forwards incoming connections to the gossiper + let context = self.clone(); + tokio::spawn(endpoint_loop(context, endpoint.clone(), gossip.clone())); + + *self.gossip.lock().await = Some(gossip); + *self.endpoint.lock().await = Some(endpoint); + Ok(()) + } + + /// Join a topic and create the subscriber loop for it. + pub async fn join_and_subscribe_topic(&self, topic: TopicId, msg_id: MsgId) -> Result<()> { + info!(&self, "Joining topic {}.", topic.to_string()); + + let Some(ref gossip) = *self.gossip.lock().await else { + warn!( + self, + "Not joining topic {topic} because there is no gossip." + ); + return Ok(()); + }; + + // restore old peers from db, if any + let peers = self.get_peers_for_topic(topic).await?; + if peers.len() == 0 { + // TODO: When there's no peers we will never be able to join the gossip? + warn!(self, "joining gossip with zero peers"); + } else { + info!(self, "joining gossip with peers: {peers:?}"); + info!( + self, + "{:?}", + self.endpoint + .lock() + .await + .as_ref() + .unwrap() + .my_addr() + .await? + ); + } + + // TODO: add timeout as the returned future might be pending forever + let connect_future = gossip.join(topic, peers).await?; + + tokio::spawn(connect_future); + tokio::spawn(subscribe_loop(self.clone(), gossip.clone(), topic, msg_id)); + + Ok(()) + } + + /// Get list of [NodeId]s for one topic. + /// This is used to rejoin a gossip group when reopening the xdc. + /// Only [NodeId] is needed because the magic endpoint caches region and derp server for [NodeId]s. + pub async fn get_peers_for_topic(&self, topic: TopicId) -> Result> { + self.sql + .query_map( + "SELECT public_key FROM iroh_gossip_peers WHERE topic = ?", + (topic.as_bytes(),), + |row| { + let data = row.get::<_, Vec>(0)?; + Ok(data) + }, + |g| { + g.map(|data| { + Ok::(NodeId::from_bytes( + &data? + .try_into() + .map_err(|_| anyhow!("Can't convert sql data to [u8; 32]"))?, + )?) + }) + .collect::, _>>() + .map_err(Into::into) + }, + ) + .await + } + + /// Cache a peers [NodeId] for one topic. + pub async fn add_peer_for_topic( + &self, + msg_id: MsgId, + topic: TopicId, + peer: NodeId, + ) -> Result<()> { + self.sql + .execute( + "INSERT INTO iroh_gossip_peers (msg_id, public_key, topic) VALUES (?, ?, ?)", + (msg_id, peer.as_bytes(), topic.as_bytes()), + ) + .await?; + Ok(()) + } + + /// Remove one cached peer from a topic. + pub async fn delete_peer_for_topic(&self, topic: TopicId, peer: NodeId) -> Result<()> { + self.sql + .execute( + "DELETE FROM iroh_gossip_peers WHERE public_key = ? topic = ?", + (peer.as_bytes(), topic.as_bytes()), + ) + .await?; + Ok(()) + } + + /// Get the iroh gossip secret key from the database or generate a new one and persist it. + pub async fn get_or_generate_iroh_keypair(&self) -> Result { + match self.get_config_parsed(Config::IrohSecretKey).await? { + Some(key) => Ok(key), + None => { + let key = SecretKey::generate(); + self.set_config(Config::IrohSecretKey, Some(&key.to_string())) + .await?; + Ok(key) + } + } + } +} + +async fn endpoint_loop(context: Context, endpoint: MagicEndpoint, gossip: Gossip) { + while let Some(conn) = endpoint.accept().await { + info!(context, "accepting connection with {:?}", conn); + let gossip = gossip.clone(); + let context = context.clone(); + tokio::spawn(async move { + if let Err(err) = handle_connection(&context, conn, gossip).await { + warn!(context, "iroh connection error: {err}"); + } + }); + } +} + +async fn handle_connection( + context: &Context, + conn: quinn::Connecting, + gossip: Gossip, +) -> anyhow::Result<()> { + let (peer_id, alpn, conn) = accept_conn(conn).await?; + match alpn.as_bytes() { + GOSSIP_ALPN => gossip + .handle_connection(conn) + .await + .context(format!("Connection to {peer_id} with ALPN {alpn} failed"))?, + _ => info!( + context, + "Ignoring connection from {peer_id}: unsupported ALPN protocol" + ), + } + Ok(()) +} + +async fn subscribe_loop( + context: Context, + gossip: Gossip, + topic: TopicId, + msg_id: MsgId, +) -> Result<()> { + let mut stream = gossip.subscribe(topic).await?; + loop { + let event = stream.recv().await?; + match event { + IrohEvent::NeighborUp(node) => { + info!(context, "NeighborUp: {:?}", node); + context.add_peer_for_topic(msg_id, topic, node).await?; + } + IrohEvent::NeighborDown(node) => { + info!(context, "NeighborDown: {:?}", node); + context.delete_peer_for_topic(topic, node).await?; + } + IrohEvent::Received(event) => { + info!(context, "Received: {:?}", event); + let payload = String::from_utf8_lossy(event.content.as_bytes()); + let mut instance = Message::load_from_db(&context, msg_id).await?; + let update: StatusUpdateItem = serde_json::from_str(&payload)?; + context + .create_status_update_record( + &mut instance, + update, + time(), + false, + ContactId::SELF, + ) + .await?; + } + }; + } +} + +#[cfg(test)] +mod tests { + use std::{os::unix::thread, str::FromStr, time::Duration}; + + use tokio::time::timeout; + + use crate::{ + chat::send_msg, + message::Viewtype, + test_utils::TestContextManager, + webxdc::{join_gossip_topic, StatusUpdateSerial}, + EventType, + }; + + use super::*; + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_can_connect() { + let mut tcm = TestContextManager::new(); + let alice = &mut tcm.alice().await; + let bob = &mut tcm.bob().await; + alice.ctx.start_io().await; + bob.ctx.start_io().await; + + // Alice sends webxdc to bob + let alice_chat = alice.create_chat(bob).await; + let mut instance = Message::new(Viewtype::File); + instance + .set_file_from_bytes( + alice, + "minimal.xdc", + include_bytes!("../test-data/webxdc/minimal.xdc"), + None, + ) + .await + .unwrap(); + + send_msg(alice, alice_chat.id, &mut instance).await.unwrap(); + + let alice_instance = alice.get_last_msg().await; + assert_eq!(alice_instance.get_viewtype(), Viewtype::Webxdc); + + let webxdc = alice.pop_sent_msg().await; + let bob_webdxc = bob.recv_msg(&webxdc).await; + bob_webdxc.chat_id.accept(bob).await.unwrap(); + + assert_eq!(bob_webdxc.get_viewtype(), Viewtype::Webxdc); + + // Alice sends webxdc update with gossip. + // This produces an SMTP message that contains the topic and a header with alices' node id + alice + .send_webxdc_status_update_struct( + alice_instance.id, + StatusUpdateItem { + payload: "test".to_string().into(), + gossip_topic: Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string()), + ..Default::default() + }, + "", + ) + .await + .unwrap(); + + alice.flush_status_updates().await.unwrap(); + bob.recv_msg(&alice.pop_sent_msg().await).await; + + let status = bob + .get_webxdc_status_updates(bob_webdxc.id, StatusUpdateSerial::new(0)) + .await + .unwrap(); + let status_update_items: Vec = serde_json::from_str(&status).unwrap(); + let topic = status_update_items[0].gossip_topic.as_ref().unwrap(); + assert_eq!(topic, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + let topic_id = TopicId::from_str(&iroh_base::base32::fmt(topic)).unwrap(); + let topics = bob.get_peers_for_topic(topic_id).await.unwrap(); + assert_eq!( + topics, + vec![alice.endpoint.lock().await.as_ref().unwrap().node_id()] + ); + + let mut stream = alice + .ctx + .gossip + .lock() + .await + .as_ref() + .unwrap() + .subscribe(topic_id) + .await + .unwrap(); + + // Bob joins topic + join_gossip_topic(bob, bob_webdxc.id, topic).await.unwrap(); + + let event = timeout(Duration::from_secs(5), stream.recv()) + .await + .unwrap() + .unwrap(); + match event { + IrohEvent::NeighborUp(node) => { + assert_eq!(node, bob.endpoint.lock().await.as_ref().unwrap().node_id()); + } + _ => panic!("Expected NeighborUp event"), + } + + // Bob sends webxdc update with gossip. + bob.send_webxdc_status_update_struct( + bob_webdxc.id, + StatusUpdateItem { + payload: "bob -> alice".to_string().into(), + gossip_topic: Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string()), + ..Default::default() + }, + "", + ) + .await + .unwrap(); + + alice.evtracker.try_recv().unwrap(); + while let Ok(event) = alice.evtracker.try_recv() { + if let EventType::WebxdcStatusUpdate { + msg_id, + status_update_serial, + } = event.typ + { + let status_update = alice + .get_status_update(msg_id, status_update_serial) + .await + .unwrap(); + let status_update_item: StatusUpdateItem = + serde_json::from_str(&status_update).unwrap(); + println!("{:?}", status_update_item.payload.to_string()); + if status_update_item + .payload + .to_string() + .contains("bob -> alice") + { + break; + } + } + } + + // Alice sends webxdc update with gossip. + alice + .send_webxdc_status_update_struct( + bob_webdxc.id, + StatusUpdateItem { + payload: "alice -> bob".to_string().into(), + gossip_topic: Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string()), + ..Default::default() + }, + "", + ) + .await + .unwrap(); + + while let Ok(event) = bob.evtracker.try_recv() { + if let EventType::WebxdcStatusUpdate { + msg_id, + status_update_serial, + } = event.typ + { + let status_update = alice + .get_status_update(msg_id, status_update_serial) + .await + .unwrap(); + + let status_update_item: StatusUpdateItem = + serde_json::from_str(&status_update).unwrap(); + + if status_update_item + .payload + .to_string() + .contains("alice -> bob") + { + break; + } + } + } + } +} diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 93f24fe0fe..486d3b3c8d 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -4,6 +4,7 @@ use std::collections::HashSet; use std::convert::TryFrom; use anyhow::{Context as _, Result}; +use iroh_net::NodeAddr; use mailparse::{parse_mail, SingleInfo}; use num_traits::FromPrimitive; use once_cell::sync::Lazy; @@ -433,11 +434,49 @@ pub(crate) async fn receive_imf_inner( } if let Some(ref status_update) = mime_parser.webxdc_status_update { - if let Err(err) = context + match context .receive_status_update(from_id, insert_msg_id, status_update) .await { - warn!(context, "receive_imf cannot update status: {err:#}."); + // join advertised gossip topics + Ok((topics, instance_id)) => { + warn!(context, "Joining topics: {:#?}", topics); + if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohPublicGossip) { + match serde_json::from_str::(node_addr) + .context("Failed to parse node address") + { + Ok(node_addr) => { + context + .endpoint + .lock() + .await + .as_ref() + .context("Failed to get magic endpoint")? + .add_node_addr(node_addr.clone()) + .context("Failed to add node address")?; + + let node_id = node_addr.node_id; + for topic in topics { + println!("Adding peer: {:?}", node_id); + context + .add_peer_for_topic(instance_id, topic, node_id) + .await?; + + println!( + "New peer topics: {:?}", + context.get_peers_for_topic(topic).await? + ); + } + } + Err(err) => { + warn!(context, "couldn't parse NodeAddr: {err}"); + } + } + } else { + error!(context, "No IrohPublicGossip header found"); + } + } + Err(err) => warn!(context, "receive_imf cannot update status: {err:#}."), } } diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index 5301f7de3e..b97f2a7081 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -900,6 +900,14 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid); .await?; } + if dbversion < 110 { + sql.execute_migration( + "CREATE TABLE iroh_gossip_peers (msg_id TEXT not NULL, topic TEXT NOT NULL, public_key TEXT NOT NULL)", + 110, + ) + .await?; + } + let new_version = sql .get_raw_config_int(VERSION_CFG) .await? diff --git a/src/webxdc.rs b/src/webxdc.rs index 12a51ed53a..09ba2dad06 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -16,10 +16,11 @@ //! - `descr` - text to send along with the updates use std::path::Path; +use std::str::FromStr; use anyhow::{anyhow, bail, ensure, format_err, Context as _, Result}; - use deltachat_derive::FromSql; +use iroh_gossip::proto::TopicId; use lettre_email::mime; use lettre_email::PartBuilder; use serde::{Deserialize, Serialize}; @@ -154,7 +155,7 @@ struct StatusUpdates { } /// Update items as sent on the wire and as stored in the database. -#[derive(Debug, Serialize, Deserialize, Default)] +#[derive(Debug, Serialize, Deserialize, Default, Clone)] pub struct StatusUpdateItem { /// The playload of the status update. pub payload: Value, @@ -181,6 +182,12 @@ pub struct StatusUpdateItem { /// If there is no ID, message is always considered to be unique. #[serde(skip_serializing_if = "Option::is_none")] pub uid: Option, + + /// If this update should only be gossiped and which topic to use. + /// Gossiped Updates will only be received by the other side if they + /// are currently online and part of the gossip topic. + #[serde(default)] + pub gossip_topic: Option, } /// Update items as passed to the UIs. @@ -305,7 +312,7 @@ impl Context { /// Takes an update-json as `{payload: PAYLOAD}` /// writes it to the database and handles events, info-messages, document name and summary. - async fn create_status_update_record( + pub(crate) async fn create_status_update_record( &self, instance: &mut Message, status_update_item: StatusUpdateItem, @@ -396,7 +403,6 @@ impl Context { instance_id: &MsgId, status_update_item: &StatusUpdateItem, ) -> Result> { - let _lock = self.sql.write_lock().await; let uid = status_update_item.uid.as_deref(); let Some(rowid) = self .sql @@ -490,6 +496,47 @@ impl Context { MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft ); + let mut ephemeral = status_update.gossip_topic.is_some(); + if send_now { + if let Some(ref topic) = status_update.gossip_topic { + let topic = TopicId::from_str(&iroh_base::base32::fmt( + topic.get(0..32).context("Can't get 32 bytes from topic")?, + ))?; + + let topic_exists = self + .sql + .query_row_optional( + "SELECT 1 FROM iroh_gossip_peers WHERE topic=?", + (topic.as_bytes(),), + |_| Ok(()), + ) + .await + .context("Failed to check if gossip topic exists")? + .is_some(); + + if !topic_exists { + info!( + self, + "Gossip topic {topic} does not exist, sending over smtp", + ); + self.join_and_subscribe_topic(topic, instance_msg_id) + .await + .context("Failed to join and subscribe to gossip topic")?; + ephemeral = false; + } else { + if let Some(ref gossip) = *self.gossip.lock().await { + println!( + "sending to topic {topic} with peers: {:?}", + self.get_peers_for_topic(topic).await? + ); + gossip + .broadcast(topic, serde_json::to_string(&status_update)?.into()) + .await?; + } + } + } + } + status_update.uid = Some(create_id()); let status_update_serial: StatusUpdateSerial = self .create_status_update_record( @@ -499,11 +546,10 @@ impl Context { send_now, ContactId::SELF, ) - .await - .context("Failed to create status update")? - .context("Duplicate status update UID was generated")?; + .await? + .context("Failed to create status update")?; - if send_now { + if send_now && !ephemeral { self.sql.insert( "INSERT INTO smtp_status_updates (msg_id, first_serial, last_serial, descr) VALUES(?, ?, ?, ?) ON CONFLICT(msg_id) @@ -595,12 +641,14 @@ impl Context { /// /// `json` is an array containing one or more update items as created by send_webxdc_status_update(), /// the array is parsed using serde, the single payloads are used as is. + /// + /// Returns: List of topics that have been advertised in the updates and the [MsgId] of the instance. pub(crate) async fn receive_status_update( &self, from_id: ContactId, msg_id: MsgId, json: &str, - ) -> Result<()> { + ) -> Result<(Vec, MsgId)> { let msg = Message::load_from_db(self, msg_id).await?; let (timestamp, mut instance, can_info_msg) = if msg.viewtype == Viewtype::Webxdc { (msg.timestamp_sort, msg, false) @@ -629,7 +677,15 @@ impl Context { } let updates: StatusUpdates = serde_json::from_str(json)?; + let mut topics = Vec::new(); for update_item in updates.updates { + if let Some(ref topic) = update_item.gossip_topic { + let topic = TopicId::from_str(&iroh_base::base32::fmt( + topic.get(0..32).context("Can't get 32 bytes from topic")?, + ))?; + topics.push(topic); + } + self.create_status_update_record( &mut instance, update_item, @@ -640,7 +696,7 @@ impl Context { .await?; } - Ok(()) + Ok((topics, instance.id)) } /// Returns status updates as an JSON-array, ready to be consumed by a webxdc. @@ -871,9 +927,18 @@ impl Message { } } +/// Join a gossip topic and subscribe to it. +pub async fn join_gossip_topic(ctx: &Context, msg_id: MsgId, topic: &str) -> Result<()> { + let topic = TopicId::from_str(&iroh_base::base32::fmt( + topic.get(0..32).context("Can't get 32 bytes from topic")?, + ))?; + ctx.join_and_subscribe_topic(topic, msg_id).await +} + #[cfg(test)] mod tests { use serde_json::json; + use std::time::Duration; use super::*; use crate::chat::{ @@ -1340,11 +1405,10 @@ mod tests { // set_draft(None) deletes the message without the need to simulate network chat_id.set_draft(&t, None).await?; - assert_eq!( - t.get_webxdc_status_updates(instance.id, StatusUpdateSerial(0)) - .await?, - "[]".to_string() - ); + assert!(t + .get_webxdc_status_updates(instance.id, StatusUpdateSerial(0)) + .await + .is_err()); assert_eq!( t.sql .count("SELECT COUNT(*) FROM msgs_status_updates;", ()) @@ -1376,6 +1440,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), + gossip_topic: None, }, 1640178619, true, @@ -1400,6 +1465,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), + gossip_topic: None, }, 1640178619, true, @@ -1433,6 +1499,7 @@ mod tests { document: None, summary: None, uid: None, + gossip_topic: None, }, 1640178619, true, @@ -1452,6 +1519,7 @@ mod tests { document: None, summary: None, uid: None, + gossip_topic: None, }, 1640178619, true, @@ -1677,6 +1745,43 @@ mod tests { Ok(()) } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_send_ephemeral_webxdc_status_update() -> Result<()> { + let alice = TestContext::new_alice().await; + alice.set_config_bool(Config::BccSelf, true).await?; + let bob = TestContext::new_bob().await; + + // Alice sends an webxdc instance and a status update + let alice_chat = alice.create_chat(&bob).await; + let alice_instance = send_webxdc_instance(&alice, alice_chat.id).await?; + alice + .send_webxdc_status_update( + alice_instance.id, + r#"{"payload" : {"foo":"bar"}}"#, + "descr text", + ) + .await?; + alice.flush_status_updates().await?; + // Not setting ephemeral should prepare a message + alice.pop_sent_msg().await; + + alice + .send_webxdc_status_update( + alice_instance.id, + r#"{"payload" : {"foo":"bar"}, "ephemeral": true}"#, + "descr text", + ) + .await?; + alice.flush_status_updates().await?; + + // Setting ephemeral should noot prepare a message + assert!(&alice + .pop_sent_msg_opt(Duration::from_secs(1)) + .await + .is_none()); + Ok(()) + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_render_webxdc_status_update_object() -> Result<()> { let t = TestContext::new_alice().await;