From 2a1f5af0a9fe9e6c9e7f983bebeba9032fbd3300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20F=C3=A9ron?= Date: Tue, 12 Nov 2024 09:12:22 +0100 Subject: [PATCH] fix: random state reusage (#326) This includes the fix whisperfish/presage#292 in particular fixing the long-standing issue #234. Also adjust usage of presage::Store API which is now asynchronous. One possibly negative side-effect is that the UI looks up in the contact names cache in read-only fashion, and only the async part of gurk can populate the cache using the store. Also fix clippy warnings. --- Cargo.lock | 543 ++++++++++++++++++++++++---------------- Cargo.toml | 24 +- src/app.rs | 183 +++++++------- src/command.rs | 54 ++-- src/dev.rs | 43 ++-- src/handlers.rs | 2 +- src/main.rs | 4 +- src/signal/impl.rs | 32 +-- src/signal/manager.rs | 12 +- src/signal/mod.rs | 7 +- src/signal/test.rs | 13 +- src/storage/copy.rs | 6 +- src/ui/draw.rs | 2 +- src/ui/name_resolver.rs | 4 +- 14 files changed, 519 insertions(+), 410 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bcdaff..f7be565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,18 +354,14 @@ dependencies = [ [[package]] name = "async-tungstenite" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5359381fd414fbdb272c48f2111c16cb0bb3447bfacd59311ff3736da9f6664" +checksum = "90e661b6cb0a6eb34d02c520b052daa3aa9ac0cc02495c9d066bbce13ead132b" dependencies = [ "futures-io", "futures-util", "log", "pin-project-lite", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", "tungstenite", ] @@ -414,12 +410,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -552,9 +542,12 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +dependencies = [ + "serde", +] [[package]] name = "cassowary" @@ -1064,6 +1057,41 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.77", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.77", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -1099,6 +1127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -1658,13 +1687,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gurk" -version = "0.5.2-dev" +version = "0.5.3-dev" dependencies = [ "aho-corasick", "anyhow", "arboard", "async-trait", - "base64 0.22.1", + "base64", "chrono", "clap", "criterion", @@ -1718,25 +1747,6 @@ dependencies = [ "whoami", ] -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "2.4.1" @@ -1756,6 +1766,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1772,31 +1788,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", -] - -[[package]] -name = "headers" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" -dependencies = [ - "http", + "hashbrown 0.14.5", ] [[package]] @@ -1921,12 +1913,6 @@ version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - [[package]] name = "hyper" version = "1.4.1" @@ -1936,7 +1922,6 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", "http", "http-body", "httparse", @@ -1957,7 +1942,6 @@ dependencies = [ "http", "hyper", "hyper-util", - "log", "rustls", "rustls-pki-types", "tokio", @@ -1965,19 +1949,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-timeout" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" -dependencies = [ - "hyper", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.7" @@ -2021,6 +1992,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -2044,6 +2021,17 @@ dependencies = [ "tiff", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.5.0" @@ -2051,7 +2039,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", + "serde", ] [[package]] @@ -2096,6 +2085,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + [[package]] name = "is-terminal" version = "0.4.13" @@ -2122,15 +2117,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2202,7 +2188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2247,7 +2233,7 @@ dependencies = [ "hex", "hkdf", "hmac", - "indexmap", + "indexmap 2.5.0", "itertools 0.13.0", "libsignal-core", "log", @@ -2270,12 +2256,12 @@ dependencies = [ [[package]] name = "libsignal-service" version = "0.1.0" -source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=f99ff8324378ea653dbd5aa0c5d55e4414b34e23#f99ff8324378ea653dbd5aa0c5d55e4414b34e23" +source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=6401dc34872a5f0c2fba32c1f136d98ccf3dd418#6401dc34872a5f0c2fba32c1f136d98ccf3dd418" dependencies = [ "aes", "aes-gcm", "async-trait", - "base64 0.22.1", + "base64", "bincode", "bytes", "cbc", @@ -2291,10 +2277,13 @@ dependencies = [ "prost", "prost-build", "rand", + "reqwest", + "reqwest-websocket", "serde", "serde_json", "sha2", "thiserror", + "tokio", "tracing", "tracing-futures", "url", @@ -2302,34 +2291,6 @@ dependencies = [ "zkgroup", ] -[[package]] -name = "libsignal-service-hyper" -version = "0.1.0" -source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=f99ff8324378ea653dbd5aa0c5d55e4414b34e23#f99ff8324378ea653dbd5aa0c5d55e4414b34e23" -dependencies = [ - "async-trait", - "async-tungstenite", - "bytes", - "futures", - "headers", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-timeout", - "hyper-util", - "libsignal-service", - "mpart-async", - "rustls-pemfile", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-rustls", - "tracing", - "tracing-futures", - "url", -] - [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -2385,7 +2346,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -2507,28 +2468,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "mpart-async" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9bdeb8c63325c5d4ec66dff19cc42c5416b5bb27b2f555b3b9debdbe2d40d9b" -dependencies = [ - "bytes", - "futures-core", - "futures-util", - "http", - "httparse", - "log", - "memchr", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "rand", - "thiserror", - "tokio", - "tokio-util", -] - [[package]] name = "multimap" version = "0.10.0" @@ -2849,12 +2788,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - [[package]] name = "openssl-src" version = "300.3.1+3.3.1" @@ -3021,7 +2954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 2.5.0", ] [[package]] @@ -3051,7 +2984,7 @@ dependencies = [ "bincode", "either", "fnv", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "nom", "quick-xml 0.31.0", @@ -3283,28 +3216,30 @@ checksum = "94e851c7654eed9e68d7d27164c454961a616cf8c203d500607ef22c737b51bb" [[package]] name = "presage" -version = "0.6.2" -source = "git+https://github.com/whisperfish/presage?rev=464626aa27829bc4d641086359afccdb0da4711f#464626aa27829bc4d641086359afccdb0da4711f" +version = "0.7.0-dev" +source = "git+https://github.com/whisperfish/presage?rev=af5273a18204a3dc07423284f3dc8fa7829cbd13#af5273a18204a3dc07423284f3dc8fa7829cbd13" dependencies = [ - "base64 0.22.1", + "base64", + "bytes", + "derivative", "futures", "hex", "libsignal-service", - "libsignal-service-hyper", - "log", "rand", "serde", "serde_json", + "serde_with", "sha2", "thiserror", "tokio", + "tracing", "url", ] [[package]] name = "presage-store-cipher" version = "0.1.0" -source = "git+https://github.com/whisperfish/presage?rev=464626aa27829bc4d641086359afccdb0da4711f#464626aa27829bc4d641086359afccdb0da4711f" +source = "git+https://github.com/whisperfish/presage?rev=af5273a18204a3dc07423284f3dc8fa7829cbd13#af5273a18204a3dc07423284f3dc8fa7829cbd13" dependencies = [ "blake3", "chacha20poly1305", @@ -3321,13 +3256,12 @@ dependencies = [ [[package]] name = "presage-store-sled" version = "0.6.0-dev" -source = "git+https://github.com/whisperfish/presage?rev=464626aa27829bc4d641086359afccdb0da4711f#464626aa27829bc4d641086359afccdb0da4711f" +source = "git+https://github.com/whisperfish/presage?rev=af5273a18204a3dc07423284f3dc8fa7829cbd13#af5273a18204a3dc07423284f3dc8fa7829cbd13" dependencies = [ "async-trait", - "base64 0.22.1", + "base64", "chrono", "fs_extra", - "log", "presage", "presage-store-cipher", "prost", @@ -3338,6 +3272,7 @@ dependencies = [ "sha2", "sled", "thiserror", + "tracing", ] [[package]] @@ -3495,6 +3430,55 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +dependencies = [ + "cfg_aliases 0.2.1", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.37" @@ -3669,6 +3653,69 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry", +] + +[[package]] +name = "reqwest-websocket" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a147e80c12e380d0c92de2f862f6b455ca4be33c16e454f1f0a8946a9ec6c817" +dependencies = [ + "async-tungstenite", + "futures-util", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-util", + "tracing", + "tungstenite", + "web-sys", +] + [[package]] name = "ring" version = "0.17.8" @@ -3710,6 +3757,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3738,7 +3791,6 @@ version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ - "log", "once_cell", "ring", "rustls-pki-types", @@ -3747,26 +3799,13 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pemfile" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] @@ -3808,15 +3847,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -3829,29 +3859,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.23" @@ -3922,6 +3929,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.5.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4145,10 +4182,10 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown", + "hashbrown 0.14.5", "hashlink", "hex", - "indexmap", + "indexmap 2.5.0", "log", "memchr", "once_cell", @@ -4216,7 +4253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936cac0ab331b14cb3921c62156d913e4c15b74fb6ec0f3146bd4ef6e4fb3c12" dependencies = [ "atoi", - "base64 0.22.1", + "base64", "bitflags 2.6.0", "byteorder", "bytes", @@ -4260,7 +4297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9734dbce698c67ecf67c442f768a5e90a49b2a4d61a9f1d59f73874bd4cf0710" dependencies = [ "atoi", - "base64 0.22.1", + "base64", "bitflags 2.6.0", "byteorder", "chrono", @@ -4403,6 +4440,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "tar" version = "0.4.41" @@ -4603,6 +4649,7 @@ checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -4635,7 +4682,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", @@ -4775,9 +4822,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" dependencies = [ "byteorder", "bytes", @@ -4786,11 +4833,8 @@ dependencies = [ "httparse", "log", "rand", - "rustls", - "rustls-pki-types", "sha1", "thiserror", - "url", "utf-8", ] @@ -5007,6 +5051,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.93" @@ -5036,6 +5092,19 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "wasm-streams" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wayland-backend" version = "0.3.6" @@ -5167,7 +5236,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -5213,7 +5282,7 @@ checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" dependencies = [ "windows-implement", "windows-interface", - "windows-result", + "windows-result 0.1.2", "windows-targets 0.52.6", ] @@ -5239,6 +5308,17 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -5248,6 +5328,25 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index e40f28f..86692ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "gurk" description = "Signal messenger client for terminal" -version = "0.5.2-dev" +version = "0.5.3-dev" authors = ["boxdot "] edition = "2021" keywords = ["signal", "tui"] @@ -28,8 +28,8 @@ debug = true dev = ["prost", "base64"] [dependencies] -presage = { git = "https://github.com/whisperfish/presage", rev = "464626aa27829bc4d641086359afccdb0da4711f" } -presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "464626aa27829bc4d641086359afccdb0da4711f" } +presage = { git = "https://github.com/whisperfish/presage", rev = "af5273a18204a3dc07423284f3dc8fa7829cbd13" } +presage-store-sled = { git = "https://github.com/whisperfish/presage", rev = "af5273a18204a3dc07423284f3dc8fa7829cbd13" } # dev feature dependencies prost = { version = "0.13.0", optional = true } @@ -49,7 +49,9 @@ hex = "0.4.3" hostname = "0.4.0" image = { version = "0.25.0", default-features = false, features = ["png"] } itertools = "0.13.0" -libsqlite3-sys = { version = "0.30.1", features = ["bundled-sqlcipher-vendored-openssl"] } +libsqlite3-sys = { version = "0.30.1", features = [ + "bundled-sqlcipher-vendored-openssl", +] } log-panics = "2.1.0" mime_guess = "2.0.4" notify-rust = "4.5.10" @@ -64,11 +66,21 @@ regex = "1.9.5" scopeguard = "1.1.0" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.87" -sqlx = { version = "0.8.1", features = ["sqlite", "runtime-tokio-rustls", "uuid", "chrono"] } +sqlx = { version = "0.8.1", features = [ + "sqlite", + "runtime-tokio-rustls", + "uuid", + "chrono", +] } textwrap = "0.16.0" thiserror = "1.0.40" thread_local = "1.1.7" -tokio = { version = "1.21.2", default-features = false, features = ["rt-multi-thread", "macros", "net", "time"] } +tokio = { version = "1.21.2", default-features = false, features = [ + "rt-multi-thread", + "macros", + "net", + "time", +] } tokio-stream = "0.1.11" toml = "0.8.0" tracing = "0.1.37" diff --git a/src/app.rs b/src/app.rs index 978114d..731d6a9 100644 --- a/src/app.rs +++ b/src/app.rs @@ -28,7 +28,6 @@ use itertools::Itertools; use notify_rust::Notification; use presage::libsignal_service::content::{Content, ContentBody, Metadata}; use presage::libsignal_service::sender::AttachmentSpec; -use presage::libsignal_service::ServiceAddress; use presage::proto::{ data_message::{Reaction, Sticker}, sync_message::Sent, @@ -141,14 +140,14 @@ impl App { } /// Resolve and cache all user names for the known user channels - pub fn populate_names_cache(&self) { + pub async fn populate_names_cache(&self) { let mut names_cache = BTreeMap::new(); for user_id in self .storage .channels() .filter_map(|channel| channel.id.user()) { - if let Some(name) = self.resolve_name(user_id) { + if let Some(name) = self.resolve_name(user_id).await { names_cache.insert(user_id, name); } } @@ -179,13 +178,26 @@ impl App { }; Some(format!( "[{}] writing...", - uuids.map(|id| self.name_by_id(id)).format(", ") + uuids.map(|id| self.name_by_id_cached(id)).format(", ") )) } else { None } } + /// Returns the name of a user by their ID from the cache without resolving it. + pub fn name_by_id_cached(&self, id: Uuid) -> String { + if self.user_id == id { + // it's me + return self.config.user.name.clone(); + }; + + let cache = self.names_cache.take().unwrap_or_default(); + let name = cache.get(&id).cloned().unwrap_or_else(|| id.to_string()); + self.names_cache.replace(Some(cache)); + name + } + /// Resolves name of a user by their id /// /// The resolution is done from the following places: @@ -193,11 +205,11 @@ impl App { /// 1. signal's profile name storage /// 2. signal's contacts storage /// 3. internal gurk's user name table - fn resolve_name(&self, user_id: Uuid) -> Option { - if let Some(name) = self.signal_manager.profile_name(user_id) { + async fn resolve_name(&self, user_id: Uuid) -> Option { + if let Some(name) = self.signal_manager.profile_name(user_id).await { debug!(name, "resolved name as profile name"); Some(name) - } else if let Some(contact) = self.signal_manager.contact(user_id) { + } else if let Some(contact) = self.signal_manager.contact(user_id).await { debug!(name = contact.name, "resolved name from contacts"); Some(contact.name) } else if let Some(name) = self @@ -213,36 +225,39 @@ impl App { } // Resolves name of a user by their id - pub fn name_by_id(&self, id: Uuid) -> String { + pub async fn name_by_id(&self, id: Uuid) -> String { if self.user_id == id { // it's me self.config.user.name.clone() } else { self.name_by_id_or_cache(id, |id| self.resolve_name(id)) + .await } } - fn name_by_id_or_cache( - &self, - id: Uuid, - on_miss: impl FnOnce(Uuid) -> Option, - ) -> String { - let mut cache = self.names_cache.take().unwrap_or_default(); - let name = if let Some(name) = cache.get(&id).cloned() { + async fn name_by_id_or_cache(&self, id: Uuid, on_miss: impl FnOnce(Uuid) -> F) -> String + where + F: Future>, + { + let cache = self.names_cache.take().unwrap_or_default(); + let name = cache.get(&id).cloned(); + self.names_cache.replace(Some(cache)); + + if let Some(name) = name { name - } else if let Some(name) = on_miss(id) { + } else if let Some(name) = on_miss(id).await { + let mut cache = self.names_cache.take().unwrap_or_default(); cache.insert(id, name.clone()); + self.names_cache.replace(Some(cache)); name } else { id.to_string() - }; - self.names_cache.replace(Some(cache)); - name + } } pub fn channel_name<'a>(&self, channel: &'a Channel) -> Cow<'a, str> { if let Some(id) = channel.user_id() { - self.name_by_id(id).into() + self.name_by_id_cached(id).into() } else { (&channel.name).into() } @@ -300,7 +315,7 @@ impl App { } Command::React => { if let Some(idx) = self.channels.state.selected() { - self.add_reaction(idx); + self.add_reaction(idx).await; } } Command::OpenUrl => { @@ -421,7 +436,7 @@ impl App { } } - pub fn add_reaction(&mut self, channel_idx: usize) -> Option<()> { + pub async fn add_reaction(&mut self, channel_idx: usize) -> Option<()> { let reaction = self.take_reaction()?; let channel = self.storage.channel(self.channels.items[channel_idx])?; let message = self.selected_message()?; @@ -449,7 +464,8 @@ impl App { self.signal_manager.user_id(), emoji, HandleReactionOptions::new().remove(true), - ); + ) + .await; self.reset_unread_messages(); self.bubble_up_channel(channel_idx); @@ -606,13 +622,7 @@ impl App { } // reactions ( - Metadata { - sender: - ServiceAddress { - uuid: sender_uuid, .. - }, - .. - }, + Metadata { sender, .. }, ContentBody::SynchronizeMessage(SyncMessage { sent: Some(Sent { @@ -652,13 +662,14 @@ impl App { self.handle_reaction( channel_id, target_sent_timestamp, - sender_uuid, + sender.raw_uuid(), emoji, HandleReactionOptions::new() .remove(remove.unwrap_or(false)) .notify(true) .bell(true), - ); + ) + .await; read.into_iter().for_each(|r| { self.handle_receipt( Uuid::parse_str(r.sender_aci.unwrap().as_str()).unwrap(), @@ -669,13 +680,7 @@ impl App { return Ok(()); } ( - Metadata { - sender: - ServiceAddress { - uuid: sender_uuid, .. - }, - .. - }, + Metadata { sender, .. }, ContentBody::DataMessage(DataMessage { body: None, group_v2, @@ -696,35 +701,30 @@ impl App { }) = group_v2 { ChannelId::from_master_key_bytes(master_key)? - } else if sender_uuid == self.user_id { + } else if sender.raw_uuid() == self.user_id { // reaction from us => target author is the user channel ChannelId::User(target_author_uuid.parse()?) } else { // reaction is from somebody else => they are the user channel - ChannelId::User(sender_uuid) + ChannelId::User(sender.raw_uuid()) }; self.handle_reaction( channel_id, target_sent_timestamp, - sender_uuid, + sender.raw_uuid(), emoji, HandleReactionOptions::new() .remove(remove.unwrap_or(false)) .notify(true) .bell(true), - ); + ) + .await; return Ok(()); } // Direct/group message by us from a different device ( - Metadata { - sender: - ServiceAddress { - uuid: sender_uuid, .. - }, - .. - }, + Metadata { sender, .. }, ContentBody::SynchronizeMessage(SyncMessage { sent: Some(Sent { @@ -745,7 +745,7 @@ impl App { }), .. }), - ) if sender_uuid == user_id => { + ) if sender.raw_uuid() == user_id => { let channel_idx = if let Some(GroupContextV2 { master_key: Some(master_key), revision: Some(revision), @@ -765,7 +765,7 @@ impl App { .try_into() .map_err(|_| anyhow!("invalid profile key"))?; let destination_uuid = destination_uuid.parse()?; - let name = self.name_by_id(destination_uuid); + let name = self.name_by_id(destination_uuid).await; self.ensure_user_is_known(destination_uuid, Some(profile_key)) .await; self.ensure_contact_channel_exists(destination_uuid, &name) @@ -794,10 +794,7 @@ impl App { } // Incoming direct/group message ( - Metadata { - sender: ServiceAddress { uuid, .. }, - .. - }, + Metadata { sender, .. }, ContentBody::DataMessage(DataMessage { mut body, group_v2, @@ -834,8 +831,9 @@ impl App { .await .context("failed to create group channel")?; - self.ensure_user_is_known(uuid, profile_key).await; - let from = self.name_by_id(uuid); + self.ensure_user_is_known(sender.raw_uuid(), profile_key) + .await; + let from = self.name_by_id(sender.raw_uuid()).await; (channel_idx, from) } else { @@ -844,9 +842,12 @@ impl App { .context("sync message with destination without profile key")? .try_into() .map_err(|_| anyhow!("invalid profile key"))?; - self.ensure_user_is_known(uuid, Some(profile_key)).await; - let name = self.name_by_id(uuid); - let channel_idx = self.ensure_contact_channel_exists(uuid, &name).await; + self.ensure_user_is_known(sender.raw_uuid(), Some(profile_key)) + .await; + let name = self.name_by_id(sender.raw_uuid()).await; + let channel_idx = self + .ensure_contact_channel_exists(sender.raw_uuid(), &name) + .await; // Reset typing notification as the Tipyng::Stop are not always sent by the server when a message is sent. let channel_id = self.channels.items[channel_idx]; let mut channel = self @@ -855,7 +856,7 @@ impl App { .expect("non-existent channel") .into_owned(); let from = channel.name.clone(); - if channel.reset_writing(uuid) { + if channel.reset_writing(sender.raw_uuid()) { self.storage.store_channel(channel); } (channel_idx, from) @@ -867,13 +868,17 @@ impl App { self.notify_about_message(&from, body.as_deref(), &attachments); // Send "Delivered" receipt - self.add_receipt_event(ReceiptEvent::new(uuid, timestamp, Receipt::Delivered)); + self.add_receipt_event(ReceiptEvent::new( + sender.raw_uuid(), + timestamp, + Receipt::Delivered, + )); let quote = quote.and_then(Message::from_quote).map(Box::new); let body_ranges = body_ranges.into_iter().filter_map(BodyRange::from_proto); let message = Message { quote, - ..Message::new(uuid, body, body_ranges, timestamp, attachments) + ..Message::new(sender.raw_uuid(), body, body_ranges, timestamp, attachments) }; if message.is_empty() { @@ -886,31 +891,19 @@ impl App { return self.handle_sync_message(metadata, sync_message); } ( - Metadata { - sender: - ServiceAddress { - uuid: sender_uuid, .. - }, - .. - }, + Metadata { sender, .. }, ContentBody::ReceiptMessage(ReceiptMessage { r#type: Some(receipt_type), timestamp: timestamps, }), ) => { let receipt = Receipt::from_i32(receipt_type); - self.handle_receipt(sender_uuid, receipt, timestamps); + self.handle_receipt(sender.raw_uuid(), receipt, timestamps); return Ok(()); } ( - Metadata { - sender: - ServiceAddress { - uuid: sender_uuid, .. - }, - .. - }, + Metadata { sender, .. }, ContentBody::TypingMessage(TypingMessage { timestamp: Some(timest), group_id, @@ -926,7 +919,7 @@ impl App { }; if self .handle_typing( - sender_uuid, + sender.raw_uuid(), group_id_bytes, TypingAction::from_i32(act), timest, @@ -1073,7 +1066,7 @@ impl App { } } - fn handle_reaction( + async fn handle_reaction( &mut self, channel_id: ChannelId, target_sent_timestamp: u64, @@ -1120,7 +1113,7 @@ impl App { let channel = self.storage.channel(channel_id)?; let channel_name = channel.name.clone(); - let sender_name = self.name_by_id(sender_uuid); + let sender_name = self.name_by_id(sender_uuid).await; let summary = if let ChannelId::Group(_) = channel_id { Cow::from(format!("{sender_name} in {channel_name}")) } else { @@ -1236,7 +1229,7 @@ impl App { }) .is_some(); if !is_known { - let name = if let Some(name) = self.signal_manager.profile_name(uuid) { + let name = if let Some(name) = self.signal_manager.profile_name(uuid).await { name } else { match profile_key { @@ -1829,8 +1822,8 @@ pub(crate) mod tests { } } - #[test] - fn test_add_reaction_with_emoji() { + #[tokio::test] + async fn test_add_reaction_with_emoji() { let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; @@ -1841,7 +1834,7 @@ pub(crate) mod tests { .select(Some(0)); app.get_input().put_char('👍'); - app.add_reaction(0); + app.add_reaction(0).await; let arrived_at = app.messages[&channel_id].items[0]; let reactions = &app @@ -1853,8 +1846,8 @@ pub(crate) mod tests { assert_eq!(reactions[0], (app.user_id, "👍".to_string())); } - #[test] - fn test_add_reaction_with_emoji_codepoint() { + #[tokio::test] + async fn test_add_reaction_with_emoji_codepoint() { let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; @@ -1867,7 +1860,7 @@ pub(crate) mod tests { for c in ":thumbsup:".chars() { app.get_input().put_char(c); } - app.add_reaction(0); + app.add_reaction(0).await; let arrived_at = app.messages[&channel_id].items[0]; let reactions = &app @@ -1879,8 +1872,8 @@ pub(crate) mod tests { assert_eq!(reactions[0], (app.user_id, "👍".to_string())); } - #[test] - fn test_remove_reaction() { + #[tokio::test] + async fn test_remove_reaction() { let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; @@ -1898,7 +1891,7 @@ pub(crate) mod tests { .into_owned(); message.reactions.push((app.user_id, "👍".to_string())); app.storage.store_message(channel_id, message); - app.add_reaction(0); + app.add_reaction(0).await; let reactions = &app .storage @@ -1908,8 +1901,8 @@ pub(crate) mod tests { assert!(reactions.is_empty()); } - #[test] - fn test_add_invalid_reaction() { + #[tokio::test] + async fn test_add_invalid_reaction() { let (mut app, _events, _sent_messages) = test_app(); let channel_id = app.channels.items[0]; app.messages @@ -1921,7 +1914,7 @@ pub(crate) mod tests { for c in ":thumbsup".chars() { app.get_input().put_char(c); } - app.add_reaction(0); + app.add_reaction(0).await; assert_eq!(app.get_input().data, ":thumbsup"); let arrived_at = app.messages[&channel_id].items[0]; diff --git a/src/command.rs b/src/command.rs index 50a5c08..d913bd2 100644 --- a/src/command.rs +++ b/src/command.rs @@ -243,7 +243,7 @@ pub enum CommandParseError { } fn parse(input: &str) -> Result { - let words: Vec<_> = input.trim().split_whitespace().collect(); + let words: Vec<_> = input.split_whitespace().collect(); use CommandParseError as E; let (cmd_str, args) = words.split_first().unwrap(); @@ -446,34 +446,9 @@ pagedown = "scroll help down entry" pageup = "scroll help up entry" "#; -#[cfg(test)] -mod tests { - use toml; - - use super::{get_keybindings, ModeKeybindingConfig, DEFAULT_KEYBINDINGS}; - - #[test] - fn default_keybindings_deserialize() { - let _keybindings: ModeKeybindingConfig = toml::from_str(DEFAULT_KEYBINDINGS).unwrap(); - } - - #[test] - fn default_keybindings_parse() { - get_keybindings(&ModeKeybindingConfig::new(), true).unwrap(); - } - - #[test] - fn custom_keybindings() { - let bindings: ModeKeybindingConfig = - toml::from_str("[normal]\n F1 = \"\"\n ctrl-h = \"help\"\n").unwrap(); - get_keybindings(&bindings, true).unwrap(); - get_keybindings(&bindings, false).unwrap(); - } -} - fn merge_keybinding_configs(mkb1: &mut ModeKeybindingConfig, mkb2: ModeKeybindingConfig) { for (mode, kb2) in mkb2 { - mkb1.entry(mode).or_insert(HashMap::new()).extend(kb2); + mkb1.entry(mode).or_default().extend(kb2); } } @@ -510,3 +485,28 @@ fn parse_keybindings(kbc: &KeybindingConfig) -> Result, } -#[derive(Serialize, Deserialize)] -#[serde(remote = "ServiceAddress")] -struct ServiceAddressDef { - pub uuid: Uuid, - #[serde(with = "ServiceIdTypeDef")] - pub identity: ServiceIdType, -} +mod service_id { + use presage::libsignal_service::protocol::ServiceId; + use serde::{Deserialize, Serialize, Serializer}; -#[derive(Serialize, Deserialize)] -#[serde(remote = "ServiceIdType")] -pub enum ServiceIdTypeDef { - AccountIdentity, - PhoneNumberIdentity, -} + pub fn serialize(value: &ServiceId, serializer: S) -> Result + where + S: Serializer, + { + value.service_id_string().serialize(serializer) + } -fn default_destination() -> ServiceAddress { - ServiceAddress { - uuid: Uuid::nil(), - identity: ServiceIdType::AccountIdentity, + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + ServiceId::parse_from_service_id_string(&s) + .ok_or_else(|| serde::de::Error::custom(format!("invalid service id string: {s}"))) } } diff --git a/src/handlers.rs b/src/handlers.rs index 7f1fb3f..b8f493f 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -36,7 +36,7 @@ impl App { .. }) = sync_message.sent { - let from_id = metadata.sender.uuid; + let from_id = metadata.sender.raw_uuid(); // Note: target_sent_timestamp points to the previous edit or the original message let edited = self .storage diff --git a/src/main.rs b/src/main.rs index a227a08..c8a380a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -131,10 +131,10 @@ async fn run_single_threaded(relink: bool) -> anyhow::Result<()> { Box::new(json_storage) }; - sync_from_signal(&*signal_manager, &mut *storage); + sync_from_signal(&*signal_manager, &mut *storage).await; let (mut app, mut app_events) = App::try_new(config, signal_manager.clone_boxed(), storage)?; - app.populate_names_cache(); + app.populate_names_cache().await; // sync task can be only spawned after we start to listen to message, because it relies on // message sender to be running diff --git a/src/signal/impl.rs b/src/signal/impl.rs index 7ae0758..cc9d15a 100644 --- a/src/signal/impl.rs +++ b/src/signal/impl.rs @@ -5,11 +5,12 @@ use std::pin::Pin; use anyhow::Context; use async_trait::async_trait; use presage::libsignal_service::content::{Content, ContentBody}; -use presage::libsignal_service::models::Contact; -use presage::libsignal_service::prelude::{Group, ProfileKey}; +use presage::libsignal_service::prelude::ProfileKey; +use presage::libsignal_service::protocol::ServiceId; use presage::libsignal_service::sender::AttachmentSpec; -use presage::libsignal_service::ServiceAddress; use presage::manager::{ReceivingMode, Registered}; +use presage::model::contacts::Contact; +use presage::model::groups::Group; use presage::proto::data_message::{Quote, Reaction}; use presage::proto::{AttachmentPointer, DataMessage, EditMessage, GroupContextV2, ReceiptMessage}; use presage::store::ContentsStore; @@ -54,7 +55,8 @@ impl SignalManager for PresageManager { let decrypted_group = self .manager .store() - .group(master_key_bytes)? + .group(master_key_bytes) + .await? .context("no group found")?; let mut members = Vec::with_capacity(decrypted_group.members.len()); @@ -100,7 +102,7 @@ impl SignalManager for PresageManager { tokio::task::spawn_local(async move { let body = ContentBody::ReceiptMessage(data_message); if let Err(error) = manager - .send_message(ServiceAddress::new_aci(sender_uuid), body, now_timestamp) + .send_message(ServiceId::Aci(sender_uuid.into()), body, now_timestamp) .await { error!(%error, %sender_uuid, "failed to send receipt"); @@ -177,7 +179,7 @@ impl SignalManager for PresageManager { }; if let Err(error) = manager - .send_message(ServiceAddress::new_aci(uuid), body, timestamp) + .send_message(ServiceId::Aci(uuid.into()), body, timestamp) .await { error!(dest =% uuid, %error, "failed to send message"); @@ -269,7 +271,7 @@ impl SignalManager for PresageManager { let body = ContentBody::DataMessage(data_message); tokio::task::spawn_local(async move { if let Err(e) = manager - .send_message(ServiceAddress::new_aci(uuid), body, timestamp) + .send_message(ServiceId::Aci(uuid.into()), body, timestamp) .await { // TODO: Proper error handling @@ -325,9 +327,9 @@ impl SignalManager for PresageManager { Ok(self.manager.clone().sync_contacts().await?) } - fn profile_name(&self, id: Uuid) -> Option { - let profile_key = self.manager.store().profile_key(&id).ok()??; - let profile = self.manager.store().profile(id, profile_key).ok()??; + async fn profile_name(&self, id: Uuid) -> Option { + let profile_key = self.manager.store().profile_key(&id).await.ok()??; + let profile = self.manager.store().profile(id, profile_key).await.ok()??; let given_name = profile.name?.given_name; if !given_name.is_empty() { Some(given_name) @@ -336,8 +338,8 @@ impl SignalManager for PresageManager { } } - fn contact(&self, id: Uuid) -> Option { - self.manager.store().contact_by_id(&id).ok()? + async fn contact(&self, id: Uuid) -> Option { + self.manager.store().contact_by_id(&id).await.ok()? } async fn receive_messages(&mut self) -> anyhow::Result>>> { @@ -348,22 +350,24 @@ impl SignalManager for PresageManager { )) } - fn contacts(&self) -> Box> { + async fn contacts(&self) -> Box> { Box::new( self.manager .store() .contacts() + .await .into_iter() .flatten() .flatten(), ) } - fn groups(&self) -> Box> { + async fn groups(&self) -> Box> { Box::new( self.manager .store() .groups() + .await .into_iter() .flatten() .flatten(), diff --git a/src/signal/manager.rs b/src/signal/manager.rs index 80bfb5a..1bcab28 100644 --- a/src/signal/manager.rs +++ b/src/signal/manager.rs @@ -5,9 +5,9 @@ use std::pin::Pin; use async_trait::async_trait; use presage::libsignal_service::content::Content; -use presage::libsignal_service::models::Contact; -use presage::libsignal_service::prelude::Group; use presage::libsignal_service::sender::AttachmentSpec; +use presage::model::contacts::Contact; +use presage::model::groups::Group; use presage::proto::AttachmentPointer; use serde::{Deserialize, Serialize}; use tokio::sync::oneshot; @@ -49,7 +49,7 @@ pub trait SignalManager { fn send_reaction(&self, channel: &Channel, message: &Message, emoji: String, remove: bool); - fn profile_name(&self, id: Uuid) -> Option; + async fn profile_name(&self, id: Uuid) -> Option; /// Resolves contact name from user's profile via Signal server async fn resolve_profile_name( @@ -60,12 +60,12 @@ pub trait SignalManager { async fn request_contacts_sync(&self) -> anyhow::Result<()>; - fn contact(&self, id: Uuid) -> Option; + async fn contact(&self, id: Uuid) -> Option; async fn receive_messages(&mut self) -> anyhow::Result>>>; - fn contacts(&self) -> Box>; - fn groups(&self) -> Box>; + async fn contacts(&self) -> Box>; + async fn groups(&self) -> Box>; } pub struct ResolvedGroup { diff --git a/src/signal/mod.rs b/src/signal/mod.rs index 32cae08..b190078 100644 --- a/src/signal/mod.rs +++ b/src/signal/mod.rs @@ -4,8 +4,8 @@ mod manager; pub mod test; use anyhow::{bail, Context as _}; -use presage::libsignal_service::configuration::SignalServers; -use presage_store_sled::{MigrationConflictStrategy, OnNewIdentity, SledStore}; +use presage::{libsignal_service::configuration::SignalServers, model::identity::OnNewIdentity}; +use presage_store_sled::{MigrationConflictStrategy, SledStore}; use crate::config::{self, Config}; @@ -46,7 +46,8 @@ pub async fn ensure_linked_device( passphrase, MigrationConflictStrategy::BackupAndDrop, OnNewIdentity::Trust, - )?; + ) + .await?; if !relink { if let Some(config) = config.clone() { diff --git a/src/signal/test.rs b/src/signal/test.rs index 5f11a9f..9dc0536 100644 --- a/src/signal/test.rs +++ b/src/signal/test.rs @@ -3,9 +3,10 @@ use std::{cell::RefCell, rc::Rc}; use async_trait::async_trait; use presage::libsignal_service::content::Content; -use presage::libsignal_service::models::Contact; -use presage::libsignal_service::prelude::{AttachmentIdentifier, Group}; +use presage::libsignal_service::prelude::AttachmentIdentifier; use presage::libsignal_service::sender::AttachmentSpec; +use presage::model::contacts::Contact; +use presage::model::groups::Group; use presage::proto::data_message::Quote; use presage::proto::AttachmentPointer; use tokio::sync::oneshot; @@ -129,11 +130,11 @@ impl SignalManager for SignalManagerMock { Ok(()) } - fn profile_name(&self, _id: Uuid) -> Option { + async fn profile_name(&self, _id: Uuid) -> Option { None } - fn contact(&self, _id: Uuid) -> Option { + async fn contact(&self, _id: Uuid) -> Option { None } @@ -148,11 +149,11 @@ impl SignalManager for SignalManagerMock { }) } - fn contacts(&self) -> Box> { + async fn contacts(&self) -> Box> { Box::new(std::iter::empty()) } - fn groups(&self) -> Box> { + async fn groups(&self) -> Box> { Box::new(std::iter::empty()) } } diff --git a/src/storage/copy.rs b/src/storage/copy.rs index 0dfe74b..db19119 100644 --- a/src/storage/copy.rs +++ b/src/storage/copy.rs @@ -42,8 +42,8 @@ pub fn copy(from: &dyn Storage, to: &mut dyn Storage) -> Stats { /// /// Note: At the moment, there is no group sync implemented in presage, so only contacts are /// synced fully. -pub fn sync_from_signal(manager: &dyn SignalManager, storage: &mut dyn Storage) { - for contact in manager.contacts() { +pub async fn sync_from_signal(manager: &dyn SignalManager, storage: &mut dyn Storage) { + for contact in manager.contacts().await { if contact.name.is_empty() { // not sure what to do with contacts without a name continue; @@ -64,7 +64,7 @@ pub fn sync_from_signal(manager: &dyn SignalManager, storage: &mut dyn Storage) } } - for (master_key_bytes, group) in manager.groups() { + for (master_key_bytes, group) in manager.groups().await { let channel_id = match ChannelId::from_master_key_bytes(master_key_bytes) { Ok(channel_id) => channel_id, Err(error) => { diff --git a/src/ui/draw.rs b/src/ui/draw.rs index da1e9d3..457fcb1 100644 --- a/src/ui/draw.rs +++ b/src/ui/draw.rs @@ -691,7 +691,7 @@ fn help_commands<'a>() -> Vec> { } fn bindings(app: &App) -> Vec { - vec![ + [ WindowMode::Normal, WindowMode::Anywhere, WindowMode::Help, diff --git a/src/ui/name_resolver.rs b/src/ui/name_resolver.rs index 6bea351..a31b175 100644 --- a/src/ui/name_resolver.rs +++ b/src/ui/name_resolver.rs @@ -68,7 +68,7 @@ impl<'a> NameResolver<'a> { .get(&id) .map(|(name, color)| (name.into(), *color)) .unwrap_or_else(|| { - let name = self.app.expect("logic error").name_by_id(id).into(); + let name = self.app.expect("logic error").name_by_id_cached(id).into(); (name, Color::Magenta) }) } @@ -91,7 +91,7 @@ impl<'a> NameResolver<'a> { impl App { fn name_and_color(&self, id: Uuid) -> (String, Color) { - let name = self.name_by_id(id); + let name = self.name_by_id_cached(id); let color = user_color(&name); let name = displayed_name(name, self.config.first_name_only); (name, color)