From 70181493b06ca6e47c0e84573eb46c7e3f713794 Mon Sep 17 00:00:00 2001 From: Septias Date: Wed, 22 Nov 2023 13:42:10 +0100 Subject: [PATCH 01/16] feat: add iroh gossip peer channel --- .github/workflows/ci.yml | 4 +- Cargo.lock | 1463 ++++++++++++++++++++++++++++++++++++-- Cargo.toml | 41 +- deny.toml | 115 +-- src/config.rs | 3 + src/context.rs | 32 +- src/debug_logging.rs | 11 +- src/headerdef.rs | 3 + src/lib.rs | 1 + src/message.rs | 34 + src/mimefactory.rs | 10 + src/peer_channels.rs | 217 ++++++ src/receive_imf.rs | 44 +- src/sql/migrations.rs | 8 +- src/tools.rs | 12 +- src/webxdc.rs | 87 ++- 16 files changed, 1951 insertions(+), 134 deletions(-) create mode 100644 src/peer_channels.rs 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..005b4ae790 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", @@ -1161,7 +1347,7 @@ dependencies = [ "tokio-stream", "tokio-tar", "tokio-util", - "toml", + "toml 0.8.2", "url", "uuid", ] @@ -1255,7 +1441,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 +1453,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 +1484,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.41", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1304,6 +1502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -1350,6 +1549,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.41", + "unicode-xid", +] + [[package]] name = "des" version = "0.8.1" @@ -1451,6 +1671,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 +1693,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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ae3fc31835f74c2a7ceda3aeede378b0ae2e74c8f1c36559fcc9ae2a4e7d3e" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + [[package]] name = "dyn-clone" version = "1.0.16" @@ -1511,6 +1760,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 +1787,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 +2015,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 +2204,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 +2334,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 +2358,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 +2425,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 +2615,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 +2650,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" @@ -2381,15 +2726,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "human-panic" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a79a67745be0cb8dd2771f03b24c2f25df98d5471fe7a595d668cfa2e6f843d" +checksum = "b82da652938b83f94cfdaaf9ae7aaadb8430d84b0dfda226998416318727eac2" dependencies = [ "backtrace", "os_info", "serde", "serde_derive", - "toml", + "toml 0.7.8", "uuid", ] @@ -2449,6 +2794,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.27", + "rustls", + "tokio", + "tokio-rustls", ] [[package]] @@ -2541,16 +2901,34 @@ 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", - "gif", - "jpeg-decoder", + "attohttpc", + "bytes", + "futures", + "http 0.2.11", + "hyper 0.14.27", + "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", "num-traits", "png", @@ -2583,6 +2961,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 +2999,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 +3020,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 +3036,170 @@ dependencies = [ "tracing-futures", "tracing-subscriber", "walkdir", - "x509-parser", + "x509-parser 0.14.0", + "zeroize", +] + +[[package]] +name = "iroh-base" +version = "0.11.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +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.11.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +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.11.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +dependencies = [ + "anyhow", + "erased_set", + "http-body-util", + "hyper 1.0.1", + "hyper-util", + "once_cell", + "prometheus-client", + "reqwest", + "serde", + "struct_iterable", + "time 0.3.30", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-net" +version = "0.11.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +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.0.1", + "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 0.5.5", + "ssh-key 0.6.3", + "stun-rs", + "surge-ping", + "thiserror", + "time 0.3.30", + "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 +3367,15 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "mach2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +dependencies = [ + "libc", +] + [[package]] name = "mailparse" version = "0.14.1" @@ -2851,6 +3418,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 +3469,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 +3525,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 +3546,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 +3576,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 +3598,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "bytes", + "futures", "libc", "log", + "tokio", ] [[package]] @@ -2998,6 +3624,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 +3646,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 +3763,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "object" version = "0.32.2" @@ -3189,9 +3854,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.2.1+3.2.0" +version = "300.2.0+3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3" +checksum = "b1ebed1d188c4cd64c2bcd73d6c1fe1092f3d98c111831923cc1b706c3859fca" dependencies = [ "cc", ] @@ -3226,6 +3891,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "os_pipe" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "overload" version = "0.1.1" @@ -3278,6 +3953,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 +4011,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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +dependencies = [ + "base64 0.21.5", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.6.0" @@ -3346,6 +4055,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.41", +] + +[[package]] +name = "pest_meta" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + [[package]] name = "pgp" version = "0.10.2" @@ -3387,7 +4141,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 +4267,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 +4322,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 +4385,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 +4448,16 @@ dependencies = [ "elliptic-curve 0.13.8", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3630,6 +4491,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.41", +] + [[package]] name = "proptest" version = "1.4.0" @@ -3652,6 +4536,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 +4560,7 @@ checksum = "6d60c2fc2390baad4b9d41ae9957ae88c3095496f88e252ef50722df8b5b78d7" dependencies = [ "bincode", "educe", - "flume", + "flume 0.10.14", "futures", "pin-project", "quinn", @@ -3743,6 +4643,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 +4749,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 +4800,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.30", + "yasna", +] + +[[package]] +name = "rcgen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" +dependencies = [ + "pem 3.0.2", "ring 0.16.20", "time 0.3.31", "yasna", @@ -3904,6 +4847,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref-cast" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "regex" version = "1.10.2" @@ -3936,6 +4899,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" @@ -3972,17 +4941,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 +5063,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", + "thiserror", + "tokio", +] + [[package]] name = "rusqlite" version = "0.30.0" @@ -4148,9 +5140,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "bfeae074e687625746172d639330f1de242a178bf3189b51e35a7a21573513ac" dependencies = [ "bitflags 2.4.1", "errno", @@ -4165,6 +5157,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", @@ -4241,6 +5234,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 +5468,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 +5489,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 +5549,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 +5660,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" @@ -4643,6 +5681,17 @@ dependencies = [ "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", +] + [[package]] name = "ssh-key" version = "0.5.1" @@ -4657,7 +5706,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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51901eb883a5b442b506a1f8fa483d143f3bab513fe721e398ec56c77624feb" +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,6 +5749,35 @@ 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.41", +] + +[[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" @@ -4698,12 +5797,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 0.5.5", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "syn" version = "1.0.109" @@ -4977,6 +6114,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" @@ -5046,30 +6219,55 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.20.2", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap", "serde", @@ -5178,12 +6376,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 +6450,7 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "sha1", + "sha1 0.10.6", "thiserror", "url", "utf-8", @@ -5242,6 +6495,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ucd-parse" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212c59636157b18c2f57eed2799e6606c52fc49c6a11685ffb0d08f06e55f428" +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 +6561,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 +6592,7 @@ dependencies = [ "form_urlencoded", "idna 0.5.0", "percent-encoding", + "serde", ] [[package]] @@ -5459,6 +6738,18 @@ version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +[[package]] +name = "watchable" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff90d0baafb3c0abbeebec1a8a305b4211c356de1d953a0dd77aab006baa8a62" +dependencies = [ + "event-listener 2.5.3", + "futures-util", + "parking_lot", + "thiserror", +] + [[package]] name = "web-sys" version = "0.3.66" @@ -5469,6 +6760,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 +6788,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 +6838,27 @@ 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-implement", + "windows-interface", + "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", + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -5544,6 +6868,28 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "windows-implement" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "windows-interface" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5725,6 +7071,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wmi" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced703d10188571ce53582c2932ce640ed3c413cff7ee6e2d961f9abdb6a63d1" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror", + "windows 0.48.0", +] + [[package]] name = "x25519-dalek" version = "2.0.0" @@ -5762,8 +7122,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1" dependencies = [ "libc", - "linux-raw-sys", - "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]] diff --git a/Cargo.toml b/Cargo.toml index e246a7b36c..e6b81bcd41 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" } @@ -46,8 +47,11 @@ async-smtp = { version = "0.9", default-features = false, features = ["runtime-t 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 +62,20 @@ 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 +109,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 @@ -112,7 +133,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 +185,5 @@ internals = [] vendored = [ "async-native-tls/vendored", "rusqlite/bundled-sqlcipher-vendored-openssl", - "reqwest/native-tls-vendored" + "reqwest/native-tls-vendored", ] 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..b4a22a3443 100644 --- a/src/config.rs +++ b/src/config.rs @@ -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..5cf63898ad 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,11 @@ 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 +395,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 +426,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; } @@ -431,8 +446,11 @@ impl Context { self.scheduler.restart(self).await; } - /// Indicate that the network likely has come back. + /// Indicates 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 +1337,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 +1624,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_create_iroh_keypair().await?; + let loaded_key = alice.get_or_create_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..dccc393df7 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/message.rs b/src/message.rs index 2711c5bf55..af73a3fa0e 100644 --- a/src/message.rs +++ b/src/message.rs @@ -326,6 +326,15 @@ WHERE id=?; Ok(ret) } + + /// Get the rfc724 message id from the database and return it. + pub async fn get_rfc724_mid(&self, context: &Context) -> Result { + context + .sql + .query_get_value("SELECT rfc724_mid from msgs WHERE id=?", (self.0,)) + .await? + .context("Can't get rfc724_mid") + } } impl std::fmt::Display for MsgId { @@ -2187,6 +2196,31 @@ mod tests { assert_eq!(msg.get_text(), "hello".to_string()); } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_get_rfc724_mid() { + let alice = TestContext::new_alice().await; + receive_imf( + &alice, + b"From: Bob \n\ + To: alice@example.org\n\ + Chat-Version: 1.0\n\ + Message-ID: <123@example.com>\n\ + Date: Fri, 29 Jan 2021 21:37:55 +0000\n\ + \n\ + hello\n", + false, + ) + .await + .unwrap(); + + // check chat-id of this message + let msg = alice.get_last_msg().await; + assert_eq!( + msg.id.get_rfc724_mid(&alice).await.unwrap(), + "123@example.com".to_string() + ); + } + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_set_override_sender_name() { // send message with overridden sender name diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 4c4a417c33..e9b8505b64 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}; @@ -1285,6 +1286,15 @@ impl<'a> MimeFactory<'a> { let json = self.msg.param.get(Param::Arg).unwrap_or_default(); parts.push(context.build_status_update_part(json)); } else if self.msg.viewtype == Viewtype::Webxdc { + 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)?, + )); + } + if let Some(json) = context .render_webxdc_status_update_object(self.msg.id, None) .await? diff --git a/src/peer_channels.rs b/src/peer_channels.rs new file mode 100644 index 0000000000..39d9ee26fe --- /dev/null +++ b/src/peer_channels.rs @@ -0,0 +1,217 @@ +//! Peer channels for webxdc updates using iroh. + +use crate::config::Config; +use crate::contact::ContactId; +use crate::context::Context; +use crate::message::{Message, MsgId}; +use crate::tools::{get_topic_from_msg_id, time}; +use crate::webxdc::StatusUpdateItem; +use anyhow::{anyhow, Context as _, Result}; +use image::EncodableLayout; +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}; + +impl Context { + /// Create magic endpoint and gossip for the context. + pub async fn create_gossip(&self) -> Result<()> { + let secret_key: SecretKey = self.get_or_create_iroh_keypair().await?; + + if self.endpoint.lock().await.is_some() { + warn!( + self, + "Tried to create gossip even tough there still exists an instance" + ); + return Ok(()); + } + + // build magic endpoint + let endpoint = MagicEndpoint::builder() + .secret_key(secret_key) + .alpns(vec![GOSSIP_ALPN.to_vec()]) + .derp_mode(DerpMode::Default) + .peers_data_path( + self.blobdir + .parent() + .context("Can't get parent of blob dir")? + .to_path_buf(), + ) + .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, rfc724_mid: &str, msg_id: MsgId) -> Result<()> { + let Some(ref gossip) = *self.gossip.lock().await else { + warn!( + &self, + "Not joining topic for {rfc724_mid:?} because there is no gossip." + ); + return Ok(()); + }; + + let topic = get_topic_from_msg_id(rfc724_mid)?; + info!(&self, "Joining topic {topic}."); + + // restore old peers from db, if any + let peers = self.get_peers_for_topic(&topic.to_string()).await?; + + let connect_future = gossip.join(topic, peers).await?; + + tokio::spawn(connect_future); + tokio::spawn(subscribe_loop( + self.clone(), + self.gossip + .lock() + .await + .as_ref() + .context("can't get 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: &str) -> Result> { + self.sql + .query_map( + "SELECT public_key FROM iroh_gossip_peers WHERE topic = ?", + (topic,), + |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, topic: TopicId, peer: NodeId) -> Result<()> { + self.sql + .execute( + "INSERT INTO iroh_gossip_peers (public_key, topic) VALUES (?, ?)", + (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 create one. + pub async fn get_or_create_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) => { + context.add_peer_for_topic(topic, node).await?; + } + IrohEvent::NeighborDown(node) => { + context.delete_peer_for_topic(topic, node).await?; + } + IrohEvent::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?; + } + }; + } +} diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 93f24fe0fe..6f6a1d688f 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; @@ -38,7 +39,10 @@ use crate::simplify; use crate::sql; use crate::stock_str; use crate::sync::Sync::*; -use crate::tools::{buf_compress, extract_grpid_from_rfc724_mid, strip_rtlo_characters}; +use crate::tools::{ + buf_compress, extract_grpid_from_rfc724_mid, get_topic_from_msg_id, smeared_time, + strip_rtlo_characters, +}; use crate::{contact, imap}; /// This is the struct that is returned after receiving one email (aka MIME message). @@ -1456,6 +1460,44 @@ RETURNING id created_db_entries.push(row_id); } + // Connect to iroh gossip group if it has been advertised. + if incoming { + if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohPublicGossip) { + info!(context, "Create connection with node_addr: {node_addr}."); + 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 rfc724_mid = mime_parser + .get_rfc724_mid() + .context("Can't get Message-ID")?; + + let topic = get_topic_from_msg_id(&rfc724_mid)?; + + let node_id = node_addr.node_id; + context + .add_peer_for_topic(topic, node_id) + .await + .with_context(|| { + format!("Failed to add peer {node_id} for topic {topic}") + })?; + } + Err(err) => { + warn!(context, "{err:#}."); + } + } + } + } + // check all parts whether they contain a new logging webxdc for (part, msg_id) in mime_parser.parts.iter().zip(&created_db_entries) { maybe_set_logging_xdc_inner( diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index 5301f7de3e..9ef2faeb73 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -895,7 +895,13 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid); SET backward_verified_key_id=(SELECT value FROM config WHERE keyname='key_id') WHERE verified_key IS NOT NULL "#, - 109, + 109) + } + + if dbversion < 110 { + sql.execute_migration( + "CREATE TABLE iroh_gossip_peers (topic TEXT NOT NULL, public_key TEXT NOT NULL)", + 108, ) .await?; } diff --git a/src/tools.rs b/src/tools.rs index 20a73eff5f..9a94b5b3e6 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -8,13 +8,14 @@ use std::fmt; use std::io::{Cursor, Write}; use std::mem; use std::path::{Path, PathBuf}; -use std::str::from_utf8; +use std::str::{from_utf8, FromStr}; use std::time::{Duration, SystemTime}; use anyhow::{bail, Context as _, Result}; use base64::Engine as _; use chrono::{Local, NaiveDateTime, NaiveTime, TimeZone}; use futures::{StreamExt, TryStreamExt}; +use iroh_gossip::proto::TopicId; use mailparse::dateparse; use mailparse::headers::Headers; use mailparse::MailHeaderMap; @@ -743,6 +744,15 @@ pub(crate) fn strip_rtlo_characters(input_str: &str) -> String { input_str.replace(|char| RTLO_CHARACTERS.contains(&char), "") } +/// Generates a [TopicId] from some rfc724_mid. +pub(crate) fn get_topic_from_msg_id(rfc724_mid: &str) -> Result { + TopicId::from_str(&iroh_base::base32::fmt( + rfc724_mid + .get(0..32) + .context("Can't get 32 bytes from rfc724_mid")?, + )) +} + #[cfg(test)] mod tests { #![allow(clippy::indexing_slicing)] diff --git a/src/webxdc.rs b/src/webxdc.rs index 12a51ed53a..c3f3216c97 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -38,6 +38,7 @@ use crate::mimeparser::SystemMessage; use crate::param::Param; use crate::param::Params; use crate::tools::create_id; +use crate::tools::get_topic_from_msg_id; use crate::tools::strip_rtlo_characters; use crate::tools::{create_smeared_timestamp, get_abs_path}; @@ -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, + + /// Wheter the message should be sent over an ephemeral channel. + /// This means it will only be received by the other side if they are currently online + /// and part of the gossip group. + #[serde(default)] + pub ephemeral: bool, } /// 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,7 +496,19 @@ impl Context { MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft ); + if send_now { + if let Some(ref gossip) = *self.gossip.lock().await { + let topic = get_topic_from_msg_id(&instance.rfc724_mid)?; + gossip + .broadcast(topic, serde_json::to_string(&status_update)?.into()) + .await?; + } + } + status_update.uid = Some(create_id()); + let ephemeral = status_update.ephemeral; + println!("ephemeral: {}", ephemeral); + let status_update_serial: StatusUpdateSerial = self .create_status_update_record( &mut instance, @@ -499,11 +517,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) @@ -655,6 +672,10 @@ impl Context { instance_msg_id: MsgId, last_known_serial: StatusUpdateSerial, ) -> Result { + let rfc724_mid = instance_msg_id.get_rfc724_mid(self).await?; + self.join_and_subscribe_topic(&rfc724_mid, instance_msg_id) + .await?; + let json = self .sql .query_map( @@ -873,6 +894,8 @@ impl Message { #[cfg(test)] mod tests { + use std::time::Duration; + use serde_json::json; use super::*; @@ -1340,11 +1363,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 +1398,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), + ephemeral: false, }, 1640178619, true, @@ -1400,6 +1423,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), + ephemeral: false, }, 1640178619, true, @@ -1433,6 +1457,7 @@ mod tests { document: None, summary: None, uid: None, + ephemeral: false, }, 1640178619, true, @@ -1452,6 +1477,7 @@ mod tests { document: None, summary: None, uid: None, + ephemeral: false, }, 1640178619, true, @@ -1677,6 +1703,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; From 60b240429a491dfe163dd7066db8831a76839d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Tue, 23 Jan 2024 22:43:59 +0100 Subject: [PATCH 02/16] fix: rebase cleanup --- Cargo.lock | 263 +++++++++++++++++++++++------------------- src/config.rs | 2 +- src/receive_imf.rs | 3 +- src/sql/migrations.rs | 2 +- 4 files changed, 149 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 005b4ae790..f013f659a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1322,6 +1322,7 @@ dependencies = [ "proptest", "qrcodegen", "quick-xml", + "quinn", "quoted_printable", "rand 0.8.5", "ratelimit", @@ -1347,7 +1348,7 @@ dependencies = [ "tokio-stream", "tokio-tar", "tokio-util", - "toml 0.8.2", + "toml", "url", "uuid", ] @@ -1492,7 +1493,7 @@ checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] @@ -1566,7 +1567,7 @@ checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", "unicode-xid", ] @@ -1701,9 +1702,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "duct" -version = "0.13.6" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ae3fc31835f74c2a7ceda3aeede378b0ae2e74c8f1c36559fcc9ae2a4e7d3e" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" dependencies = [ "libc", "once_cell", @@ -2726,15 +2727,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "human-panic" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b82da652938b83f94cfdaaf9ae7aaadb8430d84b0dfda226998416318727eac2" +checksum = "7a79a67745be0cb8dd2771f03b24c2f25df98d5471fe7a595d668cfa2e6f843d" dependencies = [ "backtrace", "os_info", "serde", "serde_derive", - "toml 0.7.8", + "toml", "uuid", ] @@ -2805,7 +2806,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.11", - "hyper 0.14.27", + "hyper 0.14.28", "rustls", "tokio", "tokio-rustls", @@ -2853,7 +2854,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2910,7 +2911,7 @@ dependencies = [ "bytes", "futures", "http 0.2.11", - "hyper 0.14.27", + "hyper 0.14.28", "log", "rand 0.8.5", "tokio", @@ -3042,8 +3043,8 @@ dependencies = [ [[package]] name = "iroh-base" -version = "0.11.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" dependencies = [ "anyhow", "bao-tree", @@ -3070,8 +3071,8 @@ dependencies = [ [[package]] name = "iroh-gossip" -version = "0.11.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" dependencies = [ "anyhow", "bytes", @@ -3111,28 +3112,28 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "0.11.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" dependencies = [ "anyhow", "erased_set", "http-body-util", - "hyper 1.0.1", + "hyper 1.1.0", "hyper-util", "once_cell", "prometheus-client", "reqwest", "serde", "struct_iterable", - "time 0.3.30", + "time 0.3.31", "tokio", "tracing", ] [[package]] name = "iroh-net" -version = "0.11.0" -source = "git+https://github.com/n0-computer/iroh?branch=main#62ac4d8bb57329bc65cf126fabace882066ddb8a" +version = "0.12.0" +source = "git+https://github.com/n0-computer/iroh?branch=main#f7264ff7f5c87e74270aae5f158fd227856d5f20" dependencies = [ "aead", "anyhow", @@ -3153,7 +3154,7 @@ dependencies = [ "hostname", "http 1.0.0", "http-body-util", - "hyper 1.0.1", + "hyper 1.1.0", "hyper-util", "igd", "iroh-base", @@ -3181,12 +3182,13 @@ dependencies = [ "serde_bytes", "serdect", "smallvec", - "socket2 0.5.5", - "ssh-key 0.6.3", + "socket2", + "ssh-key 0.6.4", + "strum", "stun-rs", "surge-ping", "thiserror", - "time 0.3.30", + "time 0.3.31", "tokio", "tokio-rustls", "tokio-rustls-acme", @@ -3369,9 +3371,9 @@ dependencies = [ [[package]] name = "mach2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -3613,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" @@ -3765,23 +3778,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] @@ -3854,9 +3867,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.2.0+3.2.0" +version = "300.2.1+3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1ebed1d188c4cd64c2bcd73d6c1fe1092f3d98c111831923cc1b706c3859fca" +checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3" dependencies = [ "cc", ] @@ -3893,12 +3906,12 @@ dependencies = [ [[package]] name = "os_pipe" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4023,9 +4036,9 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ "base64 0.21.5", "serde", @@ -4057,9 +4070,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -4068,9 +4081,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" dependencies = [ "pest", "pest_generator", @@ -4078,22 +4091,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" dependencies = [ "once_cell", "pest", @@ -4450,12 +4463,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit", ] [[package]] @@ -4511,7 +4523,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] @@ -4802,7 +4814,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem 1.1.1", "ring 0.16.20", - "time 0.3.30", + "time 0.3.31", "yasna", ] @@ -4812,7 +4824,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ - "pem 3.0.2", + "pem 3.0.3", "ring 0.16.20", "time 0.3.31", "yasna", @@ -4849,22 +4861,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] @@ -4932,6 +4944,7 @@ dependencies = [ "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -5083,7 +5096,7 @@ dependencies = [ "netlink-packet-utils", "netlink-proto", "netlink-sys", - "nix", + "nix 0.26.4", "thiserror", "tokio", ] @@ -5140,9 +5153,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.27" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfeae074e687625746172d639330f1de242a178bf3189b51e35a7a21573513ac" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", @@ -5214,7 +5227,7 @@ dependencies = [ "libc", "log", "memchr", - "nix", + "nix 0.27.1", "radix_trie", "unicode-segmentation", "unicode-width", @@ -5712,9 +5725,9 @@ dependencies = [ [[package]] name = "ssh-key" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51901eb883a5b442b506a1f8fa483d143f3bab513fe721e398ec56c77624feb" +checksum = "01f8f4ea73476c0aa5d5e6a75ce1e8634e2c3f82005ef3bbed21547ac57f2bf7" dependencies = [ "ed25519-dalek 2.1.0", "p256 0.13.2", @@ -5769,7 +5782,7 @@ dependencies = [ "proc-macro2", "quote", "struct_iterable_internal", - "syn 2.0.41", + "syn 2.0.46", ] [[package]] @@ -5783,6 +5796,9 @@ 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" @@ -5835,7 +5851,7 @@ dependencies = [ "parking_lot", "pnet_packet", "rand 0.8.5", - "socket2 0.5.5", + "socket2", "thiserror", "tokio", "tracing", @@ -6219,55 +6235,30 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", -] - -[[package]] -name = "toml" -version = "0.8.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.15" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ - "indexmap", "serde", - "serde_spanned", - "toml_datetime", - "winnow", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap", "serde", @@ -6497,9 +6488,9 @@ dependencies = [ [[package]] name = "ucd-parse" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212c59636157b18c2f57eed2799e6606c52fc49c6a11685ffb0d08f06e55f428" +checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" dependencies = [ "regex-lite", ] @@ -6740,11 +6731,11 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "watchable" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff90d0baafb3c0abbeebec1a8a305b4211c356de1d953a0dd77aab006baa8a62" +checksum = "45b42a2f611916b5965120a9cde2b60f2db4454826dd9ad5e6f47c24a5b3b259" dependencies = [ - "event-listener 2.5.3", + "event-listener 4.0.2", "futures-util", "parking_lot", "thiserror", @@ -6844,8 +6835,6 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-implement", - "windows-interface", "windows-targets 0.48.5", ] @@ -6855,7 +6844,28 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core", + "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", ] @@ -6870,24 +6880,24 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.46", ] [[package]] name = "windows-interface" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.46", ] [[package]] @@ -7073,16 +7083,16 @@ dependencies = [ [[package]] name = "wmi" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced703d10188571ce53582c2932ce640ed3c413cff7ee6e2d961f9abdb6a63d1" +checksum = "fff298e96fd8ef6bb55dcb2a7fd2f26969f962bf428ffa6b267457dd804d64d8" dependencies = [ "chrono", "futures", "log", "serde", "thiserror", - "windows 0.48.0", + "windows 0.52.0", ] [[package]] @@ -7115,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" @@ -7122,6 +7149,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1" dependencies = [ "libc", + "linux-raw-sys", + "rustix", ] [[package]] diff --git a/src/config.rs b/src/config.rs index b4a22a3443..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; diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 6f6a1d688f..813064e204 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -40,8 +40,7 @@ use crate::sql; use crate::stock_str; use crate::sync::Sync::*; use crate::tools::{ - buf_compress, extract_grpid_from_rfc724_mid, get_topic_from_msg_id, smeared_time, - strip_rtlo_characters, + buf_compress, extract_grpid_from_rfc724_mid, get_topic_from_msg_id, strip_rtlo_characters, }; use crate::{contact, imap}; diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index 9ef2faeb73..e1723e2796 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -895,7 +895,7 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid); SET backward_verified_key_id=(SELECT value FROM config WHERE keyname='key_id') WHERE verified_key IS NOT NULL "#, - 109) + 109).await?; } if dbversion < 110 { From 5d775231d08a278129d2efc70fa161b597c11f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Wed, 24 Jan 2024 13:03:07 +0100 Subject: [PATCH 03/16] cleanup --- src/context.rs | 3 ++- src/peer_channels.rs | 2 +- src/webxdc.rs | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/context.rs b/src/context.rs index 5cf63898ad..2e12e46518 100644 --- a/src/context.rs +++ b/src/context.rs @@ -249,6 +249,7 @@ pub struct InnerContext { /// [MagicEndpoint] needed for iroh peer channels. pub(crate) endpoint: Mutex>, + /// [Gossip] needed for iroh peer channels. pub(crate) gossip: Mutex>, } @@ -446,7 +447,7 @@ impl Context { self.scheduler.restart(self).await; } - /// Indicates that the network likely has come back. + /// 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; diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 39d9ee26fe..abfab1d4a6 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -58,7 +58,7 @@ impl Context { pub async fn join_and_subscribe_topic(&self, rfc724_mid: &str, msg_id: MsgId) -> Result<()> { let Some(ref gossip) = *self.gossip.lock().await else { warn!( - &self, + self, "Not joining topic for {rfc724_mid:?} because there is no gossip." ); return Ok(()); diff --git a/src/webxdc.rs b/src/webxdc.rs index c3f3216c97..226683a3da 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -507,8 +507,6 @@ impl Context { status_update.uid = Some(create_id()); let ephemeral = status_update.ephemeral; - println!("ephemeral: {}", ephemeral); - let status_update_serial: StatusUpdateSerial = self .create_status_update_record( &mut instance, From d13d8d48eca47720dde2696420cbeac4ecb23f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Thu, 25 Jan 2024 18:09:25 +0100 Subject: [PATCH 04/16] add gossip join api webxdcs can now have multiple gossip channels and decide where to send the message to. --- deltachat-jsonrpc/src/api.rs | 12 +++++- src/debug_logging.rs | 2 +- src/message.rs | 34 --------------- src/peer_channels.rs | 37 ++++++++--------- src/receive_imf.rs | 75 +++++++++++++++------------------ src/sql/migrations.rs | 8 ++-- src/tools.rs | 12 +----- src/webxdc.rs | 80 ++++++++++++++++++++++++++---------- 8 files changed, 124 insertions(+), 136 deletions(-) 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/src/debug_logging.rs b/src/debug_logging.rs index dccc393df7..c1814ea028 100644 --- a/src/debug_logging.rs +++ b/src/debug_logging.rs @@ -63,7 +63,7 @@ pub async fn debug_logging_loop(context: &Context, events: Receiver Result { - context - .sql - .query_get_value("SELECT rfc724_mid from msgs WHERE id=?", (self.0,)) - .await? - .context("Can't get rfc724_mid") - } } impl std::fmt::Display for MsgId { @@ -2196,31 +2187,6 @@ mod tests { assert_eq!(msg.get_text(), "hello".to_string()); } - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] - async fn test_get_rfc724_mid() { - let alice = TestContext::new_alice().await; - receive_imf( - &alice, - b"From: Bob \n\ - To: alice@example.org\n\ - Chat-Version: 1.0\n\ - Message-ID: <123@example.com>\n\ - Date: Fri, 29 Jan 2021 21:37:55 +0000\n\ - \n\ - hello\n", - false, - ) - .await - .unwrap(); - - // check chat-id of this message - let msg = alice.get_last_msg().await; - assert_eq!( - msg.id.get_rfc724_mid(&alice).await.unwrap(), - "123@example.com".to_string() - ); - } - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_set_override_sender_name() { // send message with overridden sender name diff --git a/src/peer_channels.rs b/src/peer_channels.rs index abfab1d4a6..77ac977b0f 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -4,7 +4,7 @@ use crate::config::Config; use crate::contact::ContactId; use crate::context::Context; use crate::message::{Message, MsgId}; -use crate::tools::{get_topic_from_msg_id, time}; +use crate::tools::time; use crate::webxdc::StatusUpdateItem; use anyhow::{anyhow, Context as _, Result}; use image::EncodableLayout; @@ -55,35 +55,25 @@ impl Context { } /// Join a topic and create the subscriber loop for it. - pub async fn join_and_subscribe_topic(&self, rfc724_mid: &str, msg_id: MsgId) -> Result<()> { + pub async fn join_and_subscribe_topic(&self, topic: TopicId, msg_id: MsgId) -> Result<()> { + info!(&self, "Joining topic {topic}."); + let Some(ref gossip) = *self.gossip.lock().await else { warn!( self, - "Not joining topic for {rfc724_mid:?} because there is no gossip." + "Not joining topic {topic} because there is no gossip." ); return Ok(()); }; - let topic = get_topic_from_msg_id(rfc724_mid)?; - info!(&self, "Joining topic {topic}."); - // restore old peers from db, if any let peers = self.get_peers_for_topic(&topic.to_string()).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(), - self.gossip - .lock() - .await - .as_ref() - .context("can't get gossip")? - .clone(), - topic, - msg_id, - )); + tokio::spawn(subscribe_loop(self.clone(), gossip.clone(), topic, msg_id)); Ok(()) } @@ -116,11 +106,16 @@ impl Context { } /// Cache a peers [NodeId] for one topic. - pub async fn add_peer_for_topic(&self, topic: TopicId, peer: NodeId) -> Result<()> { + pub async fn add_peer_for_topic( + &self, + msg_id: MsgId, + topic: TopicId, + peer: NodeId, + ) -> Result<()> { self.sql .execute( - "INSERT INTO iroh_gossip_peers (public_key, topic) VALUES (?, ?)", - (peer.as_bytes(), topic.as_bytes()), + "INSERT INTO iroh_gossip_peers (msg_id, public_key, topic) VALUES (?, ?, ?)", + (msg_id, peer.as_bytes(), topic.as_bytes()), ) .await?; Ok(()) @@ -193,7 +188,7 @@ async fn subscribe_loop( let event = stream.recv().await?; match event { IrohEvent::NeighborUp(node) => { - context.add_peer_for_topic(topic, node).await?; + context.add_peer_for_topic(msg_id, topic, node).await?; } IrohEvent::NeighborDown(node) => { context.delete_peer_for_topic(topic, node).await?; diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 813064e204..7062c9cfa6 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -39,9 +39,7 @@ use crate::simplify; use crate::sql; use crate::stock_str; use crate::sync::Sync::*; -use crate::tools::{ - buf_compress, extract_grpid_from_rfc724_mid, get_topic_from_msg_id, strip_rtlo_characters, -}; +use crate::tools::{buf_compress, extract_grpid_from_rfc724_mid, strip_rtlo_characters}; use crate::{contact, imap}; /// This is the struct that is returned after receiving one email (aka MIME message). @@ -436,11 +434,40 @@ 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)) => { + 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")?; + + for topic in topics { + let node_id = node_addr.node_id; + context + .add_peer_for_topic(instance_id, topic, node_id) + .await?; + } + } + Err(err) => { + warn!(context, "couldn't parse NodeAddr: {err}"); + } + } + } + } + Err(err) => warn!(context, "receive_imf cannot update status: {err:#}."), } } @@ -1459,44 +1486,6 @@ RETURNING id created_db_entries.push(row_id); } - // Connect to iroh gossip group if it has been advertised. - if incoming { - if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohPublicGossip) { - info!(context, "Create connection with node_addr: {node_addr}."); - 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 rfc724_mid = mime_parser - .get_rfc724_mid() - .context("Can't get Message-ID")?; - - let topic = get_topic_from_msg_id(&rfc724_mid)?; - - let node_id = node_addr.node_id; - context - .add_peer_for_topic(topic, node_id) - .await - .with_context(|| { - format!("Failed to add peer {node_id} for topic {topic}") - })?; - } - Err(err) => { - warn!(context, "{err:#}."); - } - } - } - } - // check all parts whether they contain a new logging webxdc for (part, msg_id) in mime_parser.parts.iter().zip(&created_db_entries) { maybe_set_logging_xdc_inner( diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index e1723e2796..b97f2a7081 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -895,13 +895,15 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid); SET backward_verified_key_id=(SELECT value FROM config WHERE keyname='key_id') WHERE verified_key IS NOT NULL "#, - 109).await?; + 109, + ) + .await?; } if dbversion < 110 { sql.execute_migration( - "CREATE TABLE iroh_gossip_peers (topic TEXT NOT NULL, public_key TEXT NOT NULL)", - 108, + "CREATE TABLE iroh_gossip_peers (msg_id TEXT not NULL, topic TEXT NOT NULL, public_key TEXT NOT NULL)", + 110, ) .await?; } diff --git a/src/tools.rs b/src/tools.rs index 9a94b5b3e6..20a73eff5f 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -8,14 +8,13 @@ use std::fmt; use std::io::{Cursor, Write}; use std::mem; use std::path::{Path, PathBuf}; -use std::str::{from_utf8, FromStr}; +use std::str::from_utf8; use std::time::{Duration, SystemTime}; use anyhow::{bail, Context as _, Result}; use base64::Engine as _; use chrono::{Local, NaiveDateTime, NaiveTime, TimeZone}; use futures::{StreamExt, TryStreamExt}; -use iroh_gossip::proto::TopicId; use mailparse::dateparse; use mailparse::headers::Headers; use mailparse::MailHeaderMap; @@ -744,15 +743,6 @@ pub(crate) fn strip_rtlo_characters(input_str: &str) -> String { input_str.replace(|char| RTLO_CHARACTERS.contains(&char), "") } -/// Generates a [TopicId] from some rfc724_mid. -pub(crate) fn get_topic_from_msg_id(rfc724_mid: &str) -> Result { - TopicId::from_str(&iroh_base::base32::fmt( - rfc724_mid - .get(0..32) - .context("Can't get 32 bytes from rfc724_mid")?, - )) -} - #[cfg(test)] mod tests { #![allow(clippy::indexing_slicing)] diff --git a/src/webxdc.rs b/src/webxdc.rs index 226683a3da..fa5ec60674 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -16,10 +16,12 @@ //! - `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}; @@ -38,7 +40,6 @@ use crate::mimeparser::SystemMessage; use crate::param::Param; use crate::param::Params; use crate::tools::create_id; -use crate::tools::get_topic_from_msg_id; use crate::tools::strip_rtlo_characters; use crate::tools::{create_smeared_timestamp, get_abs_path}; @@ -183,11 +184,11 @@ pub struct StatusUpdateItem { #[serde(skip_serializing_if = "Option::is_none")] pub uid: Option, - /// Wheter the message should be sent over an ephemeral channel. - /// This means it will only be received by the other side if they are currently online - /// and part of the gossip group. + /// 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 ephemeral: bool, + pub gossip_topic: Option, } /// Update items as passed to the UIs. @@ -496,17 +497,34 @@ impl Context { MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft ); + let ephemeral = status_update.gossip_topic.is_some(); if send_now { - if let Some(ref gossip) = *self.gossip.lock().await { - let topic = get_topic_from_msg_id(&instance.rfc724_mid)?; - gossip - .broadcast(topic, serde_json::to_string(&status_update)?.into()) + 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 rfc724_mid")?, + ))?; + + self.join_and_subscribe_topic(topic, instance_msg_id) .await?; + + info!(self, "here3"); + + let gossip = self.gossip.lock().await; + if let Some(ref gossip) = *gossip { + gossip + .broadcast(topic, serde_json::to_string(&status_update)?.into()) + .await?; + } else { + warn!(self, "send_webxdc_status_update: no gossip available."); + } + } else { + warn!(self, "send_webxdc_status_update: no gossip topic given.") } } status_update.uid = Some(create_id()); - let ephemeral = status_update.ephemeral; let status_update_serial: StatusUpdateSerial = self .create_status_update_record( &mut instance, @@ -610,12 +628,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) @@ -644,7 +664,17 @@ 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 rfc724_mid")?, + ))?; + topics.push(topic); + } + self.create_status_update_record( &mut instance, update_item, @@ -655,7 +685,7 @@ impl Context { .await?; } - Ok(()) + Ok((topics, instance.id)) } /// Returns status updates as an JSON-array, ready to be consumed by a webxdc. @@ -670,10 +700,6 @@ impl Context { instance_msg_id: MsgId, last_known_serial: StatusUpdateSerial, ) -> Result { - let rfc724_mid = instance_msg_id.get_rfc724_mid(self).await?; - self.join_and_subscribe_topic(&rfc724_mid, instance_msg_id) - .await?; - let json = self .sql .query_map( @@ -890,11 +916,21 @@ 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 rfc724_mid")?, + ))?; + info!(ctx, "Received join request from frontend"); + ctx.join_and_subscribe_topic(topic, msg_id).await +} + #[cfg(test)] mod tests { - use std::time::Duration; - use serde_json::json; + use std::time::Duration; use super::*; use crate::chat::{ @@ -1396,7 +1432,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), - ephemeral: false, + gossip_topic: None, }, 1640178619, true, @@ -1421,7 +1457,7 @@ mod tests { document: None, summary: None, uid: Some("iecie2Ze".to_string()), - ephemeral: false, + gossip_topic: None, }, 1640178619, true, @@ -1455,7 +1491,7 @@ mod tests { document: None, summary: None, uid: None, - ephemeral: false, + gossip_topic: None, }, 1640178619, true, @@ -1475,7 +1511,7 @@ mod tests { document: None, summary: None, uid: None, - ephemeral: false, + gossip_topic: None, }, 1640178619, true, From 820a4b9357cc155dbb9437812d76d7e16bf6fc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Thu, 25 Jan 2024 19:20:23 +0100 Subject: [PATCH 05/16] send smpt-message for advertisement --- src/receive_imf.rs | 6 ++++++ src/webxdc.rs | 49 +++++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 7062c9cfa6..01e7c70f29 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -440,6 +440,12 @@ pub(crate) async fn receive_imf_inner( { // join advertised gossip topics Ok((topics, instance_id)) => { + warn!(context, "Joining topics: {:#?}", topics); + warn!( + context, + "{:?}", + mime_parser.get_header(HeaderDef::IrohPublicGossip) + ); if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohPublicGossip) { match serde_json::from_str::(node_addr) .context("Failed to parse node address") diff --git a/src/webxdc.rs b/src/webxdc.rs index fa5ec60674..9e097e343c 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -497,30 +497,39 @@ impl Context { MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft ); - let ephemeral = status_update.gossip_topic.is_some(); + let mut ephemeral = status_update.gossip_topic.is_some(); if send_now { if let Some(ref topic) = status_update.gossip_topic { + // find out if any row with `topic = topic` exists in the gossip_peers table + let topic_exists = self + .sql + .query_row_optional( + "SELECT 1 FROM iroh_gossip_peers WHERE topic=?", + (topic,), + |_| Ok(()), + ) + .await + .context("Failed to check if gossip topic exists")? + .is_some(); + let topic = TopicId::from_str(&iroh_base::base32::fmt( - topic - .get(0..32) - .context("Can't get 32 bytes from rfc724_mid")?, + topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; - self.join_and_subscribe_topic(topic, instance_msg_id) .await?; - - info!(self, "here3"); - - let gossip = self.gossip.lock().await; - if let Some(ref gossip) = *gossip { - gossip - .broadcast(topic, serde_json::to_string(&status_update)?.into()) - .await?; + if !topic_exists { + info!( + self, + "Gossip topic {topic} does not exist, sending over smpt", + ); + ephemeral = false; } else { - warn!(self, "send_webxdc_status_update: no gossip available."); + if let Some(ref gossip) = *self.gossip.lock().await { + gossip + .broadcast(topic, serde_json::to_string(&status_update)?.into()) + .await?; + } } - } else { - warn!(self, "send_webxdc_status_update: no gossip topic given.") } } @@ -668,9 +677,7 @@ impl Context { 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 rfc724_mid")?, + topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; topics.push(topic); } @@ -919,9 +926,7 @@ 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 rfc724_mid")?, + topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; info!(ctx, "Received join request from frontend"); ctx.join_and_subscribe_topic(topic, msg_id).await From f5a7a22239dca8dd6f9bde1c267d8cfda13131e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Fri, 26 Jan 2024 15:25:31 +0100 Subject: [PATCH 06/16] add self to topic and add pubkey --- src/mimefactory.rs | 20 +++++++++++--------- src/webxdc.rs | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/mimefactory.rs b/src/mimefactory.rs index e9b8505b64..7688d4824b 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1284,17 +1284,19 @@ 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(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)?, - )); - } - if let Some(json) = context .render_webxdc_status_update_object(self.msg.id, None) .await? diff --git a/src/webxdc.rs b/src/webxdc.rs index 9e097e343c..8d8eddcba6 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -505,7 +505,7 @@ impl Context { .sql .query_row_optional( "SELECT 1 FROM iroh_gossip_peers WHERE topic=?", - (topic,), + (topic.as_bytes(),), |_| Ok(()), ) .await @@ -520,8 +520,20 @@ impl Context { if !topic_exists { info!( self, - "Gossip topic {topic} does not exist, sending over smpt", + "Gossip topic {topic} does not exist, sending over smtp", ); + let addr = self + .endpoint + .lock() + .await + .as_ref() + .unwrap() + .my_addr() + .await + .unwrap(); + + self.add_peer_for_topic(instance_msg_id, topic, addr.node_id) + .await?; ephemeral = false; } else { if let Some(ref gossip) = *self.gossip.lock().await { From eca8ed3d560104d25dea9eac92d523a5455a69ee Mon Sep 17 00:00:00 2001 From: Septias Date: Mon, 29 Jan 2024 16:12:02 +0100 Subject: [PATCH 07/16] use as_bytes everywhere --- src/peer_channels.rs | 9 ++++++--- src/receive_imf.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 77ac977b0f..29d61ccf97 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -67,7 +67,10 @@ impl Context { }; // restore old peers from db, if any - let peers = self.get_peers_for_topic(&topic.to_string()).await?; + let peers = self.get_peers_for_topic(topic).await?; + if peers.len() == 0 { + warn!(self, "joining gossip with zero peers: {peers:?}"); + } // TODO: add timeout as the returned future might be pending forever let connect_future = gossip.join(topic, peers).await?; @@ -81,11 +84,11 @@ impl Context { /// 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: &str) -> Result> { + 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,), + (topic.as_bytes(),), |row| { let data = row.get::<_, Vec>(0)?; Ok(data) diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 01e7c70f29..bec7307927 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -460,8 +460,8 @@ pub(crate) async fn receive_imf_inner( .add_node_addr(node_addr.clone()) .context("Failed to add node address")?; + let node_id = node_addr.node_id; for topic in topics { - let node_id = node_addr.node_id; context .add_peer_for_topic(instance_id, topic, node_id) .await?; From 4fb000228323fd31b1e9faf5ff1c17d4441612c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Mon, 29 Jan 2024 16:12:45 +0100 Subject: [PATCH 08/16] stufff --- src/peer_channels.rs | 2 ++ src/receive_imf.rs | 5 ----- src/webxdc.rs | 14 +++++++------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 29d61ccf97..59bd4539e0 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -191,9 +191,11 @@ async fn subscribe_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) => { diff --git a/src/receive_imf.rs b/src/receive_imf.rs index bec7307927..4913de2637 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -441,11 +441,6 @@ pub(crate) async fn receive_imf_inner( // join advertised gossip topics Ok((topics, instance_id)) => { warn!(context, "Joining topics: {:#?}", topics); - warn!( - context, - "{:?}", - mime_parser.get_header(HeaderDef::IrohPublicGossip) - ); if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohPublicGossip) { match serde_json::from_str::(node_addr) .context("Failed to parse node address") diff --git a/src/webxdc.rs b/src/webxdc.rs index 8d8eddcba6..357e526112 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -515,14 +515,13 @@ impl Context { let topic = TopicId::from_str(&iroh_base::base32::fmt( topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; - self.join_and_subscribe_topic(topic, instance_msg_id) - .await?; + if !topic_exists { info!( self, "Gossip topic {topic} does not exist, sending over smtp", ); - let addr = self + let node_id = self .endpoint .lock() .await @@ -530,9 +529,11 @@ impl Context { .unwrap() .my_addr() .await - .unwrap(); - - self.add_peer_for_topic(instance_msg_id, topic, addr.node_id) + .unwrap() + .node_id; + self.join_and_subscribe_topic(topic, instance_msg_id) + .await?; + self.add_peer_for_topic(instance_msg_id, topic, node_id) .await?; ephemeral = false; } else { @@ -940,7 +941,6 @@ pub async fn join_gossip_topic(ctx: &Context, msg_id: MsgId, topic: &str) -> Res let topic = TopicId::from_str(&iroh_base::base32::fmt( topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; - info!(ctx, "Received join request from frontend"); ctx.join_and_subscribe_topic(topic, msg_id).await } From bd37c36143a0faffa1dabe416e0ea541e5c66a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Mon, 29 Jan 2024 16:58:23 +0100 Subject: [PATCH 09/16] more logs --- src/peer_channels.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 59bd4539e0..97d574c79f 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -56,7 +56,7 @@ impl Context { /// 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}."); + info!(&self, "Joining topic {}.", topic.to_string()); let Some(ref gossip) = *self.gossip.lock().await else { warn!( @@ -69,7 +69,9 @@ impl Context { // restore old peers from db, if any let peers = self.get_peers_for_topic(topic).await?; if peers.len() == 0 { - warn!(self, "joining gossip with zero peers: {peers:?}"); + warn!(self, "joining gossip with zero peers"); + } else { + info!(self, "joining gossip with peers: {peers:?}"); } // TODO: add timeout as the returned future might be pending forever @@ -199,6 +201,7 @@ async fn subscribe_loop( 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)?; From 8385ba92c70964566ba848e9707ac778bfea79ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Fri, 9 Feb 2024 09:10:56 +0100 Subject: [PATCH 10/16] fixes --- src/peer_channels.rs | 2 +- src/webxdc.rs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 97d574c79f..bffae3a3dc 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -22,7 +22,7 @@ impl Context { if self.endpoint.lock().await.is_some() { warn!( self, - "Tried to create gossip even tough there still exists an instance" + "Tried to create endpoint even though there is already one." ); return Ok(()); } diff --git a/src/webxdc.rs b/src/webxdc.rs index 357e526112..519c061413 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -501,6 +501,11 @@ impl Context { if send_now { if let Some(ref topic) = status_update.gossip_topic { // find out if any row with `topic = topic` exists in the gossip_peers table + + 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( @@ -512,10 +517,6 @@ impl Context { .context("Failed to check if gossip topic exists")? .is_some(); - let topic = TopicId::from_str(&iroh_base::base32::fmt( - topic.get(0..32).context("Can't get 32 bytes from topic")?, - ))?; - if !topic_exists { info!( self, @@ -531,10 +532,10 @@ impl Context { .await .unwrap() .node_id; - self.join_and_subscribe_topic(topic, instance_msg_id) - .await?; self.add_peer_for_topic(instance_msg_id, topic, node_id) .await?; + self.join_and_subscribe_topic(topic, instance_msg_id) + .await?; ephemeral = false; } else { if let Some(ref gossip) = *self.gossip.lock().await { From 29581c5ed9d5c4c77d99f2ff23e8441e13387de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Wed, 21 Feb 2024 16:42:24 +0100 Subject: [PATCH 11/16] logs --- src/peer_channels.rs | 25 +++++++++++++++++-------- src/receive_imf.rs | 6 ++++++ src/webxdc.rs | 6 ++++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index bffae3a3dc..5d72b79cf0 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -8,6 +8,7 @@ use crate::tools::time; use crate::webxdc::StatusUpdateItem; 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; @@ -19,6 +20,8 @@ impl Context { pub async fn create_gossip(&self) -> Result<()> { let secret_key: SecretKey = self.get_or_create_iroh_keypair().await?; + println!("> our secret key: {}", base32::fmt(secret_key.to_bytes())); + if self.endpoint.lock().await.is_some() { warn!( self, @@ -32,12 +35,6 @@ impl Context { .secret_key(secret_key) .alpns(vec![GOSSIP_ALPN.to_vec()]) .derp_mode(DerpMode::Default) - .peers_data_path( - self.blobdir - .parent() - .context("Can't get parent of blob dir")? - .to_path_buf(), - ) .bind(0) .await?; @@ -72,6 +69,17 @@ impl Context { 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 @@ -139,7 +147,8 @@ impl Context { /// Get the iroh gossip secret key from the database or create one. pub async fn get_or_create_iroh_keypair(&self) -> Result { - match self.get_config_parsed(Config::IrohSecretKey).await? { + Ok(SecretKey::generate()) + /* match self.get_config_parsed(Config::IrohSecretKey).await? { Some(key) => Ok(key), None => { let key = SecretKey::generate(); @@ -147,7 +156,7 @@ impl Context { .await?; Ok(key) } - } + } */ } } diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 4913de2637..bdfe793326 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -457,9 +457,15 @@ pub(crate) async fn receive_imf_inner( 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) => { diff --git a/src/webxdc.rs b/src/webxdc.rs index 519c061413..1b0cbd1b33 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -500,8 +500,6 @@ impl Context { let mut ephemeral = status_update.gossip_topic.is_some(); if send_now { if let Some(ref topic) = status_update.gossip_topic { - // find out if any row with `topic = topic` exists in the gossip_peers table - let topic = TopicId::from_str(&iroh_base::base32::fmt( topic.get(0..32).context("Can't get 32 bytes from topic")?, ))?; @@ -539,6 +537,10 @@ impl Context { 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?; From 7a942ab27c387a769f627221a1b55c006964231c Mon Sep 17 00:00:00 2001 From: adz Date: Sun, 10 Mar 2024 21:41:08 +0100 Subject: [PATCH 12/16] Minor clean ups --- src/peer_channels.rs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 5d72b79cf0..e65b5ce19f 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -1,11 +1,5 @@ //! Peer channels for webxdc updates using iroh. -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; use anyhow::{anyhow, Context as _, Result}; use image::EncodableLayout; use iroh_base::base32; @@ -15,11 +9,16 @@ use iroh_net::magic_endpoint::accept_conn; use iroh_net::NodeId; use iroh_net::{derp::DerpMode, key::SecretKey, MagicEndpoint}; +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_create_iroh_keypair().await?; - + let secret_key: SecretKey = self.generate_iroh_keypair(); println!("> our secret key: {}", base32::fmt(secret_key.to_bytes())); if self.endpoint.lock().await.is_some() { @@ -146,17 +145,8 @@ impl Context { } /// Get the iroh gossip secret key from the database or create one. - pub async fn get_or_create_iroh_keypair(&self) -> Result { - Ok(SecretKey::generate()) - /* 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) - } - } */ + pub fn generate_iroh_keypair(&self) -> SecretKey { + SecretKey::generate() } } From 6d8dcdb40d8bd6418a646d2a52e2f92f4d2125cf Mon Sep 17 00:00:00 2001 From: adz Date: Sun, 10 Mar 2024 22:03:53 +0100 Subject: [PATCH 13/16] If there's no peers we can't join the gossip? --- src/peer_channels.rs | 2 ++ src/webxdc.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index e65b5ce19f..489a623d73 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -65,6 +65,7 @@ impl Context { // 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:?}"); @@ -162,6 +163,7 @@ async fn endpoint_loop(context: Context, endpoint: MagicEndpoint, gossip: Gossip }); } } + async fn handle_connection( context: &Context, conn: quinn::Connecting, diff --git a/src/webxdc.rs b/src/webxdc.rs index 1b0cbd1b33..f220f5c595 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -19,7 +19,6 @@ 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; From dae6d6e450ed7c86ca51607e1f482d5ac8b126a1 Mon Sep 17 00:00:00 2001 From: adz Date: Mon, 11 Mar 2024 13:35:48 +0100 Subject: [PATCH 14/16] Bring back code to persist iroh secret --- src/peer_channels.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/peer_channels.rs b/src/peer_channels.rs index 489a623d73..a569a14834 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -9,6 +9,7 @@ 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}; @@ -18,7 +19,7 @@ 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.generate_iroh_keypair(); + 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() { @@ -145,9 +146,17 @@ impl Context { Ok(()) } - /// Get the iroh gossip secret key from the database or create one. - pub fn generate_iroh_keypair(&self) -> SecretKey { - SecretKey::generate() + /// 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) + } + } } } From 367ffd91b2c2cc21be05d17afd774a8cf096faa7 Mon Sep 17 00:00:00 2001 From: adz Date: Mon, 11 Mar 2024 14:44:06 +0100 Subject: [PATCH 15/16] Fix method name in tests --- src/context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index 2e12e46518..fbf0cf94b6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1630,8 +1630,8 @@ mod tests { async fn test_keypair_saving() -> Result<()> { let alice = TestContext::new_alice().await; - let key = alice.get_or_create_iroh_keypair().await?; - let loaded_key = alice.get_or_create_iroh_keypair().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(()) From 09e0b0083f162b4d623b5f8cdf456c1303553e51 Mon Sep 17 00:00:00 2001 From: Septias Date: Mon, 11 Mar 2024 16:31:14 +0100 Subject: [PATCH 16/16] add integration test --- Cargo.toml | 25 ++++-- src/mimefactory.rs | 2 +- src/peer_channels.rs | 183 +++++++++++++++++++++++++++++++++++++++++++ src/receive_imf.rs | 2 + src/webxdc.rs | 15 +--- 5 files changed, 207 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e6b81bcd41..d08eecc977 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,10 +41,19 @@ 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"] } @@ -74,7 +83,9 @@ image = { version = "0.24.7", default-features = false, features = [ 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"] } +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" } @@ -125,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" diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 7688d4824b..3424dbb065 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -1275,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() { @@ -1284,7 +1285,6 @@ 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. diff --git a/src/peer_channels.rs b/src/peer_channels.rs index a569a14834..ef390c3b65 100644 --- a/src/peer_channels.rs +++ b/src/peer_channels.rs @@ -228,3 +228,186 @@ async fn subscribe_loop( }; } } + +#[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 bdfe793326..486d3b3c8d 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -472,6 +472,8 @@ pub(crate) async fn receive_imf_inner( 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/webxdc.rs b/src/webxdc.rs index f220f5c595..09ba2dad06 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -519,20 +519,9 @@ impl Context { self, "Gossip topic {topic} does not exist, sending over smtp", ); - let node_id = self - .endpoint - .lock() - .await - .as_ref() - .unwrap() - .my_addr() - .await - .unwrap() - .node_id; - self.add_peer_for_topic(instance_msg_id, topic, node_id) - .await?; self.join_and_subscribe_topic(topic, instance_msg_id) - .await?; + .await + .context("Failed to join and subscribe to gossip topic")?; ephemeral = false; } else { if let Some(ref gossip) = *self.gossip.lock().await {