From ce2017a10e92141881e0ec438a848a6ab1382a94 Mon Sep 17 00:00:00 2001 From: girlbossceo Date: Thu, 10 Aug 2023 23:12:37 +0000 Subject: [PATCH 001/175] log handling previous event time as debug Signed-off-by: girlbossceo --- src/service/rooms/event_handler/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 899f035a..cad0a451 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -226,7 +226,7 @@ impl Service { .write() .unwrap() .remove(&room_id.to_owned()); - warn!( + debug!( "Handling prev event {} took {}m{}s", prev_id, elapsed.as_secs() / 60, From 11103a92ed98e89ae535af4ed185ebd570a2ce81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Fri, 11 Aug 2023 10:48:48 +0200 Subject: [PATCH 002/175] Do not show "Invalid room version" errors when server is not in room --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/api/server_server.rs | 19 ++++++++++++++++++- src/service/rooms/state/mod.rs | 15 ++++++--------- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35a42085..26b72011 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -363,7 +363,7 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "conduit" -version = "0.6.0" +version = "0.7.0-alpha" dependencies = [ "async-trait", "axum", diff --git a/Cargo.toml b/Cargo.toml index 15dc1da4..0138a2d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = ["timokoesters "] homepage = "https://conduit.rs" repository = "https://gitlab.com/famedly/conduit" readme = "README.md" -version = "0.6.0" +version = "0.7.0-alpha" edition = "2021" # When changing this, make sure to update the `flake.lock` file by running diff --git a/src/api/server_server.rs b/src/api/server_server.rs index bb924058..9bc9687c 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -55,7 +55,7 @@ use std::{ time::{Duration, Instant, SystemTime}, }; -use tracing::{debug, error, warn}; +use tracing::{debug, error, trace, warn}; /// Wraps either an literal IP address plus port, or a hostname plus complement /// (colon-plus-port if it was specified). @@ -707,6 +707,23 @@ pub async fn send_transaction_message_route( // let mut auth_cache = EventMap::new(); for pdu in &body.pdus { + let value: CanonicalJsonObject = serde_json::from_str(pdu.get()).map_err(|e| { + warn!("Error parsing incoming event {:?}: {:?}", pdu, e); + Error::BadServerResponse("Invalid PDU in server response") + })?; + let room_id: OwnedRoomId = value + .get("room_id") + .and_then(|id| RoomId::parse(id.as_str()?).ok()) + .ok_or(Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid room id in pdu", + ))?; + + if services().rooms.state.get_room_version(&room_id).is_err() { + debug!("Server is not in room {room_id}"); + continue; + } + let r = parse_incoming_pdu(&pdu); let (event_id, value, room_id) = match r { Ok(t) => t, diff --git a/src/service/rooms/state/mod.rs b/src/service/rooms/state/mod.rs index 16e0a04d..48c60203 100644 --- a/src/service/rooms/state/mod.rs +++ b/src/service/rooms/state/mod.rs @@ -6,6 +6,7 @@ use std::{ pub use data::Data; use ruma::{ + api::client::error::ErrorKind, events::{ room::{create::RoomCreateEventContent, member::MembershipState}, AnyStrippedStateEvent, StateEventType, TimelineEventType, @@ -331,7 +332,7 @@ impl Service { "", )?; - let create_event_content: Option = create_event + let create_event_content: RoomCreateEventContent = create_event .as_ref() .map(|create_event| { serde_json::from_str(create_event.content.get()).map_err(|e| { @@ -339,14 +340,10 @@ impl Service { Error::bad_database("Invalid create event in db.") }) }) - .transpose()?; - let room_version = create_event_content - .map(|create_event| create_event.room_version) - .ok_or_else(|| { - warn!("Invalid room version for room {room_id}"); - Error::BadDatabase("Invalid room version") - })?; - Ok(room_version) + .transpose()? + .ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "No create event found"))?; + + Ok(create_event_content.room_version) } pub fn get_room_shortstatehash(&self, room_id: &RoomId) -> Result> { From f73a657a23be2d3d5690069bd7cc32a4897ee881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Fri, 11 Aug 2023 20:29:22 +0200 Subject: [PATCH 003/175] fix: ACL error shouldn't break the whole request --- src/api/server_server.rs | 5 ----- src/service/rooms/event_handler/mod.rs | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 9bc9687c..f29de32b 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -735,11 +735,6 @@ pub async fn send_transaction_message_route( }; // We do not add the event_id field to the pdu here because of signature and hashes checks - services() - .rooms - .event_handler - .acl_check(sender_servername, &room_id)?; - let mutex = Arc::clone( services() .globals diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 899f035a..1fa78b6c 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -92,6 +92,8 @@ impl Service { )); } + services().rooms.event_handler.acl_check(origin, &room_id)?; + // 1. Skip the PDU if we already have it as a timeline event if let Some(pdu_id) = services().rooms.timeline.get_pdu_id(event_id)? { return Ok(Some(pdu_id.to_vec())); From 9b55ce933a5cf62f445a061bdcd6b17e7bb58857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Sat, 12 Aug 2023 09:53:32 +0200 Subject: [PATCH 004/175] Back off from more events, don't retry auth events --- src/service/rooms/event_handler/mod.rs | 110 ++++++++++++++++--------- 1 file changed, 71 insertions(+), 39 deletions(-) diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 1fa78b6c..e93feaa5 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -119,7 +119,15 @@ impl Service { .ok_or_else(|| Error::bad_database("Failed to find first pdu in db."))?; let (incoming_pdu, val) = self - .handle_outlier_pdu(origin, &create_event, event_id, room_id, value, pub_key_map) + .handle_outlier_pdu( + origin, + &create_event, + event_id, + room_id, + value, + false, + pub_key_map, + ) .await?; self.check_room_id(room_id, &incoming_pdu)?; @@ -276,6 +284,7 @@ impl Service { event_id: &'a EventId, room_id: &'a RoomId, mut value: BTreeMap, + auth_events_known: bool, pub_key_map: &'a RwLock>>, ) -> AsyncRecursiveType<'a, Result<(Arc, BTreeMap)>> { Box::pin(async move { @@ -343,23 +352,25 @@ impl Service { self.check_room_id(room_id, &incoming_pdu)?; - // 4. fetch any missing auth events doing all checks listed here starting at 1. These are not timeline events - // 5. Reject "due to auth events" if can't get all the auth events or some of the auth events are also rejected "due to auth events" - // NOTE: Step 5 is not applied anymore because it failed too often - debug!(event_id = ?incoming_pdu.event_id, "Fetching auth events"); - self.fetch_and_handle_outliers( - origin, - &incoming_pdu - .auth_events - .iter() - .map(|x| Arc::from(&**x)) - .collect::>(), - create_event, - room_id, - room_version_id, - pub_key_map, - ) - .await; + if !auth_events_known { + // 4. fetch any missing auth events doing all checks listed here starting at 1. These are not timeline events + // 5. Reject "due to auth events" if can't get all the auth events or some of the auth events are also rejected "due to auth events" + // NOTE: Step 5 is not applied anymore because it failed too often + debug!(event_id = ?incoming_pdu.event_id, "Fetching auth events"); + self.fetch_and_handle_outliers( + origin, + &incoming_pdu + .auth_events + .iter() + .map(|x| Arc::from(&**x)) + .collect::>(), + create_event, + room_id, + room_version_id, + pub_key_map, + ) + .await; + } // 6. Reject "due to auth events" if the event doesn't pass auth based on the auth events debug!( @@ -1015,26 +1026,6 @@ impl Service { let mut pdus = vec![]; for id in events { - if let Some((time, tries)) = services() - .globals - .bad_event_ratelimiter - .read() - .unwrap() - .get(&**id) - { - // Exponential backoff - let mut min_elapsed_duration = - Duration::from_secs(5 * 60) * (*tries) * (*tries); - if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { - min_elapsed_duration = Duration::from_secs(60 * 60 * 24); - } - - if time.elapsed() < min_elapsed_duration { - info!("Backing off from {}", id); - continue; - } - } - // a. Look in the main timeline (pduid_pdu tree) // b. Look at outlier pdu tree // (get_pdu_json checks both) @@ -1052,6 +1043,26 @@ impl Service { let mut events_all = HashSet::new(); let mut i = 0; while let Some(next_id) = todo_auth_events.pop() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .unwrap() + .get(&*next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } + + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); + continue; + } + } + if events_all.contains(&next_id) { continue; } @@ -1062,7 +1073,7 @@ impl Service { } if let Ok(Some(_)) = services().rooms.timeline.get_pdu(&next_id) { - trace!("Found {} in db", id); + trace!("Found {} in db", next_id); continue; } @@ -1121,6 +1132,26 @@ impl Service { } for (next_id, value) in events_in_reverse_order.iter().rev() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .unwrap() + .get(&**next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } + + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); + continue; + } + } + match self .handle_outlier_pdu( origin, @@ -1128,6 +1159,7 @@ impl Service { next_id, room_id, value.clone(), + true, pub_key_map, ) .await From 38d6426b0eed35ed0adbdfc414bedb48eb6e2ac8 Mon Sep 17 00:00:00 2001 From: purplemeteorite Date: Tue, 4 Jul 2023 18:41:05 +0200 Subject: [PATCH 005/175] coturn setup instructions for docker --- docker/README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index c7028329..4ed70837 100644 --- a/docker/README.md +++ b/docker/README.md @@ -54,7 +54,7 @@ to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible If you just want to test Conduit for a short time, you can use the `--rm` flag, which will clean up everything related to your container after you stop it. -## Docker-compose +### Docker-compose If the `docker run` command is not for you or your setup, you can also use one of the provided `docker-compose` files. @@ -138,3 +138,56 @@ So...step by step: 6. Run `docker-compose up -d` 7. Connect to your homeserver with your preferred client and create a user. You should do this immediately after starting Conduit, because the first created user is the admin. + + + + +## Voice communication + +In order to make or receive calls, a TURN server is required. Conduit suggests using [Coturn](https://github.com/coturn/coturn) for this purpose, which is also available as a Docker image. Before proceeding with the software installation, it is essential to have the necessary configurations in place. + +### Configuration + +Create a configuration file called `coturn.conf` containing: + +```conf +use-auth-secret +static-auth-secret= +realm= +``` +These same values need to be set in conduit. You can either modify conduit.toml to include these lines: +``` +turn_uris = ["turn:?transport=udp", "turn:?transport=tcp"] +turn_secret = "" +``` +or append the following to the docker environment variables dependig on which configuration method you used earlier: +```yml +- CONDUIT_TURN_URIS=["turn:?transport=udp", "turn:?transport=tcp"] +- CONDUIT_TURN_SECRET=" +``` +Restart Conduit to apply these changes. + +### Run +Run the [Coturn](https://hub.docker.com/r/coturn/coturn) image using +```bash +docker run -d --network=host -v $(pwd)/coturn.conf:/etc/coturn/turnserver.conf coturn/coturn +``` + +or docker-compose. For the latter, paste the following section into a file called `docker-compose.yml` +and run `docker-compose up -d` in the same directory. + +```yml +version: 3 +services: + turn: + container_name: coturn-server + image: docker.io/coturn/coturn + restart: unless-stopped + network_mode: "host" + volumes: + - ./coturn.conf:/etc/coturn/turnserver.conf +``` + +To understand why the host networking mode is used and explore alternative configuration options, please visit the following link: https://github.com/coturn/coturn/blob/master/docker/coturn/README.md. +For security recommendations see Synapse's [Coturn documentation](https://github.com/matrix-org/synapse/blob/develop/docs/setup/turn/coturn.md#configuration). + From 20924a44f1a5214df22f0547ce0e686f962ea649 Mon Sep 17 00:00:00 2001 From: Jonas Zohren Date: Thu, 10 Aug 2023 14:42:04 +0000 Subject: [PATCH 006/175] Suggestion on how to generate a secure key --- docker/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/README.md b/docker/README.md index 4ed70837..dccdc35f 100644 --- a/docker/README.md +++ b/docker/README.md @@ -155,6 +155,8 @@ use-auth-secret static-auth-secret= realm= ``` +A common way to generate a suitable alphanumeric secret key is by using `pwgen -s 64 1`. + These same values need to be set in conduit. You can either modify conduit.toml to include these lines: ``` turn_uris = ["turn:?transport=udp", "turn:?transport=tcp"] From 9b3664aeeb66950d0e74104b872f8e9c739eb01d Mon Sep 17 00:00:00 2001 From: Luke McCarthy Date: Sun, 27 Aug 2023 02:14:03 +0000 Subject: [PATCH 007/175] Update README.md to fix typo & fix compatibility with new versions of docker compose --- docker/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/README.md b/docker/README.md index 9fe7ed06..b34f9d87 100644 --- a/docker/README.md +++ b/docker/README.md @@ -187,8 +187,8 @@ turn_secret = "" ``` or append the following to the docker environment variables dependig on which configuration method you used earlier: ```yml -- CONDUIT_TURN_URIS=["turn:?transport=udp", "turn:?transport=tcp"] -- CONDUIT_TURN_SECRET=" +CONDUIT_TURN_URIS: '["turn:?transport=udp", "turn:?transport=tcp"]' +CONDUIT_TURN_SECRET: "" ``` Restart Conduit to apply these changes. From 75c80df27133deb5a8fb65b1828e190925256e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Wed, 13 Sep 2023 20:54:53 +0200 Subject: [PATCH 008/175] Sliding sync improvements and redaction fixes --- Cargo.lock | 288 ++++++++++------------- Cargo.toml | 2 +- src/api/client_server/keys.rs | 58 ++++- src/api/client_server/redact.rs | 1 + src/api/client_server/room.rs | 3 +- src/api/client_server/sync.rs | 87 ++++--- src/database/key_value/rooms/timeline.rs | 2 - src/service/admin/mod.rs | 2 +- src/service/globals/mod.rs | 2 + src/service/rooms/event_handler/mod.rs | 17 +- src/service/users/mod.rs | 25 +- 11 files changed, 269 insertions(+), 218 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26b72011..9c8596aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,6 +58,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "as_variant" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38fa22307249f86fb7fad906fcae77f2564caeb56d7209103c551cd1cf4798f" + [[package]] name = "assign" version = "1.1.1" @@ -227,15 +233,6 @@ dependencies = [ "constant_time_eq 0.2.6", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -388,7 +385,7 @@ dependencies = [ "opentelemetry-jaeger", "parking_lot", "persy", - "rand 0.8.5", + "rand", "regex", "reqwest", "ring", @@ -569,17 +566,32 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", "subtle", "zeroize", ] +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.21", +] + [[package]] name = "dashmap" version = "5.4.0" @@ -601,30 +613,21 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "der" -version = "0.6.1" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] @@ -651,24 +654,25 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" dependencies = [ + "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" -version = "1.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", + "rand_core", "serde", - "sha2 0.9.9", + "sha2", "zeroize", ] @@ -726,6 +730,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + [[package]] name = "figment" version = "0.10.10" @@ -874,17 +884,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -893,7 +892,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1038,7 +1037,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1512,7 +1511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1607,12 +1606,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl-probe" version = "0.1.5" @@ -1687,7 +1680,7 @@ dependencies = [ "once_cell", "opentelemetry_api", "percent-encoding", - "rand 0.8.5", + "rand", "thiserror", "tokio", "tokio-stream", @@ -1801,7 +1794,7 @@ dependencies = [ "data-encoding", "fs2", "linked-hash-map", - "rand 0.8.5", + "rand", "thiserror", "unsigned-varint", "zigzag", @@ -1841,9 +1834,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs8" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", @@ -1855,6 +1848,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + [[package]] name = "png" version = "0.17.9" @@ -1931,19 +1930,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -1951,18 +1937,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -1972,16 +1948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -1990,16 +1957,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2026,7 +1984,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.10", + "getrandom", "redox_syscall 0.2.16", "thiserror", ] @@ -2139,7 +2097,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.8.2" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "assign", "js_int", @@ -2147,6 +2105,7 @@ dependencies = [ "ruma-appservice-api", "ruma-client-api", "ruma-common", + "ruma-events", "ruma-federation-api", "ruma-identity-service-api", "ruma-push-gateway-api", @@ -2157,10 +2116,11 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.8.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "js_int", "ruma-common", + "ruma-events", "serde", "serde_json", ] @@ -2168,7 +2128,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.16.2" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "assign", "bytes", @@ -2177,6 +2137,7 @@ dependencies = [ "js_option", "maplit", "ruma-common", + "ruma-events", "serde", "serde_html_form", "serde_json", @@ -2185,18 +2146,18 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ + "as_variant", "base64 0.21.2", "bytes", "form_urlencoded", "http", "indexmap 2.0.0", "js_int", - "js_option", "konst", "percent-encoding", - "rand 0.8.5", + "rand", "regex", "ruma-identifiers-validation", "ruma-macros", @@ -2210,13 +2171,36 @@ dependencies = [ "wildmatch", ] +[[package]] +name = "ruma-events" +version = "0.26.0" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +dependencies = [ + "as_variant", + "indexmap 2.0.0", + "js_int", + "js_option", + "percent-encoding", + "regex", + "ruma-common", + "ruma-identifiers-validation", + "ruma-macros", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "wildmatch", +] + [[package]] name = "ruma-federation-api" version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "js_int", "ruma-common", + "ruma-events", "serde", "serde_json", ] @@ -2224,7 +2208,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "js_int", "thiserror", @@ -2233,7 +2217,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "js_int", "ruma-common", @@ -2243,7 +2227,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "once_cell", "proc-macro-crate", @@ -2258,10 +2242,11 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "js_int", "ruma-common", + "ruma-events", "serde", "serde_json", ] @@ -2269,15 +2254,15 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.13.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "base64 0.21.2", "ed25519-dalek", "pkcs8", - "rand 0.7.3", + "rand", "ruma-common", "serde_json", - "sha2 0.10.7", + "sha2", "subslice", "thiserror", ] @@ -2285,11 +2270,12 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.9.1" -source = "git+https://github.com/ruma/ruma?rev=3bd58e3c899457c2d55c45268dcb8a65ae682d54#3bd58e3c899457c2d55c45268dcb8a65ae682d54" +source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "itertools", "js_int", "ruma-common", + "ruma-events", "serde", "serde_json", "thiserror", @@ -2328,6 +2314,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustls" version = "0.20.8" @@ -2458,6 +2453,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "serde" version = "1.0.164" @@ -2553,7 +2554,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2564,20 +2565,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] @@ -2588,7 +2576,7 @@ checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2617,9 +2605,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" [[package]] name = "simd-adler32" @@ -2682,9 +2670,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", "der", @@ -3145,7 +3133,7 @@ dependencies = [ "idna 0.2.3", "ipnet", "lazy_static", - "rand 0.8.5", + "rand", "smallvec", "thiserror", "tinyvec", @@ -3257,7 +3245,7 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" dependencies = [ - "getrandom 0.2.10", + "getrandom", ] [[package]] @@ -3287,12 +3275,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3587,20 +3569,6 @@ name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.21", -] [[package]] name = "zigzag" diff --git a/Cargo.toml b/Cargo.toml index 0138a2d5..ff1785e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "3bd58e3c899457c2d55c45268dcb8a65ae682d54", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "b4853aa8fa5e3a24e3689fc88044de9915f6ab67", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } diff --git a/src/api/client_server/keys.rs b/src/api/client_server/keys.rs index b8473014..7dbe040d 100644 --- a/src/api/client_server/keys.rs +++ b/src/api/client_server/keys.rs @@ -17,7 +17,11 @@ use ruma::{ DeviceKeyAlgorithm, OwnedDeviceId, OwnedUserId, UserId, }; use serde_json::json; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::{ + collections::{hash_map, BTreeMap, HashMap, HashSet}, + time::{Duration, Instant}, +}; +use tracing::debug; /// # `POST /_matrix/client/r0/keys/upload` /// @@ -335,31 +339,68 @@ pub(crate) async fn get_keys_helper bool>( let mut failures = BTreeMap::new(); + let back_off = |id| match services() + .globals + .bad_query_ratelimiter + .write() + .unwrap() + .entry(id) + { + hash_map::Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); + } + hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), + }; + let mut futures: FuturesUnordered<_> = get_over_federation .into_iter() .map(|(server, vec)| async move { + if let Some((time, tries)) = services() + .globals + .bad_query_ratelimiter + .read() + .unwrap() + .get(&*server) + { + // Exponential backoff + let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } + + if time.elapsed() < min_elapsed_duration { + debug!("Backing off query from {:?}", server); + return ( + server, + Err(Error::BadServerResponse("bad query, still backing off")), + ); + } + } + let mut device_keys_input_fed = BTreeMap::new(); for (user_id, keys) in vec { device_keys_input_fed.insert(user_id.to_owned(), keys.clone()); } ( server, - services() - .sending - .send_federation_request( + tokio::time::timeout( + Duration::from_secs(25), + services().sending.send_federation_request( server, federation::keys::get_keys::v1::Request { device_keys: device_keys_input_fed, }, - ) - .await, + ), + ) + .await + .map_err(|e| Error::BadServerResponse("Query took too long")), ) }) .collect(); while let Some((server, response)) = futures.next().await { match response { - Ok(response) => { + Ok(Ok(response)) => { for (user, masterkey) in response.master_keys { let (master_key_id, mut master_key) = services().users.parse_master_key(&user, &masterkey)?; @@ -386,7 +427,8 @@ pub(crate) async fn get_keys_helper bool>( self_signing_keys.extend(response.self_signing_keys); device_keys.extend(response.device_keys); } - Err(_e) => { + _ => { + back_off(server.to_owned()); failures.insert(server.to_string(), json!({})); } } diff --git a/src/api/client_server/redact.rs b/src/api/client_server/redact.rs index 20f7e91e..21da2221 100644 --- a/src/api/client_server/redact.rs +++ b/src/api/client_server/redact.rs @@ -34,6 +34,7 @@ pub async fn redact_event_route( PduBuilder { event_type: TimelineEventType::RoomRedaction, content: to_raw_value(&RoomRedactionEventContent { + redacts: Some(body.event_id.clone()), reason: body.reason.clone(), }) .expect("event is valid, we just created it"), diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 420dd507..0e2d9326 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -142,8 +142,9 @@ pub async fn create_room_route( content } None => { + // TODO: Add correct value for v11 let mut content = serde_json::from_str::( - to_raw_value(&RoomCreateEventContent::new(sender_user.clone())) + to_raw_value(&RoomCreateEventContent::new_v1(sender_user.clone())) .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))? .get(), ) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index dd815b52..a275b066 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1102,7 +1102,7 @@ async fn load_joined_room( fn load_timeline( sender_user: &UserId, room_id: &RoomId, - sincecount: PduCount, + roomsincecount: PduCount, limit: u64, ) -> Result<(Vec<(PduCount, PduEvent)>, bool), Error> { let timeline_pdus; @@ -1111,7 +1111,7 @@ fn load_timeline( .rooms .timeline .last_timeline_count(&sender_user, &room_id)? - > sincecount + > roomsincecount { let mut non_timeline_pdus = services() .rooms @@ -1124,7 +1124,7 @@ fn load_timeline( } r.ok() }) - .take_while(|(pducount, _)| pducount > &sincecount); + .take_while(|(pducount, _)| pducount > &roomsincecount); // Take the last events for the timeline timeline_pdus = non_timeline_pdus @@ -1172,22 +1172,22 @@ fn share_encrypted_room( pub async fn sync_events_v4_route( body: Ruma, ) -> Result> { + dbg!(&body.body); let sender_user = body.sender_user.expect("user is authenticated"); let sender_device = body.sender_device.expect("user is authenticated"); let mut body = body.body; // Setup watchers, so if there's no response, we can wait for them let watcher = services().globals.watch(&sender_user, &sender_device); - let next_batch = services().globals.current_count()?; + let next_batch = services().globals.next_count()?; - let since = body + let globalsince = body .pos .as_ref() .and_then(|string| string.parse().ok()) .unwrap_or(0); - let sincecount = PduCount::Normal(since); - if since == 0 { + if globalsince == 0 { if let Some(conn_id) = &body.conn_id { services().users.forget_sync_request_connection( sender_user.clone(), @@ -1214,7 +1214,7 @@ pub async fn sync_events_v4_route( if body.extensions.to_device.enabled.unwrap_or(false) { services() .users - .remove_to_device_events(&sender_user, &sender_device, since)?; + .remove_to_device_events(&sender_user, &sender_device, globalsince)?; } let mut left_encrypted_users = HashSet::new(); // Users that have left any encrypted rooms the sender was in @@ -1226,7 +1226,7 @@ pub async fn sync_events_v4_route( device_list_changes.extend( services() .users - .keys_changed(sender_user.as_ref(), since, None) + .keys_changed(sender_user.as_ref(), globalsince, None) .filter_map(|r| r.ok()), ); @@ -1242,7 +1242,7 @@ pub async fn sync_events_v4_route( let since_shortstatehash = services() .rooms .user - .get_token_shortstatehash(&room_id, since)?; + .get_token_shortstatehash(&room_id, globalsince)?; let since_sender_member: Option = since_shortstatehash .and_then(|shortstatehash| { @@ -1371,7 +1371,7 @@ pub async fn sync_events_v4_route( device_list_changes.extend( services() .users - .keys_changed(room_id.as_ref(), since, None) + .keys_changed(room_id.as_ref(), globalsince, None) .filter_map(|r| r.ok()), ); } @@ -1408,7 +1408,7 @@ pub async fn sync_events_v4_route( continue; } - let mut new_known_rooms = BTreeMap::new(); + let mut new_known_rooms = BTreeSet::new(); lists.insert( list_id.clone(), @@ -1424,12 +1424,12 @@ pub async fn sync_events_v4_route( let room_ids = all_joined_rooms [(u64::from(r.0) as usize)..=(u64::from(r.1) as usize)] .to_vec(); - new_known_rooms.extend(room_ids.iter().cloned().map(|r| (r, true))); + new_known_rooms.extend(room_ids.iter().cloned()); for room_id in &room_ids { let todo_room = todo_rooms.entry(room_id.clone()).or_insert(( BTreeSet::new(), 0, - true, + u64::MAX, )); let limit = list .room_details @@ -1440,10 +1440,14 @@ pub async fn sync_events_v4_route( .0 .extend(list.room_details.required_state.iter().cloned()); todo_room.1 = todo_room.1.max(limit); - if known_rooms.get(&list_id).and_then(|k| k.get(room_id)) != Some(&true) - { - todo_room.2 = false; - } + // 0 means unknown because it got out of date + todo_room.2 = todo_room.2.min( + known_rooms + .get(&list_id) + .and_then(|k| k.get(room_id)) + .copied() + .unwrap_or(0), + ); } sync_events::v4::SyncOp { op: SlidingOp::Sync, @@ -1465,26 +1469,28 @@ pub async fn sync_events_v4_route( conn_id.clone(), list_id, new_known_rooms, + globalsince, ); } } - let mut known_subscription_rooms = BTreeMap::new(); + let mut known_subscription_rooms = BTreeSet::new(); for (room_id, room) in &body.room_subscriptions { let todo_room = todo_rooms .entry(room_id.clone()) - .or_insert((BTreeSet::new(), 0, true)); + .or_insert((BTreeSet::new(), 0, u64::MAX)); let limit = room.timeline_limit.map_or(10, u64::from).min(100); todo_room.0.extend(room.required_state.iter().cloned()); todo_room.1 = todo_room.1.max(limit); - if known_rooms - .get("subscriptions") - .and_then(|k| k.get(room_id)) - != Some(&true) - { - todo_room.2 = false; - } - known_subscription_rooms.insert(room_id.clone(), true); + // 0 means unknown because it got out of date + todo_room.2 = todo_room.2.min( + known_rooms + .get("subscriptions") + .and_then(|k| k.get(room_id)) + .copied() + .unwrap_or(0), + ); + known_subscription_rooms.insert(room_id.clone()); } for r in body.unsubscribe_rooms { @@ -1499,6 +1505,7 @@ pub async fn sync_events_v4_route( conn_id.clone(), "subscriptions".to_owned(), known_subscription_rooms, + globalsince, ); } @@ -1512,12 +1519,13 @@ pub async fn sync_events_v4_route( } let mut rooms = BTreeMap::new(); - for (room_id, (required_state_request, timeline_limit, known)) in &todo_rooms { - // TODO: per-room sync tokens + for (room_id, (required_state_request, timeline_limit, roomsince)) in &todo_rooms { + let roomsincecount = PduCount::Normal(*roomsince); + let (timeline_pdus, limited) = - load_timeline(&sender_user, &room_id, sincecount, *timeline_limit)?; + load_timeline(&sender_user, &room_id, roomsincecount, *timeline_limit)?; - if *known && timeline_pdus.is_empty() { + if roomsince != &0 && timeline_pdus.is_empty() { continue; } @@ -1533,8 +1541,8 @@ pub async fn sync_events_v4_route( })) })? .or_else(|| { - if since != 0 { - Some(since.to_string()) + if roomsince != &0 { + Some(roomsince.to_string()) } else { None } @@ -1621,7 +1629,7 @@ pub async fn sync_events_v4_route( .state_accessor .get_avatar(&room_id)? .map_or(avatar, |a| a.url), - initial: Some(!known), + initial: Some(roomsince == &0), is_dm: None, invite_state: None, unread_notifications: UnreadNotificationsCount { @@ -1663,6 +1671,7 @@ pub async fn sync_events_v4_route( .into(), ), num_live: None, // Count events in timeline greater than global sync counter + timestamp: None, }, ); } @@ -1680,8 +1689,8 @@ pub async fn sync_events_v4_route( let _ = tokio::time::timeout(duration, watcher).await; } - Ok(sync_events::v4::Response { - initial: since == 0, + Ok(dbg!(sync_events::v4::Response { + initial: globalsince == 0, txn_id: body.txn_id.clone(), pos: next_batch.to_string(), lists, @@ -1712,7 +1721,7 @@ pub async fn sync_events_v4_route( global: if body.extensions.account_data.enabled.unwrap_or(false) { services() .account_data - .changes_since(None, &sender_user, since)? + .changes_since(None, &sender_user, globalsince)? .into_iter() .filter_map(|(_, v)| { serde_json::from_str(v.json().get()) @@ -1735,5 +1744,5 @@ pub async fn sync_events_v4_route( }, }, delta_token: None, - }) + })) } diff --git a/src/database/key_value/rooms/timeline.rs b/src/database/key_value/rooms/timeline.rs index 5ce2136e..ba1e85ef 100644 --- a/src/database/key_value/rooms/timeline.rs +++ b/src/database/key_value/rooms/timeline.rs @@ -84,8 +84,6 @@ impl service::rooms::timeline::Data for KeyValueDatabase { } /// Returns the pdu. - /// - /// Checks the `eventid_outlierpdu` Tree if not found in the timeline. fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result> { self.eventid_pduid .get(event_id.as_bytes())? diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 0fe5edf2..b22f8ed4 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -932,7 +932,7 @@ impl Service { services().users.create(&conduit_user, None)?; - let mut content = RoomCreateEventContent::new(conduit_user.clone()); + let mut content = RoomCreateEventContent::new_v1(conduit_user.clone()); content.federate = true; content.predecessor = None; content.room_version = services().globals.default_room_version(); diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index e9bd0da7..9bce8a2c 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -56,6 +56,7 @@ pub struct Service { pub unstable_room_versions: Vec, pub bad_event_ratelimiter: Arc>>, pub bad_signature_ratelimiter: Arc, RateLimitState>>>, + pub bad_query_ratelimiter: Arc>>, pub servername_ratelimiter: Arc>>>, pub sync_receivers: RwLock>, pub roomid_mutex_insert: RwLock>>>, @@ -160,6 +161,7 @@ impl Service { unstable_room_versions, bad_event_ratelimiter: Arc::new(RwLock::new(HashMap::new())), bad_signature_ratelimiter: Arc::new(RwLock::new(HashMap::new())), + bad_query_ratelimiter: Arc::new(RwLock::new(HashMap::new())), servername_ratelimiter: Arc::new(RwLock::new(HashMap::new())), roomid_mutex_state: RwLock::new(HashMap::new()), roomid_mutex_insert: RwLock::new(HashMap::new()), diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index e93feaa5..aa1f5fb3 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -326,7 +326,7 @@ impl Service { Ok(ruma::signatures::Verified::Signatures) => { // Redact warn!("Calculated hash does not match: {}", event_id); - match ruma::canonical_json::redact(value, room_version_id, None) { + let obj = match ruma::canonical_json::redact(value, room_version_id, None) { Ok(obj) => obj, Err(_) => { return Err(Error::BadRequest( @@ -334,7 +334,17 @@ impl Service { "Redaction failed", )) } + }; + + // Skip the PDU if it is redacted and we already have it as an outlier event + if services().rooms.timeline.get_pdu_json(event_id)?.is_some() { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Event was redacted and we already knew about it", + )); } + + obj } Ok(ruma::signatures::Verified::All) => value, }; @@ -1564,6 +1574,11 @@ impl Service { } }; + if acl_event_content.allow.is_empty() { + // Ignore broken acl events + return Ok(()); + } + if acl_event_content.is_allowed(server_name) { Ok(()) } else { diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index c345e561..6faa6d8e 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -1,6 +1,6 @@ mod data; use std::{ - collections::BTreeMap, + collections::{BTreeMap, BTreeSet}, mem, sync::{Arc, Mutex}, }; @@ -28,7 +28,7 @@ use crate::{services, Error, Result}; pub struct SlidingSyncCache { lists: BTreeMap, subscriptions: BTreeMap, - known_rooms: BTreeMap>, + known_rooms: BTreeMap>, // For every room, the roomsince number extensions: ExtensionsConfig, } @@ -61,7 +61,7 @@ impl Service { user_id: OwnedUserId, device_id: OwnedDeviceId, request: &mut sync_events::v4::Request, - ) -> BTreeMap> { + ) -> BTreeMap> { let Some(conn_id) = request.conn_id.clone() else { return BTreeMap::new(); }; @@ -127,6 +127,7 @@ impl Service { } } (_, Some(cached_filters)) => list.filters = Some(cached_filters), + (Some(list_filters), _) => list.filters = Some(list_filters.clone()), (_, _) => {} } if list.bump_event_types.is_empty() { @@ -210,7 +211,8 @@ impl Service { device_id: OwnedDeviceId, conn_id: String, list_id: String, - new_cached_rooms: BTreeMap, + new_cached_rooms: BTreeSet, + globalsince: u64, ) { let mut cache = self.connections.lock().unwrap(); let cached = Arc::clone( @@ -228,7 +230,20 @@ impl Service { let cached = &mut cached.lock().unwrap(); drop(cache); - cached.known_rooms.insert(list_id, new_cached_rooms); + for (roomid, lastsince) in cached + .known_rooms + .entry(list_id.clone()) + .or_default() + .iter_mut() + { + if !new_cached_rooms.contains(roomid) { + *lastsince = 0; + } + } + let list = cached.known_rooms.entry(list_id).or_default(); + for roomid in new_cached_rooms { + list.insert(roomid, globalsince); + } } /// Check if account is deactivated From f3b6b3e222caa3c01a6a301d38ff15e98f8b973f Mon Sep 17 00:00:00 2001 From: AndSDev Date: Tue, 7 Nov 2023 12:46:53 +0000 Subject: [PATCH 009/175] feat: send push notification on invite to invited user and etc --- src/service/rooms/timeline/mod.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 25e1c54d..e419980c 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -320,12 +320,25 @@ impl Service { let mut notifies = Vec::new(); let mut highlights = Vec::new(); - for user in services() + let mut push_target = services() .rooms .state_cache - .get_our_real_users(&pdu.room_id)? - .iter() - { + .get_our_real_users(&pdu.room_id)?; + + if pdu.kind == TimelineEventType::RoomMember { + if let Some(state_key) = &pdu.state_key { + let target_user_id = UserId::parse(state_key.clone()) + .expect("This state_key was previously validated"); + + if !push_target.contains(&target_user_id) { + let mut target = push_target.as_ref().clone(); + target.insert(target_user_id); + push_target = Arc::new(target); + } + } + } + + for user in push_target.iter() { // Don't notify the user of their own events if user == &pdu.sender { continue; From d39d30008a81a0149279eef01e2e2969d1a10078 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 15:11:26 +0100 Subject: [PATCH 010/175] Remove "creator" property from rooms >= v11 --- src/api/client_server/room.rs | 71 +++++++++++++++++++++++++------ src/service/admin/mod.rs | 17 +++++++- src/service/pdu.rs | 20 ++++++++- src/service/rooms/timeline/mod.rs | 51 ++++++++++++---------- 4 files changed, 119 insertions(+), 40 deletions(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 0e2d9326..6b824040 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -23,7 +23,7 @@ use ruma::{ }, int, serde::JsonObject, - CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId, + CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId, RoomVersionId, }; use serde_json::{json, value::to_raw_value}; use std::{cmp::max, collections::BTreeMap, sync::Arc}; @@ -127,12 +127,28 @@ pub async fn create_room_route( let mut content = content .deserialize_as::() .expect("Invalid creation content"); - content.insert( - "creator".into(), - json!(&sender_user).try_into().map_err(|_| { - Error::BadRequest(ErrorKind::BadJson, "Invalid creation content") - })?, - ); + + match room_version { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + content.insert( + "creator".into(), + json!(&sender_user).try_into().map_err(|_| { + Error::BadRequest(ErrorKind::BadJson, "Invalid creation content") + })?, + ); + } + _ => {} // V11 removed the "creator" key + } + content.insert( "room_version".into(), json!(room_version.as_str()).try_into().map_err(|_| { @@ -143,8 +159,21 @@ pub async fn create_room_route( } None => { // TODO: Add correct value for v11 + let content = match room_version { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => RoomCreateEventContent::new_v1(sender_user.clone()), + _ => RoomCreateEventContent::new_v11(), + }; let mut content = serde_json::from_str::( - to_raw_value(&RoomCreateEventContent::new_v1(sender_user.clone())) + to_raw_value(&content) .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))? .get(), ) @@ -580,12 +609,26 @@ pub async fn upgrade_room_route( )); // Send a m.room.create event containing a predecessor field and the applicable room_version - create_event_content.insert( - "creator".into(), - json!(&sender_user) - .try_into() - .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?, - ); + match body.new_version { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + create_event_content.insert( + "creator".into(), + json!(&sender_user).try_into().map_err(|_| { + Error::BadRequest(ErrorKind::BadJson, "Error forming creation event") + })?, + ); + } + _ => {} // V11 removed the "creator" key + } create_event_content.insert( "room_version".into(), json!(&body.new_version) diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index b22f8ed4..292943a3 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -932,10 +932,23 @@ impl Service { services().users.create(&conduit_user, None)?; - let mut content = RoomCreateEventContent::new_v1(conduit_user.clone()); + let room_version = services().globals.default_room_version(); + let mut content = match room_version { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => RoomCreateEventContent::new_v1(conduit_user.clone()), + _ => RoomCreateEventContent::new_v11(), + }; content.federate = true; content.predecessor = None; - content.room_version = services().globals.default_room_version(); + content.room_version = room_version; // 1. The room create event services().rooms.timeline.build_and_append_pdu( diff --git a/src/service/pdu.rs b/src/service/pdu.rs index 4a170bc2..9e7f6d1d 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -49,12 +49,28 @@ pub struct PduEvent { impl PduEvent { #[tracing::instrument(skip(self))] - pub fn redact(&mut self, reason: &PduEvent) -> crate::Result<()> { + pub fn redact( + &mut self, + room_version_id: RoomVersionId, + reason: &PduEvent, + ) -> crate::Result<()> { self.unsigned = None; let allowed: &[&str] = match self.kind { TimelineEventType::RoomMember => &["join_authorised_via_users_server", "membership"], - TimelineEventType::RoomCreate => &["creator"], + TimelineEventType::RoomCreate => match room_version_id { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => &["creator"], + _ => &[], // V11 removed the creator key + }, TimelineEventType::RoomJoinRules => &["join_rule"], TimelineEventType::RoomPowerLevels => &[ "ban", diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 25e1c54d..4f3b0e59 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -28,7 +28,7 @@ use ruma::{ state_res, state_res::{Event, RoomVersion}, uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, - OwnedServerName, RoomAliasId, RoomId, ServerName, UserId, + OwnedServerName, RoomAliasId, RoomId, RoomVersionId, ServerName, UserId, }; use serde::Deserialize; use serde_json::value::{to_raw_value, RawValue as RawJsonValue}; @@ -128,6 +128,27 @@ impl Service { self.db.get_pdu_count(event_id) } + /// Returns the version of a room, if known + pub fn get_room_version(&self, room_id: &RoomId) -> Result> { + let create_event = services().rooms.state_accessor.room_state_get( + room_id, + &StateEventType::RoomCreate, + "", + )?; + + let create_event_content: Option = create_event + .as_ref() + .map(|create_event| { + serde_json::from_str(create_event.content.get()).map_err(|e| { + warn!("Invalid create event: {}", e); + Error::bad_database("Invalid create event in db.") + }) + }) + .transpose()?; + + Ok(create_event_content.map(|content| content.room_version)) + } + // TODO Is this the same as the function above? /* #[tracing::instrument(skip(self))] @@ -645,28 +666,11 @@ impl Service { .take(20) .collect(); - let create_event = services().rooms.state_accessor.room_state_get( - room_id, - &StateEventType::RoomCreate, - "", - )?; - - let create_event_content: Option = create_event - .as_ref() - .map(|create_event| { - serde_json::from_str(create_event.content.get()).map_err(|e| { - warn!("Invalid create event: {}", e); - Error::bad_database("Invalid create event in db.") - }) - }) - .transpose()?; - // If there was no create event yet, assume we are creating a room with the default // version right now - let room_version_id = create_event_content - .map_or(services().globals.default_room_version(), |create_event| { - create_event.room_version - }); + let room_version_id = self + .get_room_version(room_id)? + .unwrap_or_else(|| services().globals.default_room_version()); let room_version = RoomVersion::new(&room_version_id).expect("room version is supported"); let auth_events = services().rooms.state.get_auth_events( @@ -1034,7 +1038,10 @@ impl Service { let mut pdu = self .get_pdu_from_id(&pdu_id)? .ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?; - pdu.redact(reason)?; + let room_version_id = self.get_room_version(&pdu.room_id)?.ok_or_else(|| { + Error::bad_database("Trying to redact PDU in in room of unknown version") + })?; + pdu.redact(room_version_id, reason)?; self.replace_pdu( &pdu_id, &utils::to_canonical_object(&pdu).expect("PDU is an object"), From a3b8eea9b4885bccdfad7279f809c472ddd89a44 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 17:46:50 +0100 Subject: [PATCH 011/175] Move "redacts" key to "content" in redaction events in v11 rooms --- src/service/rooms/timeline/mod.rs | 35 ++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 4f3b0e59..4b06acb7 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -404,9 +404,38 @@ impl Service { match pdu.kind { TimelineEventType::RoomRedaction => { - if let Some(redact_id) = &pdu.redacts { - self.redact_pdu(redact_id, pdu)?; - } + let room_version_id = self + .get_room_version(&pdu.room_id)? + .expect("Got RoomRedaction in a room of unknown version"); + match room_version_id { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + if let Some(redact_id) = &pdu.redacts { + self.redact_pdu(redact_id, pdu)?; + } + } + _ => { + #[derive(Deserialize)] + struct Redaction { + redacts: Option, + } + let content = serde_json::from_str::(pdu.content.get()) + .map_err(|_| { + Error::bad_database("Invalid content in redaction pdu.") + })?; + if let Some(redact_id) = &content.redacts { + self.redact_pdu(redact_id, pdu)?; + } + } + }; } TimelineEventType::SpaceChild => { if let Some(_state_key) = &pdu.state_key { From 18bfd79ef2d4a0bb18622bb25b3da23e05a04481 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 18:15:20 +0100 Subject: [PATCH 012/175] Remove "creator" key when upgrading rooms to v11 --- src/api/client_server/room.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 6b824040..5f62e9fa 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -627,7 +627,10 @@ pub async fn upgrade_room_route( })?, ); } - _ => {} // V11 removed the "creator" key + _ => { + // "creator" key no longer exists in V11 rooms + create_event_content.remove("creator"); + } } create_event_content.insert( "room_version".into(), From fac995036ab02fe30fca6a2dfc682612c4cf43d7 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 18:15:57 +0100 Subject: [PATCH 013/175] create_hash_and_sign_event: Use actual version of RoomCreate events, instead of the default --- src/service/rooms/timeline/mod.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 4b06acb7..a6e9f87a 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -695,11 +695,20 @@ impl Service { .take(20) .collect(); - // If there was no create event yet, assume we are creating a room with the default - // version right now - let room_version_id = self - .get_room_version(room_id)? - .unwrap_or_else(|| services().globals.default_room_version()); + // If there was no create event yet, assume we are creating a room + let room_version_id = self.get_room_version(room_id)?.unwrap_or_else(|| { + if event_type != TimelineEventType::RoomCreate { + panic!("non-create event for room of unknown version"); + } + #[derive(Deserialize)] + struct RoomCreate { + room_version: RoomVersionId, + } + let content = serde_json::from_str::(content.get()) + .expect("Invalid content in RoomCreate pdu."); + content.room_version + }); + let room_version = RoomVersion::new(&room_version_id).expect("room version is supported"); let auth_events = services().rooms.state.get_auth_events( From 9646439a94f35a7ab46274c1465ee1192215724a Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 18:16:18 +0100 Subject: [PATCH 014/175] Enable support for room v11 --- src/service/globals/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 9bce8a2c..1aa123ff 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -139,7 +139,12 @@ impl Service { RoomVersionId::V10, ]; // Experimental, partially supported room versions - let unstable_room_versions = vec![RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5]; + let unstable_room_versions = vec![ + RoomVersionId::V3, + RoomVersionId::V4, + RoomVersionId::V5, + RoomVersionId::V11, + ]; let mut s = Self { db, From 520806d41385cddee20ec8d8a83bc1c491a61280 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Fri, 1 Dec 2023 19:08:24 +0100 Subject: [PATCH 015/175] Use Ruma's redact_content_in_place instead of custom implementation --- src/service/pdu.rs | 48 ++++++---------------------------------------- src/utils/error.rs | 2 ++ 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/src/service/pdu.rs b/src/service/pdu.rs index 9e7f6d1d..c3e8d59c 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -1,5 +1,6 @@ use crate::Error; use ruma::{ + canonical_json::redact_content_in_place, events::{ room::member::RoomMemberEventContent, space::child::HierarchySpaceChildEvent, AnyEphemeralRoomEvent, AnyMessageLikeEvent, AnyStateEvent, AnyStrippedStateEvent, @@ -56,53 +57,16 @@ impl PduEvent { ) -> crate::Result<()> { self.unsigned = None; - let allowed: &[&str] = match self.kind { - TimelineEventType::RoomMember => &["join_authorised_via_users_server", "membership"], - TimelineEventType::RoomCreate => match room_version_id { - RoomVersionId::V1 - | RoomVersionId::V2 - | RoomVersionId::V3 - | RoomVersionId::V4 - | RoomVersionId::V5 - | RoomVersionId::V6 - | RoomVersionId::V7 - | RoomVersionId::V8 - | RoomVersionId::V9 - | RoomVersionId::V10 => &["creator"], - _ => &[], // V11 removed the creator key - }, - TimelineEventType::RoomJoinRules => &["join_rule"], - TimelineEventType::RoomPowerLevels => &[ - "ban", - "events", - "events_default", - "kick", - "redact", - "state_default", - "users", - "users_default", - ], - TimelineEventType::RoomHistoryVisibility => &["history_visibility"], - _ => &[], - }; - - let mut old_content: BTreeMap = - serde_json::from_str(self.content.get()) - .map_err(|_| Error::bad_database("PDU in db has invalid content."))?; - - let mut new_content = serde_json::Map::new(); - - for key in allowed { - if let Some(value) = old_content.remove(*key) { - new_content.insert((*key).to_owned(), value); - } - } + let mut content = serde_json::from_str(self.content.get()) + .map_err(|_| Error::bad_database("PDU in db has invalid content."))?; + redact_content_in_place(&mut content, &room_version_id, self.kind.to_string()) + .map_err(|e| Error::RedactionError(self.sender.server_name().to_owned(), e))?; self.unsigned = Some(to_raw_value(&json!({ "redacted_because": serde_json::to_value(reason).expect("to_value(PduEvent) always works") })).expect("to string always works")); - self.content = to_raw_value(&new_content).expect("to string always works"); + self.content = to_raw_value(&content).expect("to string always works"); Ok(()) } diff --git a/src/utils/error.rs b/src/utils/error.rs index 6e88cf59..83ef3095 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -80,6 +80,8 @@ pub enum Error { #[cfg(feature = "conduit_bin")] #[error("{0}")] PathError(#[from] axum::extract::rejection::PathRejection), + #[error("from {0}: {1}")] + RedactionError(OwnedServerName, ruma::canonical_json::RedactionError), } impl Error { From 5a7bb1e8f104b66e65a16e447d930b478640383a Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sat, 2 Dec 2023 17:51:19 +0100 Subject: [PATCH 016/175] Return error instead of panic when first event is not m.room.create --- src/service/rooms/timeline/mod.rs | 33 ++++++++++++++++++++----------- src/utils/error.rs | 2 ++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index a6e9f87a..06deb069 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -696,18 +696,27 @@ impl Service { .collect(); // If there was no create event yet, assume we are creating a room - let room_version_id = self.get_room_version(room_id)?.unwrap_or_else(|| { - if event_type != TimelineEventType::RoomCreate { - panic!("non-create event for room of unknown version"); - } - #[derive(Deserialize)] - struct RoomCreate { - room_version: RoomVersionId, - } - let content = serde_json::from_str::(content.get()) - .expect("Invalid content in RoomCreate pdu."); - content.room_version - }); + let room_version_id = self + .get_room_version(room_id)? + .or_else(|| { + if event_type == TimelineEventType::RoomCreate { + #[derive(Deserialize)] + struct RoomCreate { + room_version: RoomVersionId, + } + let content = serde_json::from_str::(content.get()) + .expect("Invalid content in RoomCreate pdu."); + Some(content.room_version) + } else { + None + } + }) + .ok_or_else(|| { + Error::InconsistentRoomState( + "non-create event for room of unknown version", + room_id.to_owned(), + ) + })?; let room_version = RoomVersion::new(&room_version_id).expect("room version is supported"); diff --git a/src/utils/error.rs b/src/utils/error.rs index 83ef3095..568ad8a0 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -82,6 +82,8 @@ pub enum Error { PathError(#[from] axum::extract::rejection::PathRejection), #[error("from {0}: {1}")] RedactionError(OwnedServerName, ruma::canonical_json::RedactionError), + #[error("{0} in {1}")] + InconsistentRoomState(&'static str, ruma::OwnedRoomId), } impl Error { From 98e81c62174a587c54ed111e0eca617c1d423efd Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 3 Dec 2023 19:38:09 +0100 Subject: [PATCH 017/175] Log underlying error when rejecting sendjoin response --- src/api/client_server/membership.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 4a1f3743..346f2575 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -619,7 +619,7 @@ async fn join_room_by_id_helper( )); } - if let Ok(signature) = signed_value["signatures"] + match signed_value["signatures"] .as_object() .ok_or(Error::BadRequest( ErrorKind::InvalidParam, @@ -630,18 +630,20 @@ async fn join_room_by_id_helper( ErrorKind::InvalidParam, "Server did not send its signature", )) - }) - { - join_event - .get_mut("signatures") - .expect("we created a valid pdu") - .as_object_mut() - .expect("we created a valid pdu") - .insert(remote_server.to_string(), signature.clone()); - } else { - warn!( - "Server {remote_server} sent invalid signature in sendjoin signatures for event {signed_value:?}", - ); + }) { + Ok(signature) => { + join_event + .get_mut("signatures") + .expect("we created a valid pdu") + .as_object_mut() + .expect("we created a valid pdu") + .insert(remote_server.to_string(), signature.clone()); + } + Err(e) => { + warn!( + "Server {remote_server} sent invalid signature in sendjoin signatures for event {signed_value:?}: {e:?}", + ); + } } } From 9d7f7b871b9783dbdce15e0491b0eaa9d948b21f Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 21:00:00 -0800 Subject: [PATCH 018/175] don't panic on missing presence status for a user --- src/api/client_server/presence.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/api/client_server/presence.rs b/src/api/client_server/presence.rs index ef88d1a0..e5cd1b8e 100644 --- a/src/api/client_server/presence.rs +++ b/src/api/client_server/presence.rs @@ -1,5 +1,8 @@ -use crate::{services, utils, Result, Ruma}; -use ruma::api::client::presence::{get_presence, set_presence}; +use crate::{services, utils, Error, Result, Ruma}; +use ruma::api::client::{ + error::ErrorKind, + presence::{get_presence, set_presence}, +}; use std::time::Duration; /// # `PUT /_matrix/client/r0/presence/{userId}/status` @@ -79,6 +82,9 @@ pub async fn get_presence_route( presence: presence.content.presence, }) } else { - todo!(); + Err(Error::BadRequest( + ErrorKind::NotFound, + "Presence state for this user was not found", + )) } } From 8f3f5c01f924820994f8bf5fe20abc5a3e6b8866 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 22:02:24 -0800 Subject: [PATCH 019/175] add shebang to .envrc All this really does is make syntax highlighting and shellcheck work by default in more editors. --- .envrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.envrc b/.envrc index 3550a30f..b9238c3b 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,3 @@ +#!/usr/bin/env bash + use flake From eb7ac91cd5a8c62fc5dbd96527712b9750394a70 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 24 Dec 2023 19:02:03 +0100 Subject: [PATCH 020/175] Reuse existing get_room_version --- src/service/rooms/timeline/mod.rs | 53 +++++++++---------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 06deb069..b0f6cb5e 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -128,27 +128,6 @@ impl Service { self.db.get_pdu_count(event_id) } - /// Returns the version of a room, if known - pub fn get_room_version(&self, room_id: &RoomId) -> Result> { - let create_event = services().rooms.state_accessor.room_state_get( - room_id, - &StateEventType::RoomCreate, - "", - )?; - - let create_event_content: Option = create_event - .as_ref() - .map(|create_event| { - serde_json::from_str(create_event.content.get()).map_err(|e| { - warn!("Invalid create event: {}", e); - Error::bad_database("Invalid create event in db.") - }) - }) - .transpose()?; - - Ok(create_event_content.map(|content| content.room_version)) - } - // TODO Is this the same as the function above? /* #[tracing::instrument(skip(self))] @@ -404,9 +383,7 @@ impl Service { match pdu.kind { TimelineEventType::RoomRedaction => { - let room_version_id = self - .get_room_version(&pdu.room_id)? - .expect("Got RoomRedaction in a room of unknown version"); + let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?; match room_version_id { RoomVersionId::V1 | RoomVersionId::V2 @@ -696,9 +673,11 @@ impl Service { .collect(); // If there was no create event yet, assume we are creating a room - let room_version_id = self - .get_room_version(room_id)? - .or_else(|| { + let room_version_id = services() + .rooms + .state + .get_room_version(room_id) + .or_else(|_| { if event_type == TimelineEventType::RoomCreate { #[derive(Deserialize)] struct RoomCreate { @@ -706,16 +685,13 @@ impl Service { } let content = serde_json::from_str::(content.get()) .expect("Invalid content in RoomCreate pdu."); - Some(content.room_version) + Ok(content.room_version) } else { - None + Err(Error::InconsistentRoomState( + "non-create event for room of unknown version", + room_id.to_owned(), + )) } - }) - .ok_or_else(|| { - Error::InconsistentRoomState( - "non-create event for room of unknown version", - room_id.to_owned(), - ) })?; let room_version = RoomVersion::new(&room_version_id).expect("room version is supported"); @@ -1085,9 +1061,10 @@ impl Service { let mut pdu = self .get_pdu_from_id(&pdu_id)? .ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?; - let room_version_id = self.get_room_version(&pdu.room_id)?.ok_or_else(|| { - Error::bad_database("Trying to redact PDU in in room of unknown version") - })?; + let room_version_id = services() + .rooms + .state + .get_room_version(&pdu.room_id)?; pdu.redact(room_version_id, reason)?; self.replace_pdu( &pdu_id, From 8175bc124629bff5808270c496d7e1f32ee1cdcb Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 24 Dec 2023 19:04:48 +0100 Subject: [PATCH 021/175] Explicitly match RoomVersionId::V11 --- src/api/client_server/room.rs | 9 ++++++--- src/service/admin/mod.rs | 3 ++- src/service/rooms/timeline/mod.rs | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 5f62e9fa..128f84f9 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -146,7 +146,8 @@ pub async fn create_room_route( })?, ); } - _ => {} // V11 removed the "creator" key + RoomVersionId::V11 => {} // V11 removed the "creator" key + _ => panic!("Unexpected room version {}", room_version), } content.insert( @@ -170,7 +171,8 @@ pub async fn create_room_route( | RoomVersionId::V8 | RoomVersionId::V9 | RoomVersionId::V10 => RoomCreateEventContent::new_v1(sender_user.clone()), - _ => RoomCreateEventContent::new_v11(), + RoomVersionId::V11 => RoomCreateEventContent::new_v11(), + _ => panic!("Unexpected room version {}", room_version), }; let mut content = serde_json::from_str::( to_raw_value(&content) @@ -627,10 +629,11 @@ pub async fn upgrade_room_route( })?, ); } - _ => { + RoomVersionId::V11 => { // "creator" key no longer exists in V11 rooms create_event_content.remove("creator"); } + _ => panic!("Unexpected room version {}", body.new_version) } create_event_content.insert( "room_version".into(), diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 292943a3..08b6e621 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -944,7 +944,8 @@ impl Service { | RoomVersionId::V8 | RoomVersionId::V9 | RoomVersionId::V10 => RoomCreateEventContent::new_v1(conduit_user.clone()), - _ => RoomCreateEventContent::new_v11(), + RoomVersionId::V11 => RoomCreateEventContent::new_v11(), + _ => panic!("Unexpected room version {}", room_version), }; content.federate = true; content.predecessor = None; diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index b0f6cb5e..d0943c9a 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -399,7 +399,7 @@ impl Service { self.redact_pdu(redact_id, pdu)?; } } - _ => { + RoomVersionId::V11 => { #[derive(Deserialize)] struct Redaction { redacts: Option, @@ -412,6 +412,7 @@ impl Service { self.redact_pdu(redact_id, pdu)?; } } + _ => panic!("Unexpected room version {}", room_version_id) }; } TimelineEventType::SpaceChild => { From 835f4ad8cfa8a222a56e21f37646a86c1acd90a7 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 16 Jan 2024 13:52:56 -0800 Subject: [PATCH 022/175] declare 1.5 support --- src/api/client_server/unversioned.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/client_server/unversioned.rs b/src/api/client_server/unversioned.rs index 797b9529..70e260ec 100644 --- a/src/api/client_server/unversioned.rs +++ b/src/api/client_server/unversioned.rs @@ -26,6 +26,7 @@ pub async fn get_supported_versions_route( "v1.2".to_owned(), "v1.3".to_owned(), "v1.4".to_owned(), + "v1.5".to_owned(), ], unstable_features: BTreeMap::from_iter([("org.matrix.e2e_cross_signing".to_owned(), true)]), }; From dc2f53e77393cf49ae9f6da9bb1db20abdf59230 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 20:40:56 -0800 Subject: [PATCH 023/175] comment out heed backend things The code in conduit doesn't compile. --- Cargo.lock | 136 +---------------------------------------------------- Cargo.toml | 6 +-- 2 files changed, 4 insertions(+), 138 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c8596aa..b4bcdc0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,15 +180,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bindgen" version = "0.65.1" @@ -368,11 +359,9 @@ dependencies = [ "base64 0.21.2", "bytes", "clap", - "crossbeam", "directories", "figment", "futures-util", - "heed", "hmac", "http", "image", @@ -487,20 +476,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -511,40 +486,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -986,42 +927,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "heed" -version = "0.10.6" -source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d" -dependencies = [ - "bytemuck", - "byteorder", - "heed-traits", - "heed-types", - "libc", - "lmdb-rkv-sys", - "once_cell", - "page_size", - "serde", - "synchronoise", - "url", -] - -[[package]] -name = "heed-traits" -version = "0.7.0" -source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d" - -[[package]] -name = "heed-types" -version = "0.7.2" -source = "git+https://github.com/timokoesters/heed.git?rev=f6f825da7fb2c758867e05ad973ef800a6fe1d5d#f6f825da7fb2c758867e05ad973ef800a6fe1d5d" -dependencies = [ - "bincode", - "bytemuck", - "byteorder", - "heed-traits", - "serde", - "serde_json", -] - [[package]] name = "hermit-abi" version = "0.2.6" @@ -1379,17 +1284,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "lmdb-rkv-sys" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b9ce6b3be08acefa3003c57b7565377432a89ec24476bbe72e11d101f852fe" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "lock_api" version = "0.4.10" @@ -1473,15 +1367,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -1524,7 +1409,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.7.1", + "memoffset", "pin-utils", "static_assertions", ] @@ -1701,16 +1586,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "page_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -2727,15 +2602,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synchronoise" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" -dependencies = [ - "crossbeam-queue", -] - [[package]] name = "thiserror" version = "1.0.40" diff --git a/Cargo.toml b/Cargo.toml index ff1785e4..6cc66508 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,10 +78,10 @@ tracing-opentelemetry = "0.18.0" lru-cache = "0.1.2" rusqlite = { version = "0.29.0", optional = true, features = ["bundled"] } parking_lot = { version = "0.12.1", optional = true } -crossbeam = { version = "0.8.2", optional = true } +# crossbeam = { version = "0.8.2", optional = true } num_cpus = "1.15.0" threadpool = "1.8.1" -heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true } +# heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true } # Used for ruma wrapper serde_html_form = "0.2.0" @@ -112,7 +112,7 @@ default = ["conduit_bin", "backend_sqlite", "backend_rocksdb", "systemd"] #backend_sled = ["sled"] backend_persy = ["persy", "parking_lot"] backend_sqlite = ["sqlite"] -backend_heed = ["heed", "crossbeam"] +#backend_heed = ["heed", "crossbeam"] backend_rocksdb = ["rocksdb"] jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"] sqlite = ["rusqlite", "parking_lot", "tokio/signal"] From 92c5b6b86cb40704da2a638847a4cc37dfe61212 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 19:34:27 -0800 Subject: [PATCH 024/175] fix `cargo check` lints --- src/api/client_server/keys.rs | 4 ++-- src/api/client_server/session.rs | 2 ++ src/api/server_server.rs | 2 +- src/database/key_value/rooms/threads.rs | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/api/client_server/keys.rs b/src/api/client_server/keys.rs index 7dbe040d..9fd00897 100644 --- a/src/api/client_server/keys.rs +++ b/src/api/client_server/keys.rs @@ -360,7 +360,7 @@ pub(crate) async fn get_keys_helper bool>( .bad_query_ratelimiter .read() .unwrap() - .get(&*server) + .get(server) { // Exponential backoff let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries); @@ -393,7 +393,7 @@ pub(crate) async fn get_keys_helper bool>( ), ) .await - .map_err(|e| Error::BadServerResponse("Query took too long")), + .map_err(|_e| Error::BadServerResponse("Query took too long")), ) }) .collect(); diff --git a/src/api/client_server/session.rs b/src/api/client_server/session.rs index 5ce62af9..5ffd8134 100644 --- a/src/api/client_server/session.rs +++ b/src/api/client_server/session.rs @@ -163,6 +163,8 @@ pub async fn login_route(body: Ruma) -> Result Result> + 'a>> { let prefix = services() .rooms @@ -27,7 +27,7 @@ impl service::rooms::threads::Data for KeyValueDatabase { self.threadid_userids .iter_from(¤t, true) .take_while(move |(k, _)| k.starts_with(&prefix)) - .map(move |(pduid, users)| { + .map(move |(pduid, _users)| { let count = utils::u64_from_bytes(&pduid[(mem::size_of::())..]) .map_err(|_| Error::bad_database("Invalid pduid in threadid_userids."))?; let mut pdu = services() From ab1fff2642be961f052dde06b2c03c588d904d51 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 19:48:14 -0800 Subject: [PATCH 025/175] fix `cargo clippy` lints --- src/api/client_server/membership.rs | 10 +- src/api/client_server/message.rs | 2 +- src/api/client_server/relations.rs | 6 +- src/api/client_server/session.rs | 10 +- src/api/client_server/state.rs | 6 +- src/api/client_server/sync.rs | 175 +++++++++--------- src/api/server_server.rs | 10 +- src/config/proxy.rs | 7 +- src/database/abstraction/watchers.rs | 1 + .../key_value/rooms/state_accessor.rs | 6 +- src/database/key_value/rooms/state_cache.rs | 2 + src/database/key_value/rooms/threads.rs | 4 +- src/database/key_value/rooms/timeline.rs | 11 +- src/main.rs | 2 +- src/service/rooms/edus/read_receipt/data.rs | 1 + src/service/rooms/event_handler/mod.rs | 4 +- src/service/rooms/lazy_loading/mod.rs | 1 + src/service/rooms/pdu_metadata/data.rs | 1 + src/service/rooms/pdu_metadata/mod.rs | 7 +- src/service/rooms/search/data.rs | 1 + src/service/rooms/spaces/mod.rs | 43 ++--- src/service/rooms/state/mod.rs | 4 +- src/service/rooms/state_accessor/mod.rs | 16 +- src/service/rooms/state_cache/data.rs | 2 + src/service/rooms/state_compressor/mod.rs | 12 +- src/service/rooms/threads/data.rs | 1 + src/service/rooms/threads/mod.rs | 4 +- src/service/rooms/timeline/data.rs | 2 + src/service/rooms/timeline/mod.rs | 53 +++--- src/service/sending/data.rs | 1 + src/service/users/mod.rs | 1 + 31 files changed, 203 insertions(+), 203 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 346f2575..ed59691d 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -400,7 +400,7 @@ pub async fn get_member_events_route( if !services() .rooms .state_accessor - .user_can_see_state_events(&sender_user, &body.room_id)? + .user_can_see_state_events(sender_user, &body.room_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -435,7 +435,7 @@ pub async fn joined_members_route( if !services() .rooms .state_accessor - .user_can_see_state_events(&sender_user, &body.room_id)? + .user_can_see_state_events(sender_user, &body.room_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -712,7 +712,7 @@ async fn join_room_by_id_helper( } info!("Running send_join auth check"); - if !state_res::event_auth::auth_check( + let authenticated = state_res::event_auth::auth_check( &state_res::RoomVersion::new(&room_version_id).expect("room version is supported"), &parsed_join_pdu, None::, // TODO: third party invite @@ -735,7 +735,9 @@ async fn join_room_by_id_helper( .map_err(|e| { warn!("Auth check failed: {e}"); Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed") - })? { + })?; + + if !authenticated { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Auth check failed", diff --git a/src/api/client_server/message.rs b/src/api/client_server/message.rs index 750e0303..0952092b 100644 --- a/src/api/client_server/message.rs +++ b/src/api/client_server/message.rs @@ -124,7 +124,7 @@ pub async fn get_message_events_route( let to = body .to .as_ref() - .and_then(|t| PduCount::try_from_string(&t).ok()); + .and_then(|t| PduCount::try_from_string(t).ok()); services().rooms.lazy_loading.lazy_load_confirm_delivery( sender_user, diff --git a/src/api/client_server/relations.rs b/src/api/client_server/relations.rs index a7cea786..124f1310 100644 --- a/src/api/client_server/relations.rs +++ b/src/api/client_server/relations.rs @@ -23,7 +23,7 @@ pub async fn get_relating_events_with_rel_type_and_event_type_route( let to = body .to .as_ref() - .and_then(|t| PduCount::try_from_string(&t).ok()); + .and_then(|t| PduCount::try_from_string(t).ok()); // Use limit or else 10, with maximum 100 let limit = body @@ -73,7 +73,7 @@ pub async fn get_relating_events_with_rel_type_route( let to = body .to .as_ref() - .and_then(|t| PduCount::try_from_string(&t).ok()); + .and_then(|t| PduCount::try_from_string(t).ok()); // Use limit or else 10, with maximum 100 let limit = body @@ -121,7 +121,7 @@ pub async fn get_relating_events_route( let to = body .to .as_ref() - .and_then(|t| PduCount::try_from_string(&t).ok()); + .and_then(|t| PduCount::try_from_string(t).ok()); // Use limit or else 10, with maximum 100 let limit = body diff --git a/src/api/client_server/session.rs b/src/api/client_server/session.rs index 5ffd8134..c17bd99b 100644 --- a/src/api/client_server/session.rs +++ b/src/api/client_server/session.rs @@ -117,12 +117,10 @@ pub async fn login_route(body: Ruma) -> Result { warn!("Unsupported or unknown login type: {:?}", &body.login_info); diff --git a/src/api/client_server/state.rs b/src/api/client_server/state.rs index d6d39390..174282a1 100644 --- a/src/api/client_server/state.rs +++ b/src/api/client_server/state.rs @@ -85,7 +85,7 @@ pub async fn get_state_events_route( if !services() .rooms .state_accessor - .user_can_see_state_events(&sender_user, &body.room_id)? + .user_can_see_state_events(sender_user, &body.room_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -118,7 +118,7 @@ pub async fn get_state_events_for_key_route( if !services() .rooms .state_accessor - .user_can_see_state_events(&sender_user, &body.room_id)? + .user_can_see_state_events(sender_user, &body.room_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -157,7 +157,7 @@ pub async fn get_state_events_for_empty_key_route( if !services() .rooms .state_accessor - .user_can_see_state_events(&sender_user, &body.room_id)? + .user_can_see_state_events(sender_user, &body.room_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index a275b066..57572284 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -554,6 +554,7 @@ async fn sync_helper( } } +#[allow(clippy::too_many_arguments)] async fn load_joined_room( sender_user: &UserId, sender_device: &DeviceId, @@ -590,7 +591,7 @@ async fn load_joined_room( || services() .rooms .user - .last_notification_read(&sender_user, &room_id)? + .last_notification_read(sender_user, room_id)? > since; let mut timeline_users = HashSet::new(); @@ -599,16 +600,16 @@ async fn load_joined_room( } services().rooms.lazy_loading.lazy_load_confirm_delivery( - &sender_user, - &sender_device, - &room_id, + sender_user, + sender_device, + room_id, sincecount, )?; // Database queries: let current_shortstatehash = - if let Some(s) = services().rooms.state.get_room_shortstatehash(&room_id)? { + if let Some(s) = services().rooms.state.get_room_shortstatehash(room_id)? { s } else { error!("Room {} has no state", room_id); @@ -618,7 +619,7 @@ async fn load_joined_room( let since_shortstatehash = services() .rooms .user - .get_token_shortstatehash(&room_id, since)?; + .get_token_shortstatehash(room_id, since)?; let (heroes, joined_member_count, invited_member_count, joined_since_last_sync, state_events) = if timeline_pdus.is_empty() && since_shortstatehash == Some(current_shortstatehash) { @@ -630,12 +631,12 @@ async fn load_joined_room( let joined_member_count = services() .rooms .state_cache - .room_joined_count(&room_id)? + .room_joined_count(room_id)? .unwrap_or(0); let invited_member_count = services() .rooms .state_cache - .room_invited_count(&room_id)? + .room_invited_count(room_id)? .unwrap_or(0); // Recalculate heroes (first 5 members) @@ -648,7 +649,7 @@ async fn load_joined_room( for hero in services() .rooms .timeline - .all_pdus(&sender_user, &room_id)? + .all_pdus(sender_user, room_id)? .filter_map(|pdu| pdu.ok()) // Ignore all broken pdus .filter(|(_, pdu)| pdu.kind == TimelineEventType::RoomMember) .map(|(_, pdu)| { @@ -669,11 +670,11 @@ async fn load_joined_room( ) && (services() .rooms .state_cache - .is_joined(&user_id, &room_id)? + .is_joined(&user_id, room_id)? || services() .rooms .state_cache - .is_invited(&user_id, &room_id)?) + .is_invited(&user_id, room_id)?) { Ok::<_, Error>(Some(state_key.clone())) } else { @@ -789,17 +790,17 @@ async fn load_joined_room( // Reset lazy loading because this is an initial sync services().rooms.lazy_loading.lazy_load_reset( - &sender_user, - &sender_device, - &room_id, + sender_user, + sender_device, + room_id, )?; // The state_events above should contain all timeline_users, let's mark them as lazy // loaded. services().rooms.lazy_loading.lazy_load_mark_sent( - &sender_user, - &sender_device, - &room_id, + sender_user, + sender_device, + room_id, lazy_loaded, next_batchcount, ); @@ -866,14 +867,14 @@ async fn load_joined_room( } if !services().rooms.lazy_loading.lazy_load_was_sent_before( - &sender_user, - &sender_device, - &room_id, + sender_user, + sender_device, + room_id, &event.sender, )? || lazy_load_send_redundant { if let Some(member_event) = services().rooms.state_accessor.room_state_get( - &room_id, + room_id, &StateEventType::RoomMember, event.sender.as_str(), )? { @@ -884,9 +885,9 @@ async fn load_joined_room( } services().rooms.lazy_loading.lazy_load_mark_sent( - &sender_user, - &sender_device, - &room_id, + sender_user, + sender_device, + room_id, lazy_loaded, next_batchcount, ); @@ -934,7 +935,7 @@ async fn load_joined_room( match new_membership { MembershipState::Join => { // A new user joined an encrypted room - if !share_encrypted_room(&sender_user, &user_id, &room_id)? { + if !share_encrypted_room(sender_user, &user_id, room_id)? { device_list_updates.insert(user_id); } } @@ -954,15 +955,15 @@ async fn load_joined_room( services() .rooms .state_cache - .room_members(&room_id) + .room_members(room_id) .flatten() .filter(|user_id| { // Don't send key updates from the sender to the sender - &sender_user != user_id + sender_user != user_id }) .filter(|user_id| { // Only send keys if the sender doesn't share an encrypted room with the target already - !share_encrypted_room(&sender_user, user_id, &room_id) + !share_encrypted_room(sender_user, user_id, room_id) .unwrap_or(false) }), ); @@ -997,7 +998,7 @@ async fn load_joined_room( services() .rooms .user - .notification_count(&sender_user, &room_id)? + .notification_count(sender_user, room_id)? .try_into() .expect("notification count can't go that high"), ) @@ -1010,7 +1011,7 @@ async fn load_joined_room( services() .rooms .user - .highlight_count(&sender_user, &room_id)? + .highlight_count(sender_user, room_id)? .try_into() .expect("highlight count can't go that high"), ) @@ -1039,15 +1040,15 @@ async fn load_joined_room( .rooms .edus .read_receipt - .readreceipts_since(&room_id, since) + .readreceipts_since(room_id, since) .filter_map(|r| r.ok()) // Filter out buggy events .map(|(_, _, v)| v) .collect(); - if services().rooms.edus.typing.last_typing_update(&room_id)? > since { + if services().rooms.edus.typing.last_typing_update(room_id)? > since { edus.push( serde_json::from_str( - &serde_json::to_string(&services().rooms.edus.typing.typings_all(&room_id)?) + &serde_json::to_string(&services().rooms.edus.typing.typings_all(room_id)?) .expect("event is valid, we just created it"), ) .expect("event is valid, we just created it"), @@ -1056,7 +1057,7 @@ async fn load_joined_room( // Save the state after this sync so we can send the correct state diff next sync services().rooms.user.associate_token_shortstatehash( - &room_id, + room_id, next_batch, current_shortstatehash, )?; @@ -1065,7 +1066,7 @@ async fn load_joined_room( account_data: RoomAccountData { events: services() .account_data - .changes_since(Some(&room_id), &sender_user, since)? + .changes_since(Some(room_id), sender_user, since)? .into_iter() .filter_map(|(_, v)| { serde_json::from_str(v.json().get()) @@ -1110,13 +1111,13 @@ fn load_timeline( if services() .rooms .timeline - .last_timeline_count(&sender_user, &room_id)? + .last_timeline_count(sender_user, room_id)? > roomsincecount { let mut non_timeline_pdus = services() .rooms .timeline - .pdus_until(&sender_user, &room_id, PduCount::max())? + .pdus_until(sender_user, room_id, PduCount::max())? .filter_map(|r| { // Filter out buggy events if r.is_err() { @@ -1172,7 +1173,6 @@ fn share_encrypted_room( pub async fn sync_events_v4_route( body: Ruma, ) -> Result> { - dbg!(&body.body); let sender_user = body.sender_user.expect("user is authenticated"); let sender_device = body.sender_device.expect("user is authenticated"); let mut body = body.body; @@ -1232,7 +1232,7 @@ pub async fn sync_events_v4_route( for room_id in &all_joined_rooms { let current_shortstatehash = - if let Some(s) = services().rooms.state.get_room_shortstatehash(&room_id)? { + if let Some(s) = services().rooms.state.get_room_shortstatehash(room_id)? { s } else { error!("Room {} has no state", room_id); @@ -1242,7 +1242,7 @@ pub async fn sync_events_v4_route( let since_shortstatehash = services() .rooms .user - .get_token_shortstatehash(&room_id, globalsince)?; + .get_token_shortstatehash(room_id, globalsince)?; let since_sender_member: Option = since_shortstatehash .and_then(|shortstatehash| { @@ -1331,7 +1331,7 @@ pub async fn sync_events_v4_route( if !share_encrypted_room( &sender_user, &user_id, - &room_id, + room_id, )? { device_list_changes.insert(user_id); } @@ -1352,7 +1352,7 @@ pub async fn sync_events_v4_route( services() .rooms .state_cache - .room_members(&room_id) + .room_members(room_id) .flatten() .filter(|user_id| { // Don't send key updates from the sender to the sender @@ -1360,7 +1360,7 @@ pub async fn sync_events_v4_route( }) .filter(|user_id| { // Only send keys if the sender doesn't share an encrypted room with the target already - !share_encrypted_room(&sender_user, user_id, &room_id) + !share_encrypted_room(&sender_user, user_id, room_id) .unwrap_or(false) }), ); @@ -1451,7 +1451,7 @@ pub async fn sync_events_v4_route( } sync_events::v4::SyncOp { op: SlidingOp::Sync, - range: Some(r.clone()), + range: Some(r), index: None, room_ids, room_id: None, @@ -1523,7 +1523,7 @@ pub async fn sync_events_v4_route( let roomsincecount = PduCount::Normal(*roomsince); let (timeline_pdus, limited) = - load_timeline(&sender_user, &room_id, roomsincecount, *timeline_limit)?; + load_timeline(&sender_user, room_id, roomsincecount, *timeline_limit)?; if roomsince != &0 && timeline_pdus.is_empty() { continue; @@ -1555,63 +1555,58 @@ pub async fn sync_events_v4_route( let required_state = required_state_request .iter() - .map(|state| { + .flat_map(|state| { services() .rooms .state_accessor - .room_state_get(&room_id, &state.0, &state.1) + .room_state_get(room_id, &state.0, &state.1) + .ok() + .flatten() + .map(|state| state.to_sync_state_event()) }) - .filter_map(|r| r.ok()) - .filter_map(|o| o) - .map(|state| state.to_sync_state_event()) .collect(); // Heroes let heroes = services() .rooms .state_cache - .room_members(&room_id) + .room_members(room_id) .filter_map(|r| r.ok()) .filter(|member| member != &sender_user) - .map(|member| { - Ok::<_, Error>( - services() - .rooms - .state_accessor - .get_member(&room_id, &member)? - .map(|memberevent| { - ( - memberevent - .displayname - .unwrap_or_else(|| member.to_string()), - memberevent.avatar_url, - ) - }), - ) + .flat_map(|member| { + services() + .rooms + .state_accessor + .get_member(room_id, &member) + .ok() + .flatten() + .map(|memberevent| { + ( + memberevent + .displayname + .unwrap_or_else(|| member.to_string()), + memberevent.avatar_url, + ) + }) }) - .filter_map(|r| r.ok()) - .filter_map(|o| o) .take(5) .collect::>(); - let name = if heroes.len() > 1 { - let last = heroes[0].0.clone(); - Some( - heroes[1..] + let name = match &heroes[..] { + [] => None, + [only] => Some(only.0.clone()), + [firsts @ .., last] => Some( + firsts .iter() .map(|h| h.0.clone()) .collect::>() .join(", ") + " and " - + &last, - ) - } else if heroes.len() == 1 { - Some(heroes[0].0.clone()) - } else { - None + + &last.0, + ), }; - let avatar = if heroes.len() == 1 { - heroes[0].1.clone() + let avatar = if let [only] = &heroes[..] { + only.1.clone() } else { None }; @@ -1619,15 +1614,11 @@ pub async fn sync_events_v4_route( rooms.insert( room_id.clone(), sync_events::v4::SlidingSyncRoom { - name: services() - .rooms - .state_accessor - .get_name(&room_id)? - .or_else(|| name), + name: services().rooms.state_accessor.get_name(room_id)?.or(name), avatar: services() .rooms .state_accessor - .get_avatar(&room_id)? + .get_avatar(room_id)? .map_or(avatar, |a| a.url), initial: Some(roomsince == &0), is_dm: None, @@ -1637,7 +1628,7 @@ pub async fn sync_events_v4_route( services() .rooms .user - .highlight_count(&sender_user, &room_id)? + .highlight_count(&sender_user, room_id)? .try_into() .expect("notification count can't go that high"), ), @@ -1645,7 +1636,7 @@ pub async fn sync_events_v4_route( services() .rooms .user - .notification_count(&sender_user, &room_id)? + .notification_count(&sender_user, room_id)? .try_into() .expect("notification count can't go that high"), ), @@ -1658,7 +1649,7 @@ pub async fn sync_events_v4_route( (services() .rooms .state_cache - .room_joined_count(&room_id)? + .room_joined_count(room_id)? .unwrap_or(0) as u32) .into(), ), @@ -1666,7 +1657,7 @@ pub async fn sync_events_v4_route( (services() .rooms .state_cache - .room_invited_count(&room_id)? + .room_invited_count(room_id)? .unwrap_or(0) as u32) .into(), ), @@ -1689,7 +1680,7 @@ pub async fn sync_events_v4_route( let _ = tokio::time::timeout(duration, watcher).await; } - Ok(dbg!(sync_events::v4::Response { + Ok(sync_events::v4::Response { initial: globalsince == 0, txn_id: body.txn_id.clone(), pos: next_batch.to_string(), @@ -1744,5 +1735,5 @@ pub async fn sync_events_v4_route( }, }, delta_token: None, - })) + }) } diff --git a/src/api/server_server.rs b/src/api/server_server.rs index a11857dc..79f921e3 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -666,7 +666,7 @@ pub fn parse_incoming_pdu( let room_version_id = services().rooms.state.get_room_version(&room_id)?; - let (event_id, value) = match gen_event_id_canonical_json(&pdu, &room_version_id) { + let (event_id, value) = match gen_event_id_canonical_json(pdu, &room_version_id) { Ok(t) => t, Err(_) => { // Event could not be converted to canonical json @@ -724,7 +724,7 @@ pub async fn send_transaction_message_route( continue; } - let r = parse_incoming_pdu(&pdu); + let r = parse_incoming_pdu(pdu); let (event_id, value, room_id) = match r { Ok(t) => t, Err(e) => { @@ -992,7 +992,7 @@ pub async fn get_event_route( if !services().rooms.state_accessor.server_can_see_event( sender_servername, - &room_id, + room_id, &body.event_id, )? { return Err(Error::BadRequest( @@ -1058,7 +1058,7 @@ pub async fn get_backfill_route( let all_events = services() .rooms .timeline - .pdus_until(&user_id!("@doesntmatter:conduit.rs"), &body.room_id, until)? + .pdus_until(user_id!("@doesntmatter:conduit.rs"), &body.room_id, until)? .take(limit.try_into().unwrap()); let events = all_events @@ -1075,7 +1075,7 @@ pub async fn get_backfill_route( }) .map(|(_, pdu)| services().rooms.timeline.get_pdu_json(&pdu.event_id)) .filter_map(|r| r.ok().flatten()) - .map(|pdu| PduEvent::convert_to_outgoing_federation_event(pdu)) + .map(PduEvent::convert_to_outgoing_federation_event) .collect(); Ok(get_backfill::v1::Response { diff --git a/src/config/proxy.rs b/src/config/proxy.rs index dcf304e9..c03463e7 100644 --- a/src/config/proxy.rs +++ b/src/config/proxy.rs @@ -29,7 +29,9 @@ use crate::Result; /// would be used for `ordinary.onion`, `matrix.myspecial.onion`, but not `hello.myspecial.onion`. #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "snake_case")] +#[derive(Default)] pub enum ProxyConfig { + #[default] None, Global { #[serde(deserialize_with = "crate::utils::deserialize_from_str")] @@ -48,11 +50,6 @@ impl ProxyConfig { }) } } -impl Default for ProxyConfig { - fn default() -> Self { - ProxyConfig::None - } -} #[derive(Clone, Debug, Deserialize)] pub struct PartialProxyConfig { diff --git a/src/database/abstraction/watchers.rs b/src/database/abstraction/watchers.rs index 55cb60b3..01156abd 100644 --- a/src/database/abstraction/watchers.rs +++ b/src/database/abstraction/watchers.rs @@ -8,6 +8,7 @@ use tokio::sync::watch; #[derive(Default)] pub(super) struct Watchers { + #[allow(clippy::type_complexity)] watchers: RwLock, (watch::Sender<()>, watch::Receiver<()>)>>, } diff --git a/src/database/key_value/rooms/state_accessor.rs b/src/database/key_value/rooms/state_accessor.rs index ad08f46e..fe40b937 100644 --- a/src/database/key_value/rooms/state_accessor.rs +++ b/src/database/key_value/rooms/state_accessor.rs @@ -20,7 +20,7 @@ impl service::rooms::state_accessor::Data for KeyValueDatabase { let parsed = services() .rooms .state_compressor - .parse_compressed_state_event(&compressed)?; + .parse_compressed_state_event(compressed)?; result.insert(parsed.0, parsed.1); i += 1; @@ -49,7 +49,7 @@ impl service::rooms::state_accessor::Data for KeyValueDatabase { let (_, eventid) = services() .rooms .state_compressor - .parse_compressed_state_event(&compressed)?; + .parse_compressed_state_event(compressed)?; if let Some(pdu) = services().rooms.timeline.get_pdu(&eventid)? { result.insert( ( @@ -101,7 +101,7 @@ impl service::rooms::state_accessor::Data for KeyValueDatabase { services() .rooms .state_compressor - .parse_compressed_state_event(&compressed) + .parse_compressed_state_event(compressed) .ok() .map(|(_, id)| id) })) diff --git a/src/database/key_value/rooms/state_cache.rs b/src/database/key_value/rooms/state_cache.rs index d0ea0c2c..3dcaf4ae 100644 --- a/src/database/key_value/rooms/state_cache.rs +++ b/src/database/key_value/rooms/state_cache.rs @@ -471,6 +471,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase { } /// Returns an iterator over all rooms a user was invited to. + #[allow(clippy::type_complexity)] #[tracing::instrument(skip(self))] fn rooms_invited<'a>( &'a self, @@ -549,6 +550,7 @@ impl service::rooms::state_cache::Data for KeyValueDatabase { } /// Returns an iterator over all rooms a user left. + #[allow(clippy::type_complexity)] #[tracing::instrument(skip(self))] fn rooms_left<'a>( &'a self, diff --git a/src/database/key_value/rooms/threads.rs b/src/database/key_value/rooms/threads.rs index 35c4e6e2..5e3dc970 100644 --- a/src/database/key_value/rooms/threads.rs +++ b/src/database/key_value/rooms/threads.rs @@ -52,13 +52,13 @@ impl service::rooms::threads::Data for KeyValueDatabase { .collect::>() .join(&[0xff][..]); - self.threadid_userids.insert(&root_id, &users)?; + self.threadid_userids.insert(root_id, &users)?; Ok(()) } fn get_participants(&self, root_id: &[u8]) -> Result>> { - if let Some(users) = self.threadid_userids.get(&root_id)? { + if let Some(users) = self.threadid_userids.get(root_id)? { Ok(Some( users .split(|b| *b == 0xff) diff --git a/src/database/key_value/rooms/timeline.rs b/src/database/key_value/rooms/timeline.rs index ba1e85ef..f322d430 100644 --- a/src/database/key_value/rooms/timeline.rs +++ b/src/database/key_value/rooms/timeline.rs @@ -39,11 +39,10 @@ impl service::rooms::timeline::Data for KeyValueDatabase { /// Returns the `count` of this pdu's id. fn get_pdu_count(&self, event_id: &EventId) -> Result> { - Ok(self - .eventid_pduid + self.eventid_pduid .get(event_id.as_bytes())? .map(|pdu_id| pdu_count(&pdu_id)) - .transpose()?) + .transpose() } /// Returns the json of a pdu. @@ -80,7 +79,7 @@ impl service::rooms::timeline::Data for KeyValueDatabase { /// Returns the pdu's id. fn get_pdu_id(&self, event_id: &EventId) -> Result>> { - Ok(self.eventid_pduid.get(event_id.as_bytes())?) + self.eventid_pduid.get(event_id.as_bytes()) } /// Returns the pdu. @@ -230,7 +229,7 @@ impl service::rooms::timeline::Data for KeyValueDatabase { room_id: &RoomId, until: PduCount, ) -> Result> + 'a>> { - let (prefix, current) = count_to_id(&room_id, until, 1, true)?; + let (prefix, current) = count_to_id(room_id, until, 1, true)?; let user_id = user_id.to_owned(); @@ -257,7 +256,7 @@ impl service::rooms::timeline::Data for KeyValueDatabase { room_id: &RoomId, from: PduCount, ) -> Result> + 'a>> { - let (prefix, current) = count_to_id(&room_id, from, 1, false)?; + let (prefix, current) = count_to_id(room_id, from, 1, false)?; let user_id = user_id.to_owned(); diff --git a/src/main.rs b/src/main.rs index c74d6ddb..683e0914 100644 --- a/src/main.rs +++ b/src/main.rs @@ -238,7 +238,7 @@ async fn spawn_task( .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } -async fn unrecognized_method( +async fn unrecognized_method( req: axum::http::Request, next: axum::middleware::Next, ) -> std::result::Result { diff --git a/src/service/rooms/edus/read_receipt/data.rs b/src/service/rooms/edus/read_receipt/data.rs index a183d196..044dad82 100644 --- a/src/service/rooms/edus/read_receipt/data.rs +++ b/src/service/rooms/edus/read_receipt/data.rs @@ -11,6 +11,7 @@ pub trait Data: Send + Sync { ) -> Result<()>; /// Returns an iterator over the most recent read_receipts in a room that happened after the event with id `since`. + #[allow(clippy::type_complexity)] fn readreceipts_since<'a>( &'a self, room_id: &RoomId, diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 29199781..e7db6f78 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -92,7 +92,7 @@ impl Service { )); } - services().rooms.event_handler.acl_check(origin, &room_id)?; + services().rooms.event_handler.acl_check(origin, room_id)?; // 1. Skip the PDU if we already have it as a timeline event if let Some(pdu_id) = services().rooms.timeline.get_pdu_id(event_id)? { @@ -276,6 +276,7 @@ impl Service { r } + #[allow(clippy::type_complexity, clippy::too_many_arguments)] #[tracing::instrument(skip(self, create_event, value, pub_key_map))] fn handle_outlier_pdu<'a>( &'a self, @@ -1009,6 +1010,7 @@ impl Service { /// b. Look at outlier pdu tree /// c. Ask origin server over federation /// d. TODO: Ask other servers over federation? + #[allow(clippy::type_complexity)] #[tracing::instrument(skip_all)] pub(crate) fn fetch_and_handle_outliers<'a>( &'a self, diff --git a/src/service/rooms/lazy_loading/mod.rs b/src/service/rooms/lazy_loading/mod.rs index e6e4f896..c51a57e9 100644 --- a/src/service/rooms/lazy_loading/mod.rs +++ b/src/service/rooms/lazy_loading/mod.rs @@ -14,6 +14,7 @@ use super::timeline::PduCount; pub struct Service { pub db: &'static dyn Data, + #[allow(clippy::type_complexity)] pub lazy_load_waiting: Mutex>>, } diff --git a/src/service/rooms/pdu_metadata/data.rs b/src/service/rooms/pdu_metadata/data.rs index 6c4cb3ce..a4df34cc 100644 --- a/src/service/rooms/pdu_metadata/data.rs +++ b/src/service/rooms/pdu_metadata/data.rs @@ -5,6 +5,7 @@ use ruma::{EventId, RoomId, UserId}; pub trait Data: Send + Sync { fn add_relation(&self, from: u64, to: u64) -> Result<()>; + #[allow(clippy::type_complexity)] fn relations_until<'a>( &'a self, user_id: &'a UserId, diff --git a/src/service/rooms/pdu_metadata/mod.rs b/src/service/rooms/pdu_metadata/mod.rs index 9ce74f4d..411f4f54 100644 --- a/src/service/rooms/pdu_metadata/mod.rs +++ b/src/service/rooms/pdu_metadata/mod.rs @@ -40,6 +40,7 @@ impl Service { } } + #[allow(clippy::too_many_arguments)] pub fn paginate_relations_with_filter( &self, sender_user: &UserId, @@ -82,7 +83,7 @@ impl Service { services() .rooms .state_accessor - .user_can_see_event(sender_user, &room_id, &pdu.event_id) + .user_can_see_event(sender_user, room_id, &pdu.event_id) .unwrap_or(false) }) .take_while(|&(k, _)| Some(k) != to) // Stop at `to` @@ -106,7 +107,7 @@ impl Service { let events_before: Vec<_> = services() .rooms .pdu_metadata - .relations_until(sender_user, &room_id, target, from)? + .relations_until(sender_user, room_id, target, from)? .filter(|r| { r.as_ref().map_or(true, |(_, pdu)| { filter_event_type.as_ref().map_or(true, |t| &pdu.kind == t) @@ -129,7 +130,7 @@ impl Service { services() .rooms .state_accessor - .user_can_see_event(sender_user, &room_id, &pdu.event_id) + .user_can_see_event(sender_user, room_id, &pdu.event_id) .unwrap_or(false) }) .take_while(|&(k, _)| Some(k) != to) // Stop at `to` diff --git a/src/service/rooms/search/data.rs b/src/service/rooms/search/data.rs index 6eef38fb..7ea7e3d1 100644 --- a/src/service/rooms/search/data.rs +++ b/src/service/rooms/search/data.rs @@ -4,6 +4,7 @@ use ruma::RoomId; pub trait Data: Send + Sync { fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()>; + #[allow(clippy::type_complexity)] fn search_pdus<'a>( &'a self, room_id: &RoomId, diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index 53232f46..615e9ca0 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -197,7 +197,7 @@ impl Service { if let Ok(response) = services() .sending .send_federation_request( - &server, + server, federation::space::get_hierarchy::v1::Request { room_id: current_room.to_owned(), suggested_only, @@ -235,7 +235,7 @@ impl Service { .room .allowed_room_ids .into_iter() - .map(|room| AllowRule::room_membership(room)) + .map(AllowRule::room_membership) .collect(), }) } @@ -245,7 +245,7 @@ impl Service { .room .allowed_room_ids .into_iter() - .map(|room| AllowRule::room_membership(room)) + .map(AllowRule::room_membership) .collect(), }) } @@ -313,7 +313,7 @@ impl Service { canonical_alias: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomCanonicalAlias, "")? + .room_state_get(room_id, &StateEventType::RoomCanonicalAlias, "")? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomCanonicalAliasEventContent| c.alias) @@ -321,11 +321,11 @@ impl Service { Error::bad_database("Invalid canonical alias event in database.") }) })?, - name: services().rooms.state_accessor.get_name(&room_id)?, + name: services().rooms.state_accessor.get_name(room_id)?, num_joined_members: services() .rooms .state_cache - .room_joined_count(&room_id)? + .room_joined_count(room_id)? .unwrap_or_else(|| { warn!("Room {} has no member count", room_id); 0 @@ -336,7 +336,7 @@ impl Service { topic: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomTopic, "")? + .room_state_get(room_id, &StateEventType::RoomTopic, "")? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomTopicEventContent| Some(c.topic)) @@ -348,7 +348,7 @@ impl Service { world_readable: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomHistoryVisibility, "")? + .room_state_get(room_id, &StateEventType::RoomHistoryVisibility, "")? .map_or(Ok(false), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomHistoryVisibilityEventContent| { @@ -363,7 +363,7 @@ impl Service { guest_can_join: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomGuestAccess, "")? + .room_state_get(room_id, &StateEventType::RoomGuestAccess, "")? .map_or(Ok(false), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomGuestAccessEventContent| { @@ -376,7 +376,7 @@ impl Service { avatar_url: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomAvatar, "")? + .room_state_get(room_id, &StateEventType::RoomAvatar, "")? .map(|s| { serde_json::from_str(s.content.get()) .map(|c: RoomAvatarEventContent| c.url) @@ -389,7 +389,7 @@ impl Service { let join_rule = services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomJoinRules, "")? + .room_state_get(room_id, &StateEventType::RoomJoinRules, "")? .map(|s| { serde_json::from_str(s.content.get()) .map(|c: RoomJoinRulesEventContent| c.join_rule) @@ -415,7 +415,7 @@ impl Service { room_type: services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomCreate, "")? + .room_state_get(room_id, &StateEventType::RoomCreate, "")? .map(|s| { serde_json::from_str::(s.content.get()).map_err(|e| { error!("Invalid room create event in database: {}", e); @@ -455,7 +455,7 @@ impl Service { SpaceRoomJoinRule::Invite => services() .rooms .state_cache - .is_joined(sender_user, &room_id)?, + .is_joined(sender_user, room_id)?, _ => false, }; @@ -479,17 +479,14 @@ impl Service { match join_rule { JoinRule::Restricted(r) => { for rule in &r.allow { - match rule { - join_rules::AllowRule::RoomMembership(rm) => { - if let Ok(true) = services() - .rooms - .state_cache - .is_joined(sender_user, &rm.room_id) - { - return Ok(true); - } + if let join_rules::AllowRule::RoomMembership(rm) = rule { + if let Ok(true) = services() + .rooms + .state_cache + .is_joined(sender_user, &rm.room_id) + { + return Ok(true); } - _ => {} } } diff --git a/src/service/rooms/state/mod.rs b/src/service/rooms/state/mod.rs index 48c60203..c209eb5a 100644 --- a/src/service/rooms/state/mod.rs +++ b/src/service/rooms/state/mod.rs @@ -41,7 +41,7 @@ impl Service { services() .rooms .state_compressor - .parse_compressed_state_event(&new) + .parse_compressed_state_event(new) .ok() .map(|(_, id)| id) }) { @@ -412,7 +412,7 @@ impl Service { services() .rooms .state_compressor - .parse_compressed_state_event(&compressed) + .parse_compressed_state_event(compressed) .ok() }) .filter_map(|(shortstatekey, event_id)| { diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index a4a62fe4..b00dc58c 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -180,7 +180,7 @@ impl Service { return Ok(*visibility); } - let currently_member = services().rooms.state_cache.is_joined(&user_id, &room_id)?; + let currently_member = services().rooms.state_cache.is_joined(user_id, room_id)?; let history_visibility = self .state_get(shortstatehash, &StateEventType::RoomHistoryVisibility, "")? @@ -197,11 +197,11 @@ impl Service { HistoryVisibility::Shared => currently_member, HistoryVisibility::Invited => { // Allow if any member on requesting server was AT LEAST invited, else deny - self.user_was_invited(shortstatehash, &user_id) + self.user_was_invited(shortstatehash, user_id) } HistoryVisibility::Joined => { // Allow if any member on requested server was joined, else deny - self.user_was_joined(shortstatehash, &user_id) + self.user_was_joined(shortstatehash, user_id) } _ => { error!("Unknown history visibility {history_visibility}"); @@ -221,10 +221,10 @@ impl Service { /// the room's history_visibility at that event's state. #[tracing::instrument(skip(self, user_id, room_id))] pub fn user_can_see_state_events(&self, user_id: &UserId, room_id: &RoomId) -> Result { - let currently_member = services().rooms.state_cache.is_joined(&user_id, &room_id)?; + let currently_member = services().rooms.state_cache.is_joined(user_id, room_id)?; let history_visibility = self - .room_state_get(&room_id, &StateEventType::RoomHistoryVisibility, "")? + .room_state_get(room_id, &StateEventType::RoomHistoryVisibility, "")? .map_or(Ok(HistoryVisibility::Shared), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomHistoryVisibilityEventContent| c.history_visibility) @@ -276,7 +276,7 @@ impl Service { services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomName, "")? + .room_state_get(room_id, &StateEventType::RoomName, "")? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) .map(|c: RoomNameEventContent| c.name) @@ -288,7 +288,7 @@ impl Service { services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomAvatar, "")? + .room_state_get(room_id, &StateEventType::RoomAvatar, "")? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) .map_err(|_| Error::bad_database("Invalid room avatar event in database.")) @@ -303,7 +303,7 @@ impl Service { services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomMember, user_id.as_str())? + .room_state_get(room_id, &StateEventType::RoomMember, user_id.as_str())? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) .map_err(|_| Error::bad_database("Invalid room member event in database.")) diff --git a/src/service/rooms/state_cache/data.rs b/src/service/rooms/state_cache/data.rs index d8bb4a44..8921909f 100644 --- a/src/service/rooms/state_cache/data.rs +++ b/src/service/rooms/state_cache/data.rs @@ -78,6 +78,7 @@ pub trait Data: Send + Sync { ) -> Box> + 'a>; /// Returns an iterator over all rooms a user was invited to. + #[allow(clippy::type_complexity)] fn rooms_invited<'a>( &'a self, user_id: &UserId, @@ -96,6 +97,7 @@ pub trait Data: Send + Sync { ) -> Result>>>; /// Returns an iterator over all rooms a user left. + #[allow(clippy::type_complexity)] fn rooms_left<'a>( &'a self, user_id: &UserId, diff --git a/src/service/rooms/state_compressor/mod.rs b/src/service/rooms/state_compressor/mod.rs index d29b020b..6118e06b 100644 --- a/src/service/rooms/state_compressor/mod.rs +++ b/src/service/rooms/state_compressor/mod.rs @@ -16,6 +16,7 @@ use self::data::StateDiff; pub struct Service { pub db: &'static dyn Data, + #[allow(clippy::type_complexity)] pub stateinfo_cache: Mutex< LruCache< u64, @@ -33,6 +34,7 @@ pub type CompressedStateEvent = [u8; 2 * size_of::()]; impl Service { /// Returns a stack with info on shortstatehash, full state, added diff and removed diff for the selected shortstatehash and each parent layer. + #[allow(clippy::type_complexity)] #[tracing::instrument(skip(self))] pub fn load_shortstatehash_info( &self, @@ -131,6 +133,7 @@ impl Service { /// * `statediffremoved` - Removed from base. Each vec is shortstatekey+shorteventid /// * `diff_to_sibling` - Approximately how much the diff grows each time for this layer /// * `parent_states` - A stack with info on shortstatehash, full state, added diff and removed diff for each parent layer + #[allow(clippy::type_complexity)] #[tracing::instrument(skip( self, statediffnew, @@ -164,7 +167,7 @@ impl Service { for removed in statediffremoved.iter() { if !parent_new.remove(removed) { // It was not added in the parent and we removed it - parent_removed.insert(removed.clone()); + parent_removed.insert(*removed); } // Else it was added in the parent and we removed it again. We can forget this change } @@ -172,7 +175,7 @@ impl Service { for new in statediffnew.iter() { if !parent_removed.remove(new) { // It was not touched in the parent and we added it - parent_new.insert(new.clone()); + parent_new.insert(*new); } // Else it was removed in the parent and we added it again. We can forget this change } @@ -217,7 +220,7 @@ impl Service { for removed in statediffremoved.iter() { if !parent_new.remove(removed) { // It was not added in the parent and we removed it - parent_removed.insert(removed.clone()); + parent_removed.insert(*removed); } // Else it was added in the parent and we removed it again. We can forget this change } @@ -225,7 +228,7 @@ impl Service { for new in statediffnew.iter() { if !parent_removed.remove(new) { // It was not touched in the parent and we added it - parent_new.insert(new.clone()); + parent_new.insert(*new); } // Else it was removed in the parent and we added it again. We can forget this change } @@ -253,6 +256,7 @@ impl Service { } /// Returns the new shortstatehash, and the state diff from the previous room state + #[allow(clippy::type_complexity)] pub fn save_state( &self, room_id: &RoomId, diff --git a/src/service/rooms/threads/data.rs b/src/service/rooms/threads/data.rs index 9221e8e8..e7159de0 100644 --- a/src/service/rooms/threads/data.rs +++ b/src/service/rooms/threads/data.rs @@ -2,6 +2,7 @@ use crate::{PduEvent, Result}; use ruma::{api::client::threads::get_threads::v1::IncludeThreads, OwnedUserId, RoomId, UserId}; pub trait Data: Send + Sync { + #[allow(clippy::type_complexity)] fn threads_until<'a>( &'a self, user_id: &'a UserId, diff --git a/src/service/rooms/threads/mod.rs b/src/service/rooms/threads/mod.rs index fb703839..c6193bc8 100644 --- a/src/service/rooms/threads/mod.rs +++ b/src/service/rooms/threads/mod.rs @@ -26,7 +26,7 @@ impl Service { self.db.threads_until(user_id, room_id, until, include) } - pub fn add_to_thread<'a>(&'a self, root_event_id: &EventId, pdu: &PduEvent) -> Result<()> { + pub fn add_to_thread(&self, root_event_id: &EventId, pdu: &PduEvent) -> Result<()> { let root_id = &services() .rooms .timeline @@ -103,7 +103,7 @@ impl Service { } let mut users = Vec::new(); - if let Some(userids) = self.db.get_participants(&root_id)? { + if let Some(userids) = self.db.get_participants(root_id)? { users.extend_from_slice(&userids); users.push(pdu.sender.clone()); } else { diff --git a/src/service/rooms/timeline/data.rs b/src/service/rooms/timeline/data.rs index afa2cfbf..6290b8cc 100644 --- a/src/service/rooms/timeline/data.rs +++ b/src/service/rooms/timeline/data.rs @@ -66,6 +66,7 @@ pub trait Data: Send + Sync { /// Returns an iterator over all events and their tokens in a room that happened before the /// event with id `until` in reverse-chronological order. + #[allow(clippy::type_complexity)] fn pdus_until<'a>( &'a self, user_id: &UserId, @@ -75,6 +76,7 @@ pub trait Data: Send + Sync { /// Returns an iterator over all events in a room that happened after the event with id `from` /// in chronological order. + #[allow(clippy::type_complexity)] fn pdus_after<'a>( &'a self, user_id: &UserId, diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 25e1c54d..61b73378 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -58,8 +58,8 @@ impl PduCount { } pub fn try_from_string(token: &str) -> Result { - if token.starts_with('-') { - token[1..].parse().map(PduCount::Backfilled) + if let Some(stripped) = token.strip_prefix('-') { + stripped.parse().map(PduCount::Backfilled) } else { token.parse().map(PduCount::Normal) } @@ -112,7 +112,7 @@ pub struct Service { impl Service { #[tracing::instrument(skip(self))] pub fn first_pdu_in_room(&self, room_id: &RoomId) -> Result>> { - self.all_pdus(&user_id!("@doesntmatter:conduit.rs"), &room_id)? + self.all_pdus(user_id!("@doesntmatter:conduit.rs"), room_id)? .next() .map(|o| o.map(|(_, p)| Arc::new(p))) .transpose() @@ -458,7 +458,7 @@ impl Service { let to_conduit = body.starts_with(&format!("{server_user}: ")) || body.starts_with(&format!("{server_user} ")) || body == format!("{server_user}:") - || body == format!("{server_user}"); + || body == server_user; // This will evaluate to false if the emergency password is set up so that // the administrator can execute commands as conduit @@ -842,7 +842,7 @@ impl Service { let target = pdu .state_key() - .filter(|v| v.starts_with("@")) + .filter(|v| v.starts_with('@')) .unwrap_or(sender.as_str()); let server_name = services().globals.server_name(); let server_user = format!("@conduit:{}", server_name); @@ -850,7 +850,7 @@ impl Service { .map_err(|_| Error::bad_database("Invalid content in pdu."))?; if content.membership == MembershipState::Leave { - if target == &server_user { + if target == server_user { warn!("Conduit user cannot leave from admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -876,7 +876,7 @@ impl Service { } if content.membership == MembershipState::Ban && pdu.state_key().is_some() { - if target == &server_user { + if target == server_user { warn!("Conduit user cannot be banned in admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -1048,7 +1048,7 @@ impl Service { #[tracing::instrument(skip(self, room_id))] pub async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Result<()> { let first_pdu = self - .all_pdus(&user_id!("@doesntmatter:conduit.rs"), &room_id)? + .all_pdus(user_id!("@doesntmatter:conduit.rs"), room_id)? .next() .expect("Room is not empty")?; @@ -1060,7 +1060,7 @@ impl Service { let power_levels: RoomPowerLevelsEventContent = services() .rooms .state_accessor - .room_state_get(&room_id, &StateEventType::RoomPowerLevels, "")? + .room_state_get(room_id, &StateEventType::RoomPowerLevels, "")? .map(|ev| { serde_json::from_str(ev.content.get()) .map_err(|_| Error::bad_database("invalid m.room.power_levels event")) @@ -1091,11 +1091,9 @@ impl Service { .await; match response { Ok(response) => { - let mut pub_key_map = RwLock::new(BTreeMap::new()); + let pub_key_map = RwLock::new(BTreeMap::new()); for pdu in response.pdus { - if let Err(e) = self - .backfill_pdu(backfill_server, pdu, &mut pub_key_map) - .await + if let Err(e) = self.backfill_pdu(backfill_server, pdu, &pub_key_map).await { warn!("Failed to add backfilled pdu: {e}"); } @@ -1142,7 +1140,7 @@ impl Service { services() .rooms .event_handler - .handle_incoming_pdu(origin, &event_id, &room_id, value, false, &pub_key_map) + .handle_incoming_pdu(origin, &event_id, &room_id, value, false, pub_key_map) .await?; let value = self.get_pdu_json(&event_id)?.expect("We just created it"); @@ -1175,24 +1173,21 @@ impl Service { drop(insert_lock); - match pdu.kind { - TimelineEventType::RoomMessage => { - #[derive(Deserialize)] - struct ExtractBody { - body: Option, - } + if pdu.kind == TimelineEventType::RoomMessage { + #[derive(Deserialize)] + struct ExtractBody { + body: Option, + } - let content = serde_json::from_str::(pdu.content.get()) - .map_err(|_| Error::bad_database("Invalid content in pdu."))?; + let content = serde_json::from_str::(pdu.content.get()) + .map_err(|_| Error::bad_database("Invalid content in pdu."))?; - if let Some(body) = content.body { - services() - .rooms - .search - .index_pdu(shortroomid, &pdu_id, &body)?; - } + if let Some(body) = content.body { + services() + .rooms + .search + .index_pdu(shortroomid, &pdu_id, &body)?; } - _ => {} } drop(mutex_lock); diff --git a/src/service/sending/data.rs b/src/service/sending/data.rs index 2e574e23..8b4d236f 100644 --- a/src/service/sending/data.rs +++ b/src/service/sending/data.rs @@ -5,6 +5,7 @@ use crate::Result; use super::{OutgoingKind, SendingEventType}; pub trait Data: Send + Sync { + #[allow(clippy::type_complexity)] fn active_requests<'a>( &'a self, ) -> Box, OutgoingKind, SendingEventType)>> + 'a>; diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index 6faa6d8e..dc34d533 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -34,6 +34,7 @@ pub struct SlidingSyncCache { pub struct Service { pub db: &'static dyn Data, + #[allow(clippy::type_complexity)] pub connections: Mutex>>>, } From 0d17aedae50e58226bc91f10253679cfc280b9ff Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 20:30:31 -0800 Subject: [PATCH 026/175] fix `cargo doc` lints Rustdoc (rightfully) thought the `[commandbody]` "tags" were broken links, so I've just made them links to nothing instead. --- src/api/server_server.rs | 2 +- src/service/admin/mod.rs | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 79f921e3..db17d586 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -341,7 +341,7 @@ fn add_port_to_hostname(destination_str: &str) -> FedDest { } /// Returns: actual_destination, host header -/// Implemented according to the specification at https://matrix.org/docs/spec/server_server/r0.1.4#resolving-server-names +/// Implemented according to the specification at /// Numbers in comments below refer to bullet points in linked section of specification async fn find_actual_destination(destination: &'_ ServerName) -> (FedDest, FedDest) { debug!("Finding actual destination for {destination}"); diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index b22f8ed4..64958fc7 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -50,7 +50,7 @@ enum AdminCommand { /// Registering a new bridge using the ID of an existing bridge will replace /// the old one. /// - /// [commandbody] + /// [commandbody]() /// # ``` /// # yaml content here /// # ``` @@ -96,7 +96,7 @@ enum AdminCommand { /// Removing a mass amount of users from a room may cause a significant amount of leave events. /// The time to leave rooms may depend significantly on joined rooms and servers. /// - /// [commandbody] + /// [commandbody]() /// # ``` /// # User list here /// # ``` @@ -121,7 +121,7 @@ enum AdminCommand { /// The PDU event is only checked for validity and is not added to the /// database. /// - /// [commandbody] + /// [commandbody]() /// # ``` /// # PDU json content here /// # ``` @@ -165,14 +165,14 @@ enum AdminCommand { EnableRoom { room_id: Box }, /// Verify json signatures - /// [commandbody] + /// [commandbody]() /// # ``` /// # json here /// # ``` SignJson, /// Verify json signatures - /// [commandbody] + /// [commandbody]() /// # ``` /// # json here /// # ``` @@ -858,12 +858,15 @@ impl Service { .expect("Regex compilation should not fail"); let text = re.replace_all(&text, "$1: $4"); - // Look for a `[commandbody]` tag. If it exists, use all lines below it that + // Look for a `[commandbody]()` tag. If it exists, use all lines below it that // start with a `#` in the USAGE section. let mut text_lines: Vec<&str> = text.lines().collect(); let mut command_body = String::new(); - if let Some(line_index) = text_lines.iter().position(|line| *line == "[commandbody]") { + if let Some(line_index) = text_lines + .iter() + .position(|line| *line == "[commandbody]()") + { text_lines.remove(line_index); while text_lines From e8ac881b2f38a8de776f1638704ed91b05cdf18c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 20 Dec 2023 15:29:09 -0800 Subject: [PATCH 027/175] add an engage file See for info. --- engage.toml | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 2 ++ 2 files changed, 66 insertions(+) create mode 100644 engage.toml diff --git a/engage.toml b/engage.toml new file mode 100644 index 00000000..3e8884eb --- /dev/null +++ b/engage.toml @@ -0,0 +1,64 @@ +interpreter = ["bash", "-euo", "pipefail", "-c"] + +[[task]] +name = "engage" +group = "versions" +script = "engage --version" + +[[task]] +name = "rustc" +group = "versions" +script = "rustc --version" + +[[task]] +name = "cargo" +group = "versions" +script = "cargo --version" + +[[task]] +name = "cargo-fmt" +group = "versions" +script = "cargo fmt --version" + +[[task]] +name = "rustdoc" +group = "versions" +script = "rustdoc --version" + +[[task]] +name = "cargo-clippy" +group = "versions" +script = "cargo clippy -- --version" + +[[task]] +name = "cargo-fmt" +group = "lints" +script = "cargo fmt --check -- --color=always" + +[[task]] +name = "cargo-doc" +group = "lints" +script = """ +RUSTDOCFLAGS="-D warnings" cargo doc \ + --workspace \ + --no-deps \ + --document-private-items \ + --color always +""" + +[[task]] +name = "cargo-clippy" +group = "lints" +script = "cargo clippy --workspace --all-targets --color=always -- -D warnings" + +[[task]] +name = "cargo" +group = "tests" +script = """ +cargo test \ + --workspace \ + --all-targets \ + --color=always \ + -- \ + --color=always +""" diff --git a/flake.nix b/flake.nix index eb3a31cb..c1eee4a6 100644 --- a/flake.nix +++ b/flake.nix @@ -82,6 +82,8 @@ rust-src rustc rustfmt + ]) ++ (with pkgs; [ + engage ]); }; From 6f052fff985c0cd559fff32c11fd32445b8110ed Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 23 Dec 2023 21:12:42 -0800 Subject: [PATCH 028/175] improve nix flake Also fix the comment in `Cargo.toml` about the rust-version stuff. --- Cargo.toml | 8 +++---- flake.nix | 67 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6cc66508..81661f0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,10 +9,10 @@ readme = "README.md" version = "0.7.0-alpha" edition = "2021" -# When changing this, make sure to update the `flake.lock` file by running -# `nix flake update`. If you don't have Nix installed or otherwise don't know -# how to do this, ping `@charles:computer.surgery` or `@dusk:gaze.systems` in -# the matrix room. +# When changing this, make sure to update the hash near the text "THE +# rust-version HASH" in `flake.nix`. If you don't have Nix installed or +# otherwise don't know how to do this, ping `@charles:computer.surgery` or +# `@dusk:gaze.systems` in the matrix room. rust-version = "1.70.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.nix b/flake.nix index c1eee4a6..ed545d7c 100644 --- a/flake.nix +++ b/flake.nix @@ -43,53 +43,64 @@ sha256 = "sha256-gdYqng0y9iHYzYPAdkC/ka3DRny3La/S5G8ASj0Ayyc="; }; - # The system's RocksDB - ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; + mkToolchain = fenix.packages.${system}.combine; + + buildToolchain = mkToolchain (with toolchain; [ + cargo + rustc + ]); + + devToolchain = mkToolchain (with toolchain; [ + cargo + clippy + rust-src + rustc + + # Always use nightly rustfmt because most of its options are unstable + fenix.packages.${system}.latest.rustfmt + ]); + + builder = + ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; - # Shared between the package and the devShell nativeBuildInputs = (with pkgs.rustPlatform; [ bindgenHook ]); - builder = - ((crane.mkLib pkgs).overrideToolchain toolchain.toolchain).buildPackage; + env = { + ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; + ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; + }; in { packages.default = builder { src = ./.; + # This is redundant with CI + doCheck = false; + inherit - stdenv + env nativeBuildInputs - ROCKSDB_INCLUDE_DIR - ROCKSDB_LIB_DIR; + stdenv; + + meta.mainProgram = cargoToml.package.name; }; devShells.default = (pkgs.mkShell.override { inherit stdenv; }) { - # Rust Analyzer needs to be able to find the path to default crate - # sources, and it can read this environment variable to do so - RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library"; - - inherit - ROCKSDB_INCLUDE_DIR - ROCKSDB_LIB_DIR; + env = env // { + # Rust Analyzer needs to be able to find the path to default crate + # sources, and it can read this environment variable to do so. The + # `rust-src` component is required in order for this to work. + RUST_SRC_PATH = "${devToolchain}/lib/rustlib/src/rust/library"; + }; # Development tools - nativeBuildInputs = nativeBuildInputs ++ (with toolchain; [ - cargo - clippy - rust-src - rustc - rustfmt - ]) ++ (with pkgs; [ + nativeBuildInputs = nativeBuildInputs ++ [ + devToolchain + ] ++ (with pkgs; [ engage ]); }; - - checks = { - packagesDefault = self.packages.${system}.default; - devShellsDefault = self.devShells.${system}.default; - }; }); } From 25ceb5ebd8e42f24020cac01ca5c29a1b1cb2b7a Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 11:22:51 -0800 Subject: [PATCH 029/175] remove commented out ci step If you want it back, just look at the git history. --- .gitlab-ci.yml | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f5ab4246..bacc7fd8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,6 @@ stages: - build - build docker image - test - - upload artifacts variables: # Make GitLab CI go fast: @@ -208,31 +207,6 @@ test:dockerlint: - if: '$CI_COMMIT_REF_NAME == "master"' - if: '$CI_COMMIT_REF_NAME == "next"' -# --------------------------------------------------------------------- # -# Store binaries as package so they have download urls # -# --------------------------------------------------------------------- # - -# DISABLED FOR NOW, NEEDS TO BE FIXED AT A LATER TIME: - -#publish:package: -# stage: "upload artifacts" -# needs: -# - "docker:tags" -# rules: -# - if: "$CI_COMMIT_TAG" -# image: curlimages/curl:latest -# tags: ["docker"] -# variables: -# GIT_STRATEGY: "none" # Don't need a clean copy of the code, we just operate on artifacts -# script: -# - 'BASE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/conduit-${CI_COMMIT_REF_SLUG}/build-${CI_PIPELINE_ID}"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_amd64/conduit "${BASE_URL}/conduit-x86_64-unknown-linux-gnu"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_arm_v7/conduit "${BASE_URL}/conduit-armv7-unknown-linux-gnu"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_arm64/conduit "${BASE_URL}/conduit-aarch64-unknown-linux-gnu"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_amd64/conduit.deb "${BASE_URL}/conduit-x86_64-unknown-linux-gnu.deb"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_arm_v7/conduit.deb "${BASE_URL}/conduit-armv7-unknown-linux-gnu.deb"' -# - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build-output/linux_arm64/conduit.deb "${BASE_URL}/conduit-aarch64-unknown-linux-gnu.deb"' - # Avoid duplicate pipelines # See: https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines workflow: From 9d592d60d2d0f62fea7eec9db0cfb044e6354c24 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 11:23:41 -0800 Subject: [PATCH 030/175] remove dockerlint step because it does nothing It's configured to let the pipeline pass even if there are warnings or errors, i.e. it's pointless. --- .gitlab-ci.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bacc7fd8..5393367a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -174,39 +174,6 @@ test:audit: reports: sast: gl-sast-report.json -test:dockerlint: - stage: "test" - needs: [] - image: "ghcr.io/hadolint/hadolint@sha256:6c4b7c23f96339489dd35f21a711996d7ce63047467a9a562287748a03ad5242" # 2.8.0-alpine - interruptible: true - script: - - hadolint --version - # First pass: Print for CI log: - - > - hadolint - --no-fail --verbose - ./Dockerfile - # Then output the results into a json for GitLab to pretty-print this in the MR: - - > - hadolint - --format gitlab_codeclimate - --failure-threshold error - ./Dockerfile > dockerlint.json - artifacts: - when: always - reports: - codequality: dockerlint.json - paths: - - dockerlint.json - rules: - - if: '$CI_COMMIT_REF_NAME != "master"' - changes: - - docker/*Dockerfile - - Dockerfile - - .gitlab-ci.yml - - if: '$CI_COMMIT_REF_NAME == "master"' - - if: '$CI_COMMIT_REF_NAME == "next"' - # Avoid duplicate pipelines # See: https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines workflow: From ffd03a256b3ff497957dd15729fe02ac4b79f0c8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 11:35:28 -0800 Subject: [PATCH 031/175] remove workflow rules I don't think these are actually necessary? At least in my own testing, I haven't seen duplicate pipelines for a single commit when converting from just a branch to a merge request. --- .gitlab-ci.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5393367a..0722c141 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -173,13 +173,3 @@ test:audit: when: always reports: sast: gl-sast-report.json - -# Avoid duplicate pipelines -# See: https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines -workflow: - rules: - - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - - if: "$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS" - when: never - - if: "$CI_COMMIT_BRANCH" - - if: "$CI_COMMIT_TAG" From 7e66d2e2c062e28f2bf16668fb41e53699dee56c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 11:36:51 -0800 Subject: [PATCH 032/175] use nix and engage to manage ci --- .gitignore | 3 + .gitlab-ci.yml | 188 ++++++------------------------------------------- 2 files changed, 26 insertions(+), 165 deletions(-) diff --git a/.gitignore b/.gitignore index 1b5d37b8..a34d70ad 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,6 @@ cached_target # Direnv cache /.direnv + +# Gitlab CI cache +/.gitlab-ci.d diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0722c141..889cf26a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,175 +1,33 @@ stages: - - build - - build docker image - - test + - ci variables: - # Make GitLab CI go fast: - GIT_SUBMODULE_STRATEGY: recursive - FF_USE_FASTZIP: 1 - CACHE_COMPRESSION_LEVEL: fastest + # Makes some things print in color + TERM: ansi -# --------------------------------------------------------------------- # -# Create and publish docker image # -# --------------------------------------------------------------------- # +before_script: + # Enable nix-command and flakes + - echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf -.docker-shared-settings: - stage: "build docker image" - needs: [] - tags: [ "docker" ] - variables: - # Docker in Docker: - DOCKER_BUILDKIT: 1 - image: - name: docker.io/docker - services: - - name: docker.io/docker:dind - alias: docker - script: - - apk add openssh-client - - eval $(ssh-agent -s) - - mkdir -p ~/.ssh && chmod 700 ~/.ssh - - printf "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config - - sh .gitlab/setup-buildx-remote-builders.sh - # Authorize against this project's own image registry: - - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - # Build multiplatform image and push to temporary tag: - - > - docker buildx build - --platform "linux/arm/v7,linux/arm64,linux/amd64" - --pull - --tag "$CI_REGISTRY_IMAGE/temporary-ci-images:$CI_JOB_ID" - --push - --provenance=false - --file "Dockerfile" . - # Build multiplatform image to deb stage and extract their .deb files: - - > - docker buildx build - --platform "linux/arm/v7,linux/arm64,linux/amd64" - --target "packager-result" - --output="type=local,dest=/tmp/build-output" - --provenance=false - --file "Dockerfile" . - # Build multiplatform image to binary stage and extract their binaries: - - > - docker buildx build - --platform "linux/arm/v7,linux/arm64,linux/amd64" - --target "builder-result" - --output="type=local,dest=/tmp/build-output" - --provenance=false - --file "Dockerfile" . - # Copy to GitLab container registry: - - > - docker buildx imagetools create - --tag "$CI_REGISTRY_IMAGE/$TAG" - --tag "$CI_REGISTRY_IMAGE/$TAG-bullseye" - --tag "$CI_REGISTRY_IMAGE/$TAG-commit-$CI_COMMIT_SHORT_SHA" - "$CI_REGISTRY_IMAGE/temporary-ci-images:$CI_JOB_ID" - # if DockerHub credentials exist, also copy to dockerhub: - - if [ -n "${DOCKER_HUB}" ]; then docker login -u "$DOCKER_HUB_USER" -p "$DOCKER_HUB_PASSWORD" "$DOCKER_HUB"; fi - - > - if [ -n "${DOCKER_HUB}" ]; then - docker buildx imagetools create - --tag "$DOCKER_HUB_IMAGE/$TAG" - --tag "$DOCKER_HUB_IMAGE/$TAG-bullseye" - --tag "$DOCKER_HUB_IMAGE/$TAG-commit-$CI_COMMIT_SHORT_SHA" - "$CI_REGISTRY_IMAGE/temporary-ci-images:$CI_JOB_ID" - ; fi - - mv /tmp/build-output ./ - artifacts: - paths: - - "./build-output/" - -docker:next: - extends: .docker-shared-settings - rules: - - if: '$BUILD_SERVER_SSH_PRIVATE_KEY && $CI_COMMIT_BRANCH == "next"' - variables: - TAG: "matrix-conduit:next" - -docker:master: - extends: .docker-shared-settings - rules: - - if: '$BUILD_SERVER_SSH_PRIVATE_KEY && $CI_COMMIT_BRANCH == "master"' - variables: - TAG: "matrix-conduit:latest" - -docker:tags: - extends: .docker-shared-settings - rules: - - if: "$BUILD_SERVER_SSH_PRIVATE_KEY && $CI_COMMIT_TAG" - variables: - TAG: "matrix-conduit:$CI_COMMIT_TAG" - - -docker build debugging: - extends: .docker-shared-settings - rules: - - if: "$CI_MERGE_REQUEST_TITLE =~ /.*[Dd]ocker.*/" - variables: - TAG: "matrix-conduit-docker-tests:latest" - -# --------------------------------------------------------------------- # -# Run tests # -# --------------------------------------------------------------------- # + # Add nix-community binary cache + - echo "extra-substituters = https://nix-community.cachix.org" >> /etc/nix/nix.conf + - echo "extra-trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" >> /etc/nix/nix.conf -cargo check: - stage: test - image: docker.io/rust:1.70.0-bullseye - needs: [] - interruptible: true - before_script: - - "rustup show && rustc --version && cargo --version" # Print version info for debugging - - apt-get update && apt-get -y --no-install-recommends install libclang-dev # dependency for rocksdb - script: - - cargo check - - -.test-shared-settings: - stage: "test" - needs: [] - image: "registry.gitlab.com/jfowl/conduit-containers/rust-with-tools:latest" - tags: ["docker"] - variables: - CARGO_INCREMENTAL: "false" # https://matklad.github.io/2021/09/04/fast-rust-builds.html#ci-workflow - interruptible: true - -test:cargo: - extends: .test-shared-settings - before_script: - - apt-get update && apt-get -y --no-install-recommends install libclang-dev # dependency for rocksdb - script: - - rustc --version && cargo --version # Print version info for debugging - - "cargo test --color always --workspace --verbose --locked --no-fail-fast" + # Install direnv and nix-direnv + - nix-env -iA nixpkgs.direnv nixpkgs.nix-direnv -test:clippy: - extends: .test-shared-settings - allow_failure: true - before_script: - - rustup component add clippy - - apt-get update && apt-get -y --no-install-recommends install libclang-dev # dependency for rocksdb - script: - - rustc --version && cargo --version # Print version info for debugging - - "cargo clippy --color always --verbose --message-format=json | gitlab-report -p clippy > $CI_PROJECT_DIR/gl-code-quality-report.json" - artifacts: - when: always - reports: - codequality: gl-code-quality-report.json + # Allow .envrc + - direnv allow -test:format: - extends: .test-shared-settings - before_script: - - rustup component add rustfmt - script: - - cargo fmt --all -- --check + # Set CARGO_HOME to a cacheable path + - export CARGO_HOME="$(git rev-parse --show-toplevel)/.gitlab-ci.d/cargo" -test:audit: - extends: .test-shared-settings - allow_failure: true +ci: + stage: ci + image: nixos/nix:2.19.2 script: - - cargo audit --color always || true - - cargo audit --stale --json | gitlab-report -p audit > gl-sast-report.json - artifacts: - when: always - reports: - sast: gl-sast-report.json + - direnv exec . engage + cache: + paths: + - target + - .gitlab-ci.d From f8bdfd82b02dbbd46cdc19f2c862378b127b2b0d Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 12:14:03 -0800 Subject: [PATCH 033/175] update flake.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'crane': 'github:ipetkov/crane/8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e' (2023-07-07) → 'github:ipetkov/crane/742170d82cd65c925dcddc5c3d6185699fbbad08' (2024-01-18) • Removed input 'crane/flake-compat' • Removed input 'crane/flake-utils' • Removed input 'crane/rust-overlay' • Removed input 'crane/rust-overlay/flake-utils' • Removed input 'crane/rust-overlay/nixpkgs' • Updated input 'fenix': 'github:nix-community/fenix/39096fe3f379036ff4a5fa198950b8e79defe939' (2023-07-16) → 'github:nix-community/fenix/e132ea0eb0c799a2109a91688e499d7bf4962801' (2024-01-18) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/996e054f1eb1dbfc8455ecabff0f6ff22ba7f7c8' (2023-07-15) → 'github:rust-lang/rust-analyzer/9d9b34354d2f13e33568c9c55b226dd014a146a0' (2024-01-17) • Updated input 'flake-utils': 'github:numtide/flake-utils/919d646de7be200f3bf08cb76ae1f09402b6f9b4' (2023-07-11) → 'github:numtide/flake-utils/1ef2e671c3b0c19053962c07dbda38332dcebf26' (2024-01-15) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/8acef304efe70152463a6399f73e636bcc363813' (2023-07-15) → 'github:NixOS/nixpkgs/842d9d80cfd4560648c785f8a4e6f3b096790e19' (2024-01-17) --- flake.lock | 78 +++++++++++------------------------------------------- flake.nix | 1 - 2 files changed, 16 insertions(+), 63 deletions(-) diff --git a/flake.lock b/flake.lock index 00655252..7f361dd5 100644 --- a/flake.lock +++ b/flake.lock @@ -2,21 +2,16 @@ "nodes": { "crane": { "inputs": { - "flake-compat": "flake-compat", - "flake-utils": [ - "flake-utils" - ], "nixpkgs": [ "nixpkgs" - ], - "rust-overlay": "rust-overlay" + ] }, "locked": { - "lastModified": 1688772518, - "narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=", + "lastModified": 1705597458, + "narHash": "sha256-vJ8Ib9ruxbaBxGEcA0d7dHqxpc6Z+SGR2XIxVeSMuLM=", "owner": "ipetkov", "repo": "crane", - "rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e", + "rev": "742170d82cd65c925dcddc5c3d6185699fbbad08", "type": "github" }, "original": { @@ -33,11 +28,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1689488573, - "narHash": "sha256-diVASflKCCryTYv0djvMnP2444mFsIG0ge5pa7ahauQ=", + "lastModified": 1705559032, + "narHash": "sha256-Cb+Jd1+Gz4Wi+8elPnUIHnqQmE1qjDRZ+PsJaPaAffY=", "owner": "nix-community", "repo": "fenix", - "rev": "39096fe3f379036ff4a5fa198950b8e79defe939", + "rev": "e132ea0eb0c799a2109a91688e499d7bf4962801", "type": "github" }, "original": { @@ -46,32 +41,16 @@ "type": "github" } }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", "owner": "numtide", "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", "type": "github" }, "original": { @@ -82,11 +61,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689444953, - "narHash": "sha256-0o56bfb2LC38wrinPdCGLDScd77LVcr7CrH1zK7qvDg=", + "lastModified": 1705496572, + "narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8acef304efe70152463a6399f73e636bcc363813", + "rev": "842d9d80cfd4560648c785f8a4e6f3b096790e19", "type": "github" }, "original": { @@ -107,11 +86,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1689441253, - "narHash": "sha256-4MSDZaFI4DOfsLIZYPMBl0snzWhX1/OqR/QHir382CY=", + "lastModified": 1705523001, + "narHash": "sha256-TWq5vJ6m+9HGSDMsQAmz1TMegMi79R3TTyKjnPWsQp8=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "996e054f1eb1dbfc8455ecabff0f6ff22ba7f7c8", + "rev": "9d9b34354d2f13e33568c9c55b226dd014a146a0", "type": "github" }, "original": { @@ -121,31 +100,6 @@ "type": "github" } }, - "rust-overlay": { - "inputs": { - "flake-utils": [ - "crane", - "flake-utils" - ], - "nixpkgs": [ - "crane", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1688351637, - "narHash": "sha256-CLTufJ29VxNOIZ8UTg0lepsn3X03AmopmaLTTeHDCL4=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "f9b92316727af9e6c7fee4a761242f7f46880329", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index ed545d7c..65cfc301 100644 --- a/flake.nix +++ b/flake.nix @@ -10,7 +10,6 @@ crane = { url = "github:ipetkov/crane"; inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-utils.follows = "flake-utils"; }; }; From 02781e4f9b494baf9cd238b6614f217c9474c3e2 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 13:05:55 -0800 Subject: [PATCH 034/175] use nix-filter to filter sources This prevents nix from rebuilding conduit when files that don't actually effect the build are changed. --- flake.lock | 16 ++++++++++++++++ flake.nix | 11 ++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 7f361dd5..128539bb 100644 --- a/flake.lock +++ b/flake.lock @@ -59,6 +59,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1705332318, + "narHash": "sha256-kcw1yFeJe9N4PjQji9ZeX47jg0p9A0DuU4djKvg1a7I=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "3449dc925982ad46246cfc36469baf66e1b64f17", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1705496572, @@ -80,6 +95,7 @@ "crane": "crane", "fenix": "fenix", "flake-utils": "flake-utils", + "nix-filter": "nix-filter", "nixpkgs": "nixpkgs" } }, diff --git a/flake.nix b/flake.nix index 65cfc301..62ba8289 100644 --- a/flake.nix +++ b/flake.nix @@ -2,6 +2,7 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; + nix-filter.url = "github:numtide/nix-filter"; fenix = { url = "github:nix-community/fenix"; @@ -17,6 +18,7 @@ { self , nixpkgs , flake-utils + , nix-filter , fenix , crane @@ -73,7 +75,14 @@ in { packages.default = builder { - src = ./.; + src = nix-filter { + root = ./.; + include = [ + "src" + "Cargo.toml" + "Cargo.lock" + ]; + }; # This is redundant with CI doCheck = false; From 4de54db3054c95a7931bb7be7f9f04578d06024f Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 18 Jan 2024 13:31:46 -0800 Subject: [PATCH 035/175] redo docker image and build it in ci --- .gitlab-ci.yml | 13 +++++ Dockerfile | 132 ------------------------------------------------- flake.nix | 20 ++++++++ 3 files changed, 33 insertions(+), 132 deletions(-) delete mode 100644 Dockerfile diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 889cf26a..ac1495fc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,6 @@ stages: - ci + - artifacts variables: # Makes some things print in color @@ -31,3 +32,15 @@ ci: paths: - target - .gitlab-ci.d + +docker: + stage: artifacts + image: nixos/nix:2.19.2 + script: + - nix build .#oci-image + + # Make the output less difficult to find + - cp result docker-image.tar.gz + artifacts: + paths: + - docker-image.tar.gz diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 943f6864..00000000 --- a/Dockerfile +++ /dev/null @@ -1,132 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM docker.io/rust:1.70-bullseye AS base - -FROM base AS builder -WORKDIR /usr/src/conduit - -# Install required packages to build Conduit and it's dependencies -RUN apt-get update && \ - apt-get -y --no-install-recommends install libclang-dev=1:11.0-51+nmu5 - -# == Build dependencies without our own code separately for caching == -# -# Need a fake main.rs since Cargo refuses to build anything otherwise. -# -# See https://github.com/rust-lang/cargo/issues/2644 for a Cargo feature -# request that would allow just dependencies to be compiled, presumably -# regardless of whether source files are available. -RUN mkdir src && touch src/lib.rs && echo 'fn main() {}' > src/main.rs -COPY Cargo.toml Cargo.lock ./ -RUN cargo build --release && rm -r src - -# Copy over actual Conduit sources -COPY src src - -# main.rs and lib.rs need their timestamp updated for this to work correctly since -# otherwise the build with the fake main.rs from above is newer than the -# source files (COPY preserves timestamps). -# -# Builds conduit and places the binary at /usr/src/conduit/target/release/conduit -RUN touch src/main.rs && touch src/lib.rs && cargo build --release - - -# ONLY USEFUL FOR CI: target stage to extract build artifacts -FROM scratch AS builder-result -COPY --from=builder /usr/src/conduit/target/release/conduit /conduit - - - -# --------------------------------------------------------------------------------------------------------------- -# Build cargo-deb, a tool to package up rust binaries into .deb packages for Debian/Ubuntu based systems: -# --------------------------------------------------------------------------------------------------------------- -FROM base AS build-cargo-deb - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - dpkg \ - dpkg-dev \ - liblzma-dev - -RUN cargo install cargo-deb -# => binary is in /usr/local/cargo/bin/cargo-deb - - -# --------------------------------------------------------------------------------------------------------------- -# Package conduit build-result into a .deb package: -# --------------------------------------------------------------------------------------------------------------- -FROM builder AS packager -WORKDIR /usr/src/conduit - -COPY ./LICENSE ./LICENSE -COPY ./README.md ./README.md -COPY debian ./debian -COPY --from=build-cargo-deb /usr/local/cargo/bin/cargo-deb /usr/local/cargo/bin/cargo-deb - -# --no-build makes cargo-deb reuse already compiled project -RUN cargo deb --no-build -# => Package is in /usr/src/conduit/target/debian/__.deb - - -# ONLY USEFUL FOR CI: target stage to extract build artifacts -FROM scratch AS packager-result -COPY --from=packager /usr/src/conduit/target/debian/*.deb /conduit.deb - - -# --------------------------------------------------------------------------------------------------------------- -# Stuff below this line actually ends up in the resulting docker image -# --------------------------------------------------------------------------------------------------------------- -FROM docker.io/debian:bullseye-slim AS runner - -# Standard port on which Conduit launches. -# You still need to map the port when using the docker command or docker-compose. -EXPOSE 6167 - -ARG DEFAULT_DB_PATH=/var/lib/matrix-conduit - -ENV CONDUIT_PORT=6167 \ - CONDUIT_ADDRESS="0.0.0.0" \ - CONDUIT_DATABASE_PATH=${DEFAULT_DB_PATH} \ - CONDUIT_CONFIG='' -# └─> Set no config file to do all configuration with env vars - -# Conduit needs: -# dpkg: to install conduit.deb -# ca-certificates: for https -# iproute2 & wget: for the healthcheck script -RUN apt-get update && apt-get -y --no-install-recommends install \ - dpkg \ - ca-certificates \ - iproute2 \ - wget \ - && rm -rf /var/lib/apt/lists/* - -# Test if Conduit is still alive, uses the same endpoint as Element -COPY ./docker/healthcheck.sh /srv/conduit/healthcheck.sh -HEALTHCHECK --start-period=5s --interval=5s CMD ./healthcheck.sh - -# Install conduit.deb: -COPY --from=packager /usr/src/conduit/target/debian/*.deb /srv/conduit/ -RUN dpkg -i /srv/conduit/*.deb - -# Improve security: Don't run stuff as root, that does not need to run as root -# Most distros also use 1000:1000 for the first real user, so this should resolve volume mounting problems. -ARG USER_ID=1000 -ARG GROUP_ID=1000 -RUN set -x ; \ - groupadd -r -g ${GROUP_ID} conduit ; \ - useradd -l -r -M -d /srv/conduit -o -u ${USER_ID} -g conduit conduit && exit 0 ; exit 1 - -# Create database directory, change ownership of Conduit files to conduit user and group and make the healthcheck executable: -RUN chown -cR conduit:conduit /srv/conduit && \ - chmod +x /srv/conduit/healthcheck.sh && \ - mkdir -p ${DEFAULT_DB_PATH} && \ - chown -cR conduit:conduit ${DEFAULT_DB_PATH} - -# Change user to conduit, no root permissions afterwards: -USER conduit -# Set container home directory -WORKDIR /srv/conduit - -# Run Conduit and print backtraces on panics -ENV RUST_BACKTRACE=1 -ENTRYPOINT [ "/usr/sbin/matrix-conduit" ] diff --git a/flake.nix b/flake.nix index 62ba8289..b4a32d0a 100644 --- a/flake.nix +++ b/flake.nix @@ -95,6 +95,26 @@ meta.mainProgram = cargoToml.package.name; }; + packages.oci-image = + let + package = self.packages.${system}.default; + in + pkgs.dockerTools.buildImage { + name = package.pname; + tag = "latest"; + config = { + # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are + # handled as expected + Entrypoint = [ + "${pkgs.lib.getExe' pkgs.tini "tini"}" + "--" + ]; + Cmd = [ + "${pkgs.lib.getExe package}" + ]; + }; + }; + devShells.default = (pkgs.mkShell.override { inherit stdenv; }) { env = env // { # Rust Analyzer needs to be able to find the path to default crate From 0b7ed5adc9ad17811eb8ef43b6b1e94c5a17d6b1 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Fri, 19 Jan 2024 12:10:23 -0800 Subject: [PATCH 036/175] add debian package building in ci This uses a separate step and docker image, which I'm not a huge fan of. At least I could get this to work for now, but I won't be shocked when it breaks later. I know, I know, fixing this kind of problem is the exact reason I bothered to do this, but I was really struggling to do better here. Maybe I can take a second pass at this later. Also, this explicitly names the caches, because without this, various things related to linking will break. --- .gitlab-ci.yml | 30 +++++++++++++++++++++++++----- Cargo.toml | 2 ++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac1495fc..48fe6244 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,17 +8,17 @@ variables: before_script: # Enable nix-command and flakes - - echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf + - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi # Add nix-community binary cache - - echo "extra-substituters = https://nix-community.cachix.org" >> /etc/nix/nix.conf - - echo "extra-trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" >> /etc/nix/nix.conf + - if command -v nix > /dev/null; then echo "extra-substituters = https://nix-community.cachix.org" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" >> /etc/nix/nix.conf; fi # Install direnv and nix-direnv - - nix-env -iA nixpkgs.direnv nixpkgs.nix-direnv + - if command -v nix > /dev/null; then nix-env -iA nixpkgs.direnv nixpkgs.nix-direnv; fi # Allow .envrc - - direnv allow + - if command -v nix > /dev/null; then direnv allow; fi # Set CARGO_HOME to a cacheable path - export CARGO_HOME="$(git rev-parse --show-toplevel)/.gitlab-ci.d/cargo" @@ -29,6 +29,7 @@ ci: script: - direnv exec . engage cache: + key: nix paths: - target - .gitlab-ci.d @@ -44,3 +45,22 @@ docker: artifacts: paths: - docker-image.tar.gz + +debian: + stage: artifacts + image: rust:1.70.0 + script: + - apt-get update && apt-get install -y --no-install-recommends libclang-dev + - cargo install cargo-deb + - cargo deb + + # Make the output less difficult to find + - mv target/debian/*.deb . + artifacts: + paths: + - "*.deb" + cache: + key: debian + paths: + - target + - .gitlab-ci.d diff --git a/Cargo.toml b/Cargo.toml index 81661f0b..8c139156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,8 @@ edition = "2021" # rust-version HASH" in `flake.nix`. If you don't have Nix installed or # otherwise don't know how to do this, ping `@charles:computer.surgery` or # `@dusk:gaze.systems` in the matrix room. +# +# Also make sure to update the docker image tags in `.gitlab-ci.yml`. rust-version = "1.70.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 69d0003222e6fcf7abe6305a08aff6a8eba74659 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 2 Aug 2023 01:00:06 +0200 Subject: [PATCH 037/175] Use upstream `reqwest` instead of vendored one This uses the `ClientBuilder::dns_resolver` function that was added in reqwest 0.11.13, instead of the homebrew `ClientBuilder::resolve_fn`. --- Cargo.lock | 84 +++++++++++--------------------------- Cargo.toml | 3 +- src/service/globals/mod.rs | 45 ++++++++++++++++++-- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4bcdc0a..d5e1d161 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,10 +155,10 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "rustls 0.21.2", - "rustls-pemfile 1.0.2", + "rustls", + "rustls-pemfile", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "tower-service", ] @@ -364,6 +364,7 @@ dependencies = [ "futures-util", "hmac", "http", + "hyper", "image", "jsonwebtoken", "lazy_static", @@ -1022,15 +1023,16 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", - "rustls 0.20.8", + "rustls", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls", ] [[package]] @@ -1898,10 +1900,11 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "reqwest" -version = "0.11.9" -source = "git+https://github.com/timokoesters/reqwest?rev=57b7cf4feb921573dfafad7d34b9ac6e44ead0bd#57b7cf4feb921573dfafad7d34b9ac6e44ead0bd" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.13.1", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -1913,25 +1916,26 @@ dependencies = [ "hyper-rustls", "ipnet", "js-sys", - "lazy_static", "log", "mime", + "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.20.8", + "rustls", "rustls-native-certs", - "rustls-pemfile 0.2.1", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls", "tokio-socks", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.7.0", + "winreg 0.10.1", ] [[package]] @@ -2198,18 +2202,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustls" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.21.2" @@ -2229,20 +2221,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.2", + "rustls-pemfile", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" -dependencies = [ - "base64 0.13.1", -] - [[package]] name = "rustls-pemfile" version = "1.0.2" @@ -2756,24 +2739,13 @@ dependencies = [ "syn 2.0.21", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki", -] - [[package]] name = "tokio-rustls" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.2", + "rustls", "tokio", ] @@ -3223,16 +3195,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "weezl" version = "0.1.7" @@ -3407,9 +3369,9 @@ dependencies = [ [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 8c139156..a35cf233 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,8 @@ rand = "0.8.5" # Used to hash passwords rust-argon2 = "1.0.0" # Used to send requests -reqwest = { default-features = false, features = ["rustls-tls-native-roots", "socks"], git = "https://github.com/timokoesters/reqwest", rev = "57b7cf4feb921573dfafad7d34b9ac6e44ead0bd" } +hyper = "0.14.26" +reqwest = { version = "0.11.18", default-features = false, features = ["rustls-tls-native-roots", "socks"] } # Used for conduit::Error type thiserror = "1.0.40" # Used to generate thumbnails for images diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 9bce8a2c..96b2954f 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -8,6 +8,12 @@ use ruma::{ use crate::api::server_server::FedDest; use crate::{services, Config, Error, Result}; +use futures_util::FutureExt; +use hyper::{ + client::connect::dns::{GaiResolver, Name}, + service::Service as HyperService, +}; +use reqwest::dns::{Addrs, Resolve, Resolving}; use ruma::{ api::{ client::sync::sync_events, @@ -17,8 +23,10 @@ use ruma::{ }; use std::{ collections::{BTreeMap, HashMap}, + error::Error as StdError, fs, - future::Future, + future::{self, Future}, + iter, net::{IpAddr, SocketAddr}, path::PathBuf, sync::{ @@ -99,6 +107,35 @@ impl Default for RotationHandler { } } +pub struct Resolver { + inner: GaiResolver, + overrides: Box Option + Send + Sync>, +} + +impl Resolver { + pub fn new(overrides: Box Option + Send + Sync>) -> Resolver { + Resolver { + inner: GaiResolver::new(), + overrides, + } + } +} + +impl Resolve for Resolver { + fn resolve(&self, name: Name) -> Resolving { + if let Some(addr) = (self.overrides)(name.as_str()) { + let once: Box + Send> = Box::new(iter::once(addr)); + return Box::pin(future::ready(Ok(once))); + } + let this = &mut self.inner.clone(); + Box::pin(HyperService::::call(this, name).map(|result| { + result + .map(|addrs| -> Addrs { Box::new(addrs) }) + .map_err(|err| -> Box { Box::new(err) }) + })) + } +} + impl Service { pub fn load(db: &'static dyn Data, config: Config) -> Result { let keypair = db.load_keypair(); @@ -122,12 +159,12 @@ impl Service { let default_client = reqwest_client_builder(&config)?.build()?; let name_override = Arc::clone(&tls_name_override); let federation_client = reqwest_client_builder(&config)? - .resolve_fn(move |domain| { + .dns_resolver(Arc::new(Resolver::new(Box::new(move |domain| { let read_guard = name_override.read().unwrap(); - let (override_name, port) = read_guard.get(&domain)?; + let (override_name, port) = read_guard.get(domain)?; let first_name = override_name.get(0)?; Some(SocketAddr::new(*first_name, *port)) - }) + })))) .build()?; // Supported and stable room versions From fe86d28428a0cae53ac9ca5f5efe7783cb00022c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 15:11:17 -0800 Subject: [PATCH 038/175] move resolver logic into the resolver Honestly not sure why it wasn't done like this before. This code is much less awkward to follow and more compartmentalized. These changes were mainly motivated by a clippy lint triggering on the original code, which then made me wonder if I could get rid of some of the `Box`ing. Turns out I could, and this is the result of that. --- src/service/globals/mod.rs | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 96b2954f..f034415e 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -109,11 +109,11 @@ impl Default for RotationHandler { pub struct Resolver { inner: GaiResolver, - overrides: Box Option + Send + Sync>, + overrides: Arc>, } impl Resolver { - pub fn new(overrides: Box Option + Send + Sync>) -> Resolver { + pub fn new(overrides: Arc>) -> Self { Resolver { inner: GaiResolver::new(), overrides, @@ -123,16 +123,26 @@ impl Resolver { impl Resolve for Resolver { fn resolve(&self, name: Name) -> Resolving { - if let Some(addr) = (self.overrides)(name.as_str()) { - let once: Box + Send> = Box::new(iter::once(addr)); - return Box::pin(future::ready(Ok(once))); - } - let this = &mut self.inner.clone(); - Box::pin(HyperService::::call(this, name).map(|result| { - result - .map(|addrs| -> Addrs { Box::new(addrs) }) - .map_err(|err| -> Box { Box::new(err) }) - })) + self.overrides + .read() + .expect("lock should not be poisoned") + .get(name.as_str()) + .and_then(|(override_name, port)| { + override_name.get(0).map(|first_name| { + let x: Box + Send> = + Box::new(iter::once(SocketAddr::new(*first_name, *port))); + let x: Resolving = Box::pin(future::ready(Ok(x))); + x + }) + }) + .unwrap_or_else(|| { + let this = &mut self.inner.clone(); + Box::pin(HyperService::::call(this, name).map(|result| { + result + .map(|addrs| -> Addrs { Box::new(addrs) }) + .map_err(|err| -> Box { Box::new(err) }) + })) + }) } } @@ -157,14 +167,8 @@ impl Service { .map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes())); let default_client = reqwest_client_builder(&config)?.build()?; - let name_override = Arc::clone(&tls_name_override); let federation_client = reqwest_client_builder(&config)? - .dns_resolver(Arc::new(Resolver::new(Box::new(move |domain| { - let read_guard = name_override.read().unwrap(); - let (override_name, port) = read_guard.get(domain)?; - let first_name = override_name.get(0)?; - Some(SocketAddr::new(*first_name, *port)) - })))) + .dns_resolver(Arc::new(Resolver::new(tls_name_override.clone()))) .build()?; // Supported and stable room versions From f7cc4fb3bb8ec1bfc39ccb89e770c809d5708343 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:24:34 -0800 Subject: [PATCH 039/175] state artifacts' targets and rename artifacts This will make it more obvious what's what and be more internally consistent. --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 48fe6244..53fd73f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,19 +34,19 @@ ci: - target - .gitlab-ci.d -docker: +oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 script: - nix build .#oci-image # Make the output less difficult to find - - cp result docker-image.tar.gz + - cp result oci-image.tar.gz artifacts: paths: - - docker-image.tar.gz + - oci-image.tar.gz -debian: +debian:x86_64-unknown-linux-gnu: stage: artifacts image: rust:1.70.0 script: @@ -55,10 +55,10 @@ debian: - cargo deb # Make the output less difficult to find - - mv target/debian/*.deb . + - mv target/debian/*.deb conduit.deb artifacts: paths: - - "*.deb" + - conduit.deb cache: key: debian paths: From bd2b146d5da633eb3ec80033a317feea87d23c64 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:16:29 -0800 Subject: [PATCH 040/175] add crane binary cache This way we don't need to build e.g. crane-utils every time. --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53fd73f9..deacb811 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,10 @@ before_script: # Enable nix-command and flakes - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi + # Add crane binary cache + - if command -v nix > /dev/null; then echo "extra-substituters = https://crane.cachix.org" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" >> /etc/nix/nix.conf; fi + # Add nix-community binary cache - if command -v nix > /dev/null; then echo "extra-substituters = https://nix-community.cachix.org" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" >> /etc/nix/nix.conf; fi From 6ae776218cc2da4e46fb587bd08b5164b24c41ce Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:20:48 -0800 Subject: [PATCH 041/175] add our own binary cache The machine I'm hosting this on doesn't have incredible upload speeds but it should be good enough? --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index deacb811..746641c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,10 @@ before_script: # Enable nix-command and flakes - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi + # Add our own binary cache + - if command -v nix > /dev/null; then echo "extra-substituters = https://nix.computer.surgery/conduit" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = conduit:ZGAf6P6LhNvnoJJ3Me3PRg7tlLSrPxcQ2RiE5LIppjo=" >> /etc/nix/nix.conf; fi + # Add crane binary cache - if command -v nix > /dev/null; then echo "extra-substituters = https://crane.cachix.org" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" >> /etc/nix/nix.conf; fi From bdc46f63929f19ddc124f0ed4a78885b1514343c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 11:34:46 -0800 Subject: [PATCH 042/175] add script to build and push to binary cache This is even useful for local development, as you can pre-populate the binary cache before running CI (assuming you have the token). Also, it being in a script makes it easier to test. We've added attic as a flake input even though the flake itself doesn't use it so that we can use `--inputs-from .` in Nix commands to reference a locked version of attic. This helps with reproducibility and caching, and to makes it easy to update attic because it's part of the normal flake lifecycle. --- .envrc | 2 + flake.lock | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++-- flake.nix | 2 + 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/.envrc b/.envrc index b9238c3b..403a9bdf 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,5 @@ #!/usr/bin/env bash use flake + +PATH_add bin diff --git a/flake.lock b/flake.lock index 128539bb..acad901c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,6 +1,50 @@ { "nodes": { + "attic": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1705617092, + "narHash": "sha256-n9PK4O4X4S1JkwpkMuYm1wHZYJzRqif8g3RuVIPD+rY=", + "owner": "zhaofengli", + "repo": "attic", + "rev": "fbe252a5c21febbe920c025560cbd63b20e24f3b", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "main", + "repo": "attic", + "type": "github" + } + }, "crane": { + "inputs": { + "nixpkgs": [ + "attic", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1702918879, + "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", + "owner": "ipetkov", + "repo": "crane", + "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -41,7 +85,38 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { "inputs": { "systems": "systems" }, @@ -75,6 +150,38 @@ } }, "nixpkgs": { + "locked": { + "lastModified": 1702539185, + "narHash": "sha256-KnIRG5NMdLIpEkZTnN5zovNYc0hhXjAgv6pfd5Z4c7U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "aa9d4729cbc99dabacb50e3994dcefb3ea0f7447", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1702780907, + "narHash": "sha256-blbrBBXjjZt6OKTcYX1jpe9SRof2P9ZYWPzq22tzXAA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { "locked": { "lastModified": 1705496572, "narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=", @@ -92,11 +199,12 @@ }, "root": { "inputs": { - "crane": "crane", + "attic": "attic", + "crane": "crane_2", "fenix": "fenix", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "nix-filter": "nix-filter", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs_2" } }, "rust-analyzer-src": { diff --git a/flake.nix b/flake.nix index b4a32d0a..51148bad 100644 --- a/flake.nix +++ b/flake.nix @@ -12,6 +12,7 @@ url = "github:ipetkov/crane"; inputs.nixpkgs.follows = "nixpkgs"; }; + attic.url = "github:zhaofengli/attic?ref=main"; }; outputs = @@ -22,6 +23,7 @@ , fenix , crane + , ... }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; From 5cc53c9e14ef5319f2dd8f88aa58d6e966cfdb20 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 11:37:35 -0800 Subject: [PATCH 043/175] push oci image and x86_64-*-gnu build to bin cache This will allow most Nix users to use the `default` package and without having to build from source. And also allows any weirdos to get the OCI image from the Nix binary cache if they want. No idea why that would be desireable though lol --- .gitlab-ci.yml | 8 +++++++- bin/nix-build-and-cache | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100755 bin/nix-build-and-cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 746641c8..199429a5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,13 @@ oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 script: - - nix build .#oci-image + # Push artifacts and build requirements to binary cache + # + # Since the OCI image package is based on the binary package, this has the + # fun side effect of uploading the normal binary too. Conduit users who are + # deploying with Nix can leverage this fact by adding our binary cache to + # their systems. + - ./bin/nix-build-and-cache .#oci-image # Make the output less difficult to find - cp result oci-image.tar.gz diff --git a/bin/nix-build-and-cache b/bin/nix-build-and-cache new file mode 100755 index 00000000..b37ebd85 --- /dev/null +++ b/bin/nix-build-and-cache @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# The first argument must be the desired installable +INSTALLABLE="$1" + +# Build the installable and forward any other arguments too +nix build "$@" + +if [ ! -z ${ATTIC_TOKEN+x} ]; then + +nix run --inputs-from . attic -- login \ + conduit \ + https://nix.computer.surgery/conduit \ + "$ATTIC_TOKEN" + + push_args=( + # Attic and its build dependencies + "$(nix path-info --inputs-from . attic)" + "$(nix path-info --inputs-from . attic --derivation)" + + # The target installable and its build dependencies + "$(nix path-info "$INSTALLABLE" --derivation)" + "$(nix path-info "$INSTALLABLE")" + ) + + nix run --inputs-from . attic -- push conduit "${push_args[@]}" +else + echo "\$ATTIC_TOKEN is unset, skipping uploading to the binary cache" +fi From 249fc7769d14e4b4eb9d7f6abc645972c4fc27b8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:24:04 -0800 Subject: [PATCH 044/175] don't bother with mold For now, at least. I suspect it will make cross compilation more difficult. --- flake.nix | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/flake.nix b/flake.nix index 51148bad..d4be7d9e 100644 --- a/flake.nix +++ b/flake.nix @@ -28,12 +28,6 @@ let pkgs = nixpkgs.legacyPackages.${system}; - # Use mold on Linux - stdenv = if pkgs.stdenv.isLinux then - pkgs.stdenvAdapters.useMoldLinker pkgs.stdenv - else - pkgs.stdenv; - # Nix-accessible `Cargo.toml` cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); @@ -91,8 +85,7 @@ inherit env - nativeBuildInputs - stdenv; + nativeBuildInputs; meta.mainProgram = cargoToml.package.name; }; @@ -117,7 +110,7 @@ }; }; - devShells.default = (pkgs.mkShell.override { inherit stdenv; }) { + devShells.default = pkgs.mkShell { env = env // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The From 9cef03127bcc0e076286721f6f7d5564e0af36c8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 10:45:02 -0800 Subject: [PATCH 045/175] remove `with` for `nativeBuildInputs` It's going to get more involved and that `with` was too specific. --- flake.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index d4be7d9e..15538efd 100644 --- a/flake.nix +++ b/flake.nix @@ -60,9 +60,9 @@ builder = ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; - nativeBuildInputs = (with pkgs.rustPlatform; [ - bindgenHook - ]); + nativeBuildInputs = [ + pkgs.rustPlatform.bindgenHook + ]; env = { ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; From cf4015b8307249ccf3f7c036306a1dc69f0af795 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:25:08 -0800 Subject: [PATCH 046/175] rename pkgs to pkgsHost This will make organizing cross compilation easier. --- flake.nix | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.nix b/flake.nix index 15538efd..039bf0b5 100644 --- a/flake.nix +++ b/flake.nix @@ -26,7 +26,7 @@ , ... }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; + pkgsHost = nixpkgs.legacyPackages.${system}; # Nix-accessible `Cargo.toml` cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); @@ -58,15 +58,15 @@ ]); builder = - ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; + ((crane.mkLib pkgsHost).overrideToolchain buildToolchain).buildPackage; nativeBuildInputs = [ - pkgs.rustPlatform.bindgenHook + pkgsHost.rustPlatform.bindgenHook ]; env = { - ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; + ROCKSDB_INCLUDE_DIR = "${pkgsHost.rocksdb}/include"; + ROCKSDB_LIB_DIR = "${pkgsHost.rocksdb}/lib"; }; in { @@ -94,23 +94,23 @@ let package = self.packages.${system}.default; in - pkgs.dockerTools.buildImage { + pkgsHost.dockerTools.buildImage { name = package.pname; tag = "latest"; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are # handled as expected Entrypoint = [ - "${pkgs.lib.getExe' pkgs.tini "tini"}" + "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" "--" ]; Cmd = [ - "${pkgs.lib.getExe package}" + "${pkgsHost.lib.getExe package}" ]; }; }; - devShells.default = pkgs.mkShell { + devShells.default = pkgsHost.mkShell { env = env // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The @@ -121,7 +121,7 @@ # Development tools nativeBuildInputs = nativeBuildInputs ++ [ devToolchain - ] ++ (with pkgs; [ + ] ++ (with pkgsHost; [ engage ]); }; From 692a31620d747a9a640cb3464221c3024c546e09 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:26:16 -0800 Subject: [PATCH 047/175] make let bindings take pkgs as an argument Again, will make cross compilation easier to set up. --- flake.nix | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/flake.nix b/flake.nix index 039bf0b5..76f8bb25 100644 --- a/flake.nix +++ b/flake.nix @@ -57,20 +57,20 @@ fenix.packages.${system}.latest.rustfmt ]); - builder = - ((crane.mkLib pkgsHost).overrideToolchain buildToolchain).buildPackage; + builder = pkgs: + ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; - nativeBuildInputs = [ - pkgsHost.rustPlatform.bindgenHook + nativeBuildInputs = pkgs: [ + pkgs.rustPlatform.bindgenHook ]; - env = { - ROCKSDB_INCLUDE_DIR = "${pkgsHost.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgsHost.rocksdb}/lib"; + env = pkgs: { + ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; + ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; }; in { - packages.default = builder { + packages.default = builder pkgsHost { src = nix-filter { root = ./.; include = [ @@ -83,9 +83,8 @@ # This is redundant with CI doCheck = false; - inherit - env - nativeBuildInputs; + env = env pkgsHost; + nativeBuildInputs = nativeBuildInputs pkgsHost; meta.mainProgram = cargoToml.package.name; }; @@ -111,7 +110,7 @@ }; devShells.default = pkgsHost.mkShell { - env = env // { + env = env pkgsHost // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The # `rust-src` component is required in order for this to work. @@ -119,7 +118,7 @@ }; # Development tools - nativeBuildInputs = nativeBuildInputs ++ [ + nativeBuildInputs = nativeBuildInputs pkgsHost ++ [ devToolchain ] ++ (with pkgsHost; [ engage From 52954f7a11e795211bbecc54df456724773251b6 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:48:58 -0800 Subject: [PATCH 048/175] use fromToolchainFile I *think* this will make it easier to pull in extra rustc targets. --- .gitlab-ci.yml | 1 + Cargo.toml | 7 +------ flake.nix | 36 ++++++++++++------------------------ rust-toolchain.toml | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 199429a5..1f6dab3a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -62,6 +62,7 @@ oci-image:x86_64-unknown-linux-gnu: debian:x86_64-unknown-linux-gnu: stage: artifacts + # See also `rust-toolchain.toml` image: rust:1.70.0 script: - apt-get update && apt-get install -y --no-install-recommends libclang-dev diff --git a/Cargo.toml b/Cargo.toml index a35cf233..40919599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,7 @@ readme = "README.md" version = "0.7.0-alpha" edition = "2021" -# When changing this, make sure to update the hash near the text "THE -# rust-version HASH" in `flake.nix`. If you don't have Nix installed or -# otherwise don't know how to do this, ping `@charles:computer.surgery` or -# `@dusk:gaze.systems` in the matrix room. -# -# Also make sure to update the docker image tags in `.gitlab-ci.yml`. +# See also `rust-toolchain.toml` rust-version = "1.70.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.nix b/flake.nix index 76f8bb25..89a4eb43 100644 --- a/flake.nix +++ b/flake.nix @@ -32,33 +32,15 @@ cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); # The Rust toolchain to use - toolchain = fenix.packages.${system}.toolchainOf { - # Use the Rust version defined in `Cargo.toml` - channel = cargoToml.package.rust-version; + toolchain = fenix.packages.${system}.fromToolchainFile { + file = ./rust-toolchain.toml; - # THE rust-version HASH + # See also `rust-toolchain.toml` sha256 = "sha256-gdYqng0y9iHYzYPAdkC/ka3DRny3La/S5G8ASj0Ayyc="; }; - mkToolchain = fenix.packages.${system}.combine; - - buildToolchain = mkToolchain (with toolchain; [ - cargo - rustc - ]); - - devToolchain = mkToolchain (with toolchain; [ - cargo - clippy - rust-src - rustc - - # Always use nightly rustfmt because most of its options are unstable - fenix.packages.${system}.latest.rustfmt - ]); - builder = pkgs: - ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; + ((crane.mkLib pkgs).overrideToolchain toolchain).buildPackage; nativeBuildInputs = pkgs: [ pkgs.rustPlatform.bindgenHook @@ -114,12 +96,18 @@ # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The # `rust-src` component is required in order for this to work. - RUST_SRC_PATH = "${devToolchain}/lib/rustlib/src/rust/library"; + RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; }; # Development tools nativeBuildInputs = nativeBuildInputs pkgsHost ++ [ - devToolchain + # Always use nightly rustfmt because most of its options are unstable + # + # This needs to come before `toolchain` in this list, otherwise + # `$PATH` will have stable rustfmt instead. + fenix.packages.${system}.latest.rustfmt + + toolchain ] ++ (with pkgsHost; [ engage ]); diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..cc3e2545 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,17 @@ +# This is the authoritiative configuration of this project's Rust toolchain. +# +# Other files that need upkeep when this changes: +# +# * `.gitlab-ci.yml` +# * `Cargo.toml` +# * `flake.nix` +# +# Search in those files for `rust-toolchain.toml` to find the relevant places. +# If you're having trouble making the relevant changes, bug a maintainer. + +[toolchain] +channel = "1.70.0" +components = [ + # For rust-analyzer + "rust-src", +] From 3ac9be5a789f34cd980ad68b6a3824fc3ba3c7a0 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:10:23 -0800 Subject: [PATCH 049/175] add x86_64-unknown-linux-gnu This is probably the most common target and usually doesn't involve cross compilation. --- rust-toolchain.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index cc3e2545..8d153e8b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -15,3 +15,6 @@ components = [ # For rust-analyzer "rust-src", ] +targets = [ + "x86_64-unknown-linux-gnu", +] From 67d280dd2e71dca6e412b94ce63d328f408f3490 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:56:00 -0800 Subject: [PATCH 050/175] factor package expression into a function We'll need to call it repeatedly to make packages for cross. --- flake.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 89a4eb43..a86422c3 100644 --- a/flake.nix +++ b/flake.nix @@ -50,9 +50,8 @@ ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; }; - in - { - packages.default = builder pkgsHost { + + package = pkgs: builder pkgs { src = nix-filter { root = ./.; include = [ @@ -65,11 +64,14 @@ # This is redundant with CI doCheck = false; - env = env pkgsHost; - nativeBuildInputs = nativeBuildInputs pkgsHost; + env = env pkgs; + nativeBuildInputs = nativeBuildInputs pkgs; meta.mainProgram = cargoToml.package.name; }; + in + { + packages.default = package pkgsHost; packages.oci-image = let From d29591d47d6de9c82539f18994a268f5215a4ee6 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 23:07:30 -0800 Subject: [PATCH 051/175] group packages in attrset literal This will make generating packages for cross possible. --- flake.nix | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/flake.nix b/flake.nix index a86422c3..9d73ba9b 100644 --- a/flake.nix +++ b/flake.nix @@ -71,25 +71,27 @@ }; in { - packages.default = package pkgsHost; - - packages.oci-image = - let - package = self.packages.${system}.default; - in - pkgsHost.dockerTools.buildImage { - name = package.pname; - tag = "latest"; - config = { - # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are - # handled as expected - Entrypoint = [ - "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" - "--" - ]; - Cmd = [ - "${pkgsHost.lib.getExe package}" - ]; + packages = { + default = package pkgsHost; + + oci-image = + let + package = self.packages.${system}.default; + in + pkgsHost.dockerTools.buildImage { + name = package.pname; + tag = "latest"; + config = { + # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) + # are handled as expected + Entrypoint = [ + "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" + "--" + ]; + Cmd = [ + "${pkgsHost.lib.getExe package}" + ]; + }; }; }; From 3a3cafe912b16d4ce786bedd37247ea200f125b9 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 21:29:03 -0800 Subject: [PATCH 052/175] preempt cross problems by using my crane fork I imagine this will get fixed/merged upstream in the near future. --- flake.lock | 11 ++++++----- flake.nix | 5 ++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index acad901c..4508f7ce 100644 --- a/flake.lock +++ b/flake.lock @@ -51,15 +51,16 @@ ] }, "locked": { - "lastModified": 1705597458, - "narHash": "sha256-vJ8Ib9ruxbaBxGEcA0d7dHqxpc6Z+SGR2XIxVeSMuLM=", - "owner": "ipetkov", + "lastModified": 1706070683, + "narHash": "sha256-iQoXIFviH5QbSKDkWyFJKKUtTcSiCvl1tW18ax+pKfI=", + "owner": "CobaltCause", "repo": "crane", - "rev": "742170d82cd65c925dcddc5c3d6185699fbbad08", + "rev": "8060686afabc5b042e8982200cb2cc3fd22cf416", "type": "github" }, "original": { - "owner": "ipetkov", + "owner": "CobaltCause", + "ref": "crimes-for-cross", "repo": "crane", "type": "github" } diff --git a/flake.nix b/flake.nix index 9d73ba9b..ba577123 100644 --- a/flake.nix +++ b/flake.nix @@ -9,7 +9,10 @@ inputs.nixpkgs.follows = "nixpkgs"; }; crane = { - url = "github:ipetkov/crane"; + # TODO: Switch back to upstream after [this issue][0] is fixed + # + # [0]: https://github.com/ipetkov/crane/issues/497 + url = "github:CobaltCause/crane?ref=crimes-for-cross"; inputs.nixpkgs.follows = "nixpkgs"; }; attic.url = "github:zhaofengli/attic?ref=main"; From 81ae579b2546e9fe6d9eda4ed33507f4f159c67c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:22:18 -0800 Subject: [PATCH 053/175] add static cross to x86_64-unknown-linux-musl --- .gitlab-ci.yml | 13 +++++++ flake.nix | 89 +++++++++++++++++++++++++++++++++++++++++++-- rust-toolchain.toml | 1 + 3 files changed, 100 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1f6dab3a..95953e20 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,19 @@ ci: - target - .gitlab-ci.d +static:x86_64-unknown-linux-musl: + stage: artifacts + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#static-x86_64-unknown-linux-musl + + # Make the output less difficult to find + - cp result/bin/conduit conduit + artifacts: + paths: + - conduit + oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 diff --git a/flake.nix b/flake.nix index ba577123..c30c9483 100644 --- a/flake.nix +++ b/flake.nix @@ -46,13 +46,82 @@ ((crane.mkLib pkgs).overrideToolchain toolchain).buildPackage; nativeBuildInputs = pkgs: [ - pkgs.rustPlatform.bindgenHook + # bindgen needs the build platform's libclang. Apparently due to + # "splicing weirdness", pkgs.rustPlatform.bindgenHook on its own doesn't + # quite do the right thing here. + pkgs.buildPackages.rustPlatform.bindgenHook ]; env = pkgs: { ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; - }; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isStatic { + ROCKSDB_STATIC = ""; + } + // { + CARGO_BUILD_RUSTFLAGS = let inherit (pkgs) lib stdenv; in + lib.concatStringsSep " " ([] + ++ lib.optionals + # This disables PIE for static builds, which isn't great in terms + # of security. Unfortunately, my hand is forced because nixpkgs' + # `libstdc++.a` is built without `-fPIE`, which precludes us from + # leaving PIE enabled. + stdenv.hostPlatform.isStatic + ["-C" "relocation-model=static"] + ++ lib.optionals + (stdenv.buildPlatform.config != pkgs.stdenv.hostPlatform.config) + ["-l" "c"] + ); + } + + # What follows is stolen from [here][0]. Its purpose is to properly + # configure compilers and linkers for various stages of the build, and + # even covers the case of build scripts that need native code compiled and + # run on the build platform (I think). + # + # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L64-L78 + // ( + let + inherit (pkgs.rust.lib) envVars; + in + pkgs.lib.optionalAttrs + (pkgs.stdenv.targetPlatform.rust.rustcTarget + != pkgs.stdenv.hostPlatform.rust.rustcTarget) + ( + let + inherit (pkgs.stdenv.targetPlatform.rust) cargoEnvVarTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForTarget; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForTarget; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = + envVars.linkerForTarget; + } + ) + // ( + let + inherit (pkgs.stdenv.hostPlatform.rust) cargoEnvVarTarget rustcTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForHost; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForHost; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.linkerForHost; + CARGO_BUILD_TARGET = rustcTarget; + } + ) + // ( + let + inherit (pkgs.stdenv.buildPlatform.rust) cargoEnvVarTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForBuild; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForBuild; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.linkerForBuild; + HOST_CC = "${pkgs.buildPackages.stdenv.cc}/bin/cc"; + HOST_CXX = "${pkgs.buildPackages.stdenv.cc}/bin/c++"; + } + )); package = pkgs: builder pkgs { src = nix-filter { @@ -96,7 +165,21 @@ ]; }; }; - }; + } // builtins.listToAttrs ( + builtins.map + (crossSystem: { + name = "static-${crossSystem}"; + value = package (import nixpkgs { + inherit system; + crossSystem = { + config = crossSystem; + }; + }).pkgsStatic; + }) + [ + "x86_64-unknown-linux-musl" + ] + ); devShells.default = pkgsHost.mkShell { env = env pkgsHost // { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8d153e8b..9a21cdb4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -17,4 +17,5 @@ components = [ ] targets = [ "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", ] From 0e8e4f10833aa4ee7104a599e5fe56f2fa027a9b Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:49:52 -0800 Subject: [PATCH 054/175] add static cross to aarch64-unknown-linux-musl --- .gitlab-ci.yml | 13 +++++++++++++ flake.nix | 19 +++++++++++++++++++ rust-toolchain.toml | 1 + 3 files changed, 33 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 95953e20..6695e431 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,6 +55,19 @@ static:x86_64-unknown-linux-musl: paths: - conduit +static:aarch64-unknown-linux-musl: + stage: artifacts + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#static-aarch64-unknown-linux-musl + + # Make the output less difficult to find + - cp result/bin/conduit conduit + artifacts: + paths: + - conduit + oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 diff --git a/flake.nix b/flake.nix index c30c9483..e7b8cdbf 100644 --- a/flake.nix +++ b/flake.nix @@ -72,6 +72,24 @@ ++ lib.optionals (stdenv.buildPlatform.config != pkgs.stdenv.hostPlatform.config) ["-l" "c"] + ++ lib.optionals + # This check has to match the one [here][0]. We only need to set + # these flags when using a different linker. Don't ask me why, + # though, because I don't know. All I know is it breaks otherwise. + # + # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39 + ( + pkgs.stdenv.hostPlatform.isAarch64 + && pkgs.stdenv.hostPlatform.isStatic + && !pkgs.stdenv.isDarwin + && !pkgs.stdenv.cc.bintools.isLLVM + ) + [ + "-l" + "stdc++" + "-L" + "${stdenv.cc.cc.lib}/${stdenv.hostPlatform.config}/lib" + ] ); } @@ -178,6 +196,7 @@ }) [ "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-musl" ] ); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 9a21cdb4..8ef64c92 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -18,4 +18,5 @@ components = [ targets = [ "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-musl", ] From 2a04a361e090bcd44939b5c7680ee4c445516790 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 19:36:17 -0800 Subject: [PATCH 055/175] break oci image builder into a function Now it can be reused for different `pkgs` and `package`s. --- flake.nix | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/flake.nix b/flake.nix index e7b8cdbf..5f4df1e1 100644 --- a/flake.nix +++ b/flake.nix @@ -159,30 +159,29 @@ meta.mainProgram = cargoToml.package.name; }; - in - { - packages = { - default = package pkgsHost; - oci-image = - let - package = self.packages.${system}.default; - in - pkgsHost.dockerTools.buildImage { + mkOciImage = pkgs: package: + pkgs.dockerTools.buildImage { name = package.pname; tag = "latest"; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) # are handled as expected Entrypoint = [ - "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" + "${pkgs.lib.getExe' pkgs.tini "tini"}" "--" ]; Cmd = [ - "${pkgsHost.lib.getExe package}" + "${pkgs.lib.getExe package}" ]; }; }; + in + { + packages = { + default = package pkgsHost; + + oci-image = mkOciImage pkgsHost self.packages.${system}.default; } // builtins.listToAttrs ( builtins.map (crossSystem: { From 7c1a3e41d94dbc4d5b395dae300bd3d42b937c50 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 19:38:25 -0800 Subject: [PATCH 056/175] add package to build an aarch64 oci image And build it as an artifact in CI. --- .gitlab-ci.yml | 17 +++++++++++++++++ flake.nix | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6695e431..a28db4d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -86,6 +86,23 @@ oci-image:x86_64-unknown-linux-gnu: paths: - oci-image.tar.gz +oci-image:aarch64-unknown-linux-musl: + stage: artifacts + needs: + # Wait for the static binary job to finish before starting so we don't have + # to build that twice for no reason + - static:aarch64-unknown-linux-musl + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl + + # Make the output less difficult to find + - cp result oci-image.tar.gz + artifacts: + paths: + - oci-image.tar.gz + debian:x86_64-unknown-linux-gnu: stage: artifacts # See also `rust-toolchain.toml` diff --git a/flake.nix b/flake.nix index 5f4df1e1..1bc5c148 100644 --- a/flake.nix +++ b/flake.nix @@ -182,6 +182,16 @@ default = package pkgsHost; oci-image = mkOciImage pkgsHost self.packages.${system}.default; + + # Build an OCI image from the musl aarch64 build so we don't have to + # build for aarch64 twice (to make a gnu version specifically for the + # OCI image) + oci-image-aarch64-unknown-linux-musl = mkOciImage + pkgsHost + self.packages.${system}.static-aarch64-unknown-linux-musl; + + # Don't build a musl x86_64 OCI image because that would be pointless. + # Just use the gnu one (i.e. `self.packages."x86_64-linux".oci-image`). } // builtins.listToAttrs ( builtins.map (crossSystem: { From 9453dbc7408c2ad043c5801bd0f25edd2f1769b7 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 20:33:15 -0800 Subject: [PATCH 057/175] update rust toolchain It comes with a bunch of new lints (yay!) so I fixed them all so CI will keep working. Also apparently something about linking changed because I had to change the checks for deciding the linker flags for static x86_64 builds to keep working. --- .gitlab-ci.yml | 2 +- Cargo.toml | 2 +- flake.nix | 8 ++++++-- rust-toolchain.toml | 2 +- src/api/client_server/media.rs | 2 +- src/database/abstraction/persy.rs | 6 +++--- src/database/abstraction/sqlite.rs | 2 +- src/database/key_value/account_data.rs | 5 ++--- src/database/key_value/globals.rs | 4 ++-- src/database/key_value/rooms/short.rs | 5 ++--- src/database/key_value/users.rs | 5 ++--- src/service/globals/mod.rs | 2 +- src/service/pdu.rs | 2 +- src/service/rooms/timeline/mod.rs | 25 +++++++++++++------------ src/service/sending/mod.rs | 2 +- src/service/users/mod.rs | 18 ++++++++++++------ 16 files changed, 50 insertions(+), 42 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a28db4d5..f2438c8e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -106,7 +106,7 @@ oci-image:aarch64-unknown-linux-musl: debian:x86_64-unknown-linux-gnu: stage: artifacts # See also `rust-toolchain.toml` - image: rust:1.70.0 + image: rust:1.75.0 script: - apt-get update && apt-get install -y --no-install-recommends libclang-dev - cargo install cargo-deb diff --git a/Cargo.toml b/Cargo.toml index 40919599..156de3c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ version = "0.7.0-alpha" edition = "2021" # See also `rust-toolchain.toml` -rust-version = "1.70.0" +rust-version = "1.75.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.nix b/flake.nix index 1bc5c148..e10ea4ee 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ file = ./rust-toolchain.toml; # See also `rust-toolchain.toml` - sha256 = "sha256-gdYqng0y9iHYzYPAdkC/ka3DRny3La/S5G8ASj0Ayyc="; + sha256 = "sha256-SXRtAuO4IqNOQq+nLbrsDFbVk+3aVA8NNpSZsKlVH/8="; }; builder = pkgs: @@ -79,7 +79,11 @@ # # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39 ( - pkgs.stdenv.hostPlatform.isAarch64 + (pkgs.stdenv.hostPlatform.isAarch64 + # Nixpkgs doesn't check for x86_64 here but we do, because I + # observed a failure building statically for x86_64 without + # including it here. Linkers are weird. + || pkgs.stdenv.hostPlatform.isx86_64) && pkgs.stdenv.hostPlatform.isStatic && !pkgs.stdenv.isDarwin && !pkgs.stdenv.cc.bintools.isLLVM diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8ef64c92..f7a94340 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -10,7 +10,7 @@ # If you're having trouble making the relevant changes, bug a maintainer. [toolchain] -channel = "1.70.0" +channel = "1.75.0" components = [ # For rust-analyzer "rust-src", diff --git a/src/api/client_server/media.rs b/src/api/client_server/media.rs index 75f8e156..7fc65c26 100644 --- a/src/api/client_server/media.rs +++ b/src/api/client_server/media.rs @@ -51,7 +51,7 @@ pub async fn create_content_route( .await?; Ok(create_content::v3::Response { - content_uri: mxc.try_into().expect("Invalid mxc:// URI"), + content_uri: mxc.into(), blurhash: None, }) } diff --git a/src/database/abstraction/persy.rs b/src/database/abstraction/persy.rs index 1fa7a0df..da7d4cf0 100644 --- a/src/database/abstraction/persy.rs +++ b/src/database/abstraction/persy.rs @@ -116,7 +116,7 @@ impl KvTree for PersyTree { match iter { Ok(iter) => Box::new(iter.filter_map(|(k, v)| { v.into_iter() - .map(|val| ((*k).to_owned().into(), (*val).to_owned().into())) + .map(|val| ((*k).to_owned(), (*val).to_owned())) .next() })), Err(e) => { @@ -142,7 +142,7 @@ impl KvTree for PersyTree { Ok(iter) => { let map = iter.filter_map(|(k, v)| { v.into_iter() - .map(|val| ((*k).to_owned().into(), (*val).to_owned().into())) + .map(|val| ((*k).to_owned(), (*val).to_owned())) .next() }); if backwards { @@ -179,7 +179,7 @@ impl KvTree for PersyTree { iter.take_while(move |(k, _)| (*k).starts_with(&owned_prefix)) .filter_map(|(k, v)| { v.into_iter() - .map(|val| ((*k).to_owned().into(), (*val).to_owned().into())) + .map(|val| ((*k).to_owned(), (*val).to_owned())) .next() }), ) diff --git a/src/database/abstraction/sqlite.rs b/src/database/abstraction/sqlite.rs index b69efb61..222a8433 100644 --- a/src/database/abstraction/sqlite.rs +++ b/src/database/abstraction/sqlite.rs @@ -33,7 +33,7 @@ impl Iterator for PreparedStatementIterator<'_> { struct NonAliasingBox(*mut T); impl Drop for NonAliasingBox { fn drop(&mut self) { - unsafe { Box::from_raw(self.0) }; + drop(unsafe { Box::from_raw(self.0) }); } } diff --git a/src/database/key_value/account_data.rs b/src/database/key_value/account_data.rs index e1eef966..970b36b5 100644 --- a/src/database/key_value/account_data.rs +++ b/src/database/key_value/account_data.rs @@ -123,13 +123,12 @@ impl service::account_data::Data for KeyValueDatabase { .take_while(move |(k, _)| k.starts_with(&prefix)) .map(|(k, v)| { Ok::<_, Error>(( - RoomAccountDataEventType::try_from( + RoomAccountDataEventType::from( utils::string_from_bytes(k.rsplit(|&b| b == 0xff).next().ok_or_else( || Error::bad_database("RoomUserData ID in db is invalid."), )?) .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, - ) - .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, + ), serde_json::from_slice::>(&v).map_err(|_| { Error::bad_database("Database contains invalid account data.") })?, diff --git a/src/database/key_value/globals.rs b/src/database/key_value/globals.rs index 11aa0641..7a70af18 100644 --- a/src/database/key_value/globals.rs +++ b/src/database/key_value/globals.rs @@ -256,8 +256,8 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n" .. } = new_keys; - keys.verify_keys.extend(verify_keys.into_iter()); - keys.old_verify_keys.extend(old_verify_keys.into_iter()); + keys.verify_keys.extend(verify_keys); + keys.old_verify_keys.extend(old_verify_keys); self.server_signingkeys.insert( origin.as_bytes(), diff --git a/src/database/key_value/rooms/short.rs b/src/database/key_value/rooms/short.rs index c0223170..98cfa48a 100644 --- a/src/database/key_value/rooms/short.rs +++ b/src/database/key_value/rooms/short.rs @@ -157,10 +157,9 @@ impl service::rooms::short::Data for KeyValueDatabase { .ok_or_else(|| Error::bad_database("Invalid statekey in shortstatekey_statekey."))?; let event_type = - StateEventType::try_from(utils::string_from_bytes(eventtype_bytes).map_err(|_| { + StateEventType::from(utils::string_from_bytes(eventtype_bytes).map_err(|_| { Error::bad_database("Event type in shortstatekey_statekey is invalid unicode.") - })?) - .map_err(|_| Error::bad_database("Event type in shortstatekey_statekey is invalid."))?; + })?); let state_key = utils::string_from_bytes(statekey_bytes).map_err(|_| { Error::bad_database("Statekey in shortstatekey_statekey is invalid unicode.") diff --git a/src/database/key_value/users.rs b/src/database/key_value/users.rs index 2b09d684..0e6db83a 100644 --- a/src/database/key_value/users.rs +++ b/src/database/key_value/users.rs @@ -146,10 +146,9 @@ impl service::users::Data for KeyValueDatabase { self.userid_avatarurl .get(user_id.as_bytes())? .map(|bytes| { - let s = utils::string_from_bytes(&bytes) - .map_err(|_| Error::bad_database("Avatar URL in db is invalid."))?; - s.try_into() + utils::string_from_bytes(&bytes) .map_err(|_| Error::bad_database("Avatar URL in db is invalid.")) + .map(Into::into) }) .transpose() } diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index f034415e..f7822940 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -128,7 +128,7 @@ impl Resolve for Resolver { .expect("lock should not be poisoned") .get(name.as_str()) .and_then(|(override_name, port)| { - override_name.get(0).map(|first_name| { + override_name.first().map(|first_name| { let x: Box + Send> = Box::new(iter::once(SocketAddr::new(*first_name, *port))); let x: Resolving = Box::pin(future::ready(Ok(x))); diff --git a/src/service/pdu.rs b/src/service/pdu.rs index 4a170bc2..c8d78604 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -385,7 +385,7 @@ impl PartialEq for PduEvent { } impl PartialOrd for PduEvent { fn partial_cmp(&self, other: &Self) -> Option { - self.event_id.partial_cmp(&other.event_id) + Some(self.cmp(other)) } } impl Ord for PduEvent { diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 06a076e8..ef09d061 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -90,18 +90,6 @@ impl Ord for PduCount { } } } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn comparisons() { - assert!(PduCount::Normal(1) < PduCount::Normal(2)); - assert!(PduCount::Backfilled(2) < PduCount::Backfilled(1)); - assert!(PduCount::Normal(1) > PduCount::Backfilled(1)); - assert!(PduCount::Backfilled(1) < PduCount::Normal(1)); - } -} pub struct Service { pub db: &'static dyn Data, @@ -1208,3 +1196,16 @@ impl Service { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn comparisons() { + assert!(PduCount::Normal(1) < PduCount::Normal(2)); + assert!(PduCount::Backfilled(2) < PduCount::Backfilled(1)); + assert!(PduCount::Normal(1) > PduCount::Backfilled(1)); + assert!(PduCount::Backfilled(1) < PduCount::Normal(1)); + } +} diff --git a/src/service/sending/mod.rs b/src/service/sending/mod.rs index b4411444..f80c4f0a 100644 --- a/src/service/sending/mod.rs +++ b/src/service/sending/mod.rs @@ -131,7 +131,7 @@ impl Service { for (key, outgoing_kind, event) in self.db.active_requests().filter_map(|r| r.ok()) { let entry = initial_transactions .entry(outgoing_kind.clone()) - .or_insert_with(Vec::new); + .or_default(); if entry.len() > 30 { warn!( diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index dc34d533..fb983a41 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -138,12 +138,18 @@ impl Service { cached.lists.insert(list_id.clone(), list.clone()); } - cached - .subscriptions - .extend(request.room_subscriptions.clone().into_iter()); - request - .room_subscriptions - .extend(cached.subscriptions.clone().into_iter()); + cached.subscriptions.extend( + request + .room_subscriptions + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); + request.room_subscriptions.extend( + cached + .subscriptions + .iter() + .map(|(k, v)| (k.clone(), v.clone())), + ); request.extensions.e2ee.enabled = request .extensions From a7892a28ec9395fbd5fd99aa09ed8de1206434be Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 22:00:32 -0800 Subject: [PATCH 058/175] refer directly to stdenv since it's in scope --- flake.nix | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/flake.nix b/flake.nix index e10ea4ee..c9ef7914 100644 --- a/flake.nix +++ b/flake.nix @@ -70,7 +70,7 @@ stdenv.hostPlatform.isStatic ["-C" "relocation-model=static"] ++ lib.optionals - (stdenv.buildPlatform.config != pkgs.stdenv.hostPlatform.config) + (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ["-l" "c"] ++ lib.optionals # This check has to match the one [here][0]. We only need to set @@ -79,14 +79,13 @@ # # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39 ( - (pkgs.stdenv.hostPlatform.isAarch64 - # Nixpkgs doesn't check for x86_64 here but we do, because I - # observed a failure building statically for x86_64 without - # including it here. Linkers are weird. - || pkgs.stdenv.hostPlatform.isx86_64) - && pkgs.stdenv.hostPlatform.isStatic - && !pkgs.stdenv.isDarwin - && !pkgs.stdenv.cc.bintools.isLLVM + # Nixpkgs doesn't check for x86_64 here but we do, because I + # observed a failure building statically for x86_64 without + # including it here. Linkers are weird. + (stdenv.hostPlatform.isAarch64 || stdenv.hostPlatform.isx86_64) + && stdenv.hostPlatform.isStatic + && !stdenv.isDarwin + && !stdenv.cc.bintools.isLLVM ) [ "-l" From 3e389256f5f191d6a26eecc622ec0e70661745c0 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Fri, 26 Jan 2024 00:11:14 -0800 Subject: [PATCH 059/175] switch lint config to `manifest-lint` feature I removed some lint configuration in the process: * `#[allow(clippy::suspicious_else_formatting)]` because nothing is currently triggering it. * `#[warn(clippy::future_not_send)]` because some stuff under `src/lib.rs` is. And also like, auto-trait leakage generally means this isn't a problem, and if things really need to be `Send`, then you'll probably know to mark it manually. * `#[warn(rust_2018_idioms)]` and replaced it with `explicit-outlives-requirements = "warn"` which is the most useful lint in that group that isn't enabled by default. --- Cargo.toml | 14 ++++++++++++++ src/lib.rs | 9 --------- src/main.rs | 10 ---------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 156de3c2..5292399a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,14 @@ +# Keep alphabetically sorted +[workspace.lints.rust] +explicit_outlives_requirements = "warn" +unused_qualifications = "warn" + +# Keep alphabetically sorted +[workspace.lints.clippy] +cloned_instead_of_copied = "warn" +dbg_macro = "warn" +str_to_string = "warn" + [package] name = "conduit" description = "A Matrix homeserver written in Rust" @@ -14,6 +25,9 @@ rust-version = "1.75.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lints] +workspace = true + [dependencies] # Web framework axum = { version = "0.6.18", default-features = false, features = ["form", "headers", "http1", "http2", "json", "matched-path"], optional = true } diff --git a/src/lib.rs b/src/lib.rs index dc6a9d2f..66d0c57c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,3 @@ -#![warn( - rust_2018_idioms, - unused_qualifications, - clippy::cloned_instead_of_copied, - clippy::str_to_string -)] -#![allow(clippy::suspicious_else_formatting)] -#![deny(clippy::dbg_macro)] - pub mod api; mod config; mod database; diff --git a/src/main.rs b/src/main.rs index 683e0914..524f6886 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,3 @@ -#![warn( - rust_2018_idioms, - unused_qualifications, - clippy::cloned_instead_of_copied, - clippy::str_to_string, - clippy::future_not_send -)] -#![allow(clippy::suspicious_else_formatting)] -#![deny(clippy::dbg_macro)] - use std::{future::Future, io, net::SocketAddr, sync::atomic, time::Duration}; use axum::{ From 0df5d18fd6eb08b8398453b287b17c8bc2bae621 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Fri, 26 Jan 2024 21:38:13 -0800 Subject: [PATCH 060/175] change docker tag back to `next` I misunderstood what the general meaning of the `latest` tag was. --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c9ef7914..a16ea58c 100644 --- a/flake.nix +++ b/flake.nix @@ -166,7 +166,7 @@ mkOciImage = pkgs: package: pkgs.dockerTools.buildImage { name = package.pname; - tag = "latest"; + tag = "next"; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) # are handled as expected From dffd771e7c9f48a0a63f9bc945ce1ee3c9afaa69 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sat, 27 Jan 2024 12:23:57 -0800 Subject: [PATCH 061/175] add ca certificates to the OCI image Without this, checking the authority of TLS certificates fails, making Conduit (rightly) refuse to connect to anything. --- flake.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flake.nix b/flake.nix index a16ea58c..31a84131 100644 --- a/flake.nix +++ b/flake.nix @@ -167,6 +167,9 @@ pkgs.dockerTools.buildImage { name = package.pname; tag = "next"; + copyToRoot = [ + pkgs.dockerTools.caCertificates + ]; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) # are handled as expected From cf8f1f25467c02f86433a5b0ef49e639e9b1eb45 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 24 Dec 2023 00:51:26 -0800 Subject: [PATCH 062/175] make a bunch of changes so complement works again Well, kinda. It crashed on me after 10 minutes because the tests timed out like in . Sounds like this means it's a them problem though. I want to use Nix to build this image instead in the future but this will at least make it work for now and give me a reference for while I'm porting it. I also want to make Conduit natively understand Complement's requirements instead of `sed`ing a bunch of stuff and needing a reverse proxy in the container. Should be more reliable that way. I'm not making this run in CI until the above stuff is addressed and until I can decide on a way to pin the revision of Complement being tested against. --- bin/complement | 37 +++++++++++++++++++++++++++++++++++ complement/Dockerfile | 45 ++++++++++++++++++++----------------------- complement/README.md | 16 +++++++-------- flake.nix | 7 +++++++ 4 files changed, 72 insertions(+), 33 deletions(-) create mode 100755 bin/complement diff --git a/bin/complement b/bin/complement new file mode 100755 index 00000000..291953dd --- /dev/null +++ b/bin/complement @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Path to Complement's source code +COMPLEMENT_SRC="$1" + +# A `.jsonl` file to write test logs to +LOG_FILE="$2" + +# A `.jsonl` file to write test results to +RESULTS_FILE="$3" + +OCI_IMAGE="complement-conduit:dev" + +env \ + -C "$(git rev-parse --show-toplevel)" \ + docker build \ + --tag "$OCI_IMAGE" \ + --file complement/Dockerfile \ + . + +# It's okay (likely, even) that `go test` exits nonzero +set +o pipefail +env \ + -C "$COMPLEMENT_SRC" \ + COMPLEMENT_BASE_IMAGE="$OCI_IMAGE" \ + go test -json ./tests | tee "$LOG_FILE" +set -o pipefail + +# Post-process the results into an easy-to-compare format +cat "$LOG_FILE" | jq -c ' + select( + (.Action == "pass" or .Action == "fail" or .Action == "skip") + and .Test != null + ) | {Action: .Action, Test: .Test} + ' | sort > "$RESULTS_FILE" diff --git a/complement/Dockerfile b/complement/Dockerfile index 50173a1c..813af10e 100644 --- a/complement/Dockerfile +++ b/complement/Dockerfile @@ -1,26 +1,30 @@ -# For use in our CI only. This requires a build artifact created by a previous run pipline stage to be placed in cached_target/release/conduit -FROM registry.gitlab.com/jfowl/conduit-containers/rust-with-tools:commit-16a08e9b as builder -#FROM rust:latest as builder +FROM rust:1.75.0 WORKDIR /workdir -ARG RUSTC_WRAPPER -ARG AWS_ACCESS_KEY_ID -ARG AWS_SECRET_ACCESS_KEY -ARG SCCACHE_BUCKET -ARG SCCACHE_ENDPOINT -ARG SCCACHE_S3_USE_SSL +RUN apt-get update && apt-get install -y --no-install-recommends \ + libclang-dev -COPY . . -RUN mkdir -p target/release -RUN test -e cached_target/release/conduit && cp cached_target/release/conduit target/release/conduit || cargo build --release - -## Actual image -FROM debian:bullseye -WORKDIR /workdir +COPY Cargo.toml Cargo.toml +COPY Cargo.lock Cargo.lock +COPY src src +RUN cargo build --release \ + && mv target/release/conduit conduit \ + && rm -rf target # Install caddy -RUN apt-get update && apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-testing-archive-keyring.gpg && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-testing.list && apt-get update && apt-get install -y caddy +RUN apt-get update \ + && apt-get install -y \ + debian-keyring \ + debian-archive-keyring \ + apt-transport-https \ + curl \ + && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/gpg.key' \ + | gpg --dearmor -o /usr/share/keyrings/caddy-testing-archive-keyring.gpg \ + && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/debian.deb.txt' \ + | tee /etc/apt/sources.list.d/caddy-testing.list \ + && apt-get update \ + && apt-get install -y caddy COPY conduit-example.toml conduit.toml COPY complement/caddy.json caddy.json @@ -29,16 +33,9 @@ ENV SERVER_NAME=localhost ENV CONDUIT_CONFIG=/workdir/conduit.toml RUN sed -i "s/port = 6167/port = 8008/g" conduit.toml -RUN echo "allow_federation = true" >> conduit.toml -RUN echo "allow_check_for_updates = true" >> conduit.toml -RUN echo "allow_encryption = true" >> conduit.toml -RUN echo "allow_registration = true" >> conduit.toml RUN echo "log = \"warn,_=off,sled=off\"" >> conduit.toml RUN sed -i "s/address = \"127.0.0.1\"/address = \"0.0.0.0\"/g" conduit.toml -COPY --from=builder /workdir/target/release/conduit /workdir/conduit -RUN chmod +x /workdir/conduit - EXPOSE 8008 8448 CMD uname -a && \ diff --git a/complement/README.md b/complement/README.md index b86aab38..185b251a 100644 --- a/complement/README.md +++ b/complement/README.md @@ -1,13 +1,11 @@ -# Running Conduit on Complement +# Complement -This assumes that you're familiar with complement, if not, please readme -[their readme](https://github.com/matrix-org/complement#running). +## What's that? -Complement works with "base images", this directory (and Dockerfile) helps build the conduit complement-ready docker -image. +Have a look at [its repository](https://github.com/matrix-org/complement). -To build, `cd` to the base directory of the workspace, and run this: +## How do I use it with Conduit? -`docker build -t complement-conduit:dev -f complement/Dockerfile .` - -Then use `complement-conduit:dev` as a base image for running complement tests. +The script at [`../bin/complement`](../bin/complement) has automation for this. +It takes a few command line arguments, you can read the script to find out what +those are. diff --git a/flake.nix b/flake.nix index 31a84131..bf50e584 100644 --- a/flake.nix +++ b/flake.nix @@ -234,6 +234,13 @@ toolchain ] ++ (with pkgsHost; [ engage + + # Needed for Complement + go + olm + + # Needed for our script for Complement + jq ]); }; }); From c167f7a6ad32d27a390ea5017572f7461a4271c4 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 28 Jan 2024 13:31:03 -0800 Subject: [PATCH 063/175] switch crane input back to upstream Thanks to the crane maintainer to fixing my issue in a way that doesn't suck, unlike my attempt in the fork we were briefly using. --- flake.lock | 12 ++++++------ flake.nix | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 4508f7ce..85b0ab53 100644 --- a/flake.lock +++ b/flake.lock @@ -51,16 +51,16 @@ ] }, "locked": { - "lastModified": 1706070683, - "narHash": "sha256-iQoXIFviH5QbSKDkWyFJKKUtTcSiCvl1tW18ax+pKfI=", - "owner": "CobaltCause", + "lastModified": 1706473964, + "narHash": "sha256-Fq6xleee/TsX6NbtoRuI96bBuDHMU57PrcK9z1QEKbk=", + "owner": "ipetkov", "repo": "crane", - "rev": "8060686afabc5b042e8982200cb2cc3fd22cf416", + "rev": "c798790eabec3e3da48190ae3698ac227aab770c", "type": "github" }, "original": { - "owner": "CobaltCause", - "ref": "crimes-for-cross", + "owner": "ipetkov", + "ref": "master", "repo": "crane", "type": "github" } diff --git a/flake.nix b/flake.nix index bf50e584..94259685 100644 --- a/flake.nix +++ b/flake.nix @@ -9,10 +9,7 @@ inputs.nixpkgs.follows = "nixpkgs"; }; crane = { - # TODO: Switch back to upstream after [this issue][0] is fixed - # - # [0]: https://github.com/ipetkov/crane/issues/497 - url = "github:CobaltCause/crane?ref=crimes-for-cross"; + url = "github:ipetkov/crane?ref=master"; inputs.nixpkgs.follows = "nixpkgs"; }; attic.url = "github:zhaofengli/attic?ref=main"; From 2d47710b551616786dfa935d6a769f34c30b4161 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 29 Jan 2024 14:50:30 -0800 Subject: [PATCH 064/175] update DEPLOY.md with new build links --- DEPLOY.md | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/DEPLOY.md b/DEPLOY.md index cb318eee..dcb1777d 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -12,11 +12,13 @@ only offer Linux binaries. You may simply download the binary that fits your machine. Run `uname -m` to see what you need. Now copy the appropriate url: -| CPU Architecture | Download stable version | Download development version | -| ------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------- | -| x84_64 / amd64 (Most servers and computers) | [Binary][x84_64-glibc-master] / [.deb][x84_64-glibc-master-deb] | [Binary][x84_64-glibc-next] / [.deb][x84_64-glibc-next-deb] | -| armv7 (e.g. Raspberry Pi by default) | [Binary][armv7-glibc-master] / [.deb][armv7-glibc-master-deb] | [Binary][armv7-glibc-next] / [.deb][armv7-glibc-next-deb] | -| armv8 / aarch64 | [Binary][armv8-glibc-master] / [.deb][armv8-glibc-master-deb] | [Binary][armv8-glibc-next] / [.deb][armv8-glibc-next-deb] | +**Stable versions:** + +| CPU Architecture | Download stable version | +| ------------------------------------------- | --------------------------------------------------------------- | +| x84_64 / amd64 (Most servers and computers) | [Binary][x84_64-glibc-master] / [.deb][x84_64-glibc-master-deb] | +| armv7 (e.g. Raspberry Pi by default) | [Binary][armv7-glibc-master] / [.deb][armv7-glibc-master-deb] | +| armv8 / aarch64 | [Binary][armv8-glibc-master] / [.deb][armv8-glibc-master-deb] | These builds were created on and linked against the glibc version shipped with Debian bullseye. If you use a system with an older glibc version (e.g. RHEL8), you might need to compile Conduit yourself. @@ -24,15 +26,19 @@ If you use a system with an older glibc version (e.g. RHEL8), you might need to [x84_64-glibc-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_amd64/conduit?job=docker:master [armv7-glibc-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_arm_v7/conduit?job=docker:master [armv8-glibc-master]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_arm64/conduit?job=docker:master -[x84_64-glibc-next]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_amd64/conduit?job=docker:next -[armv7-glibc-next]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_arm_v7/conduit?job=docker:next -[armv8-glibc-next]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_arm64/conduit?job=docker:next [x84_64-glibc-master-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_amd64/conduit.deb?job=docker:master [armv7-glibc-master-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_arm_v7/conduit.deb?job=docker:master [armv8-glibc-master-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/master/raw/build-output/linux_arm64/conduit.deb?job=docker:master -[x84_64-glibc-next-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_amd64/conduit.deb?job=docker:next -[armv7-glibc-next-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_arm_v7/conduit.deb?job=docker:next -[armv8-glibc-next-deb]: https://gitlab.com/famedly/conduit/-/jobs/artifacts/next/raw/build-output/linux_arm64/conduit.deb?job=docker:next + +**Latest versions:** + +| Target | Type | Download | +|-|-|-| +| `x86_64-unknown-linux-gnu` | Dynamically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit.deb?job=debian:x86_64-unknown-linux-gnu) | +| `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:x86_64-unknown-linux-musl) | +| `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:aarch64-unknown-linux-musl) | +| `x86_64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | +| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image.tar.gz?job=oci-image:aarch64-unknown-linux-musl) | ```bash $ sudo wget -O /usr/local/bin/matrix-conduit From a43bde69fa6ae1517e5475f9bd4d228bad3b0fea Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 29 Jan 2024 15:34:16 -0800 Subject: [PATCH 065/175] pass pkgsCrossStatic to mkOciImage, not pkgsHost This fixes a bug where the aarch64 OCI image had metadata saying it was an x86_64 OCI image. On top of that, I think the metadata was actually right (aside from Conduit's binary): since all other packages were being pulled from `pkgsHost`, an OCI image cross compiled for aarch64 from a different architecture would result in unexecutable binaries (e.g. tini) since they were compiled for the completely wrong architecture. --- .gitlab-ci.yml | 3 +++ flake.nix | 65 +++++++++++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f2438c8e..d4e49ce4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -68,6 +68,9 @@ static:aarch64-unknown-linux-musl: paths: - conduit +# Note that although we have an `oci-image-x86_64-unknown-linux-musl` output, +# we don't build it because it would be largely redundant to this one since it's +# all containerized anyway. oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 diff --git a/flake.nix b/flake.nix index 94259685..e0bc6fbb 100644 --- a/flake.nix +++ b/flake.nix @@ -183,34 +183,45 @@ { packages = { default = package pkgsHost; - oci-image = mkOciImage pkgsHost self.packages.${system}.default; - - # Build an OCI image from the musl aarch64 build so we don't have to - # build for aarch64 twice (to make a gnu version specifically for the - # OCI image) - oci-image-aarch64-unknown-linux-musl = mkOciImage - pkgsHost - self.packages.${system}.static-aarch64-unknown-linux-musl; - - # Don't build a musl x86_64 OCI image because that would be pointless. - # Just use the gnu one (i.e. `self.packages."x86_64-linux".oci-image`). - } // builtins.listToAttrs ( - builtins.map - (crossSystem: { - name = "static-${crossSystem}"; - value = package (import nixpkgs { - inherit system; - crossSystem = { - config = crossSystem; - }; - }).pkgsStatic; - }) - [ - "x86_64-unknown-linux-musl" - "aarch64-unknown-linux-musl" - ] - ); + } + // + builtins.listToAttrs + (builtins.concatLists + (builtins.map + (crossSystem: + let + binaryName = "static-${crossSystem}"; + pkgsCrossStatic = + (import nixpkgs { + inherit system; + crossSystem = { + config = crossSystem; + }; + }).pkgsStatic; + in + [ + # An output for a statically-linked binary + { + name = binaryName; + value = package pkgsCrossStatic; + } + + # An output for an OCI image based on that binary + { + name = "oci-image-${crossSystem}"; + value = mkOciImage + pkgsCrossStatic + self.packages.${system}.${binaryName}; + } + ] + ) + [ + "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-musl" + ] + ) + ); devShells.default = pkgsHost.mkShell { env = env pkgsHost // { From 1274b48ebb09ac1f1576cbb9e3417a4ca2256273 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 29 Jan 2024 15:54:31 -0800 Subject: [PATCH 066/175] run `cargo update` `IndexMap::remove` was deprecated in favor of explicitly named methods. I assume that we actually needed to be using `shift_remove`, otherwise we probably wouldn't be bothering with `indexmap` here in the first place. I wonder if this fixes any bugs lol --- Cargo.lock | 1232 ++++++++++++++++++++++++------------------- src/database/mod.rs | 6 +- 2 files changed, 696 insertions(+), 542 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5e1d161..81b270db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -10,35 +19,36 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] name = "arc-swap" @@ -72,20 +82,23 @@ checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "atomic" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] [[package]] name = "autocfg" @@ -95,9 +108,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", @@ -162,6 +175,21 @@ dependencies = [ "tower-service", ] +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -170,9 +198,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -198,7 +226,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] @@ -209,19 +237,19 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.2" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "blake2b_simd" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq 0.2.6", + "constant_time_eq", ] [[package]] @@ -235,27 +263,27 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "bzip2-sys" @@ -270,11 +298,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -294,9 +323,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -305,43 +334,41 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstyle", - "bitflags 1.3.2", "clap_lex", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "color_quant" @@ -356,7 +383,7 @@ dependencies = [ "async-trait", "axum", "axum-server", - "base64 0.21.2", + "base64 0.21.7", "bytes", "clap", "directories", @@ -378,7 +405,7 @@ dependencies = [ "rand", "regex", "reqwest", - "ring", + "ring 0.16.20", "rocksdb", "ruma", "rusqlite", @@ -406,9 +433,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_panic" @@ -418,21 +445,15 @@ checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" [[package]] name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "constant_time_eq" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -440,15 +461,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -464,9 +485,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" @@ -479,22 +500,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -508,9 +525,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if", "cpufeatures", @@ -525,23 +542,23 @@ dependencies = [ [[package]] name = "curve25519-dalek-derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.12.3", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core", @@ -549,9 +566,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" @@ -563,6 +580,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.10.7" @@ -596,9 +622,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "signature", @@ -606,29 +632,30 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek", "ed25519", "rand_core", "serde", "sha2", + "subtle", "zeroize", ] [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -647,9 +674,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fallible-iterator" @@ -665,38 +692,38 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] [[package]] name = "fiat-crypto" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" +checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" [[package]] name = "figment" -version = "0.10.10" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4547e226f4c9ab860571e070a9034192b3175580ecea38da34fcdb53a018c9a5" +checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" dependencies = [ "atomic", "pear", "serde", - "toml", + "toml 0.8.8", "uncased", "version_check", ] [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -710,9 +737,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -729,9 +756,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -744,9 +771,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -754,15 +781,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -771,38 +798,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -828,9 +855,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -847,6 +874,12 @@ dependencies = [ "weezl", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "glob" version = "0.3.1" @@ -855,9 +888,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.19" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -865,7 +898,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -880,9 +913,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -890,21 +923,20 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.3", ] [[package]] name = "headers" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64 0.21.7", "bytes", "headers-core", "http", @@ -930,12 +962,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hmac" @@ -959,9 +988,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -970,9 +999,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -981,9 +1010,9 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" @@ -993,15 +1022,15 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1014,7 +1043,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -1023,9 +1052,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -1048,9 +1077,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1058,16 +1087,15 @@ dependencies = [ [[package]] name = "image" -version = "0.24.6" +version = "0.24.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" dependencies = [ "bytemuck", "byteorder", "color_quant", "gif", "jpeg-decoder", - "num-rational", "num-traits", "png", ] @@ -1084,12 +1112,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.3", "serde", ] @@ -1111,17 +1139,17 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.3", + "socket2", "widestring", "windows-sys 0.48.0", - "winreg 0.50.0", + "winreg", ] [[package]] name = "ipnet" -version = "2.7.2" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itertools" @@ -1134,30 +1162,30 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -1186,9 +1214,9 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -1196,9 +1224,9 @@ dependencies = [ [[package]] name = "konst" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9a8bb6c7c71d151b25936b03e012a4c00daea99e3a3797c6ead66b0a0d55e2" +checksum = "8d712a8c49d4274f8d8a5cf61368cb5f3c143d149882b1a2918129e53395fdb0" dependencies = [ "const_panic", "konst_kernel", @@ -1207,9 +1235,9 @@ dependencies = [ [[package]] name = "konst_kernel" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55d2ab266022e7309df89ed712bddc753e3a3c395c3ced1bb2e4470ec2a8146d" +checksum = "dac6ea8c376b6e208a81cf39b8e82bebf49652454d98a4829e907dac16ef1790" dependencies = [ "typewit", ] @@ -1228,18 +1256,29 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall", ] [[package]] @@ -1271,9 +1310,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.9" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" dependencies = [ "cc", "pkg-config", @@ -1288,9 +1327,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1298,9 +1337,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru-cache" @@ -1339,7 +1378,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1350,15 +1389,15 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -1393,9 +1432,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", @@ -1404,16 +1443,15 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", "memoffset", "pin-utils", - "static_assertions", ] [[package]] @@ -1438,9 +1476,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -1458,40 +1496,38 @@ dependencies = [ ] [[package]] -name = "num-rational" -version = "0.4.1" +name = "num-traits" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", - "num-integer", - "num-traits", ] [[package]] -name = "num-traits" -version = "0.2.15" +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "autocfg", + "hermit-abi", + "libc", ] [[package]] -name = "num_cpus" -version = "1.15.0" +name = "object" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ - "hermit-abi", - "libc", + "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl-probe" @@ -1600,28 +1636,28 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pear" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec95680a7087503575284e5063e14b694b7a9c0b065e5dceec661e0497127e8" +checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ "inlinable_string", "pear_codegen", @@ -1630,14 +1666,14 @@ dependencies = [ [[package]] name = "pear_codegen" -version = "0.2.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9661a3a53f93f09f2ea882018e4d7c88f6ff2956d809a276060476fd8c879d3c" +checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] @@ -1657,15 +1693,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "persy" -version = "1.4.4" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3712821f12453814409ec149071bd4832a8ec458e648579c104aee30ed70b300" +checksum = "3cd38c602b23c2f451842d89f27cd5e0d4b292176daf40feeda859c658dcdc76" dependencies = [ "crc", "data-encoding", @@ -1679,29 +1715,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1721,21 +1757,21 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "platforms" -version = "3.1.2" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "png" -version = "0.17.9" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" +checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1744,6 +1780,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1752,12 +1794,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] @@ -1767,27 +1809,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] name = "proc-macro2" -version = "1.0.61" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363a6f739a0c0addeaf6ed75150b95743aa18643a3c6f40409ed7b6db3a6911f" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "proc-macro2-diagnostics" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", "version_check", "yansi", ] @@ -1800,9 +1842,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1839,42 +1881,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -1886,6 +1920,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1894,17 +1939,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -1927,6 +1972,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-rustls", "tokio-socks", @@ -1935,7 +1981,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.10.1", + "winreg", ] [[package]] @@ -1957,12 +2003,26 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "rocksdb" version = "0.21.0" @@ -2028,11 +2088,11 @@ version = "0.11.3" source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "as_variant", - "base64 0.21.2", + "base64 0.21.7", "bytes", "form_urlencoded", "http", - "indexmap 2.0.0", + "indexmap 2.2.1", "js_int", "konst", "percent-encoding", @@ -2056,7 +2116,7 @@ version = "0.26.0" source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "as_variant", - "indexmap 2.0.0", + "indexmap 2.2.1", "js_int", "js_option", "percent-encoding", @@ -2114,8 +2174,8 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn 2.0.21", - "toml", + "syn 2.0.48", + "toml 0.7.8", ] [[package]] @@ -2135,7 +2195,7 @@ name = "ruma-signatures" version = "0.13.1" source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "ed25519-dalek", "pkcs8", "rand", @@ -2167,7 +2227,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" dependencies = [ - "bitflags 2.3.2", + "bitflags 2.4.2", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -2177,16 +2237,22 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" +checksum = "a5885493fdf0be6cdff808d1533ce878d21cfa49c7086fa00c66355cd9141bfc" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "blake2b_simd", - "constant_time_eq 0.1.5", + "constant_time_eq", "crossbeam-utils", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2204,12 +2270,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.2" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -2228,58 +2294,58 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", ] [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.52.0", ] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -2290,9 +2356,9 @@ checksum = "621e3680f3e07db4c9c2c3fb07c6223ab2fab2e54bd3c04c3ae037990f428c32" [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2303,9 +2369,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2313,38 +2379,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "serde_html_form" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53192e38d5c88564b924dbe9b60865ecbb71b81d38c4e61c817cffd3e36ef696" +checksum = "20e1066e1cfa6692a722cf40386a2caec36da5ddc4a2c16df592f0f609677e8c" dependencies = [ "form_urlencoded", - "indexmap 1.9.3", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2352,9 +2418,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -2363,18 +2429,19 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.11" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" dependencies = [ + "itoa", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -2393,11 +2460,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.22" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452e67b9c20c37fa79df53201dc03839651086ed9bbe92b3ca585ca9fdaa7d85" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2417,9 +2484,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -2428,9 +2495,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -2439,18 +2506,18 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2463,15 +2530,18 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simple_asn1" @@ -2487,34 +2557,24 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "socket2" -version = "0.4.9" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -2526,22 +2586,22 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "subslice" version = "0.2.3" @@ -2570,9 +2630,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.21" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1182caafaab7018eaea9b404afa8184c0baf42a04d5e10ae4f4843c2029c8aab" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -2585,24 +2645,45 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] @@ -2639,9 +2720,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-ctl" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1" +checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c" dependencies = [ "libc", "paste", @@ -2650,9 +2731,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.5.3+5.3.0-patched" +version = "0.5.4+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8" +checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" dependencies = [ "cc", "libc", @@ -2660,9 +2741,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979" +checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -2670,11 +2751,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ + "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -2682,15 +2765,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -2712,31 +2795,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", "signal-hook-registry", - "socket2 0.4.9", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] @@ -2774,9 +2857,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -2788,32 +2871,57 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.5" +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.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ + "indexmap 2.2.1", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.2.1", "serde", "serde_spanned", "toml_datetime", @@ -2837,11 +2945,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8bd22a874a2d0b70452d5597b12c537331d49060824a95f49f108994f94aa4c" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.3.2", + "bitflags 2.4.2", "bytes", "futures-core", "futures-util", @@ -2869,11 +2977,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2882,20 +2989,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2914,12 +3021,23 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -2933,15 +3051,15 @@ dependencies = [ "opentelemetry", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -2952,7 +3070,7 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", ] [[package]] @@ -3002,42 +3120,51 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typewit" -version = "1.4.0" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fb9ae6a3cafaf0a5d14c2302ca525f9ae8e07a0f0e6949de88d882c37a6e24" +dependencies = [ + "typewit_proc_macros", +] + +[[package]] +name = "typewit_proc_macros" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4061a10d4d8f3081a8ccc025182afd8434302d8d4b4503ec6d8510d09df08c2d" +checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6" [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -3050,15 +3177,15 @@ dependencies = [ [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "unsigned-varint" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" [[package]] name = "untrusted" @@ -3066,22 +3193,28 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", ] [[package]] name = "uuid" -version = "1.3.4" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ "getrandom", ] @@ -3121,9 +3254,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3131,24 +3264,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -3158,9 +3291,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3168,28 +3301,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.21", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -3197,9 +3330,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "widestring" @@ -3209,9 +3342,9 @@ checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "wildmatch" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" +checksum = "495ec47bf3c1345005f40724f0269362c8556cbc43aed0526ed44cae1d35fceb" [[package]] name = "winapi" @@ -3237,145 +3370,145 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.48.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - [[package]] name = "winreg" version = "0.50.0" @@ -3388,15 +3521,35 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" + +[[package]] +name = "zerocopy" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zigzag" @@ -3409,11 +3562,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/src/database/mod.rs b/src/database/mod.rs index e247d9f0..425ef4e9 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -852,7 +852,9 @@ impl KeyValueDatabase { if rule.is_some() { let mut rule = rule.unwrap().clone(); rule.rule_id = content_rule_transformation[1].to_owned(); - rules_list.content.remove(content_rule_transformation[0]); + rules_list + .content + .shift_remove(content_rule_transformation[0]); rules_list.content.insert(rule); } } @@ -875,7 +877,7 @@ impl KeyValueDatabase { if let Some(rule) = rule { let mut rule = rule.clone(); rule.rule_id = transformation[1].to_owned(); - rules_list.underride.remove(transformation[0]); + rules_list.underride.shift_remove(transformation[0]); rules_list.underride.insert(rule); } } From 7fb9e99649786afbed97d31d2a26e68374e2b15d Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 29 Jan 2024 16:08:29 -0800 Subject: [PATCH 067/175] update ring and jsonwebtoken to remove ring ^0.16 --- Cargo.lock | 81 ++++++++++++++++++------------------------------------ Cargo.toml | 4 +-- 2 files changed, 28 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81b270db..94a0c5e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,12 +190,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -383,7 +377,7 @@ dependencies = [ "async-trait", "axum", "axum-server", - "base64 0.21.7", + "base64", "bytes", "clap", "directories", @@ -405,7 +399,7 @@ dependencies = [ "rand", "regex", "reqwest", - "ring 0.16.20", + "ring", "rocksdb", "ruma", "rusqlite", @@ -860,8 +854,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -936,7 +932,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "headers-core", "http", @@ -1210,13 +1206,14 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "8.3.0" +version = "9.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" dependencies = [ - "base64 0.21.7", + "base64", + "js-sys", "pem", - "ring 0.16.20", + "ring", "serde", "serde_json", "simple_asn1", @@ -1684,11 +1681,12 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem" -version = "1.1.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.13.1", + "base64", + "serde", ] [[package]] @@ -1949,7 +1947,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "encoding_rs", "futures-core", @@ -1994,21 +1992,6 @@ dependencies = [ "quick-error", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.7" @@ -2018,8 +2001,8 @@ dependencies = [ "cc", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.48.0", ] @@ -2088,7 +2071,7 @@ version = "0.11.3" source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ "as_variant", - "base64 0.21.7", + "base64", "bytes", "form_urlencoded", "http", @@ -2195,7 +2178,7 @@ name = "ruma-signatures" version = "0.13.1" source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" dependencies = [ - "base64 0.21.7", + "base64", "ed25519-dalek", "pkcs8", "rand", @@ -2241,7 +2224,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5885493fdf0be6cdff808d1533ce878d21cfa49c7086fa00c66355cd9141bfc" dependencies = [ - "base64 0.21.7", + "base64", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -2275,7 +2258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring", "rustls-webpki", "sct", ] @@ -2298,7 +2281,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.7", + "base64", ] [[package]] @@ -2307,8 +2290,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -2344,8 +2327,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -2580,12 +2563,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -3187,12 +3164,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 5292399a..c00d56a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,13 +73,13 @@ image = { version = "0.24.6", default-features = false, features = ["jpeg", "png # Used to encode server public key base64 = "0.21.2" # Used when hashing the state -ring = "0.16.20" +ring = "0.17.7" # Used when querying the SRV record of other servers trust-dns-resolver = "0.22.0" # Used to find matching events for appservices regex = "1.8.1" # jwt jsonwebtokens -jsonwebtoken = "8.3.0" +jsonwebtoken = "9.2.0" # Performance measurements tracing = { version = "0.1.37", features = [] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } From d6c57f9b2e55c16218728aaf52b6ceae7908a3aa Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Tue, 30 Jan 2024 17:04:47 +0000 Subject: [PATCH 068/175] Publish oci image to the gitlab registry --- .gitlab-ci.yml | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- DEPLOY.md | 4 ++-- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d4e49ce4..639319c5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ stages: - ci - artifacts + - publish variables: # Makes some things print in color @@ -84,10 +85,10 @@ oci-image:x86_64-unknown-linux-gnu: - ./bin/nix-build-and-cache .#oci-image # Make the output less difficult to find - - cp result oci-image.tar.gz + - cp result oci-image-amd64.tar.gz artifacts: paths: - - oci-image.tar.gz + - oci-image-amd64.tar.gz oci-image:aarch64-unknown-linux-musl: stage: artifacts @@ -101,10 +102,10 @@ oci-image:aarch64-unknown-linux-musl: - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl # Make the output less difficult to find - - cp result oci-image.tar.gz + - cp result oci-image-arm64v8.tar.gz artifacts: paths: - - oci-image.tar.gz + - oci-image-arm64v8.tar.gz debian:x86_64-unknown-linux-gnu: stage: artifacts @@ -125,3 +126,44 @@ debian:x86_64-unknown-linux-gnu: paths: - target - .gitlab-ci.d + +docker-publish: + stage: publish + image: docker:25.0.0 + services: + - docker:25.0.0-dind + variables: + IMAGE_NAME: $CI_REGISTRY_IMAGE/matrix-conduit + IMAGE_SUFFIX_AMD64: amd64 + IMAGE_SUFFIX_ARM64V8: arm64v8 + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + script: + - docker load -i oci-image-amd64.tar.gz + - IMAGE_ID_AMD64=$(docker images -q conduit:next) + - docker load -i oci-image-arm64v8.tar.gz + - IMAGE_ID_ARM64V8=$(docker images -q conduit:next) + # Tag and push the architecture specific images + - docker tag $IMAGE_ID_AMD64 $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_AMD64 + - docker tag $IMAGE_ID_ARM64V8 $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_ARM64V8 + - docker push $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_AMD64 + - docker push $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_ARM64V8 + # Tag the multi-arch image + - docker manifest create $IMAGE_NAME:$CI_COMMIT_SHA --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_AMD64 --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_ARM64V8 + - docker manifest push $IMAGE_NAME:$CI_COMMIT_SHA + # Tag and push the git ref + - docker manifest create $IMAGE_NAME:$CI_COMMIT_REF_NAME --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_AMD64 --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_ARM64V8 + - docker manifest push $IMAGE_NAME:$CI_COMMIT_REF_NAME + # Tag git tags as 'latest' + - | + if [[ -n "$CI_COMMIT_TAG" ]]; then + docker manifest create $IMAGE_NAME:latest --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_AMD64 --amend $IMAGE_NAME:$CI_COMMIT_SHA-$IMAGE_SUFFIX_ARM64V8 + docker manifest push $IMAGE_NAME:latest + fi + dependencies: + - oci-image:x86_64-unknown-linux-gnu + - oci-image:aarch64-unknown-linux-musl + only: + - next + - master + - tags diff --git a/DEPLOY.md b/DEPLOY.md index dcb1777d..c74fb3f0 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -37,8 +37,8 @@ If you use a system with an older glibc version (e.g. RHEL8), you might need to | `x86_64-unknown-linux-gnu` | Dynamically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit.deb?job=debian:x86_64-unknown-linux-gnu) | | `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:x86_64-unknown-linux-musl) | | `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:aarch64-unknown-linux-musl) | -| `x86_64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | -| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image.tar.gz?job=oci-image:aarch64-unknown-linux-musl) | +| `x86_64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | +| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=oci-image:aarch64-unknown-linux-musl) | ```bash $ sudo wget -O /usr/local/bin/matrix-conduit From 3a63f9dfb66f60fd9cc755de1aaea7b05687af26 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Fri, 2 Feb 2024 03:50:49 +0100 Subject: [PATCH 069/175] feat: support non-flake users This uses flakes-compat to read the `flake.nix` and expose it to non-flake users. Signed-off-by: Raito Bezarius --- default.nix | 10 ++++++++++ flake.lock | 17 +++++++++++++++++ flake.nix | 4 ++++ 3 files changed, 31 insertions(+) create mode 100644 default.nix diff --git a/default.nix b/default.nix new file mode 100644 index 00000000..f620865d --- /dev/null +++ b/default.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).defaultNix diff --git a/flake.lock b/flake.lock index 85b0ab53..1c97e5c6 100644 --- a/flake.lock +++ b/flake.lock @@ -102,6 +102,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "locked": { "lastModified": 1667395993, @@ -203,6 +219,7 @@ "attic": "attic", "crane": "crane_2", "fenix": "fenix", + "flake-compat": "flake-compat_2", "flake-utils": "flake-utils_2", "nix-filter": "nix-filter", "nixpkgs": "nixpkgs_2" diff --git a/flake.nix b/flake.nix index e0bc6fbb..6ca4c72d 100644 --- a/flake.nix +++ b/flake.nix @@ -3,6 +3,10 @@ nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; nix-filter.url = "github:numtide/nix-filter"; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; fenix = { url = "github:nix-community/fenix"; From a2ac491c5460da736c8872747aa3417a65c81a4e Mon Sep 17 00:00:00 2001 From: strawberry Date: Sat, 25 Nov 2023 12:42:05 -0500 Subject: [PATCH 070/175] bump ruma, add wrong room keys error code, tiny logging change can't update ruma to very latest commit because of the weird JsOption thing for syncv4 that i can't wrap my head around how to use, not important anyways Signed-off-by: strawberry --- Cargo.toml | 5 ++++- src/api/client_server/membership.rs | 6 +++--- src/api/client_server/room.rs | 2 +- src/service/admin/mod.rs | 2 +- src/service/rooms/spaces/mod.rs | 6 +++--- src/service/rooms/state_accessor/mod.rs | 10 ++++++++-- src/utils/error.rs | 8 +++++--- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c00d56a9..0fa69147 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "b4853aa8fa5e3a24e3689fc88044de9915f6ab67", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "5446ea979b314b90da1734f20efaff443d64f73d", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } @@ -116,6 +116,9 @@ async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } +# stupid ruma using JsOption instead of Option +js_option = "0.1" + [target.'cfg(unix)'.dependencies] nix = { version = "0.26.2", features = ["resource"] } diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index ed59691d..09f70a03 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -64,7 +64,7 @@ pub async fn join_room_by_id_route( .map(|user| user.server_name().to_owned()), ); - servers.push(body.room_id.server_name().to_owned()); + servers.push(body.room_id.server_name().unwrap().into()); join_room_by_id_helper( body.sender_user.as_deref(), @@ -105,7 +105,7 @@ pub async fn join_room_by_id_or_alias_route( .map(|user| user.server_name().to_owned()), ); - servers.push(room_id.server_name().to_owned()); + servers.push(room_id.server_name().unwrap().into()); (servers, room_id) } @@ -1366,7 +1366,7 @@ pub async fn leave_all_rooms(user_id: &UserId) -> Result<()> { pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option) -> Result<()> { // Ask a remote server if we don't have this room if !services().rooms.metadata.exists(room_id)? - && room_id.server_name() != services().globals.server_name() + && room_id.server_name() != Some(services().globals.server_name()) { if let Err(e) = remote_leave_room(user_id, room_id).await { warn!("Failed to leave room {} remotely: {}", user_id, e); diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 0e2d9326..20409a28 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -366,7 +366,7 @@ pub async fn create_room_route( services().rooms.timeline.build_and_append_pdu( PduBuilder { event_type: TimelineEventType::RoomName, - content: to_raw_value(&RoomNameEventContent::new(Some(name.clone()))) + content: to_raw_value(&RoomNameEventContent::new(name.clone())) .expect("event is valid, we just created it"), unsigned: None, state_key: Some("".to_owned()), diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 64958fc7..bd682550 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -1051,7 +1051,7 @@ impl Service { services().rooms.timeline.build_and_append_pdu( PduBuilder { event_type: TimelineEventType::RoomName, - content: to_raw_value(&RoomNameEventContent::new(Some(room_name))) + content: to_raw_value(&RoomNameEventContent::new(room_name)) .expect("event is valid, we just created it"), unsigned: None, state_key: Some("".to_owned()), diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index 615e9ca0..0e84221f 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -134,7 +134,7 @@ impl Service { if serde_json::from_str::(pdu.content.get()) .ok() - .and_then(|c| c.via) + .and_then(|c| Some(c.via)) .map_or(true, |v| v.is_empty()) { continue; @@ -185,7 +185,7 @@ impl Service { stack.push(children_ids); } } else { - let server = current_room.server_name(); + let server = current_room.server_name().unwrap(); if server == services().globals.server_name() { continue; } @@ -193,7 +193,7 @@ impl Service { // Early return so the client can see some data already break; } - warn!("Asking {server} for /hierarchy"); + debug!("Asking {server} for /hierarchy"); if let Ok(response) = services() .sending .send_federation_request( diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index b00dc58c..14c3bae7 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -279,8 +279,14 @@ impl Service { .room_state_get(room_id, &StateEventType::RoomName, "")? .map_or(Ok(None), |s| { serde_json::from_str(s.content.get()) - .map(|c: RoomNameEventContent| c.name) - .map_err(|_| Error::bad_database("Invalid room name event in database.")) + .map(|c: RoomNameEventContent| Some(c.name)) + .map_err(|e| { + error!( + "Invalid room name event in database for room {}. {}", + room_id, e + ); + Error::bad_database("Invalid room name event in database.") + }) }) } diff --git a/src/utils/error.rs b/src/utils/error.rs index 6e88cf59..765a31bb 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -116,9 +116,11 @@ impl Error { Self::BadRequest(kind, _) => ( kind.clone(), match kind { - Forbidden | GuestAccessForbidden | ThreepidAuthFailed | ThreepidDenied => { - StatusCode::FORBIDDEN - } + WrongRoomKeysVersion { .. } + | Forbidden + | GuestAccessForbidden + | ThreepidAuthFailed + | ThreepidDenied => StatusCode::FORBIDDEN, Unauthorized | UnknownToken { .. } | MissingToken => StatusCode::UNAUTHORIZED, NotFound | Unrecognized => StatusCode::NOT_FOUND, LimitExceeded { .. } => StatusCode::TOO_MANY_REQUESTS, From 6dcc8b6cf1dd8554c54e435132ee90a9a7353ca8 Mon Sep 17 00:00:00 2001 From: strawberry Date: Sun, 7 Jan 2024 21:21:13 -0500 Subject: [PATCH 071/175] bump ruma to latest commit (syncv3 JsOption and push optional power levels) Signed-off-by: strawberry --- Cargo.toml | 2 +- src/api/client_server/sync.rs | 18 ++++++++++++++---- src/service/pusher/mod.rs | 12 ++++++++---- src/service/rooms/state_accessor/mod.rs | 5 +++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0fa69147..03f0cd6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "5446ea979b314b90da1734f20efaff443d64f73d", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "9a5142052c808275f47613d4b66cb6c9fc286079", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 57572284..5e675297 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1614,12 +1614,22 @@ pub async fn sync_events_v4_route( rooms.insert( room_id.clone(), sync_events::v4::SlidingSyncRoom { - name: services().rooms.state_accessor.get_name(room_id)?.or(name), - avatar: services() + name: services() .rooms .state_accessor - .get_avatar(room_id)? - .map_or(avatar, |a| a.url), + .get_name(room_id)? + .or_else(|| name), + avatar: if let Some(avatar) = avatar { + ruma::JsOption::Some(avatar) + } else { + match services().rooms.state_accessor.get_avatar(room_id)? { + ruma::JsOption::Some(avatar) => { + js_option::JsOption::Some(avatar.url.unwrap()) + } + ruma::JsOption::Null => ruma::JsOption::Null, + ruma::JsOption::Undefined => ruma::JsOption::Undefined, + } + }, initial: Some(roomsince == &0), is_dm: None, invite_state: None, diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index 315c5ef0..418b7a8f 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -1,6 +1,6 @@ mod data; pub use data::Data; -use ruma::events::AnySyncTimelineEvent; +use ruma::{events::AnySyncTimelineEvent, push::PushConditionPowerLevelsCtx}; use crate::{services, Error, PduEvent, Result}; use bytes::BytesMut; @@ -193,6 +193,12 @@ impl Service { pdu: &Raw, room_id: &RoomId, ) -> Result<&'a [Action]> { + let power_levels = PushConditionPowerLevelsCtx { + users: power_levels.users.clone(), + users_default: power_levels.users_default, + notifications: power_levels.notifications.clone(), + }; + let ctx = PushConditionRoomCtx { room_id: room_id.to_owned(), member_count: 10_u32.into(), // TODO: get member count efficiently @@ -201,9 +207,7 @@ impl Service { .users .displayname(user)? .unwrap_or_else(|| user.localpart().to_owned()), - users_power_levels: power_levels.users.clone(), - default_power_level: power_levels.users_default, - notification_power_levels: power_levels.notifications.clone(), + power_levels: Some(power_levels), }; Ok(ruleset.get_actions(pdu, &ctx)) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 14c3bae7..f49d8a3c 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -5,6 +5,7 @@ use std::{ }; pub use data::Data; +use js_option::JsOption; use lru_cache::LruCache; use ruma::{ events::{ @@ -290,12 +291,12 @@ impl Service { }) } - pub fn get_avatar(&self, room_id: &RoomId) -> Result> { + pub fn get_avatar(&self, room_id: &RoomId) -> Result> { services() .rooms .state_accessor .room_state_get(room_id, &StateEventType::RoomAvatar, "")? - .map_or(Ok(None), |s| { + .map_or(Ok(JsOption::Undefined), |s| { serde_json::from_str(s.content.get()) .map_err(|_| Error::bad_database("Invalid room avatar event in database.")) }) From e7070843456bf259e395b98c60f9b185eb75e86b Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 16 Feb 2024 20:52:07 +0000 Subject: [PATCH 072/175] chore: bump ruma to latest commit (as of 2024-02-16) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 03f0cd6f..0cf062f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "9a5142052c808275f47613d4b66cb6c9fc286079", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "f1a8497ecb0cc24b0159f301336a3bf3896d476e", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } From d841b81c56ab24210e966201258c6f7b9438340a Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 16 Feb 2024 20:52:19 +0000 Subject: [PATCH 073/175] chore: update Cargo.lock --- Cargo.lock | 79 +++++++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94a0c5e3..fc17fda3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -387,6 +387,7 @@ dependencies = [ "http", "hyper", "image", + "js_option", "jsonwebtoken", "lazy_static", "lru-cache", @@ -708,7 +709,7 @@ dependencies = [ "atomic", "pear", "serde", - "toml 0.8.8", + "toml", "uncased", "version_check", ] @@ -1802,12 +1803,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit 0.20.7", ] [[package]] @@ -2018,8 +2018,8 @@ dependencies = [ [[package]] name = "ruma" -version = "0.8.2" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.9.4" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "assign", "js_int", @@ -2037,8 +2037,8 @@ dependencies = [ [[package]] name = "ruma-appservice-api" -version = "0.8.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.9.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "js_int", "ruma-common", @@ -2049,9 +2049,10 @@ dependencies = [ [[package]] name = "ruma-client-api" -version = "0.16.2" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.17.4" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ + "as_variant", "assign", "bytes", "http", @@ -2067,8 +2068,8 @@ dependencies = [ [[package]] name = "ruma-common" -version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.12.1" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "as_variant", "base64", @@ -2095,8 +2096,8 @@ dependencies = [ [[package]] name = "ruma-events" -version = "0.26.0" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.27.11" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "as_variant", "indexmap 2.2.1", @@ -2117,8 +2118,8 @@ dependencies = [ [[package]] name = "ruma-federation-api" -version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.8.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "js_int", "ruma-common", @@ -2129,8 +2130,8 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" -version = "0.9.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.9.3" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "js_int", "thiserror", @@ -2138,8 +2139,8 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" -version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.8.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "js_int", "ruma-common", @@ -2148,8 +2149,8 @@ dependencies = [ [[package]] name = "ruma-macros" -version = "0.11.3" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.12.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "once_cell", "proc-macro-crate", @@ -2158,13 +2159,13 @@ dependencies = [ "ruma-identifiers-validation", "serde", "syn 2.0.48", - "toml 0.7.8", + "toml", ] [[package]] name = "ruma-push-gateway-api" -version = "0.7.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.8.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "js_int", "ruma-common", @@ -2175,8 +2176,8 @@ dependencies = [ [[package]] name = "ruma-signatures" -version = "0.13.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.14.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "base64", "ed25519-dalek", @@ -2191,8 +2192,8 @@ dependencies = [ [[package]] name = "ruma-state-res" -version = "0.9.1" -source = "git+https://github.com/ruma/ruma?rev=b4853aa8fa5e3a24e3689fc88044de9915f6ab67#b4853aa8fa5e3a24e3689fc88044de9915f6ab67" +version = "0.10.0" +source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" dependencies = [ "itertools", "js_int", @@ -2846,18 +2847,6 @@ dependencies = [ "tracing", ] -[[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.8" @@ -2881,13 +2870,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.2.1", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] From 4c06f329c4d2f5128d6293de9bb0342559422746 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 16 Feb 2024 21:13:59 +0000 Subject: [PATCH 074/175] refactor: appease clippy --- src/api/client_server/sync.rs | 2 +- src/service/rooms/event_handler/mod.rs | 13 ++++++++++--- src/service/rooms/spaces/mod.rs | 3 +-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 5e675297..490a947b 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1618,7 +1618,7 @@ pub async fn sync_events_v4_route( .rooms .state_accessor .get_name(room_id)? - .or_else(|| name), + .or(name), avatar: if let Some(avatar) = avatar { ruma::JsOption::Some(avatar) } else { diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index e7db6f78..375d1ff0 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -966,14 +966,21 @@ impl Service { debug!("Resolving state"); - let lock = services().globals.stateres_mutex.lock(); - let state = match state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| { + let fetch_event = |id: &_| { let res = services().rooms.timeline.get_pdu(id); if let Err(e) = &res { error!("LOOK AT ME Failed to fetch event: {}", e); } res.ok().flatten() - }) { + }; + + let lock = services().globals.stateres_mutex.lock(); + let state = match state_res::resolve( + room_version_id, + &fork_states, + auth_chain_sets, + fetch_event, + ) { Ok(new_state) => new_state, Err(_) => { return Err(Error::bad_database("State resolution failed, either an event could not be found or deserialization")); diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index 0e84221f..90523667 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -133,8 +133,7 @@ impl Service { .ok_or_else(|| Error::bad_database("Event in space state not found"))?; if serde_json::from_str::(pdu.content.get()) - .ok() - .and_then(|c| Some(c.via)) + .ok().map(|c| c.via) .map_or(true, |v| v.is_empty()) { continue; From 976a73a0e5e9aa7fc880a39f6478ec13943e2d3c Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 16 Feb 2024 21:19:40 +0000 Subject: [PATCH 075/175] style: appease rustfmt --- src/api/client_server/sync.rs | 6 +----- src/service/rooms/spaces/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 490a947b..86b3b248 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1614,11 +1614,7 @@ pub async fn sync_events_v4_route( rooms.insert( room_id.clone(), sync_events::v4::SlidingSyncRoom { - name: services() - .rooms - .state_accessor - .get_name(room_id)? - .or(name), + name: services().rooms.state_accessor.get_name(room_id)?.or(name), avatar: if let Some(avatar) = avatar { ruma::JsOption::Some(avatar) } else { diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index 90523667..07d576a9 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -133,7 +133,8 @@ impl Service { .ok_or_else(|| Error::bad_database("Event in space state not found"))?; if serde_json::from_str::(pdu.content.get()) - .ok().map(|c| c.via) + .ok() + .map(|c| c.via) .map_or(true, |v| v.is_empty()) { continue; From 1c6a4b1b24c92e8fc4132c453fffab66d922dc71 Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Sun, 18 Feb 2024 01:36:50 +0000 Subject: [PATCH 076/175] feat(ci): push oci-image to docker hub --- .gitlab-ci.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 639319c5..4f4aa695 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -127,17 +127,14 @@ debian:x86_64-unknown-linux-gnu: - target - .gitlab-ci.d -docker-publish: +.push-oci-image: stage: publish image: docker:25.0.0 services: - docker:25.0.0-dind variables: - IMAGE_NAME: $CI_REGISTRY_IMAGE/matrix-conduit IMAGE_SUFFIX_AMD64: amd64 IMAGE_SUFFIX_ARM64V8: arm64v8 - before_script: - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker load -i oci-image-amd64.tar.gz - IMAGE_ID_AMD64=$(docker images -q conduit:next) @@ -167,3 +164,17 @@ docker-publish: - next - master - tags + +oci-image:push-gitlab: + extends: .push-oci-image + variables: + IMAGE_NAME: $CI_REGISTRY_IMAGE/matrix-conduit + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + +oci-image:push-dockerhub: + extends: .push-oci-image + variables: + IMAGE_NAME: matrixconduit/matrix-conduit + before_script: + - docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWORD \ No newline at end of file From ace9637bc299df4c59efbeb3e1c432b239b7a165 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 23 Feb 2024 19:39:30 +0000 Subject: [PATCH 077/175] replace unwraps with expects --- src/api/client_server/membership.rs | 14 ++++++++++++-- src/api/client_server/sync.rs | 2 +- src/service/rooms/spaces/mod.rs | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 09f70a03..5c78a1c2 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -64,7 +64,12 @@ pub async fn join_room_by_id_route( .map(|user| user.server_name().to_owned()), ); - servers.push(body.room_id.server_name().unwrap().into()); + servers.push( + body.room_id + .server_name() + .expect("Room IDs should always have a server name") + .into(), + ); join_room_by_id_helper( body.sender_user.as_deref(), @@ -105,7 +110,12 @@ pub async fn join_room_by_id_or_alias_route( .map(|user| user.server_name().to_owned()), ); - servers.push(room_id.server_name().unwrap().into()); + servers.push( + room_id + .server_name() + .expect("Room IDs should always have a server name") + .into(), + ); (servers, room_id) } diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 86b3b248..600a9737 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1620,7 +1620,7 @@ pub async fn sync_events_v4_route( } else { match services().rooms.state_accessor.get_avatar(room_id)? { ruma::JsOption::Some(avatar) => { - js_option::JsOption::Some(avatar.url.unwrap()) + js_option::JsOption::from_option(avatar.url) } ruma::JsOption::Null => ruma::JsOption::Null, ruma::JsOption::Undefined => ruma::JsOption::Undefined, diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index 07d576a9..b0a9ed2a 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -185,7 +185,9 @@ impl Service { stack.push(children_ids); } } else { - let server = current_room.server_name().unwrap(); + let server = current_room + .server_name() + .expect("Room IDs should always have a server name"); if server == services().globals.server_name() { continue; } From 8aa915acb90552398530cc20efa1c71f788da9f6 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 23 Feb 2024 20:29:17 +0000 Subject: [PATCH 078/175] bump ruma, support deprecated user login field --- Cargo.lock | 24 ++++++++--------- Cargo.toml | 2 +- src/api/client_server/session.rs | 45 ++++++++++++++++++++------------ 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc17fda3..e20c3f0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2019,7 +2019,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.9.4" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "assign", "js_int", @@ -2038,7 +2038,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "js_int", "ruma-common", @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.17.4" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "as_variant", "assign", @@ -2069,7 +2069,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.12.1" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "as_variant", "base64", @@ -2097,7 +2097,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.27.11" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "as_variant", "indexmap 2.2.1", @@ -2119,7 +2119,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "js_int", "ruma-common", @@ -2131,7 +2131,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.3" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "js_int", "thiserror", @@ -2140,7 +2140,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "js_int", "ruma-common", @@ -2150,7 +2150,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.12.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "once_cell", "proc-macro-crate", @@ -2165,7 +2165,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "js_int", "ruma-common", @@ -2177,7 +2177,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.14.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "base64", "ed25519-dalek", @@ -2193,7 +2193,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.10.0" -source = "git+https://github.com/ruma/ruma?rev=f1a8497ecb0cc24b0159f301336a3bf3896d476e#f1a8497ecb0cc24b0159f301336a3bf3896d476e" +source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" dependencies = [ "itertools", "js_int", diff --git a/Cargo.toml b/Cargo.toml index 0cf062f6..4bc9ad5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "f1a8497ecb0cc24b0159f301336a3bf3896d476e", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } diff --git a/src/api/client_server/session.rs b/src/api/client_server/session.rs index c17bd99b..23f0b457 100644 --- a/src/api/client_server/session.rs +++ b/src/api/client_server/session.rs @@ -42,24 +42,31 @@ pub async fn get_login_types_route( /// Note: You can use [`GET /_matrix/client/r0/login`](fn.get_supported_versions_route.html) to see /// supported login types. pub async fn login_route(body: Ruma) -> Result { + // To allow deprecated login methods + #![allow(deprecated)] // Validate login method // TODO: Other login methods let user_id = match &body.login_info { login::v3::LoginInfo::Password(login::v3::Password { identifier, password, + user, + address: _, + medium: _, }) => { - let username = if let UserIdentifier::UserIdOrLocalpart(user_id) = identifier { - user_id.to_lowercase() + let user_id = if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { + UserId::parse_with_server_name( + user_id.to_lowercase(), + services().globals.server_name(), + ) + } else if let Some(user) = user { + UserId::parse(user) } else { warn!("Bad login type: {:?}", &body.login_info); return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); - }; - let user_id = - UserId::parse_with_server_name(username, services().globals.server_name()) - .map_err(|_| { - Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.") - })?; + } + .map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."))?; + let hash = services() .users .password_hash(&user_id)? @@ -105,22 +112,28 @@ pub async fn login_route(body: Ruma) -> Result { + login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService { + identifier, + user, + }) => { if !body.from_appservice { return Err(Error::BadRequest( ErrorKind::Forbidden, "Forbidden login type.", )); }; - let username = if let UserIdentifier::UserIdOrLocalpart(user_id) = identifier { - user_id.to_lowercase() + if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { + UserId::parse_with_server_name( + user_id.to_lowercase(), + services().globals.server_name(), + ) + } else if let Some(user) = user { + UserId::parse(user) } else { + warn!("Bad login type: {:?}", &body.login_info); return Err(Error::BadRequest(ErrorKind::Forbidden, "Bad login type.")); - }; - - UserId::parse_with_server_name(username, services().globals.server_name()).map_err( - |_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."), - )? + } + .map_err(|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."))? } _ => { warn!("Unsupported or unknown login type: {:?}", &body.login_info); From b27e9ea95cdddce51eca99f0fd003de131c23556 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 25 Feb 2024 08:49:20 +0000 Subject: [PATCH 079/175] chore: bump ruma to latest commit (as of 2024-02-25) --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e20c3f0b..78e85266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2019,7 +2019,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.9.4" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "assign", "js_int", @@ -2038,7 +2038,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "js_int", "ruma-common", @@ -2050,7 +2050,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.17.4" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "as_variant", "assign", @@ -2069,7 +2069,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.12.1" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "as_variant", "base64", @@ -2097,7 +2097,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.27.11" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "as_variant", "indexmap 2.2.1", @@ -2119,7 +2119,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "js_int", "ruma-common", @@ -2131,7 +2131,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.3" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "js_int", "thiserror", @@ -2140,7 +2140,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "js_int", "ruma-common", @@ -2150,7 +2150,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.12.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "once_cell", "proc-macro-crate", @@ -2165,7 +2165,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "js_int", "ruma-common", @@ -2177,7 +2177,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.14.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "base64", "ed25519-dalek", @@ -2193,7 +2193,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.10.0" -source = "git+https://github.com/ruma/ruma?rev=abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3#abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3" +source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "itertools", "js_int", diff --git a/Cargo.toml b/Cargo.toml index 4bc9ad5a..4f873cff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "abebde0cf1cbf3eb1cf8295b240c5d3f926da3a3", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "1a1c61ee1e8f0936e956a3b69c931ce12ee28475", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } From 21a5fa3ef0ccb1ad9ae9ea6328146e6dd69e4d78 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 25 Feb 2024 10:30:30 +0000 Subject: [PATCH 080/175] refactor: use re-exported JsOption from ruma rather than directly adding it as a dependency --- Cargo.lock | 1 - Cargo.toml | 3 --- src/api/client_server/sync.rs | 12 +++++------- src/service/rooms/state_accessor/mod.rs | 3 +-- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78e85266..e99928e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -387,7 +387,6 @@ dependencies = [ "http", "hyper", "image", - "js_option", "jsonwebtoken", "lazy_static", "lru-cache", diff --git a/Cargo.toml b/Cargo.toml index 4f873cff..e8c1c8bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,9 +116,6 @@ async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } -# stupid ruma using JsOption instead of Option -js_option = "0.1" - [target.'cfg(unix)'.dependencies] nix = { version = "0.26.2", features = ["resource"] } diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 600a9737..04fdb2bb 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -20,7 +20,7 @@ use ruma::{ StateEventType, TimelineEventType, }, serde::Raw, - uint, DeviceId, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, + uint, DeviceId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, }; use std::{ collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet}, @@ -1616,14 +1616,12 @@ pub async fn sync_events_v4_route( sync_events::v4::SlidingSyncRoom { name: services().rooms.state_accessor.get_name(room_id)?.or(name), avatar: if let Some(avatar) = avatar { - ruma::JsOption::Some(avatar) + JsOption::Some(avatar) } else { match services().rooms.state_accessor.get_avatar(room_id)? { - ruma::JsOption::Some(avatar) => { - js_option::JsOption::from_option(avatar.url) - } - ruma::JsOption::Null => ruma::JsOption::Null, - ruma::JsOption::Undefined => ruma::JsOption::Undefined, + JsOption::Some(avatar) => JsOption::from_option(avatar.url), + JsOption::Null => JsOption::Null, + JsOption::Undefined => JsOption::Undefined, } }, initial: Some(roomsince == &0), diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index f49d8a3c..903ad47b 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -5,7 +5,6 @@ use std::{ }; pub use data::Data; -use js_option::JsOption; use lru_cache::LruCache; use ruma::{ events::{ @@ -17,7 +16,7 @@ use ruma::{ }, StateEventType, }, - EventId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, + EventId, JsOption, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, }; use tracing::error; From f4e57fdb225e8bf87608dce62b759755b74c8393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Thu, 1 Feb 2024 12:05:59 +0100 Subject: [PATCH 081/175] Avoid federation when it is not necessary --- src/api/server_server.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index db17d586..1ba2edc0 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -1799,6 +1799,13 @@ pub async fn get_devices_route( return Err(Error::bad_config("Federation is disabled.")); } + if body.user_id.server_name() != services().globals.server_name() { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Tried to access user from other server.", + )); + } + let sender_servername = body .sender_servername .as_ref() @@ -1873,6 +1880,13 @@ pub async fn get_profile_information_route( return Err(Error::bad_config("Federation is disabled.")); } + if body.user_id.server_name() != services().globals.server_name() { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Tried to access user from other server.", + )); + } + let mut displayname = None; let mut avatar_url = None; let mut blurhash = None; @@ -1909,6 +1923,17 @@ pub async fn get_keys_route(body: Ruma) -> Result Date: Wed, 28 Feb 2024 16:24:26 +0100 Subject: [PATCH 082/175] fix: avoid panic when client is confused about rooms --- src/api/client_server/sync.rs | 3 +++ src/database/key_value/rooms/timeline.rs | 2 +- src/service/rooms/event_handler/mod.rs | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 57572284..eefdffa2 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1476,6 +1476,9 @@ pub async fn sync_events_v4_route( let mut known_subscription_rooms = BTreeSet::new(); for (room_id, room) in &body.room_subscriptions { + if !services().rooms.metadata.exists(room_id)? { + continue; + } let todo_room = todo_rooms .entry(room_id.clone()) .or_insert((BTreeSet::new(), 0, u64::MAX)); diff --git a/src/database/key_value/rooms/timeline.rs b/src/database/key_value/rooms/timeline.rs index f322d430..0331a624 100644 --- a/src/database/key_value/rooms/timeline.rs +++ b/src/database/key_value/rooms/timeline.rs @@ -331,7 +331,7 @@ fn count_to_id( .rooms .short .get_shortroomid(room_id)? - .expect("room exists") + .ok_or_else(|| Error::bad_database("Looked for bad shortroomid in timeline"))? .to_be_bytes() .to_vec(); let mut pdu_id = prefix.clone(); diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index e7db6f78..4debc607 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -184,7 +184,22 @@ impl Service { } if errors >= 5 { - break; + // Timeout other events + match services() + .globals + .bad_event_ratelimiter + .write() + .unwrap() + .entry((*prev_id).to_owned()) + { + hash_map::Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); + } + hash_map::Entry::Occupied(mut e) => { + *e.get_mut() = (Instant::now(), e.get().1 + 1) + } + } + continue; } if let Some((pdu, json)) = eventid_info.remove(&*prev_id) { From 726b6f0fa64bfbb13953366256e52052912cab96 Mon Sep 17 00:00:00 2001 From: olly1240 Date: Tue, 24 Oct 2023 11:56:49 +0000 Subject: [PATCH 083/175] Fixed nginx proxy_pass directive --- DEPLOY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPLOY.md b/DEPLOY.md index c74fb3f0..dcc41bdc 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -279,7 +279,7 @@ server { client_max_body_size 20M; location /_matrix/ { - proxy_pass http://127.0.0.1:6167$request_uri; + proxy_pass http://127.0.0.1:6167; proxy_set_header Host $http_host; proxy_buffering off; proxy_read_timeout 5m; From 62dda7a43f2797200d08f72078267892887fd135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Thu, 29 Feb 2024 10:28:06 +0100 Subject: [PATCH 084/175] improvement: delete old rocksdb LOG files --- src/database/abstraction/rocksdb.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/database/abstraction/rocksdb.rs b/src/database/abstraction/rocksdb.rs index b40c4393..7a93d787 100644 --- a/src/database/abstraction/rocksdb.rs +++ b/src/database/abstraction/rocksdb.rs @@ -49,6 +49,9 @@ fn db_options(max_open_files: i32, rocksdb_cache: &rocksdb::Cache) -> rocksdb::O db_opts.set_max_background_jobs(6); db_opts.set_bytes_per_sync(1048576); + // https://github.com/facebook/rocksdb/issues/849 + db_opts.set_keep_log_file_num(100); + // https://github.com/facebook/rocksdb/wiki/WAL-Recovery-Modes#ktoleratecorruptedtailrecords // // Unclean shutdowns of a Matrix homeserver are likely to be fine when From a159fff08aa07d9aa865bb03acbcdaec8cde5c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Thu, 29 Feb 2024 10:28:38 +0100 Subject: [PATCH 085/175] improvement: deactivate old presence code because it slows down sync The problem is that for each sync, it creates a new rocksdb iterator for each room, and creating iterators is somewhat expensive --- src/service/rooms/edus/presence/mod.rs | 37 ++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/service/rooms/edus/presence/mod.rs b/src/service/rooms/edus/presence/mod.rs index 860aea18..4b929d28 100644 --- a/src/service/rooms/edus/presence/mod.rs +++ b/src/service/rooms/edus/presence/mod.rs @@ -17,29 +17,32 @@ impl Service { /// make sure users outside these rooms can't see them. pub fn update_presence( &self, - user_id: &UserId, - room_id: &RoomId, - presence: PresenceEvent, + _user_id: &UserId, + _room_id: &RoomId, + _presence: PresenceEvent, ) -> Result<()> { - self.db.update_presence(user_id, room_id, presence) + // self.db.update_presence(user_id, room_id, presence) + Ok(()) } /// Resets the presence timeout, so the user will stay in their current presence state. - pub fn ping_presence(&self, user_id: &UserId) -> Result<()> { - self.db.ping_presence(user_id) + pub fn ping_presence(&self, _user_id: &UserId) -> Result<()> { + // self.db.ping_presence(user_id) + Ok(()) } pub fn get_last_presence_event( &self, - user_id: &UserId, - room_id: &RoomId, + _user_id: &UserId, + _room_id: &RoomId, ) -> Result> { - let last_update = match self.db.last_presence_update(user_id)? { - Some(last) => last, - None => return Ok(None), - }; + // let last_update = match self.db.last_presence_update(user_id)? { + // Some(last) => last, + // None => return Ok(None), + // }; - self.db.get_presence_event(room_id, user_id, last_update) + // self.db.get_presence_event(room_id, user_id, last_update) + Ok(None) } /* TODO @@ -111,12 +114,12 @@ impl Service { }*/ /// Returns the most recent presence updates that happened after the event with id `since`. - #[tracing::instrument(skip(self, since, room_id))] pub fn presence_since( &self, - room_id: &RoomId, - since: u64, + _room_id: &RoomId, + _since: u64, ) -> Result> { - self.db.presence_since(room_id, since) + // self.db.presence_since(room_id, since) + Ok(HashMap::new()) } } From e06e15d4ec614d284d494bac795299f05e5711fb Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 3 Mar 2024 11:26:18 +0000 Subject: [PATCH 086/175] fix(accounts): don't give guests admin --- src/api/client_server/account.rs | 29 +++++++++++++-------- src/service/admin/mod.rs | 42 +++++++++++++++---------------- src/service/rooms/timeline/mod.rs | 20 ++++----------- 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index 46551305..3a791215 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -149,17 +149,18 @@ pub async fn register_route(body: Ruma) -> Result) -> Result| { services() @@ -1105,6 +1095,24 @@ impl Service { Ok(()) } + /// Gets the room ID of the admin room + /// + /// If the room does not exist, this function panics, since it should have been created on first run + // ^ was the case before this function when the following code was re-used in multiple places + pub(crate) fn get_admin_room(&self) -> OwnedRoomId { + let admin_room_alias: Box = + format!("#admins:{}", services().globals.server_name()) + .try_into() + .expect("#admins:server_name is a valid alias name"); + + services() + .rooms + .alias + .resolve_local_alias(&admin_room_alias) + .expect("Room ID should be valid unicode, since this server created it") + .expect("Admin room must exist") + } + /// Invite the user to the conduit admin room. /// /// In conduit, this is equivalent to granting admin privileges. @@ -1113,15 +1121,7 @@ impl Service { user_id: &UserId, displayname: String, ) -> Result<()> { - let admin_room_alias: Box = - format!("#admins:{}", services().globals.server_name()) - .try_into() - .expect("#admins:server_name is a valid alias name"); - let room_id = services() - .rooms - .alias - .resolve_local_alias(&admin_room_alias)? - .expect("Admin room must exist"); + let room_id = services().admin.get_admin_room(); let mutex_state = Arc::clone( services() diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index ef09d061..13193e52 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -28,7 +28,7 @@ use ruma::{ state_res, state_res::{Event, RoomVersion}, uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, - OwnedServerName, RoomAliasId, RoomId, ServerName, UserId, + OwnedServerName, RoomId, ServerName, UserId, }; use serde::Deserialize; use serde_json::value::{to_raw_value, RawValue as RawJsonValue}; @@ -448,12 +448,7 @@ impl Service { .search .index_pdu(shortroomid, &pdu_id, &body)?; - let admin_room = services().rooms.alias.resolve_local_alias( - <&RoomAliasId>::try_from( - format!("#admins:{}", services().globals.server_name()).as_str(), - ) - .expect("#admins:server_name is a valid room alias"), - )?; + let admin_room = services().admin.get_admin_room(); let server_user = format!("@conduit:{}", services().globals.server_name()); let to_conduit = body.starts_with(&format!("{server_user}: ")) @@ -466,7 +461,7 @@ impl Service { let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none(); - if to_conduit && !from_conduit && admin_room.as_ref() == Some(&pdu.room_id) { + if to_conduit && !from_conduit && admin_room == pdu.room_id { services().admin.process_message(body); } } @@ -820,13 +815,8 @@ impl Service { let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?; - let admin_room = services().rooms.alias.resolve_local_alias( - <&RoomAliasId>::try_from( - format!("#admins:{}", services().globals.server_name()).as_str(), - ) - .expect("#admins:server_name is a valid room alias"), - )?; - if admin_room.filter(|v| v == room_id).is_some() { + let admin_room = services().admin.get_admin_room(); + if admin_room == room_id { match pdu.event_type() { TimelineEventType::RoomEncryption => { warn!("Encryption is not allowed in the admins room"); From 56a57d5489978a6b7a0a016a52e0a4a3347e687f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Sun, 3 Mar 2024 15:55:34 +0100 Subject: [PATCH 087/175] docs: small fixes for the README --- README.md | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5e01c8c1..bf7bde5e 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,6 @@ There are still a few important features missing: - E2EE emoji comparison over federation (E2EE chat works) - Outgoing read receipts, typing, presence over federation (incoming works) -Check out the [Conduit 1.0 Release Milestone](https://gitlab.com/famedly/conduit/-/milestones/3). - #### How can I deploy my own? - Simple install (this was tested the most): [DEPLOY.md](DEPLOY.md) @@ -44,13 +42,21 @@ If you want to connect an Appservice to Conduit, take a look at [APPSERVICES.md] #### How can I contribute? -1. Look for an issue you would like to work on and make sure it's not assigned - to other users -2. Ask someone to assign the issue to you (comment on the issue or chat in - [#conduit:fachschaften.org](https://matrix.to/#/#conduit:fachschaften.org)) -3. Fork the repo and work on the issue.[#conduit:fachschaften.org](https://matrix.to/#/#conduit:fachschaften.org) is happy to help :) +1. Look for an issue you would like to work on and make sure no one else is currently working on it. +2. Tell us that you are working on the issue (comment on the issue or chat in + [#conduit:fachschaften.org](https://matrix.to/#/#conduit:fachschaften.org)). If it is more complicated, please explain your approach and ask questions. +3. Fork the repo, create a new branch and push commits. 4. Submit a MR +#### Contact + +If you have any questions, feel free to +- Ask in `#conduit:fachschaften.org` on Matrix +- Write an E-Mail to `conduit@koesters.xyz` +- Send an direct message to `@timokoesters:fachschaften.org` on Matrix +- [Open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new) + + #### Thanks to Thanks to FUTO, Famedly, Prototype Fund (DLR and German BMBF) and all individuals for financially supporting this project. @@ -60,14 +66,6 @@ Thanks to the contributors to Conduit and all libraries we use, for example: - Ruma: A clean library for the Matrix Spec in Rust - axum: A modular web framework -#### Contact - -If you run into any question, feel free to -- Ask us in `#conduit:fachschaften.org` on Matrix -- Write an E-Mail to `conduit@koesters.xyz` -- Send an direct message to `timokoesters@fachschaften.org` on Matrix -- [Open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new) - #### Donate Liberapay: \ From da5975d7271a717b2f788931771b879d0ea78bd9 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 3 Mar 2024 22:42:24 +0000 Subject: [PATCH 088/175] fix: avoid panics when admin room is not available --- src/api/client_server/account.rs | 50 +++--- src/service/admin/mod.rs | 276 +++++++++++++++--------------- src/service/rooms/timeline/mod.rs | 148 ++++++++-------- 3 files changed, 239 insertions(+), 235 deletions(-) diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index 3a791215..d4529a40 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -149,18 +149,17 @@ pub async fn register_route(body: Ruma) -> Result) -> Result| { - services() - .rooms - .timeline - .build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMessage, - content: to_raw_value(&message) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: None, - redacts: None, - }, - &conduit_user, - &conduit_room, - mutex_lock, - ) - .unwrap(); - }; - - loop { - tokio::select! { - Some(event) = receiver.recv() => { - let message_content = match event { - AdminRoomEvent::SendMessage(content) => content, - AdminRoomEvent::ProcessMessage(room_message) => self.process_admin_message(room_message).await - }; - - let mutex_state = Arc::clone( - services().globals - .roomid_mutex_state - .write() - .unwrap() - .entry(conduit_room.to_owned()) - .or_default(), - ); - - let state_lock = mutex_state.lock().await; - - send_message(message_content, &state_lock); - - drop(state_lock); + if let Ok(Some(conduit_room)) = services().admin.get_admin_room() { + let send_message = |message: RoomMessageEventContent, + mutex_lock: &MutexGuard<'_, ()>| { + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMessage, + content: to_raw_value(&message) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: None, + redacts: None, + }, + &conduit_user, + &conduit_room, + mutex_lock, + ) + .unwrap(); + }; + + loop { + tokio::select! { + Some(event) = receiver.recv() => { + let message_content = match event { + AdminRoomEvent::SendMessage(content) => content, + AdminRoomEvent::ProcessMessage(room_message) => self.process_admin_message(room_message).await + }; + + let mutex_state = Arc::clone( + services().globals + .roomid_mutex_state + .write() + .unwrap() + .entry(conduit_room.to_owned()) + .or_default(), + ); + + let state_lock = mutex_state.lock().await; + + send_message(message_content, &state_lock); + + drop(state_lock); + } } } } @@ -1097,9 +1098,8 @@ impl Service { /// Gets the room ID of the admin room /// - /// If the room does not exist, this function panics, since it should have been created on first run - // ^ was the case before this function when the following code was re-used in multiple places - pub(crate) fn get_admin_room(&self) -> OwnedRoomId { + /// Errors are propagated from the database, and will have None if there is no admin room + pub(crate) fn get_admin_room(&self) -> Result> { let admin_room_alias: Box = format!("#admins:{}", services().globals.server_name()) .try_into() @@ -1109,8 +1109,6 @@ impl Service { .rooms .alias .resolve_local_alias(&admin_room_alias) - .expect("Room ID should be valid unicode, since this server created it") - .expect("Admin room must exist") } /// Invite the user to the conduit admin room. @@ -1121,94 +1119,93 @@ impl Service { user_id: &UserId, displayname: String, ) -> Result<()> { - let room_id = services().admin.get_admin_room(); - - let mutex_state = Arc::clone( - services() - .globals - .roomid_mutex_state - .write() - .unwrap() - .entry(room_id.clone()) - .or_default(), - ); - let state_lock = mutex_state.lock().await; - - // Use the server user to grant the new admin's power level - let conduit_user = - UserId::parse_with_server_name("conduit", services().globals.server_name()) - .expect("@conduit:server_name is valid"); - - // Invite and join the real user - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Invite, - displayname: None, - avatar_url: None, - is_direct: None, - third_party_invite: None, - blurhash: None, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(user_id.to_string()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Join, - displayname: Some(displayname), - avatar_url: None, - is_direct: None, - third_party_invite: None, - blurhash: None, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(user_id.to_string()), - redacts: None, - }, - user_id, - &room_id, - &state_lock, - )?; - - // Set power level - let mut users = BTreeMap::new(); - users.insert(conduit_user.to_owned(), 100.into()); - users.insert(user_id.to_owned(), 100.into()); - - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomPowerLevels, - content: to_raw_value(&RoomPowerLevelsEventContent { - users, - ..Default::default() - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; - - // Send welcome message - services().rooms.timeline.build_and_append_pdu( + if let Some(room_id) = services().admin.get_admin_room()? { + let mutex_state = Arc::clone( + services() + .globals + .roomid_mutex_state + .write() + .unwrap() + .entry(room_id.clone()) + .or_default(), + ); + let state_lock = mutex_state.lock().await; + + // Use the server user to grant the new admin's power level + let conduit_user = + UserId::parse_with_server_name("conduit", services().globals.server_name()) + .expect("@conduit:server_name is valid"); + + // Invite and join the real user + services().rooms.timeline.build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Invite, + displayname: None, + avatar_url: None, + is_direct: None, + third_party_invite: None, + blurhash: None, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + )?; + services().rooms.timeline.build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Join, + displayname: Some(displayname), + avatar_url: None, + is_direct: None, + third_party_invite: None, + blurhash: None, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + user_id, + &room_id, + &state_lock, + )?; + + // Set power level + let mut users = BTreeMap::new(); + users.insert(conduit_user.to_owned(), 100.into()); + users.insert(user_id.to_owned(), 100.into()); + + services().rooms.timeline.build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomPowerLevels, + content: to_raw_value(&RoomPowerLevelsEventContent { + users, + ..Default::default() + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + )?; + + // Send welcome message + services().rooms.timeline.build_and_append_pdu( PduBuilder { event_type: TimelineEventType::RoomMessage, content: to_raw_value(&RoomMessageEventContent::text_html( @@ -1225,7 +1222,10 @@ impl Service { &state_lock, )?; - Ok(()) + Ok(()) + } else { + Ok(()) + } } } diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 13193e52..b66fc645 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -448,7 +448,6 @@ impl Service { .search .index_pdu(shortroomid, &pdu_id, &body)?; - let admin_room = services().admin.get_admin_room(); let server_user = format!("@conduit:{}", services().globals.server_name()); let to_conduit = body.starts_with(&format!("{server_user}: ")) @@ -461,8 +460,10 @@ impl Service { let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none(); - if to_conduit && !from_conduit && admin_room == pdu.room_id { - services().admin.process_message(body); + if let Some(admin_room) = services().admin.get_admin_room()? { + if to_conduit && !from_conduit && admin_room == pdu.room_id { + services().admin.process_message(body); + } } } } @@ -815,84 +816,85 @@ impl Service { let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?; - let admin_room = services().admin.get_admin_room(); - if admin_room == room_id { - match pdu.event_type() { - TimelineEventType::RoomEncryption => { - warn!("Encryption is not allowed in the admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Encryption is not allowed in the admins room.", - )); - } - TimelineEventType::RoomMember => { - #[derive(Deserialize)] - struct ExtractMembership { - membership: MembershipState, + if let Some(admin_room) = services().admin.get_admin_room()? { + if admin_room == room_id { + match pdu.event_type() { + TimelineEventType::RoomEncryption => { + warn!("Encryption is not allowed in the admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Encryption is not allowed in the admins room.", + )); } - - let target = pdu - .state_key() - .filter(|v| v.starts_with('@')) - .unwrap_or(sender.as_str()); - let server_name = services().globals.server_name(); - let server_user = format!("@conduit:{}", server_name); - let content = serde_json::from_str::(pdu.content.get()) - .map_err(|_| Error::bad_database("Invalid content in pdu."))?; - - if content.membership == MembershipState::Leave { - if target == server_user { - warn!("Conduit user cannot leave from admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Conduit user cannot leave from admins room.", - )); + TimelineEventType::RoomMember => { + #[derive(Deserialize)] + struct ExtractMembership { + membership: MembershipState, } - let count = services() - .rooms - .state_cache - .room_members(room_id) - .filter_map(|m| m.ok()) - .filter(|m| m.server_name() == server_name) - .filter(|m| m != target) - .count(); - if count < 2 { - warn!("Last admin cannot leave from admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Last admin cannot leave from admins room.", - )); + let target = pdu + .state_key() + .filter(|v| v.starts_with('@')) + .unwrap_or(sender.as_str()); + let server_name = services().globals.server_name(); + let server_user = format!("@conduit:{}", server_name); + let content = serde_json::from_str::(pdu.content.get()) + .map_err(|_| Error::bad_database("Invalid content in pdu."))?; + + if content.membership == MembershipState::Leave { + if target == server_user { + warn!("Conduit user cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Conduit user cannot leave from admins room.", + )); + } + + let count = services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(|m| m.ok()) + .filter(|m| m.server_name() == server_name) + .filter(|m| m != target) + .count(); + if count < 2 { + warn!("Last admin cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Last admin cannot leave from admins room.", + )); + } } - } - if content.membership == MembershipState::Ban && pdu.state_key().is_some() { - if target == server_user { - warn!("Conduit user cannot be banned in admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Conduit user cannot be banned in admins room.", - )); - } - - let count = services() - .rooms - .state_cache - .room_members(room_id) - .filter_map(|m| m.ok()) - .filter(|m| m.server_name() == server_name) - .filter(|m| m != target) - .count(); - if count < 2 { - warn!("Last admin cannot be banned in admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Last admin cannot be banned in admins room.", - )); + if content.membership == MembershipState::Ban && pdu.state_key().is_some() { + if target == server_user { + warn!("Conduit user cannot be banned in admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Conduit user cannot be banned in admins room.", + )); + } + + let count = services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(|m| m.ok()) + .filter(|m| m.server_name() == server_name) + .filter(|m| m != target) + .count(); + if count < 2 { + warn!("Last admin cannot be banned in admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Last admin cannot be banned in admins room.", + )); + } } } + _ => {} } - _ => {} } } From 4934020ee705a5ca28839583281f257f4ee1ec24 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 4 Mar 2024 09:32:21 +0000 Subject: [PATCH 089/175] style: remove unnecessary else block --- src/service/admin/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 44c7934a..f6e52f7a 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -1221,11 +1221,8 @@ impl Service { &room_id, &state_lock, )?; - - Ok(()) - } else { - Ok(()) } + Ok(()) } } From becaad677f22e3fb9f4a4e076f576110daae9393 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 14:22:54 +0000 Subject: [PATCH 090/175] refactor: use async-aware RwLocks and Mutexes where possible --- Cargo.lock | 12 + Cargo.toml | 1 + src/api/client_server/keys.rs | 27 +- src/api/client_server/membership.rs | 263 +++++++------ src/api/client_server/message.rs | 43 ++- src/api/client_server/profile.rs | 26 +- src/api/client_server/redact.rs | 38 +- src/api/client_server/room.rs | 493 +++++++++++++----------- src/api/client_server/state.rs | 30 +- src/api/client_server/sync.rs | 130 ++++--- src/api/server_server.rs | 13 +- src/lib.rs | 3 + src/service/admin/mod.rs | 503 +++++++++++++------------ src/service/globals/mod.rs | 18 +- src/service/mod.rs | 39 +- src/service/rooms/event_handler/mod.rs | 427 +++++++++++---------- src/service/rooms/lazy_loading/mod.rs | 14 +- src/service/rooms/spaces/mod.rs | 11 +- src/service/rooms/state/mod.rs | 2 +- src/service/rooms/timeline/mod.rs | 56 ++- src/service/users/mod.rs | 6 +- 21 files changed, 1160 insertions(+), 995 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e99928e0..426661bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" +[[package]] +name = "async-recursion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "async-trait" version = "0.1.77" @@ -374,6 +385,7 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" name = "conduit" version = "0.7.0-alpha" dependencies = [ + "async-recursion", "async-trait", "axum", "axum-server", diff --git a/Cargo.toml b/Cargo.toml index e8c1c8bf..93ff2f3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,6 +115,7 @@ lazy_static = "1.4.0" async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } +async-recursion = "1.0.5" [target.'cfg(unix)'.dependencies] nix = { version = "0.26.2", features = ["resource"] } diff --git a/src/api/client_server/keys.rs b/src/api/client_server/keys.rs index 9fd00897..4af8890d 100644 --- a/src/api/client_server/keys.rs +++ b/src/api/client_server/keys.rs @@ -339,17 +339,19 @@ pub(crate) async fn get_keys_helper bool>( let mut failures = BTreeMap::new(); - let back_off = |id| match services() - .globals - .bad_query_ratelimiter - .write() - .unwrap() - .entry(id) - { - hash_map::Entry::Vacant(e) => { - e.insert((Instant::now(), 1)); + let back_off = |id| async { + match services() + .globals + .bad_query_ratelimiter + .write() + .await + .entry(id) + { + hash_map::Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); + } + hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), } - hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), }; let mut futures: FuturesUnordered<_> = get_over_federation @@ -359,7 +361,7 @@ pub(crate) async fn get_keys_helper bool>( .globals .bad_query_ratelimiter .read() - .unwrap() + .await .get(server) { // Exponential backoff @@ -428,7 +430,8 @@ pub(crate) async fn get_keys_helper bool>( device_keys.extend(response.device_keys); } _ => { - back_off(server.to_owned()); + back_off(server.to_owned()).await; + failures.insert(server.to_string(), json!({})); } } diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 5c78a1c2..bc84b262 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -26,9 +26,10 @@ use ruma::{ use serde_json::value::{to_raw_value, RawValue as RawJsonValue}; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - sync::{Arc, RwLock}, + sync::Arc, time::{Duration, Instant}, }; +use tokio::sync::RwLock; use tracing::{debug, error, info, warn}; use crate::{ @@ -212,24 +213,28 @@ pub async fn kick_user_route( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(body.room_id.clone()) .or_default(), ); let state_lock = mutex_state.lock().await; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&event).expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(body.user_id.to_string()), - redacts: None, - }, - sender_user, - &body.room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(body.user_id.to_string()), + redacts: None, + }, + sender_user, + &body.room_id, + &state_lock, + ) + .await?; drop(state_lock); @@ -276,24 +281,28 @@ pub async fn ban_user_route(body: Ruma) -> Result t, Err(_) => continue, }; @@ -710,7 +723,7 @@ async fn join_room_by_id_helper( .iter() .map(|pdu| validate_and_add_event_id(pdu, &room_version_id, &pub_key_map)) { - let (event_id, value) = match result { + let (event_id, value) = match result.await { Ok(t) => t, Err(_) => continue, }; @@ -784,12 +797,16 @@ async fn join_room_by_id_helper( let statehash_after_join = services().rooms.state.append_to_state(&parsed_join_pdu)?; info!("Appending new room join event"); - services().rooms.timeline.append_pdu( - &parsed_join_pdu, - join_event, - vec![(*parsed_join_pdu.event_id).to_owned()], - &state_lock, - )?; + services() + .rooms + .timeline + .append_pdu( + &parsed_join_pdu, + join_event, + vec![(*parsed_join_pdu.event_id).to_owned()], + &state_lock, + ) + .await?; info!("Setting final room state for new room"); // We set the room state after inserting the pdu, so that we never have a moment in time @@ -902,18 +919,23 @@ async fn join_room_by_id_helper( }; // Try normal join first - let error = match services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&event).expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(sender_user.to_string()), - redacts: None, - }, - sender_user, - room_id, - &state_lock, - ) { + let error = match services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&event).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_user.to_string()), + redacts: None, + }, + sender_user, + room_id, + &state_lock, + ) + .await + { Ok(_event_id) => return Ok(join_room_by_id::v3::Response::new(room_id.to_owned())), Err(e) => e, }; @@ -1109,7 +1131,7 @@ async fn make_join_request( make_join_response_and_server } -fn validate_and_add_event_id( +async fn validate_and_add_event_id( pdu: &RawJsonValue, room_version: &RoomVersionId, pub_key_map: &RwLock>>, @@ -1125,24 +1147,26 @@ fn validate_and_add_event_id( )) .expect("ruma's reference hashes are valid event ids"); - let back_off = |id| match services() - .globals - .bad_event_ratelimiter - .write() - .unwrap() - .entry(id) - { - Entry::Vacant(e) => { - e.insert((Instant::now(), 1)); + let back_off = |id| async { + match services() + .globals + .bad_event_ratelimiter + .write() + .await + .entry(id) + { + Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); + } + Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), } - Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), }; if let Some((time, tries)) = services() .globals .bad_event_ratelimiter .read() - .unwrap() + .await .get(&event_id) { // Exponential backoff @@ -1157,15 +1181,10 @@ fn validate_and_add_event_id( } } - if let Err(e) = ruma::signatures::verify_event( - &*pub_key_map - .read() - .map_err(|_| Error::bad_database("RwLock is poisoned."))?, - &value, - room_version, - ) { + if let Err(e) = ruma::signatures::verify_event(&*pub_key_map.read().await, &value, room_version) + { warn!("Event {} failed verification {:?} {}", event_id, pdu, e); - back_off(event_id); + back_off(event_id).await; return Err(Error::BadServerResponse("Event failed verification.")); } @@ -1191,7 +1210,7 @@ pub(crate) async fn invite_helper<'a>( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); @@ -1312,34 +1331,38 @@ pub(crate) async fn invite_helper<'a>( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); let state_lock = mutex_state.lock().await; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Invite, - displayname: services().users.displayname(user_id)?, - avatar_url: services().users.avatar_url(user_id)?, - is_direct: Some(is_direct), - third_party_invite: None, - blurhash: services().users.blurhash(user_id)?, - reason, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(user_id.to_string()), - redacts: None, - }, - sender_user, - room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Invite, + displayname: services().users.displayname(user_id)?, + avatar_url: services().users.avatar_url(user_id)?, + is_direct: Some(is_direct), + third_party_invite: None, + blurhash: services().users.blurhash(user_id)?, + reason, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + sender_user, + room_id, + &state_lock, + ) + .await?; drop(state_lock); @@ -1407,7 +1430,7 @@ pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option JoinRule::Public, - // according to spec "invite" is the default - _ => JoinRule::Invite, - })) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomJoinRules, + content: to_raw_value(&RoomJoinRulesEventContent::new(match preset { + RoomPreset::PublicChat => JoinRule::Public, + // according to spec "invite" is the default + _ => JoinRule::Invite, + })) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &room_id, + &state_lock, + ) + .await?; // 5.2 History Visibility - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomHistoryVisibility, - content: to_raw_value(&RoomHistoryVisibilityEventContent::new( - HistoryVisibility::Shared, - )) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomHistoryVisibility, + content: to_raw_value(&RoomHistoryVisibilityEventContent::new( + HistoryVisibility::Shared, + )) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &room_id, + &state_lock, + ) + .await?; // 5.3 Guest Access - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomGuestAccess, - content: to_raw_value(&RoomGuestAccessEventContent::new(match preset { - RoomPreset::PublicChat => GuestAccess::Forbidden, - _ => GuestAccess::CanJoin, - })) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomGuestAccess, + content: to_raw_value(&RoomGuestAccessEventContent::new(match preset { + RoomPreset::PublicChat => GuestAccess::Forbidden, + _ => GuestAccess::CanJoin, + })) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &room_id, + &state_lock, + ) + .await?; // 6. Events listed in initial_state for event in &body.initial_state { @@ -353,47 +381,54 @@ pub async fn create_room_route( continue; } - services().rooms.timeline.build_and_append_pdu( - pdu_builder, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock) + .await?; } // 7. Events implied by name and topic if let Some(name) = &body.name { - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomName, - content: to_raw_value(&RoomNameEventContent::new(name.clone())) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomName, + content: to_raw_value(&RoomNameEventContent::new(name.clone())) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &room_id, + &state_lock, + ) + .await?; } if let Some(topic) = &body.topic { - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomTopic, - content: to_raw_value(&RoomTopicEventContent { - topic: topic.clone(), - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomTopic, + content: to_raw_value(&RoomTopicEventContent { + topic: topic.clone(), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &room_id, + &state_lock, + ) + .await?; } // 8. Events implied by invite (and TODO: invite_3pid) @@ -523,7 +558,7 @@ pub async fn upgrade_room_route( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(body.room_id.clone()) .or_default(), ); @@ -531,22 +566,26 @@ pub async fn upgrade_room_route( // Send a m.room.tombstone event to the old room to indicate that it is not intended to be used any further // Fail if the sender does not have the required permissions - let tombstone_event_id = services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomTombstone, - content: to_raw_value(&RoomTombstoneEventContent { - body: "This room has been replaced".to_owned(), - replacement_room: replacement_room.clone(), - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &body.room_id, - &state_lock, - )?; + let tombstone_event_id = services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomTombstone, + content: to_raw_value(&RoomTombstoneEventContent { + body: "This room has been replaced".to_owned(), + replacement_room: replacement_room.clone(), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &body.room_id, + &state_lock, + ) + .await?; // Change lock to replacement room drop(state_lock); @@ -555,7 +594,7 @@ pub async fn upgrade_room_route( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(replacement_room.clone()) .or_default(), ); @@ -613,43 +652,51 @@ pub async fn upgrade_room_route( )); } - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomCreate, - content: to_raw_value(&create_event_content) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &replacement_room, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomCreate, + content: to_raw_value(&create_event_content) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &replacement_room, + &state_lock, + ) + .await?; // Join the new room - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Join, - displayname: services().users.displayname(sender_user)?, - avatar_url: services().users.avatar_url(sender_user)?, - is_direct: None, - third_party_invite: None, - blurhash: services().users.blurhash(sender_user)?, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(sender_user.to_string()), - redacts: None, - }, - sender_user, - &replacement_room, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Join, + displayname: services().users.displayname(sender_user)?, + avatar_url: services().users.avatar_url(sender_user)?, + is_direct: None, + third_party_invite: None, + blurhash: services().users.blurhash(sender_user)?, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(sender_user.to_string()), + redacts: None, + }, + sender_user, + &replacement_room, + &state_lock, + ) + .await?; // Recommended transferable state events list from the specs let transferable_state_events = vec![ @@ -676,18 +723,22 @@ pub async fn upgrade_room_route( None => continue, // Skipping missing events. }; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: event_type.to_string().into(), - content: event_content, - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &replacement_room, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: event_type.to_string().into(), + content: event_content, + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &replacement_room, + &state_lock, + ) + .await?; } // Moves any local aliases to the new room @@ -721,19 +772,23 @@ pub async fn upgrade_room_route( power_levels_event_content.invite = new_level; // Modify the power levels in the old room to prevent sending of events and inviting new users - let _ = services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomPowerLevels, - content: to_raw_value(&power_levels_event_content) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - sender_user, - &body.room_id, - &state_lock, - )?; + let _ = services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomPowerLevels, + content: to_raw_value(&power_levels_event_content) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + sender_user, + &body.room_id, + &state_lock, + ) + .await?; drop(state_lock); diff --git a/src/api/client_server/state.rs b/src/api/client_server/state.rs index 174282a1..e62aa013 100644 --- a/src/api/client_server/state.rs +++ b/src/api/client_server/state.rs @@ -227,24 +227,28 @@ async fn send_state_event_for_key_helper( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); let state_lock = mutex_state.lock().await; - let event_id = services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: event_type.to_string().into(), - content: serde_json::from_str(json.json().get()).expect("content is valid json"), - unsigned: None, - state_key: Some(state_key), - redacts: None, - }, - sender_user, - room_id, - &state_lock, - )?; + let event_id = services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: event_type.to_string().into(), + content: serde_json::from_str(json.json().get()).expect("content is valid json"), + unsigned: None, + state_key: Some(state_key), + redacts: None, + }, + sender_user, + room_id, + &state_lock, + ) + .await?; Ok(event_id) } diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 76b48d10..5ac00c60 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1,6 +1,7 @@ use crate::{ service::rooms::timeline::PduCount, services, Error, PduEvent, Result, Ruma, RumaResponse, }; + use ruma::{ api::client::{ filter::{FilterDefinition, LazyLoadOptions}, @@ -75,7 +76,7 @@ pub async fn sync_events_route( .globals .sync_receivers .write() - .unwrap() + .await .entry((sender_user.clone(), sender_device.clone())) { Entry::Vacant(v) => { @@ -147,7 +148,7 @@ async fn sync_helper_wrapper( .globals .sync_receivers .write() - .unwrap() + .await .entry((sender_user, sender_device)) { Entry::Occupied(o) => { @@ -302,11 +303,11 @@ async fn sync_helper( .globals .roomid_mutex_insert .write() - .unwrap() + .await .entry(room_id.clone()) .or_default(), ); - let insert_lock = mutex_insert.lock().unwrap(); + let insert_lock = mutex_insert.lock().await; drop(insert_lock); } @@ -434,11 +435,11 @@ async fn sync_helper( .globals .roomid_mutex_insert .write() - .unwrap() + .await .entry(room_id.clone()) .or_default(), ); - let insert_lock = mutex_insert.lock().unwrap(); + let insert_lock = mutex_insert.lock().await; drop(insert_lock); } @@ -577,11 +578,11 @@ async fn load_joined_room( .globals .roomid_mutex_insert .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); - let insert_lock = mutex_insert.lock().unwrap(); + let insert_lock = mutex_insert.lock().await; drop(insert_lock); } @@ -599,12 +600,11 @@ async fn load_joined_room( timeline_users.insert(event.sender.as_str().to_owned()); } - services().rooms.lazy_loading.lazy_load_confirm_delivery( - sender_user, - sender_device, - room_id, - sincecount, - )?; + services() + .rooms + .lazy_loading + .lazy_load_confirm_delivery(sender_user, sender_device, room_id, sincecount) + .await?; // Database queries: @@ -797,13 +797,17 @@ async fn load_joined_room( // The state_events above should contain all timeline_users, let's mark them as lazy // loaded. - services().rooms.lazy_loading.lazy_load_mark_sent( - sender_user, - sender_device, - room_id, - lazy_loaded, - next_batchcount, - ); + services() + .rooms + .lazy_loading + .lazy_load_mark_sent( + sender_user, + sender_device, + room_id, + lazy_loaded, + next_batchcount, + ) + .await; ( heroes, @@ -884,13 +888,17 @@ async fn load_joined_room( } } - services().rooms.lazy_loading.lazy_load_mark_sent( - sender_user, - sender_device, - room_id, - lazy_loaded, - next_batchcount, - ); + services() + .rooms + .lazy_loading + .lazy_load_mark_sent( + sender_user, + sender_device, + room_id, + lazy_loaded, + next_batchcount, + ) + .await; let encrypted_room = services() .rooms @@ -1189,11 +1197,14 @@ pub async fn sync_events_v4_route( if globalsince == 0 { if let Some(conn_id) = &body.conn_id { - services().users.forget_sync_request_connection( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - ) + services() + .users + .forget_sync_request_connection( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + ) + .await } } @@ -1463,14 +1474,17 @@ pub async fn sync_events_v4_route( ); if let Some(conn_id) = &body.conn_id { - services().users.update_sync_known_rooms( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - list_id, - new_known_rooms, - globalsince, - ); + services() + .users + .update_sync_known_rooms( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + list_id, + new_known_rooms, + globalsince, + ) + .await; } } @@ -1502,23 +1516,29 @@ pub async fn sync_events_v4_route( } if let Some(conn_id) = &body.conn_id { - services().users.update_sync_known_rooms( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - "subscriptions".to_owned(), - known_subscription_rooms, - globalsince, - ); + services() + .users + .update_sync_known_rooms( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + "subscriptions".to_owned(), + known_subscription_rooms, + globalsince, + ) + .await; } if let Some(conn_id) = &body.conn_id { - services().users.update_sync_subscriptions( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - body.room_subscriptions, - ); + services() + .users + .update_sync_subscriptions( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + body.room_subscriptions, + ) + .await; } let mut rooms = BTreeMap::new(); diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 1ba2edc0..f946feaf 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -51,9 +51,10 @@ use std::{ fmt::Debug, mem, net::{IpAddr, SocketAddr}, - sync::{Arc, RwLock}, + sync::Arc, time::{Duration, Instant, SystemTime}, }; +use tokio::sync::RwLock; use tracing::{debug, error, warn}; @@ -137,7 +138,7 @@ where .globals .actual_destination_cache .read() - .unwrap() + .await .get(destination) .cloned(); @@ -290,7 +291,7 @@ where .globals .actual_destination_cache .write() - .unwrap() + .await .insert( OwnedServerName::from(destination), (actual_destination, host), @@ -740,7 +741,7 @@ pub async fn send_transaction_message_route( .globals .roomid_mutex_federation .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); @@ -1409,7 +1410,7 @@ pub async fn create_join_event_template_route( .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(body.room_id.to_owned()) .or_default(), ); @@ -1579,7 +1580,7 @@ async fn create_join_event( .globals .roomid_mutex_federation .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); diff --git a/src/lib.rs b/src/lib.rs index 66d0c57c..9c1170dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,9 @@ mod database; mod service; mod utils; +// Not async due to services() being used in many closures, and async colsures are not stable as of writing +// This is the case for every other occurence of sync Mutex/RwLock, except for database related ones, where +// the current maintainer (Timo) as asked to not modify those use std::sync::RwLock; pub use api::ruma_wrapper::{Ruma, RumaResponse}; diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index f6e52f7a..d99be878 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -1,7 +1,7 @@ use std::{ collections::BTreeMap, convert::{TryFrom, TryInto}, - sync::{Arc, RwLock}, + sync::Arc, time::Instant, }; @@ -26,7 +26,7 @@ use ruma::{ EventId, OwnedRoomAliasId, OwnedRoomId, RoomAliasId, RoomId, RoomVersionId, ServerName, UserId, }; use serde_json::value::to_raw_value; -use tokio::sync::{mpsc, Mutex, MutexGuard}; +use tokio::sync::{mpsc, Mutex, RwLock}; use crate::{ api::client_server::{leave_all_rooms, AUTO_GEN_PASSWORD_LENGTH}, @@ -215,27 +215,6 @@ impl Service { .expect("@conduit:server_name is valid"); if let Ok(Some(conduit_room)) = services().admin.get_admin_room() { - let send_message = |message: RoomMessageEventContent, - mutex_lock: &MutexGuard<'_, ()>| { - services() - .rooms - .timeline - .build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMessage, - content: to_raw_value(&message) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: None, - redacts: None, - }, - &conduit_user, - &conduit_room, - mutex_lock, - ) - .unwrap(); - }; - loop { tokio::select! { Some(event) = receiver.recv() => { @@ -248,16 +227,30 @@ impl Service { services().globals .roomid_mutex_state .write() - .unwrap() + .await .entry(conduit_room.to_owned()) .or_default(), ); let state_lock = mutex_state.lock().await; - send_message(message_content, &state_lock); - - drop(state_lock); + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMessage, + content: to_raw_value(&message_content) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: None, + redacts: None, + }, + &conduit_user, + &conduit_room, + &state_lock, + ) + .await.unwrap(); } } } @@ -425,11 +418,7 @@ impl Service { Err(e) => RoomMessageEventContent::text_plain(e.to_string()), }, AdminCommand::IncomingFederation => { - let map = services() - .globals - .roomid_federationhandletime - .read() - .unwrap(); + let map = services().globals.roomid_federationhandletime.read().await; let mut msg: String = format!("Handling {} incoming pdus:\n", map.len()); for (r, (e, i)) in map.iter() { @@ -543,7 +532,7 @@ impl Service { } } AdminCommand::MemoryUsage => { - let response1 = services().memory_usage(); + let response1 = services().memory_usage().await; let response2 = services().globals.db.memory_usage(); RoomMessageEventContent::text_plain(format!( @@ -556,7 +545,7 @@ impl Service { RoomMessageEventContent::text_plain("Done.") } AdminCommand::ClearServiceCaches { amount } => { - services().clear_caches(amount); + services().clear_caches(amount).await; RoomMessageEventContent::text_plain("Done.") } @@ -797,7 +786,7 @@ impl Service { .fetch_required_signing_keys(&value, &pub_key_map) .await?; - let pub_key_map = pub_key_map.read().unwrap(); + let pub_key_map = pub_key_map.read().await; match ruma::signatures::verify_json(&pub_key_map, &value) { Ok(_) => RoomMessageEventContent::text_plain("Signature correct"), Err(e) => RoomMessageEventContent::text_plain(format!( @@ -913,7 +902,7 @@ impl Service { .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.clone()) .or_default(), ); @@ -932,164 +921,202 @@ impl Service { content.room_version = services().globals.default_room_version(); // 1. The room create event - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomCreate, - content: to_raw_value(&content).expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomCreate, + content: to_raw_value(&content).expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 2. Make conduit bot join - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Join, - displayname: None, - avatar_url: None, - is_direct: None, - third_party_invite: None, - blurhash: None, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(conduit_user.to_string()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Join, + displayname: None, + avatar_url: None, + is_direct: None, + third_party_invite: None, + blurhash: None, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(conduit_user.to_string()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 3. Power levels let mut users = BTreeMap::new(); users.insert(conduit_user.clone(), 100.into()); - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomPowerLevels, - content: to_raw_value(&RoomPowerLevelsEventContent { - users, - ..Default::default() - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomPowerLevels, + content: to_raw_value(&RoomPowerLevelsEventContent { + users, + ..Default::default() + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 4.1 Join Rules - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomJoinRules, - content: to_raw_value(&RoomJoinRulesEventContent::new(JoinRule::Invite)) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomJoinRules, + content: to_raw_value(&RoomJoinRulesEventContent::new(JoinRule::Invite)) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 4.2 History Visibility - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomHistoryVisibility, - content: to_raw_value(&RoomHistoryVisibilityEventContent::new( - HistoryVisibility::Shared, - )) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomHistoryVisibility, + content: to_raw_value(&RoomHistoryVisibilityEventContent::new( + HistoryVisibility::Shared, + )) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 4.3 Guest Access - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomGuestAccess, - content: to_raw_value(&RoomGuestAccessEventContent::new(GuestAccess::Forbidden)) + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomGuestAccess, + content: to_raw_value(&RoomGuestAccessEventContent::new( + GuestAccess::Forbidden, + )) .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 5. Events implied by name and topic let room_name = format!("{} Admin Room", services().globals.server_name()); - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomName, - content: to_raw_value(&RoomNameEventContent::new(room_name)) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomName, + content: to_raw_value(&RoomNameEventContent::new(room_name)) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomTopic, - content: to_raw_value(&RoomTopicEventContent { - topic: format!("Manage {}", services().globals.server_name()), - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomTopic, + content: to_raw_value(&RoomTopicEventContent { + topic: format!("Manage {}", services().globals.server_name()), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // 6. Room alias let alias: OwnedRoomAliasId = format!("#admins:{}", services().globals.server_name()) .try_into() .expect("#admins:server_name is a valid alias name"); - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomCanonicalAlias, - content: to_raw_value(&RoomCanonicalAliasEventContent { - alias: Some(alias.clone()), - alt_aliases: Vec::new(), - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomCanonicalAlias, + content: to_raw_value(&RoomCanonicalAliasEventContent { + alias: Some(alias.clone()), + alt_aliases: Vec::new(), + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; services().rooms.alias.set_alias(&alias, &room_id)?; @@ -1125,7 +1152,7 @@ impl Service { .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.clone()) .or_default(), ); @@ -1137,72 +1164,84 @@ impl Service { .expect("@conduit:server_name is valid"); // Invite and join the real user - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Invite, - displayname: None, - avatar_url: None, - is_direct: None, - third_party_invite: None, - blurhash: None, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(user_id.to_string()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomMember, - content: to_raw_value(&RoomMemberEventContent { - membership: MembershipState::Join, - displayname: Some(displayname), - avatar_url: None, - is_direct: None, - third_party_invite: None, - blurhash: None, - reason: None, - join_authorized_via_users_server: None, - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some(user_id.to_string()), - redacts: None, - }, - user_id, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Invite, + displayname: None, + avatar_url: None, + is_direct: None, + third_party_invite: None, + blurhash: None, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomMember, + content: to_raw_value(&RoomMemberEventContent { + membership: MembershipState::Join, + displayname: Some(displayname), + avatar_url: None, + is_direct: None, + third_party_invite: None, + blurhash: None, + reason: None, + join_authorized_via_users_server: None, + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some(user_id.to_string()), + redacts: None, + }, + user_id, + &room_id, + &state_lock, + ) + .await?; // Set power level let mut users = BTreeMap::new(); users.insert(conduit_user.to_owned(), 100.into()); users.insert(user_id.to_owned(), 100.into()); - services().rooms.timeline.build_and_append_pdu( - PduBuilder { - event_type: TimelineEventType::RoomPowerLevels, - content: to_raw_value(&RoomPowerLevelsEventContent { - users, - ..Default::default() - }) - .expect("event is valid, we just created it"), - unsigned: None, - state_key: Some("".to_owned()), - redacts: None, - }, - &conduit_user, - &room_id, - &state_lock, - )?; + services() + .rooms + .timeline + .build_and_append_pdu( + PduBuilder { + event_type: TimelineEventType::RoomPowerLevels, + content: to_raw_value(&RoomPowerLevelsEventContent { + users, + ..Default::default() + }) + .expect("event is valid, we just created it"), + unsigned: None, + state_key: Some("".to_owned()), + redacts: None, + }, + &conduit_user, + &room_id, + &state_lock, + ) + .await?; // Send welcome message services().rooms.timeline.build_and_append_pdu( @@ -1220,7 +1259,7 @@ impl Service { &conduit_user, &room_id, &state_lock, - )?; + ).await?; } Ok(()) } diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index f7822940..c3e02ad5 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -31,11 +31,11 @@ use std::{ path::PathBuf, sync::{ atomic::{self, AtomicBool}, - Arc, Mutex, RwLock, + Arc, RwLock as SyncRwLock, }, time::{Duration, Instant}, }; -use tokio::sync::{broadcast, watch::Receiver, Mutex as TokioMutex, Semaphore}; +use tokio::sync::{broadcast, watch::Receiver, Mutex, RwLock, Semaphore}; use tracing::{error, info}; use trust_dns_resolver::TokioAsyncResolver; @@ -53,7 +53,7 @@ pub struct Service { pub db: &'static dyn Data, pub actual_destination_cache: Arc>, // actual_destination, host - pub tls_name_override: Arc>, + pub tls_name_override: Arc>, pub config: Config, keypair: Arc, dns_resolver: TokioAsyncResolver, @@ -68,8 +68,8 @@ pub struct Service { pub servername_ratelimiter: Arc>>>, pub sync_receivers: RwLock>, pub roomid_mutex_insert: RwLock>>>, - pub roomid_mutex_state: RwLock>>>, - pub roomid_mutex_federation: RwLock>>>, // this lock will be held longer + pub roomid_mutex_state: RwLock>>>, + pub roomid_mutex_federation: RwLock>>>, // this lock will be held longer pub roomid_federationhandletime: RwLock>, pub stateres_mutex: Arc>, pub rotate: RotationHandler, @@ -109,11 +109,11 @@ impl Default for RotationHandler { pub struct Resolver { inner: GaiResolver, - overrides: Arc>, + overrides: Arc>, } impl Resolver { - pub fn new(overrides: Arc>) -> Self { + pub fn new(overrides: Arc>) -> Self { Resolver { inner: GaiResolver::new(), overrides, @@ -125,7 +125,7 @@ impl Resolve for Resolver { fn resolve(&self, name: Name) -> Resolving { self.overrides .read() - .expect("lock should not be poisoned") + .unwrap() .get(name.as_str()) .and_then(|(override_name, port)| { override_name.first().map(|first_name| { @@ -159,7 +159,7 @@ impl Service { } }; - let tls_name_override = Arc::new(RwLock::new(TlsNameMap::new())); + let tls_name_override = Arc::new(SyncRwLock::new(TlsNameMap::new())); let jwt_decoding_key = config .jwt_secret diff --git a/src/service/mod.rs b/src/service/mod.rs index f85da788..c1616c40 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -1,9 +1,10 @@ use std::{ collections::{BTreeMap, HashMap}, - sync::{Arc, Mutex}, + sync::{Arc, Mutex as SyncMutex}, }; use lru_cache::LruCache; +use tokio::sync::Mutex; use crate::{Config, Result}; @@ -79,17 +80,17 @@ impl Services { state: rooms::state::Service { db }, state_accessor: rooms::state_accessor::Service { db, - server_visibility_cache: Mutex::new(LruCache::new( + server_visibility_cache: SyncMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), - user_visibility_cache: Mutex::new(LruCache::new( + user_visibility_cache: SyncMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), }, state_cache: rooms::state_cache::Service { db }, state_compressor: rooms::state_compressor::Service { db, - stateinfo_cache: Mutex::new(LruCache::new( + stateinfo_cache: SyncMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), }, @@ -107,7 +108,7 @@ impl Services { uiaa: uiaa::Service { db }, users: users::Service { db, - connections: Mutex::new(BTreeMap::new()), + connections: SyncMutex::new(BTreeMap::new()), }, account_data: account_data::Service { db }, admin: admin::Service::build(), @@ -118,14 +119,8 @@ impl Services { globals: globals::Service::load(db, config)?, }) } - fn memory_usage(&self) -> String { - let lazy_load_waiting = self - .rooms - .lazy_loading - .lazy_load_waiting - .lock() - .unwrap() - .len(); + async fn memory_usage(&self) -> String { + let lazy_load_waiting = self.rooms.lazy_loading.lazy_load_waiting.lock().await.len(); let server_visibility_cache = self .rooms .state_accessor @@ -152,15 +147,9 @@ impl Services { .timeline .lasttimelinecount_cache .lock() - .unwrap() - .len(); - let roomid_spacechunk_cache = self - .rooms - .spaces - .roomid_spacechunk_cache - .lock() - .unwrap() + .await .len(); + let roomid_spacechunk_cache = self.rooms.spaces.roomid_spacechunk_cache.lock().await.len(); format!( "\ @@ -173,13 +162,13 @@ roomid_spacechunk_cache: {roomid_spacechunk_cache}\ " ) } - fn clear_caches(&self, amount: u32) { + async fn clear_caches(&self, amount: u32) { if amount > 0 { self.rooms .lazy_loading .lazy_load_waiting .lock() - .unwrap() + .await .clear(); } if amount > 1 { @@ -211,7 +200,7 @@ roomid_spacechunk_cache: {roomid_spacechunk_cache}\ .timeline .lasttimelinecount_cache .lock() - .unwrap() + .await .clear(); } if amount > 5 { @@ -219,7 +208,7 @@ roomid_spacechunk_cache: {roomid_spacechunk_cache}\ .spaces .roomid_spacechunk_cache .lock() - .unwrap() + .await .clear(); } } diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 99fc2cb1..7cc662ee 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -1,25 +1,24 @@ /// An async function that can recursively call itself. type AsyncRecursiveType<'a, T> = Pin + 'a + Send>>; -use ruma::{ - api::federation::discovery::{get_remote_server_keys, get_server_keys}, - CanonicalJsonObject, CanonicalJsonValue, OwnedServerName, OwnedServerSigningKeyId, - RoomVersionId, -}; use std::{ collections::{hash_map, BTreeMap, HashMap, HashSet}, pin::Pin, - sync::{Arc, RwLock, RwLockWriteGuard}, + sync::Arc, time::{Duration, Instant, SystemTime}, }; -use tokio::sync::Semaphore; +use async_recursion::async_recursion; use futures_util::{stream::FuturesUnordered, Future, StreamExt}; use ruma::{ api::{ client::error::ErrorKind, federation::{ - discovery::get_remote_server_keys_batch::{self, v2::QueryCriteria}, + discovery::{ + get_remote_server_keys, + get_remote_server_keys_batch::{self, v2::QueryCriteria}, + get_server_keys, + }, event::{get_event, get_room_state_ids}, membership::create_join_event, }, @@ -31,9 +30,11 @@ use ruma::{ int, serde::Base64, state_res::{self, RoomVersion, StateMap}, - uint, EventId, MilliSecondsSinceUnixEpoch, RoomId, ServerName, + uint, CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch, + OwnedServerName, OwnedServerSigningKeyId, RoomId, RoomVersionId, ServerName, }; use serde_json::value::RawValue as RawJsonValue; +use tokio::sync::{RwLock, RwLockWriteGuard, Semaphore}; use tracing::{debug, error, info, trace, warn}; use crate::{service::*, services, Error, PduEvent, Result}; @@ -168,7 +169,7 @@ impl Service { .globals .bad_event_ratelimiter .read() - .unwrap() + .await .get(&*prev_id) { // Exponential backoff @@ -189,7 +190,7 @@ impl Service { .globals .bad_event_ratelimiter .write() - .unwrap() + .await .entry((*prev_id).to_owned()) { hash_map::Entry::Vacant(e) => { @@ -213,7 +214,7 @@ impl Service { .globals .roomid_federationhandletime .write() - .unwrap() + .await .insert(room_id.to_owned(), ((*prev_id).to_owned(), start_time)); if let Err(e) = self @@ -233,7 +234,7 @@ impl Service { .globals .bad_event_ratelimiter .write() - .unwrap() + .await .entry((*prev_id).to_owned()) { hash_map::Entry::Vacant(e) => { @@ -249,7 +250,7 @@ impl Service { .globals .roomid_federationhandletime .write() - .unwrap() + .await .remove(&room_id.to_owned()); debug!( "Handling prev event {} took {}m{}s", @@ -267,7 +268,7 @@ impl Service { .globals .roomid_federationhandletime .write() - .unwrap() + .await .insert(room_id.to_owned(), (event_id.to_owned(), start_time)); let r = services() .rooms @@ -285,7 +286,7 @@ impl Service { .globals .roomid_federationhandletime .write() - .unwrap() + .await .remove(&room_id.to_owned()); r @@ -326,11 +327,8 @@ impl Service { let room_version = RoomVersion::new(room_version_id).expect("room version is supported"); - let mut val = match ruma::signatures::verify_event( - &pub_key_map.read().expect("RwLock is poisoned."), - &value, - room_version_id, - ) { + let guard = pub_key_map.read().await; + let mut val = match ruma::signatures::verify_event(&guard, &value, room_version_id) { Err(e) => { // Drop warn!("Dropping bad event {}: {}", event_id, e,); @@ -365,6 +363,8 @@ impl Service { Ok(ruma::signatures::Verified::All) => value, }; + drop(guard); + // Now that we have checked the signature and hashes we can add the eventID and convert // to our PduEvent type val.insert( @@ -692,13 +692,15 @@ impl Service { { Ok(res) => { debug!("Fetching state events at event."); + let collect = res + .pdu_ids + .iter() + .map(|x| Arc::from(&**x)) + .collect::>(); let state_vec = self .fetch_and_handle_outliers( origin, - &res.pdu_ids - .iter() - .map(|x| Arc::from(&**x)) - .collect::>(), + &collect, create_event, room_id, room_version_id, @@ -805,7 +807,7 @@ impl Service { .globals .roomid_mutex_state .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); @@ -884,14 +886,18 @@ impl Service { debug!("Starting soft fail auth check"); if soft_fail { - services().rooms.timeline.append_incoming_pdu( - &incoming_pdu, - val, - extremities.iter().map(|e| (**e).to_owned()).collect(), - state_ids_compressed, - soft_fail, - &state_lock, - )?; + services() + .rooms + .timeline + .append_incoming_pdu( + &incoming_pdu, + val, + extremities.iter().map(|e| (**e).to_owned()).collect(), + state_ids_compressed, + soft_fail, + &state_lock, + ) + .await?; // Soft fail, we keep the event as an outlier but don't add it to the timeline warn!("Event was soft failed: {:?}", incoming_pdu); @@ -912,14 +918,18 @@ impl Service { // We use the `state_at_event` instead of `state_after` so we accurately // represent the state for this event. - let pdu_id = services().rooms.timeline.append_incoming_pdu( - &incoming_pdu, - val, - extremities.iter().map(|e| (**e).to_owned()).collect(), - state_ids_compressed, - soft_fail, - &state_lock, - )?; + let pdu_id = services() + .rooms + .timeline + .append_incoming_pdu( + &incoming_pdu, + val, + extremities.iter().map(|e| (**e).to_owned()).collect(), + state_ids_compressed, + soft_fail, + &state_lock, + ) + .await?; debug!("Appended incoming pdu"); @@ -1034,7 +1044,8 @@ impl Service { /// d. TODO: Ask other servers over federation? #[allow(clippy::type_complexity)] #[tracing::instrument(skip_all)] - pub(crate) fn fetch_and_handle_outliers<'a>( + #[async_recursion] + pub(crate) async fn fetch_and_handle_outliers<'a>( &'a self, origin: &'a ServerName, events: &'a [Arc], @@ -1042,176 +1053,175 @@ impl Service { room_id: &'a RoomId, room_version_id: &'a RoomVersionId, pub_key_map: &'a RwLock>>, - ) -> AsyncRecursiveType<'a, Vec<(Arc, Option>)>> - { - Box::pin(async move { - let back_off = |id| match services() + ) -> Vec<(Arc, Option>)> { + let back_off = |id| async move { + match services() .globals .bad_event_ratelimiter .write() - .unwrap() + .await .entry(id) { hash_map::Entry::Vacant(e) => { e.insert((Instant::now(), 1)); } hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), - }; - - let mut pdus = vec![]; - for id in events { - // a. Look in the main timeline (pduid_pdu tree) - // b. Look at outlier pdu tree - // (get_pdu_json checks both) - if let Ok(Some(local_pdu)) = services().rooms.timeline.get_pdu(id) { - trace!("Found {} in db", id); - pdus.push((local_pdu, None)); - continue; - } + } + }; - // c. Ask origin server over federation - // We also handle its auth chain here so we don't get a stack overflow in - // handle_outlier_pdu. - let mut todo_auth_events = vec![Arc::clone(id)]; - let mut events_in_reverse_order = Vec::new(); - let mut events_all = HashSet::new(); - let mut i = 0; - while let Some(next_id) = todo_auth_events.pop() { - if let Some((time, tries)) = services() - .globals - .bad_event_ratelimiter - .read() - .unwrap() - .get(&*next_id) - { - // Exponential backoff - let mut min_elapsed_duration = - Duration::from_secs(5 * 60) * (*tries) * (*tries); - if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { - min_elapsed_duration = Duration::from_secs(60 * 60 * 24); - } + let mut pdus = vec![]; + for id in events { + // a. Look in the main timeline (pduid_pdu tree) + // b. Look at outlier pdu tree + // (get_pdu_json checks both) + if let Ok(Some(local_pdu)) = services().rooms.timeline.get_pdu(id) { + trace!("Found {} in db", id); + pdus.push((local_pdu, None)); + continue; + } - if time.elapsed() < min_elapsed_duration { - info!("Backing off from {}", next_id); - continue; - } + // c. Ask origin server over federation + // We also handle its auth chain here so we don't get a stack overflow in + // handle_outlier_pdu. + let mut todo_auth_events = vec![Arc::clone(id)]; + let mut events_in_reverse_order = Vec::new(); + let mut events_all = HashSet::new(); + let mut i = 0; + while let Some(next_id) = todo_auth_events.pop() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .await + .get(&*next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); } - if events_all.contains(&next_id) { + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); continue; } + } - i += 1; - if i % 100 == 0 { - tokio::task::yield_now().await; - } + if events_all.contains(&next_id) { + continue; + } - if let Ok(Some(_)) = services().rooms.timeline.get_pdu(&next_id) { - trace!("Found {} in db", next_id); - continue; - } + i += 1; + if i % 100 == 0 { + tokio::task::yield_now().await; + } - info!("Fetching {} over federation.", next_id); - match services() - .sending - .send_federation_request( - origin, - get_event::v1::Request { - event_id: (*next_id).to_owned(), - }, - ) - .await - { - Ok(res) => { - info!("Got {} over federation", next_id); - let (calculated_event_id, value) = - match pdu::gen_event_id_canonical_json(&res.pdu, room_version_id) { - Ok(t) => t, - Err(_) => { - back_off((*next_id).to_owned()); - continue; - } - }; - - if calculated_event_id != *next_id { - warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}", - next_id, calculated_event_id, &res.pdu); - } + if let Ok(Some(_)) = services().rooms.timeline.get_pdu(&next_id) { + trace!("Found {} in db", next_id); + continue; + } - if let Some(auth_events) = - value.get("auth_events").and_then(|c| c.as_array()) - { - for auth_event in auth_events { - if let Ok(auth_event) = - serde_json::from_value(auth_event.clone().into()) - { - let a: Arc = auth_event; - todo_auth_events.push(a); - } else { - warn!("Auth event id is not valid"); - } + info!("Fetching {} over federation.", next_id); + match services() + .sending + .send_federation_request( + origin, + get_event::v1::Request { + event_id: (*next_id).to_owned(), + }, + ) + .await + { + Ok(res) => { + info!("Got {} over federation", next_id); + let (calculated_event_id, value) = + match pdu::gen_event_id_canonical_json(&res.pdu, room_version_id) { + Ok(t) => t, + Err(_) => { + back_off((*next_id).to_owned()).await; + continue; } - } else { - warn!("Auth event list invalid"); - } + }; - events_in_reverse_order.push((next_id.clone(), value)); - events_all.insert(next_id); + if calculated_event_id != *next_id { + warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}", + next_id, calculated_event_id, &res.pdu); } - Err(_) => { - warn!("Failed to fetch event: {}", next_id); - back_off((*next_id).to_owned()); + + if let Some(auth_events) = + value.get("auth_events").and_then(|c| c.as_array()) + { + for auth_event in auth_events { + if let Ok(auth_event) = + serde_json::from_value(auth_event.clone().into()) + { + let a: Arc = auth_event; + todo_auth_events.push(a); + } else { + warn!("Auth event id is not valid"); + } + } + } else { + warn!("Auth event list invalid"); } + + events_in_reverse_order.push((next_id.clone(), value)); + events_all.insert(next_id); + } + Err(_) => { + warn!("Failed to fetch event: {}", next_id); + back_off((*next_id).to_owned()).await; } } + } - for (next_id, value) in events_in_reverse_order.iter().rev() { - if let Some((time, tries)) = services() - .globals - .bad_event_ratelimiter - .read() - .unwrap() - .get(&**next_id) - { - // Exponential backoff - let mut min_elapsed_duration = - Duration::from_secs(5 * 60) * (*tries) * (*tries); - if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { - min_elapsed_duration = Duration::from_secs(60 * 60 * 24); - } + for (next_id, value) in events_in_reverse_order.iter().rev() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .await + .get(&**next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } - if time.elapsed() < min_elapsed_duration { - info!("Backing off from {}", next_id); - continue; - } + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); + continue; } + } - match self - .handle_outlier_pdu( - origin, - create_event, - next_id, - room_id, - value.clone(), - true, - pub_key_map, - ) - .await - { - Ok((pdu, json)) => { - if next_id == id { - pdus.push((pdu, Some(json))); - } - } - Err(e) => { - warn!("Authentication of event {} failed: {:?}", next_id, e); - back_off((**next_id).to_owned()); + match self + .handle_outlier_pdu( + origin, + create_event, + next_id, + room_id, + value.clone(), + true, + pub_key_map, + ) + .await + { + Ok((pdu, json)) => { + if next_id == id { + pdus.push((pdu, Some(json))); } } + Err(e) => { + warn!("Authentication of event {} failed: {:?}", next_id, e); + back_off((**next_id).to_owned()).await; + } } } - pdus - }) + } + pdus } async fn fetch_unknown_prev_events( @@ -1360,7 +1370,7 @@ impl Service { pub_key_map .write() - .map_err(|_| Error::bad_database("RwLock is poisoned."))? + .await .insert(signature_server.clone(), keys); } @@ -1369,7 +1379,7 @@ impl Service { // Gets a list of servers for which we don't have the signing key yet. We go over // the PDUs and either cache the key or add it to the list that needs to be retrieved. - fn get_server_keys_from_cache( + async fn get_server_keys_from_cache( &self, pdu: &RawJsonValue, servers: &mut BTreeMap>, @@ -1393,7 +1403,7 @@ impl Service { .globals .bad_event_ratelimiter .read() - .unwrap() + .await .get(event_id) { // Exponential backoff @@ -1469,17 +1479,19 @@ impl Service { > = BTreeMap::new(); { - let mut pkm = pub_key_map - .write() - .map_err(|_| Error::bad_database("RwLock is poisoned."))?; + let mut pkm = pub_key_map.write().await; // Try to fetch keys, failure is okay // Servers we couldn't find in the cache will be added to `servers` for pdu in &event.room_state.state { - let _ = self.get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm); + let _ = self + .get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm) + .await; } for pdu in &event.room_state.auth_chain { - let _ = self.get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm); + let _ = self + .get_server_keys_from_cache(pdu, &mut servers, room_version, &mut pkm) + .await; } drop(pkm); @@ -1503,9 +1515,7 @@ impl Service { .await { trace!("Got signing keys: {:?}", keys); - let mut pkm = pub_key_map - .write() - .map_err(|_| Error::bad_database("RwLock is poisoned."))?; + let mut pkm = pub_key_map.write().await; for k in keys.server_keys { let k = match k.deserialize() { Ok(key) => key, @@ -1564,10 +1574,7 @@ impl Service { .into_iter() .map(|(k, v)| (k.to_string(), v.key)) .collect(); - pub_key_map - .write() - .map_err(|_| Error::bad_database("RwLock is poisoned."))? - .insert(origin.to_string(), result); + pub_key_map.write().await.insert(origin.to_string(), result); } } info!("Done handling result"); @@ -1632,14 +1639,14 @@ impl Service { .globals .servername_ratelimiter .read() - .unwrap() + .await .get(origin) .map(|s| Arc::clone(s).acquire_owned()); let permit = match permit { Some(p) => p, None => { - let mut write = services().globals.servername_ratelimiter.write().unwrap(); + let mut write = services().globals.servername_ratelimiter.write().await; let s = Arc::clone( write .entry(origin.to_owned()) @@ -1651,24 +1658,26 @@ impl Service { } .await; - let back_off = |id| match services() - .globals - .bad_signature_ratelimiter - .write() - .unwrap() - .entry(id) - { - hash_map::Entry::Vacant(e) => { - e.insert((Instant::now(), 1)); + let back_off = |id| async { + match services() + .globals + .bad_signature_ratelimiter + .write() + .await + .entry(id) + { + hash_map::Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); + } + hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), } - hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), }; if let Some((time, tries)) = services() .globals .bad_signature_ratelimiter .read() - .unwrap() + .await .get(&signature_ids) { // Exponential backoff @@ -1775,7 +1784,7 @@ impl Service { drop(permit); - back_off(signature_ids); + back_off(signature_ids).await; warn!("Failed to find public key for server: {}", origin); Err(Error::BadServerResponse( diff --git a/src/service/rooms/lazy_loading/mod.rs b/src/service/rooms/lazy_loading/mod.rs index c51a57e9..e2594a0a 100644 --- a/src/service/rooms/lazy_loading/mod.rs +++ b/src/service/rooms/lazy_loading/mod.rs @@ -1,11 +1,9 @@ mod data; -use std::{ - collections::{HashMap, HashSet}, - sync::Mutex, -}; +use std::collections::{HashMap, HashSet}; pub use data::Data; use ruma::{DeviceId, OwnedDeviceId, OwnedRoomId, OwnedUserId, RoomId, UserId}; +use tokio::sync::Mutex; use crate::Result; @@ -33,7 +31,7 @@ impl Service { } #[tracing::instrument(skip(self))] - pub fn lazy_load_mark_sent( + pub async fn lazy_load_mark_sent( &self, user_id: &UserId, device_id: &DeviceId, @@ -41,7 +39,7 @@ impl Service { lazy_load: HashSet, count: PduCount, ) { - self.lazy_load_waiting.lock().unwrap().insert( + self.lazy_load_waiting.lock().await.insert( ( user_id.to_owned(), device_id.to_owned(), @@ -53,14 +51,14 @@ impl Service { } #[tracing::instrument(skip(self))] - pub fn lazy_load_confirm_delivery( + pub async fn lazy_load_confirm_delivery( &self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId, since: PduCount, ) -> Result<()> { - if let Some(user_ids) = self.lazy_load_waiting.lock().unwrap().remove(&( + if let Some(user_ids) = self.lazy_load_waiting.lock().await.remove(&( user_id.to_owned(), device_id.to_owned(), room_id.to_owned(), diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index b0a9ed2a..981d4a37 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use lru_cache::LruCache; use ruma::{ @@ -25,6 +25,7 @@ use ruma::{ space::SpaceRoomJoinRule, OwnedRoomId, RoomId, UserId, }; +use tokio::sync::Mutex; use tracing::{debug, error, warn}; @@ -79,7 +80,7 @@ impl Service { if let Some(cached) = self .roomid_spacechunk_cache .lock() - .unwrap() + .await .get_mut(¤t_room.to_owned()) .as_ref() { @@ -171,7 +172,7 @@ impl Service { .transpose()? .unwrap_or(JoinRule::Invite); - self.roomid_spacechunk_cache.lock().unwrap().insert( + self.roomid_spacechunk_cache.lock().await.insert( current_room.clone(), Some(CachedSpaceChunk { chunk, @@ -265,7 +266,7 @@ impl Service { } } - self.roomid_spacechunk_cache.lock().unwrap().insert( + self.roomid_spacechunk_cache.lock().await.insert( current_room.clone(), Some(CachedSpaceChunk { chunk, @@ -289,7 +290,7 @@ impl Service { } else { self.roomid_spacechunk_cache .lock() - .unwrap() + .await .insert(current_room.clone(), None); } } diff --git a/src/service/rooms/state/mod.rs b/src/service/rooms/state/mod.rs index c209eb5a..f6581bb5 100644 --- a/src/service/rooms/state/mod.rs +++ b/src/service/rooms/state/mod.rs @@ -95,7 +95,7 @@ impl Service { .spaces .roomid_spacechunk_cache .lock() - .unwrap() + .await .remove(&pdu.room_id); } _ => continue, diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index b66fc645..097cc82f 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -2,12 +2,8 @@ mod data; use std::{ cmp::Ordering, - collections::{BTreeMap, HashMap}, -}; - -use std::{ - collections::HashSet, - sync::{Arc, Mutex, RwLock}, + collections::{BTreeMap, HashMap, HashSet}, + sync::Arc, }; pub use data::Data; @@ -32,7 +28,7 @@ use ruma::{ }; use serde::Deserialize; use serde_json::value::{to_raw_value, RawValue as RawJsonValue}; -use tokio::sync::MutexGuard; +use tokio::sync::{Mutex, MutexGuard, RwLock}; use tracing::{error, info, warn}; use crate::{ @@ -201,7 +197,7 @@ impl Service { /// /// Returns pdu id #[tracing::instrument(skip(self, pdu, pdu_json, leaves))] - pub fn append_pdu<'a>( + pub async fn append_pdu<'a>( &self, pdu: &PduEvent, mut pdu_json: CanonicalJsonObject, @@ -263,11 +259,11 @@ impl Service { .globals .roomid_mutex_insert .write() - .unwrap() + .await .entry(pdu.room_id.clone()) .or_default(), ); - let insert_lock = mutex_insert.lock().unwrap(); + let insert_lock = mutex_insert.lock().await; let count1 = services().globals.next_count()?; // Mark as read first so the sending client doesn't get a notification even if appending @@ -395,7 +391,7 @@ impl Service { .spaces .roomid_spacechunk_cache .lock() - .unwrap() + .await .remove(&pdu.room_id); } } @@ -806,7 +802,7 @@ impl Service { /// Creates a new persisted data unit and adds it to a room. This function takes a /// roomid_mutex_state, meaning that only this function is able to mutate the room state. #[tracing::instrument(skip(self, state_lock))] - pub fn build_and_append_pdu( + pub async fn build_and_append_pdu( &self, pdu_builder: PduBuilder, sender: &UserId, @@ -902,14 +898,16 @@ impl Service { // pdu without it's state. This is okay because append_pdu can't fail. let statehashid = services().rooms.state.append_to_state(&pdu)?; - let pdu_id = self.append_pdu( - &pdu, - pdu_json, - // Since this PDU references all pdu_leaves we can update the leaves - // of the room - vec![(*pdu.event_id).to_owned()], - state_lock, - )?; + let pdu_id = self + .append_pdu( + &pdu, + pdu_json, + // Since this PDU references all pdu_leaves we can update the leaves + // of the room + vec![(*pdu.event_id).to_owned()], + state_lock, + ) + .await?; // We set the room state after inserting the pdu, so that we never have a moment in time // where events in the current room state do not exist @@ -947,7 +945,7 @@ impl Service { /// Append the incoming event setting the state snapshot to the state from the /// server that sent the event. #[tracing::instrument(skip_all)] - pub fn append_incoming_pdu<'a>( + pub async fn append_incoming_pdu<'a>( &self, pdu: &PduEvent, pdu_json: CanonicalJsonObject, @@ -977,11 +975,11 @@ impl Service { return Ok(None); } - let pdu_id = - services() - .rooms - .timeline - .append_pdu(pdu, pdu_json, new_room_leaves, state_lock)?; + let pdu_id = services() + .rooms + .timeline + .append_pdu(pdu, pdu_json, new_room_leaves, state_lock) + .await?; Ok(Some(pdu_id)) } @@ -1118,7 +1116,7 @@ impl Service { .globals .roomid_mutex_federation .write() - .unwrap() + .await .entry(room_id.to_owned()) .or_default(), ); @@ -1150,11 +1148,11 @@ impl Service { .globals .roomid_mutex_insert .write() - .unwrap() + .await .entry(room_id.clone()) .or_default(), ); - let insert_lock = mutex_insert.lock().unwrap(); + let insert_lock = mutex_insert.lock().await; let count = services().globals.next_count()?; let mut pdu_id = shortroomid.to_be_bytes().to_vec(); diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index fb983a41..c83463ed 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -45,7 +45,7 @@ impl Service { self.db.exists(user_id) } - pub fn forget_sync_request_connection( + pub async fn forget_sync_request_connection( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, @@ -186,7 +186,7 @@ impl Service { cached.known_rooms.clone() } - pub fn update_sync_subscriptions( + pub async fn update_sync_subscriptions( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, @@ -212,7 +212,7 @@ impl Service { cached.subscriptions = subscriptions; } - pub fn update_sync_known_rooms( + pub async fn update_sync_known_rooms( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, From c58af8485de8eb5e01ad0a2c1f2669102efa7754 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 19:58:39 +0000 Subject: [PATCH 091/175] revert: remove dependency on async_recursion --- Cargo.lock | 12 - Cargo.toml | 1 - src/service/rooms/event_handler/mod.rs | 289 +++++++++++++------------ 3 files changed, 146 insertions(+), 156 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 426661bf..e99928e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,17 +80,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" -[[package]] -name = "async-recursion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "async-trait" version = "0.1.77" @@ -385,7 +374,6 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" name = "conduit" version = "0.7.0-alpha" dependencies = [ - "async-recursion", "async-trait", "axum", "axum-server", diff --git a/Cargo.toml b/Cargo.toml index 93ff2f3b..e8c1c8bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,7 +115,6 @@ lazy_static = "1.4.0" async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } -async-recursion = "1.0.5" [target.'cfg(unix)'.dependencies] nix = { version = "0.26.2", features = ["resource"] } diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 7cc662ee..1547d406 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -8,7 +8,6 @@ use std::{ time::{Duration, Instant, SystemTime}, }; -use async_recursion::async_recursion; use futures_util::{stream::FuturesUnordered, Future, StreamExt}; use ruma::{ api::{ @@ -1044,8 +1043,7 @@ impl Service { /// d. TODO: Ask other servers over federation? #[allow(clippy::type_complexity)] #[tracing::instrument(skip_all)] - #[async_recursion] - pub(crate) async fn fetch_and_handle_outliers<'a>( + pub(crate) fn fetch_and_handle_outliers<'a>( &'a self, origin: &'a ServerName, events: &'a [Arc], @@ -1053,175 +1051,180 @@ impl Service { room_id: &'a RoomId, room_version_id: &'a RoomVersionId, pub_key_map: &'a RwLock>>, - ) -> Vec<(Arc, Option>)> { - let back_off = |id| async move { - match services() - .globals - .bad_event_ratelimiter - .write() - .await - .entry(id) - { - hash_map::Entry::Vacant(e) => { - e.insert((Instant::now(), 1)); - } - hash_map::Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), - } - }; - - let mut pdus = vec![]; - for id in events { - // a. Look in the main timeline (pduid_pdu tree) - // b. Look at outlier pdu tree - // (get_pdu_json checks both) - if let Ok(Some(local_pdu)) = services().rooms.timeline.get_pdu(id) { - trace!("Found {} in db", id); - pdus.push((local_pdu, None)); - continue; - } - - // c. Ask origin server over federation - // We also handle its auth chain here so we don't get a stack overflow in - // handle_outlier_pdu. - let mut todo_auth_events = vec![Arc::clone(id)]; - let mut events_in_reverse_order = Vec::new(); - let mut events_all = HashSet::new(); - let mut i = 0; - while let Some(next_id) = todo_auth_events.pop() { - if let Some((time, tries)) = services() + ) -> AsyncRecursiveType<'a, Vec<(Arc, Option>)>> + { + Box::pin(async move { + let back_off = |id| async move { + match services() .globals .bad_event_ratelimiter - .read() + .write() .await - .get(&*next_id) + .entry(id) { - // Exponential backoff - let mut min_elapsed_duration = - Duration::from_secs(5 * 60) * (*tries) * (*tries); - if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { - min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + hash_map::Entry::Vacant(e) => { + e.insert((Instant::now(), 1)); } - - if time.elapsed() < min_elapsed_duration { - info!("Backing off from {}", next_id); - continue; + hash_map::Entry::Occupied(mut e) => { + *e.get_mut() = (Instant::now(), e.get().1 + 1) } } + }; - if events_all.contains(&next_id) { + let mut pdus = vec![]; + for id in events { + // a. Look in the main timeline (pduid_pdu tree) + // b. Look at outlier pdu tree + // (get_pdu_json checks both) + if let Ok(Some(local_pdu)) = services().rooms.timeline.get_pdu(id) { + trace!("Found {} in db", id); + pdus.push((local_pdu, None)); continue; } - i += 1; - if i % 100 == 0 { - tokio::task::yield_now().await; - } + // c. Ask origin server over federation + // We also handle its auth chain here so we don't get a stack overflow in + // handle_outlier_pdu. + let mut todo_auth_events = vec![Arc::clone(id)]; + let mut events_in_reverse_order = Vec::new(); + let mut events_all = HashSet::new(); + let mut i = 0; + while let Some(next_id) = todo_auth_events.pop() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .await + .get(&*next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } - if let Ok(Some(_)) = services().rooms.timeline.get_pdu(&next_id) { - trace!("Found {} in db", next_id); - continue; - } + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); + continue; + } + } - info!("Fetching {} over federation.", next_id); - match services() - .sending - .send_federation_request( - origin, - get_event::v1::Request { - event_id: (*next_id).to_owned(), - }, - ) - .await - { - Ok(res) => { - info!("Got {} over federation", next_id); - let (calculated_event_id, value) = - match pdu::gen_event_id_canonical_json(&res.pdu, room_version_id) { - Ok(t) => t, - Err(_) => { - back_off((*next_id).to_owned()).await; - continue; - } - }; + if events_all.contains(&next_id) { + continue; + } + + i += 1; + if i % 100 == 0 { + tokio::task::yield_now().await; + } + + if let Ok(Some(_)) = services().rooms.timeline.get_pdu(&next_id) { + trace!("Found {} in db", next_id); + continue; + } - if calculated_event_id != *next_id { - warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}", + info!("Fetching {} over federation.", next_id); + match services() + .sending + .send_federation_request( + origin, + get_event::v1::Request { + event_id: (*next_id).to_owned(), + }, + ) + .await + { + Ok(res) => { + info!("Got {} over federation", next_id); + let (calculated_event_id, value) = + match pdu::gen_event_id_canonical_json(&res.pdu, room_version_id) { + Ok(t) => t, + Err(_) => { + back_off((*next_id).to_owned()).await; + continue; + } + }; + + if calculated_event_id != *next_id { + warn!("Server didn't return event id we requested: requested: {}, we got {}. Event: {:?}", next_id, calculated_event_id, &res.pdu); - } + } - if let Some(auth_events) = - value.get("auth_events").and_then(|c| c.as_array()) - { - for auth_event in auth_events { - if let Ok(auth_event) = - serde_json::from_value(auth_event.clone().into()) - { - let a: Arc = auth_event; - todo_auth_events.push(a); - } else { - warn!("Auth event id is not valid"); + if let Some(auth_events) = + value.get("auth_events").and_then(|c| c.as_array()) + { + for auth_event in auth_events { + if let Ok(auth_event) = + serde_json::from_value(auth_event.clone().into()) + { + let a: Arc = auth_event; + todo_auth_events.push(a); + } else { + warn!("Auth event id is not valid"); + } } + } else { + warn!("Auth event list invalid"); } - } else { - warn!("Auth event list invalid"); - } - events_in_reverse_order.push((next_id.clone(), value)); - events_all.insert(next_id); - } - Err(_) => { - warn!("Failed to fetch event: {}", next_id); - back_off((*next_id).to_owned()).await; + events_in_reverse_order.push((next_id.clone(), value)); + events_all.insert(next_id); + } + Err(_) => { + warn!("Failed to fetch event: {}", next_id); + back_off((*next_id).to_owned()).await; + } } } - } - for (next_id, value) in events_in_reverse_order.iter().rev() { - if let Some((time, tries)) = services() - .globals - .bad_event_ratelimiter - .read() - .await - .get(&**next_id) - { - // Exponential backoff - let mut min_elapsed_duration = - Duration::from_secs(5 * 60) * (*tries) * (*tries); - if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { - min_elapsed_duration = Duration::from_secs(60 * 60 * 24); - } + for (next_id, value) in events_in_reverse_order.iter().rev() { + if let Some((time, tries)) = services() + .globals + .bad_event_ratelimiter + .read() + .await + .get(&**next_id) + { + // Exponential backoff + let mut min_elapsed_duration = + Duration::from_secs(5 * 60) * (*tries) * (*tries); + if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { + min_elapsed_duration = Duration::from_secs(60 * 60 * 24); + } - if time.elapsed() < min_elapsed_duration { - info!("Backing off from {}", next_id); - continue; + if time.elapsed() < min_elapsed_duration { + info!("Backing off from {}", next_id); + continue; + } } - } - match self - .handle_outlier_pdu( - origin, - create_event, - next_id, - room_id, - value.clone(), - true, - pub_key_map, - ) - .await - { - Ok((pdu, json)) => { - if next_id == id { - pdus.push((pdu, Some(json))); + match self + .handle_outlier_pdu( + origin, + create_event, + next_id, + room_id, + value.clone(), + true, + pub_key_map, + ) + .await + { + Ok((pdu, json)) => { + if next_id == id { + pdus.push((pdu, Some(json))); + } + } + Err(e) => { + warn!("Authentication of event {} failed: {:?}", next_id, e); + back_off((**next_id).to_owned()).await; } - } - Err(e) => { - warn!("Authentication of event {} failed: {:?}", next_id, e); - back_off((**next_id).to_owned()).await; } } } - } - pdus + pdus + }) } async fn fetch_unknown_prev_events( From e33d8430d31d022933d37ad74bacdc482590c018 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 20:00:22 +0000 Subject: [PATCH 092/175] typo: colsures -> closures --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 9c1170dd..13bda4c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ mod database; mod service; mod utils; -// Not async due to services() being used in many closures, and async colsures are not stable as of writing +// Not async due to services() being used in many closures, and async closures are not stable as of writing // This is the case for every other occurence of sync Mutex/RwLock, except for database related ones, where // the current maintainer (Timo) as asked to not modify those use std::sync::RwLock; From 17dd8cb918b4592fb45ebbaa297414100ffe939c Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 20:15:11 +0000 Subject: [PATCH 093/175] style: rename Sync(Mutex|RwLock) to Std(Mutex|RwLock) --- src/service/globals/mod.rs | 10 +++++----- src/service/mod.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index c3e02ad5..22dc6959 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -31,7 +31,7 @@ use std::{ path::PathBuf, sync::{ atomic::{self, AtomicBool}, - Arc, RwLock as SyncRwLock, + Arc, RwLock as StdRwLock, }, time::{Duration, Instant}, }; @@ -53,7 +53,7 @@ pub struct Service { pub db: &'static dyn Data, pub actual_destination_cache: Arc>, // actual_destination, host - pub tls_name_override: Arc>, + pub tls_name_override: Arc>, pub config: Config, keypair: Arc, dns_resolver: TokioAsyncResolver, @@ -109,11 +109,11 @@ impl Default for RotationHandler { pub struct Resolver { inner: GaiResolver, - overrides: Arc>, + overrides: Arc>, } impl Resolver { - pub fn new(overrides: Arc>) -> Self { + pub fn new(overrides: Arc>) -> Self { Resolver { inner: GaiResolver::new(), overrides, @@ -159,7 +159,7 @@ impl Service { } }; - let tls_name_override = Arc::new(SyncRwLock::new(TlsNameMap::new())); + let tls_name_override = Arc::new(StdRwLock::new(TlsNameMap::new())); let jwt_decoding_key = config .jwt_secret diff --git a/src/service/mod.rs b/src/service/mod.rs index c1616c40..8f9fb0a5 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -1,6 +1,6 @@ use std::{ collections::{BTreeMap, HashMap}, - sync::{Arc, Mutex as SyncMutex}, + sync::{Arc, Mutex as StdMutex}, }; use lru_cache::LruCache; @@ -80,17 +80,17 @@ impl Services { state: rooms::state::Service { db }, state_accessor: rooms::state_accessor::Service { db, - server_visibility_cache: SyncMutex::new(LruCache::new( + server_visibility_cache: StdMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), - user_visibility_cache: SyncMutex::new(LruCache::new( + user_visibility_cache: StdMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), }, state_cache: rooms::state_cache::Service { db }, state_compressor: rooms::state_compressor::Service { db, - stateinfo_cache: SyncMutex::new(LruCache::new( + stateinfo_cache: StdMutex::new(LruCache::new( (100.0 * config.conduit_cache_capacity_modifier) as usize, )), }, @@ -108,7 +108,7 @@ impl Services { uiaa: uiaa::Service { db }, users: users::Service { db, - connections: SyncMutex::new(BTreeMap::new()), + connections: StdMutex::new(BTreeMap::new()), }, account_data: account_data::Service { db }, admin: admin::Service::build(), From 07bb369c5cee46fba463f94dfb95151f46d2c8f9 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 20:20:19 +0000 Subject: [PATCH 094/175] perf: remove unnecessary async --- src/api/client_server/sync.rs | 66 ++++++++++++++--------------------- src/service/users/mod.rs | 6 ++-- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 5ac00c60..c510f5f5 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1197,14 +1197,11 @@ pub async fn sync_events_v4_route( if globalsince == 0 { if let Some(conn_id) = &body.conn_id { - services() - .users - .forget_sync_request_connection( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - ) - .await + services().users.forget_sync_request_connection( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + ) } } @@ -1474,17 +1471,14 @@ pub async fn sync_events_v4_route( ); if let Some(conn_id) = &body.conn_id { - services() - .users - .update_sync_known_rooms( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - list_id, - new_known_rooms, - globalsince, - ) - .await; + services().users.update_sync_known_rooms( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + list_id, + new_known_rooms, + globalsince, + ); } } @@ -1516,29 +1510,23 @@ pub async fn sync_events_v4_route( } if let Some(conn_id) = &body.conn_id { - services() - .users - .update_sync_known_rooms( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - "subscriptions".to_owned(), - known_subscription_rooms, - globalsince, - ) - .await; + services().users.update_sync_known_rooms( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + "subscriptions".to_owned(), + known_subscription_rooms, + globalsince, + ); } if let Some(conn_id) = &body.conn_id { - services() - .users - .update_sync_subscriptions( - sender_user.clone(), - sender_device.clone(), - conn_id.clone(), - body.room_subscriptions, - ) - .await; + services().users.update_sync_subscriptions( + sender_user.clone(), + sender_device.clone(), + conn_id.clone(), + body.room_subscriptions, + ); } let mut rooms = BTreeMap::new(); diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index c83463ed..fb983a41 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -45,7 +45,7 @@ impl Service { self.db.exists(user_id) } - pub async fn forget_sync_request_connection( + pub fn forget_sync_request_connection( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, @@ -186,7 +186,7 @@ impl Service { cached.known_rooms.clone() } - pub async fn update_sync_subscriptions( + pub fn update_sync_subscriptions( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, @@ -212,7 +212,7 @@ impl Service { cached.subscriptions = subscriptions; } - pub async fn update_sync_known_rooms( + pub fn update_sync_known_rooms( &self, user_id: OwnedUserId, device_id: OwnedDeviceId, From ee7efdd403ec514c84d20c51ad7536c4b38f3349 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 5 Mar 2024 20:31:40 +0000 Subject: [PATCH 095/175] typo: as -> has --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 13bda4c2..70c6f373 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ mod utils; // Not async due to services() being used in many closures, and async closures are not stable as of writing // This is the case for every other occurence of sync Mutex/RwLock, except for database related ones, where -// the current maintainer (Timo) as asked to not modify those +// the current maintainer (Timo) has asked to not modify those use std::sync::RwLock; pub use api::ruma_wrapper::{Ruma, RumaResponse}; From 161ad8f9a4dc56695656cd3c4a1a750bd6f93514 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 22:37:23 -0800 Subject: [PATCH 096/175] update to latest crane before a regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once these issues are fixed, or at least just the one against crane, we can go back to `ref=master`. Flake lock file updates: • Updated input 'crane': 'github:ipetkov/crane/c798790eabec3e3da48190ae3698ac227aab770c' (2024-01-28) → 'github:ipetkov/crane/2c653e4478476a52c6aa3ac0495e4dea7449ea0e' (2024-02-11) --- flake.lock | 8 ++++---- flake.nix | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 1c97e5c6..e8748923 100644 --- a/flake.lock +++ b/flake.lock @@ -51,17 +51,17 @@ ] }, "locked": { - "lastModified": 1706473964, - "narHash": "sha256-Fq6xleee/TsX6NbtoRuI96bBuDHMU57PrcK9z1QEKbk=", + "lastModified": 1707685877, + "narHash": "sha256-XoXRS+5whotelr1rHiZle5t5hDg9kpguS5yk8c8qzOc=", "owner": "ipetkov", "repo": "crane", - "rev": "c798790eabec3e3da48190ae3698ac227aab770c", + "rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e", "type": "github" }, "original": { "owner": "ipetkov", - "ref": "master", "repo": "crane", + "rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 6ca4c72d..d1a947a6 100644 --- a/flake.nix +++ b/flake.nix @@ -13,7 +13,12 @@ inputs.nixpkgs.follows = "nixpkgs"; }; crane = { - url = "github:ipetkov/crane?ref=master"; + # Pin latest crane that's not affected by the following bugs: + # + # * + # * + # * + url = "github:ipetkov/crane?rev=2c653e4478476a52c6aa3ac0495e4dea7449ea0e"; inputs.nixpkgs.follows = "nixpkgs"; }; attic.url = "github:zhaofengli/attic?ref=main"; From e70f33741c04781ece5032c10a9261a1a72d3780 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 22:40:47 -0800 Subject: [PATCH 097/175] update flake.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also switch names to match the newer upstream nixpkgs code. Flake lock file updates: • Updated input 'attic': 'github:zhaofengli/attic/fbe252a5c21febbe920c025560cbd63b20e24f3b' (2024-01-18) → 'github:zhaofengli/attic/6eabc3f02fae3683bffab483e614bebfcd476b21' (2024-02-14) • Updated input 'fenix': 'github:nix-community/fenix/e132ea0eb0c799a2109a91688e499d7bf4962801' (2024-01-18) → 'github:nix-community/fenix/c8943ea9e98d41325ff57d4ec14736d330b321b2' (2024-03-05) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/9d9b34354d2f13e33568c9c55b226dd014a146a0' (2024-01-17) → 'github:rust-lang/rust-analyzer/9f14343f9ee24f53f17492c5f9b653427e2ad15e' (2024-03-04) • Updated input 'flake-utils': 'github:numtide/flake-utils/1ef2e671c3b0c19053962c07dbda38332dcebf26' (2024-01-15) → 'github:numtide/flake-utils/d465f4819400de7c8d874d50b982301f28a84605' (2024-02-28) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/842d9d80cfd4560648c785f8a4e6f3b096790e19' (2024-01-17) → 'github:NixOS/nixpkgs/b8697e57f10292a6165a20f03d2f42920dfaf973' (2024-03-03) --- flake.lock | 30 +++++++++++++++--------------- flake.nix | 10 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/flake.lock b/flake.lock index e8748923..1c2142f2 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1705617092, - "narHash": "sha256-n9PK4O4X4S1JkwpkMuYm1wHZYJzRqif8g3RuVIPD+rY=", + "lastModified": 1707922053, + "narHash": "sha256-wSZjK+rOXn+UQiP1NbdNn5/UW6UcBxjvlqr2wh++MbM=", "owner": "zhaofengli", "repo": "attic", - "rev": "fbe252a5c21febbe920c025560cbd63b20e24f3b", + "rev": "6eabc3f02fae3683bffab483e614bebfcd476b21", "type": "github" }, "original": { @@ -73,11 +73,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1705559032, - "narHash": "sha256-Cb+Jd1+Gz4Wi+8elPnUIHnqQmE1qjDRZ+PsJaPaAffY=", + "lastModified": 1709619709, + "narHash": "sha256-l6EPVJfwfelWST7qWQeP6t/TDK3HHv5uUB1b2vw4mOQ=", "owner": "nix-community", "repo": "fenix", - "rev": "e132ea0eb0c799a2109a91688e499d7bf4962801", + "rev": "c8943ea9e98d41325ff57d4ec14736d330b321b2", "type": "github" }, "original": { @@ -138,11 +138,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1705496572, - "narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=", + "lastModified": 1709479366, + "narHash": "sha256-n6F0n8UV6lnTZbYPl1A9q1BS0p4hduAv1mGAP17CVd0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "842d9d80cfd4560648c785f8a4e6f3b096790e19", + "rev": "b8697e57f10292a6165a20f03d2f42920dfaf973", "type": "github" }, "original": { @@ -228,11 +228,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1705523001, - "narHash": "sha256-TWq5vJ6m+9HGSDMsQAmz1TMegMi79R3TTyKjnPWsQp8=", + "lastModified": 1709571018, + "narHash": "sha256-ISFrxHxE0J5g7lDAscbK88hwaT5uewvWoma9TlFmRzM=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "9d9b34354d2f13e33568c9c55b226dd014a146a0", + "rev": "9f14343f9ee24f53f17492c5f9b653427e2ad15e", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d1a947a6..460bffc3 100644 --- a/flake.nix +++ b/flake.nix @@ -55,7 +55,7 @@ # bindgen needs the build platform's libclang. Apparently due to # "splicing weirdness", pkgs.rustPlatform.bindgenHook on its own doesn't # quite do the right thing here. - pkgs.buildPackages.rustPlatform.bindgenHook + pkgs.pkgsBuildHost.rustPlatform.bindgenHook ]; env = pkgs: { @@ -83,7 +83,7 @@ # these flags when using a different linker. Don't ask me why, # though, because I don't know. All I know is it breaks otherwise. # - # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39 + # [0]: https://github.com/NixOS/nixpkgs/blob/5cdb38bb16c6d0a38779db14fcc766bc1b2394d6/pkgs/build-support/rust/lib/default.nix#L37-L40 ( # Nixpkgs doesn't check for x86_64 here but we do, because I # observed a failure building statically for x86_64 without @@ -107,7 +107,7 @@ # even covers the case of build scripts that need native code compiled and # run on the build platform (I think). # - # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L64-L78 + # [0]: https://github.com/NixOS/nixpkgs/blob/5cdb38bb16c6d0a38779db14fcc766bc1b2394d6/pkgs/build-support/rust/lib/default.nix#L57-L80 // ( let inherit (pkgs.rust.lib) envVars; @@ -145,8 +145,8 @@ "CC_${cargoEnvVarTarget}" = envVars.ccForBuild; "CXX_${cargoEnvVarTarget}" = envVars.cxxForBuild; "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.linkerForBuild; - HOST_CC = "${pkgs.buildPackages.stdenv.cc}/bin/cc"; - HOST_CXX = "${pkgs.buildPackages.stdenv.cc}/bin/c++"; + HOST_CC = "${pkgs.pkgsBuildHost.stdenv.cc}/bin/cc"; + HOST_CXX = "${pkgs.pkgsBuildHost.stdenv.cc}/bin/c++"; } )); From 10b7b174b6bac0921f704ab768799128bf298ef1 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 20:49:41 -0800 Subject: [PATCH 098/175] fix documented target triple Even though it doesn't really matter because it's containerized anyway. --- DEPLOY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPLOY.md b/DEPLOY.md index dcc41bdc..1a6f4835 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -37,7 +37,7 @@ If you use a system with an older glibc version (e.g. RHEL8), you might need to | `x86_64-unknown-linux-gnu` | Dynamically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit.deb?job=debian:x86_64-unknown-linux-gnu) | | `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:x86_64-unknown-linux-musl) | | `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:aarch64-unknown-linux-musl) | -| `x86_64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | +| `x86_64-unknown-linux-gnu` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | | `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=oci-image:aarch64-unknown-linux-musl) | ```bash From 4f352a711af865ca7e75e772a09aa96fc3219af4 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 20:42:58 -0800 Subject: [PATCH 099/175] add trailing newline to file Please fix your editor configuration... --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4f4aa695..59de64f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -177,4 +177,4 @@ oci-image:push-dockerhub: variables: IMAGE_NAME: matrixconduit/matrix-conduit before_script: - - docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWORD \ No newline at end of file + - docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWORD From 6281c64c331d9dd70b018eda1a124a0f12164f82 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 20:44:15 -0800 Subject: [PATCH 100/175] upgrade nixos/nix image --- .gitlab-ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 59de64f3..2fe90bf7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,7 +34,7 @@ before_script: ci: stage: ci - image: nixos/nix:2.19.2 + image: nixos/nix:2.20.4 script: - direnv exec . engage cache: @@ -45,7 +45,7 @@ ci: static:x86_64-unknown-linux-musl: stage: artifacts - image: nixos/nix:2.19.2 + image: nixos/nix:2.20.4 script: # Push artifacts and build requirements to binary cache - ./bin/nix-build-and-cache .#static-x86_64-unknown-linux-musl @@ -58,7 +58,7 @@ static:x86_64-unknown-linux-musl: static:aarch64-unknown-linux-musl: stage: artifacts - image: nixos/nix:2.19.2 + image: nixos/nix:2.20.4 script: # Push artifacts and build requirements to binary cache - ./bin/nix-build-and-cache .#static-aarch64-unknown-linux-musl @@ -74,7 +74,7 @@ static:aarch64-unknown-linux-musl: # all containerized anyway. oci-image:x86_64-unknown-linux-gnu: stage: artifacts - image: nixos/nix:2.19.2 + image: nixos/nix:2.20.4 script: # Push artifacts and build requirements to binary cache # @@ -96,7 +96,7 @@ oci-image:aarch64-unknown-linux-musl: # Wait for the static binary job to finish before starting so we don't have # to build that twice for no reason - static:aarch64-unknown-linux-musl - image: nixos/nix:2.19.2 + image: nixos/nix:2.20.4 script: # Push artifacts and build requirements to binary cache - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl From 4e09c9e58a9de466887db659a6f9e02999a2f035 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 20:38:57 -0800 Subject: [PATCH 101/175] build all nix-based artifacts in a single job This will reduce the amount of full builds that need to be done by runs that don't have write access to the nix binary cache. --- .gitlab-ci.yml | 61 +++++++++++--------------------------------------- DEPLOY.md | 8 +++---- 2 files changed, 17 insertions(+), 52 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2fe90bf7..b24481b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,68 +43,34 @@ ci: - target - .gitlab-ci.d -static:x86_64-unknown-linux-musl: +nix:artifacts: stage: artifacts image: nixos/nix:2.20.4 script: - # Push artifacts and build requirements to binary cache - ./bin/nix-build-and-cache .#static-x86_64-unknown-linux-musl + - cp result/bin/conduit x86_64-unknown-linux-musl - # Make the output less difficult to find - - cp result/bin/conduit conduit - artifacts: - paths: - - conduit - -static:aarch64-unknown-linux-musl: - stage: artifacts - image: nixos/nix:2.20.4 - script: - # Push artifacts and build requirements to binary cache - - ./bin/nix-build-and-cache .#static-aarch64-unknown-linux-musl - - # Make the output less difficult to find - - cp result/bin/conduit conduit - artifacts: - paths: - - conduit - -# Note that although we have an `oci-image-x86_64-unknown-linux-musl` output, -# we don't build it because it would be largely redundant to this one since it's -# all containerized anyway. -oci-image:x86_64-unknown-linux-gnu: - stage: artifacts - image: nixos/nix:2.20.4 - script: - # Push artifacts and build requirements to binary cache - # # Since the OCI image package is based on the binary package, this has the # fun side effect of uploading the normal binary too. Conduit users who are # deploying with Nix can leverage this fact by adding our binary cache to # their systems. + # + # Note that although we have an `oci-image-x86_64-unknown-linux-musl` + # output, we don't build it because it would be largely redundant to this + # one since it's all containerized anyway. - ./bin/nix-build-and-cache .#oci-image - - # Make the output less difficult to find - cp result oci-image-amd64.tar.gz - artifacts: - paths: - - oci-image-amd64.tar.gz -oci-image:aarch64-unknown-linux-musl: - stage: artifacts - needs: - # Wait for the static binary job to finish before starting so we don't have - # to build that twice for no reason - - static:aarch64-unknown-linux-musl - image: nixos/nix:2.20.4 - script: - # Push artifacts and build requirements to binary cache - - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl + - ./bin/nix-build-and-cache .#static-aarch64-unknown-linux-musl + - cp result/bin/conduit aarch64-unknown-linux-musl - # Make the output less difficult to find + - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl - cp result oci-image-arm64v8.tar.gz artifacts: paths: + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-musl + - oci-image-amd64.tar.gz - oci-image-arm64v8.tar.gz debian:x86_64-unknown-linux-gnu: @@ -158,8 +124,7 @@ debian:x86_64-unknown-linux-gnu: docker manifest push $IMAGE_NAME:latest fi dependencies: - - oci-image:x86_64-unknown-linux-gnu - - oci-image:aarch64-unknown-linux-musl + - nix:artifacts only: - next - master diff --git a/DEPLOY.md b/DEPLOY.md index 1a6f4835..ccf52c32 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -35,10 +35,10 @@ If you use a system with an older glibc version (e.g. RHEL8), you might need to | Target | Type | Download | |-|-|-| | `x86_64-unknown-linux-gnu` | Dynamically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit.deb?job=debian:x86_64-unknown-linux-gnu) | -| `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:x86_64-unknown-linux-musl) | -| `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit?job=static:aarch64-unknown-linux-musl) | -| `x86_64-unknown-linux-gnu` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=oci-image:x86_64-unknown-linux-musl) | -| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=oci-image:aarch64-unknown-linux-musl) | +| `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/x86_64-unknown-linux-musl?job=nix:artifacts) | +| `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/aarch64-unknown-linux-musl?job=nix:artifacts) | +| `x86_64-unknown-linux-gnu` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=nix:artifacts) | +| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=nix:artifacts) | ```bash $ sudo wget -O /usr/local/bin/matrix-conduit From d5a9c6ac32e15ca11a0f684274be9ca8356cdfcc Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 23:12:17 -0800 Subject: [PATCH 102/175] use nix-built binary to produce debian package Currently just for `x86_64-unknown-linux-musl`. Theoretically, we can use this same mechanism for `aarch64-unknown-linux-musl`. Practically, I'm not sure just this will even work. --- .gitlab-ci.yml | 30 ++++++++---------------------- DEPLOY.md | 10 +++++----- flake.nix | 3 +++ 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b24481b1..866ef11f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,13 +43,18 @@ ci: - target - .gitlab-ci.d -nix:artifacts: +artifacts: stage: artifacts image: nixos/nix:2.20.4 script: - ./bin/nix-build-and-cache .#static-x86_64-unknown-linux-musl - cp result/bin/conduit x86_64-unknown-linux-musl + - mkdir -p target/release + - cp result/bin/conduit target/release + - direnv exec . cargo deb --no-build + - mv target/debian/*.deb x86_64-unknown-linux-musl.deb + # Since the OCI image package is based on the binary package, this has the # fun side effect of uploading the normal binary too. Conduit users who are # deploying with Nix can leverage this fact by adding our binary cache to @@ -70,29 +75,10 @@ nix:artifacts: paths: - x86_64-unknown-linux-musl - aarch64-unknown-linux-musl + - x86_64-unknown-linux-musl.deb - oci-image-amd64.tar.gz - oci-image-arm64v8.tar.gz -debian:x86_64-unknown-linux-gnu: - stage: artifacts - # See also `rust-toolchain.toml` - image: rust:1.75.0 - script: - - apt-get update && apt-get install -y --no-install-recommends libclang-dev - - cargo install cargo-deb - - cargo deb - - # Make the output less difficult to find - - mv target/debian/*.deb conduit.deb - artifacts: - paths: - - conduit.deb - cache: - key: debian - paths: - - target - - .gitlab-ci.d - .push-oci-image: stage: publish image: docker:25.0.0 @@ -124,7 +110,7 @@ debian:x86_64-unknown-linux-gnu: docker manifest push $IMAGE_NAME:latest fi dependencies: - - nix:artifacts + - artifacts only: - next - master diff --git a/DEPLOY.md b/DEPLOY.md index ccf52c32..dd279688 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -34,11 +34,11 @@ If you use a system with an older glibc version (e.g. RHEL8), you might need to | Target | Type | Download | |-|-|-| -| `x86_64-unknown-linux-gnu` | Dynamically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/conduit.deb?job=debian:x86_64-unknown-linux-gnu) | -| `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/x86_64-unknown-linux-musl?job=nix:artifacts) | -| `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/aarch64-unknown-linux-musl?job=nix:artifacts) | -| `x86_64-unknown-linux-gnu` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=nix:artifacts) | -| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=nix:artifacts) | +| `x86_64-unknown-linux-musl` | Statically linked Debian package | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/x86_64-unknown-linux-musl.deb?job=artifacts) | +| `x86_64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/x86_64-unknown-linux-musl?job=artifacts) | +| `aarch64-unknown-linux-musl` | Statically linked binary | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/aarch64-unknown-linux-musl?job=artifacts) | +| `x86_64-unknown-linux-gnu` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-amd64.tar.gz?job=artifacts) | +| `aarch64-unknown-linux-musl` | OCI image | [link](https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/next/raw/oci-image-arm64v8.tar.gz?job=artifacts) | ```bash $ sudo wget -O /usr/local/bin/matrix-conduit diff --git a/flake.nix b/flake.nix index 460bffc3..cc95aecb 100644 --- a/flake.nix +++ b/flake.nix @@ -252,6 +252,9 @@ ] ++ (with pkgsHost; [ engage + # Needed for producing Debian packages + cargo-deb + # Needed for Complement go olm From d411e9037c860368e433f9e413fc28b31f3e0e38 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 5 Mar 2024 12:05:50 -0800 Subject: [PATCH 103/175] upload all devshell inputs to the cache This will also include attic, so we don't need to explicitly do this in `./bin/nix-build-and-cache` anymore, which is good because that script gets called a good number of times and doing that repeatedly was a bit of a waste. --- .gitlab-ci.yml | 3 +++ bin/nix-build-and-cache | 15 +++++---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 866ef11f..e0ed08ee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,6 +36,9 @@ ci: stage: ci image: nixos/nix:2.20.4 script: + # Cache the inputs required for the devShell + - ./bin/nix-build-and-cache .#devShells.x86_64-linux.default.inputDerivation + - direnv exec . engage cache: key: nix diff --git a/bin/nix-build-and-cache b/bin/nix-build-and-cache index b37ebd85..0eb816c3 100755 --- a/bin/nix-build-and-cache +++ b/bin/nix-build-and-cache @@ -15,17 +15,12 @@ nix run --inputs-from . attic -- login \ https://nix.computer.surgery/conduit \ "$ATTIC_TOKEN" - push_args=( - # Attic and its build dependencies - "$(nix path-info --inputs-from . attic)" - "$(nix path-info --inputs-from . attic --derivation)" - - # The target installable and its build dependencies - "$(nix path-info "$INSTALLABLE" --derivation)" + # Push the target installable and its build dependencies + nix run --inputs-from . attic -- \ + push \ + conduit \ + "$(nix path-info "$INSTALLABLE" --derivation)" \ "$(nix path-info "$INSTALLABLE")" - ) - - nix run --inputs-from . attic -- push conduit "${push_args[@]}" else echo "\$ATTIC_TOKEN is unset, skipping uploading to the binary cache" fi From ae69da635b4745468896d43efd1f429d5312ca80 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 4 Mar 2024 23:47:46 -0800 Subject: [PATCH 104/175] allow overriding the attic endpoint And also the public key so that pulling from the new endpoint will work. This allows other people to host their own attic instances and configure their (CI) environment to override the default endpoint so e.g. they can take advantage of a binary cache without having write access to the official one. I didn't actually test this change but I think it should work. Also why'd I format the script like that, ew lol --- .gitlab-ci.yml | 4 ++++ bin/nix-build-and-cache | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0ed08ee..0e56598c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,6 +15,10 @@ before_script: - if command -v nix > /dev/null; then echo "extra-substituters = https://nix.computer.surgery/conduit" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = conduit:ZGAf6P6LhNvnoJJ3Me3PRg7tlLSrPxcQ2RiE5LIppjo=" >> /etc/nix/nix.conf; fi + # Add alternate binary cache + - if command -v nix > /dev/null && [ -n "$ATTIC_ENDPOINT" ]; then echo "extra-substituters = $ATTIC_ENDPOINT" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null && [ -n "$ATTIC_PUBLIC_KEY" ]; then echo "extra-trusted-public-keys = $ATTIC_PUBLIC_KEY" >> /etc/nix/nix.conf; fi + # Add crane binary cache - if command -v nix > /dev/null; then echo "extra-substituters = https://crane.cachix.org" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" >> /etc/nix/nix.conf; fi diff --git a/bin/nix-build-and-cache b/bin/nix-build-and-cache index 0eb816c3..350e1717 100755 --- a/bin/nix-build-and-cache +++ b/bin/nix-build-and-cache @@ -9,10 +9,10 @@ INSTALLABLE="$1" nix build "$@" if [ ! -z ${ATTIC_TOKEN+x} ]; then - -nix run --inputs-from . attic -- login \ - conduit \ - https://nix.computer.surgery/conduit \ + nix run --inputs-from . attic -- \ + login \ + conduit \ + "${ATTIC_ENDPOINT:-https://nix.computer.surgery/conduit}" \ "$ATTIC_TOKEN" # Push the target installable and its build dependencies From 0d2f1348daa573b3f0e577ffccfe605c88fab8b5 Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Wed, 6 Mar 2024 11:47:15 +0100 Subject: [PATCH 105/175] feat: run ci on demand to prevent unnecessary job executions --- .gitlab-ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0e56598c..348e7b19 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,6 +49,13 @@ ci: paths: - target - .gitlab-ci.d + rules: + # CI on upstream runners (only available for maintainers) + - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $IS_UPSTREAM_CI == "true" + # Manual CI on forks + - if: $IS_UPSTREAM_CI != "true" + when: manual + - if: $CI artifacts: stage: artifacts @@ -85,6 +92,14 @@ artifacts: - x86_64-unknown-linux-musl.deb - oci-image-amd64.tar.gz - oci-image-arm64v8.tar.gz + rules: + # CI required for all MRs + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + # Optional CI on forks + - if: $IS_UPSTREAM_CI != "true" + when: manual + allow_failure: true + - if: $CI .push-oci-image: stage: publish From fa930182aea942380f8db19b5e18152e17d9e634 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 27 Dec 2023 13:22:21 +0000 Subject: [PATCH 106/175] fix(appservices): don't panic on empty registration url perf(appservices): cache regex for namespaces --- src/api/appservice_server.rs | 166 ++++++++++---------- src/api/client_server/alias.rs | 34 ++-- src/api/ruma_wrapper/axum.rs | 15 +- src/database/key_value/appservice.rs | 11 +- src/database/key_value/rooms/state_cache.rs | 47 ++---- src/database/mod.rs | 20 ++- src/service/admin/mod.rs | 7 +- src/service/appservice/data.rs | 8 +- src/service/appservice/mod.rs | 114 +++++++++++++- src/service/mod.rs | 7 +- src/service/rooms/state_cache/data.rs | 8 +- src/service/rooms/state_cache/mod.rs | 4 +- src/service/rooms/timeline/mod.rs | 116 ++++++-------- src/service/sending/mod.rs | 19 ++- src/utils/error.rs | 5 + 15 files changed, 336 insertions(+), 245 deletions(-) diff --git a/src/api/appservice_server.rs b/src/api/appservice_server.rs index 082a1bc2..ab4da79f 100644 --- a/src/api/appservice_server.rs +++ b/src/api/appservice_server.rs @@ -1,105 +1,111 @@ use crate::{services, utils, Error, Result}; use bytes::BytesMut; -use ruma::api::{IncomingResponse, MatrixVersion, OutgoingRequest, SendAccessToken}; +use ruma::api::{ + appservice::Registration, IncomingResponse, MatrixVersion, OutgoingRequest, SendAccessToken, +}; use std::{fmt::Debug, mem, time::Duration}; use tracing::warn; +/// Sends a request to an appservice +/// +/// Only returns None if there is no url specified in the appservice registration file #[tracing::instrument(skip(request))] pub(crate) async fn send_request( - registration: serde_yaml::Value, + registration: Registration, request: T, -) -> Result +) -> Option> where T: Debug, { - let destination = registration.get("url").unwrap().as_str().unwrap(); - let hs_token = registration.get("hs_token").unwrap().as_str().unwrap(); + if let Some(destination) = registration.url { + let hs_token = registration.hs_token.as_str(); - let mut http_request = request - .try_into_http_request::( - destination, - SendAccessToken::IfRequired(hs_token), - &[MatrixVersion::V1_0], - ) - .unwrap() - .map(|body| body.freeze()); + let mut http_request = request + .try_into_http_request::( + &destination, + SendAccessToken::IfRequired(hs_token), + &[MatrixVersion::V1_0], + ) + .unwrap() + .map(|body| body.freeze()); - let mut parts = http_request.uri().clone().into_parts(); - let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); - let symbol = if old_path_and_query.contains('?') { - "&" - } else { - "?" - }; + let mut parts = http_request.uri().clone().into_parts(); + let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); + let symbol = if old_path_and_query.contains('?') { + "&" + } else { + "?" + }; + + parts.path_and_query = Some( + (old_path_and_query + symbol + "access_token=" + hs_token) + .parse() + .unwrap(), + ); + *http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid"); - parts.path_and_query = Some( - (old_path_and_query + symbol + "access_token=" + hs_token) - .parse() - .unwrap(), - ); - *http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid"); + let mut reqwest_request = reqwest::Request::try_from(http_request) + .expect("all http requests are valid reqwest requests"); - let mut reqwest_request = reqwest::Request::try_from(http_request) - .expect("all http requests are valid reqwest requests"); + *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); - *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); + let url = reqwest_request.url().clone(); + let mut response = match services() + .globals + .default_client() + .execute(reqwest_request) + .await + { + Ok(r) => r, + Err(e) => { + warn!( + "Could not send request to appservice {:?} at {}: {}", + registration.id, destination, e + ); + return Some(Err(e.into())); + } + }; - let url = reqwest_request.url().clone(); - let mut response = match services() - .globals - .default_client() - .execute(reqwest_request) - .await - { - Ok(r) => r, - Err(e) => { + // reqwest::Response -> http::Response conversion + let status = response.status(); + let mut http_response_builder = http::Response::builder() + .status(status) + .version(response.version()); + mem::swap( + response.headers_mut(), + http_response_builder + .headers_mut() + .expect("http::response::Builder is usable"), + ); + + let body = response.bytes().await.unwrap_or_else(|e| { + warn!("server error: {}", e); + Vec::new().into() + }); // TODO: handle timeout + + if status != 200 { warn!( - "Could not send request to appservice {:?} at {}: {}", - registration.get("id"), + "Appservice returned bad response {} {}\n{}\n{:?}", destination, - e + status, + url, + utils::string_from_bytes(&body) ); - return Err(e.into()); } - }; - - // reqwest::Response -> http::Response conversion - let status = response.status(); - let mut http_response_builder = http::Response::builder() - .status(status) - .version(response.version()); - mem::swap( - response.headers_mut(), - http_response_builder - .headers_mut() - .expect("http::response::Builder is usable"), - ); - let body = response.bytes().await.unwrap_or_else(|e| { - warn!("server error: {}", e); - Vec::new().into() - }); // TODO: handle timeout - - if status != 200 { - warn!( - "Appservice returned bad response {} {}\n{}\n{:?}", - destination, - status, - url, - utils::string_from_bytes(&body) + let response = T::IncomingResponse::try_from_http_response( + http_response_builder + .body(body) + .expect("reqwest body is valid http body"), ); + Some(response.map_err(|_| { + warn!( + "Appservice returned invalid response bytes {}\n{}", + destination, url + ); + Error::BadServerResponse("Server returned bad response.") + })) + } else { + None } - - let response = T::IncomingResponse::try_from_http_response( - http_response_builder - .body(body) - .expect("reqwest body is valid http body"), - ); - response.map_err(|_| { - warn!( - "Appservice returned invalid response bytes {}\n{}", - destination, url - ); - Error::BadServerResponse("Server returned bad response.") - }) } diff --git a/src/api/client_server/alias.rs b/src/api/client_server/alias.rs index 7660ca2f..d3a6e39a 100644 --- a/src/api/client_server/alias.rs +++ b/src/api/client_server/alias.rs @@ -1,6 +1,5 @@ use crate::{services, Error, Result, Ruma}; use rand::seq::SliceRandom; -use regex::Regex; use ruma::{ api::{ appservice, @@ -101,31 +100,28 @@ pub(crate) async fn get_alias_helper( match services().rooms.alias.resolve_local_alias(&room_alias)? { Some(r) => room_id = Some(r), None => { - for (_id, registration) in services().appservice.all()? { - let aliases = registration - .get("namespaces") - .and_then(|ns| ns.get("aliases")) - .and_then(|aliases| aliases.as_sequence()) - .map_or_else(Vec::new, |aliases| { - aliases - .iter() - .filter_map(|aliases| Regex::new(aliases.get("regex")?.as_str()?).ok()) - .collect::>() - }); - - if aliases - .iter() - .any(|aliases| aliases.is_match(room_alias.as_str())) - && services() + for appservice in services() + .appservice + .registration_info + .read() + .await + .values() + { + if appservice.aliases.is_match(room_alias.as_str()) + && if let Some(opt_result) = services() .sending .send_appservice_request( - registration, + appservice.registration.clone(), appservice::query::query_room_alias::v1::Request { room_alias: room_alias.clone(), }, ) .await - .is_ok() + { + opt_result.is_ok() + } else { + false + } { room_id = Some( services() diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index bbd48614..e841f13a 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -81,12 +81,9 @@ where let mut json_body = serde_json::from_slice::(&body).ok(); let appservices = services().appservice.all().unwrap(); - let appservice_registration = appservices.iter().find(|(_id, registration)| { - registration - .get("as_token") - .and_then(|as_token| as_token.as_str()) - .map_or(false, |as_token| token == Some(as_token)) - }); + let appservice_registration = appservices + .iter() + .find(|(_id, registration)| Some(registration.as_token.as_str()) == token); let (sender_user, sender_device, sender_servername, from_appservice) = if let Some((_id, registration)) = appservice_registration { @@ -95,11 +92,7 @@ where let user_id = query_params.user_id.map_or_else( || { UserId::parse_with_server_name( - registration - .get("sender_localpart") - .unwrap() - .as_str() - .unwrap(), + registration.sender_localpart.as_str(), services().globals.server_name(), ) .unwrap() diff --git a/src/database/key_value/appservice.rs b/src/database/key_value/appservice.rs index 9a821a65..3243183d 100644 --- a/src/database/key_value/appservice.rs +++ b/src/database/key_value/appservice.rs @@ -1,10 +1,11 @@ +use ruma::api::appservice::Registration; + use crate::{database::KeyValueDatabase, service, utils, Error, Result}; impl service::appservice::Data for KeyValueDatabase { /// Registers an appservice and returns the ID to the caller - fn register_appservice(&self, yaml: serde_yaml::Value) -> Result { - // TODO: Rumaify - let id = yaml.get("id").unwrap().as_str().unwrap(); + fn register_appservice(&self, yaml: Registration) -> Result { + let id = yaml.id.as_str(); self.id_appserviceregistrations.insert( id.as_bytes(), serde_yaml::to_string(&yaml).unwrap().as_bytes(), @@ -32,7 +33,7 @@ impl service::appservice::Data for KeyValueDatabase { Ok(()) } - fn get_registration(&self, id: &str) -> Result> { + fn get_registration(&self, id: &str) -> Result> { self.cached_registrations .read() .unwrap() @@ -64,7 +65,7 @@ impl service::appservice::Data for KeyValueDatabase { ))) } - fn all(&self) -> Result> { + fn all(&self) -> Result> { self.iter_ids()? .filter_map(|id| id.ok()) .map(move |id| { diff --git a/src/database/key_value/rooms/state_cache.rs b/src/database/key_value/rooms/state_cache.rs index 3dcaf4ae..49e3842b 100644 --- a/src/database/key_value/rooms/state_cache.rs +++ b/src/database/key_value/rooms/state_cache.rs @@ -1,13 +1,16 @@ use std::{collections::HashSet, sync::Arc}; -use regex::Regex; use ruma::{ events::{AnyStrippedStateEvent, AnySyncStateEvent}, serde::Raw, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, }; -use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; +use crate::{ + database::KeyValueDatabase, + service::{self, appservice::RegistrationInfo}, + services, utils, Error, Result, +}; impl service::rooms::state_cache::Data for KeyValueDatabase { fn mark_as_once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> { @@ -184,46 +187,28 @@ impl service::rooms::state_cache::Data for KeyValueDatabase { } #[tracing::instrument(skip(self, room_id, appservice))] - fn appservice_in_room( - &self, - room_id: &RoomId, - appservice: &(String, serde_yaml::Value), - ) -> Result { + fn appservice_in_room(&self, room_id: &RoomId, appservice: &RegistrationInfo) -> Result { let maybe = self .appservice_in_room_cache .read() .unwrap() .get(room_id) - .and_then(|map| map.get(&appservice.0)) + .and_then(|map| map.get(&appservice.registration.id)) .copied(); if let Some(b) = maybe { Ok(b) - } else if let Some(namespaces) = appservice.1.get("namespaces") { - let users = namespaces - .get("users") - .and_then(|users| users.as_sequence()) - .map_or_else(Vec::new, |users| { - users - .iter() - .filter_map(|users| Regex::new(users.get("regex")?.as_str()?).ok()) - .collect::>() - }); - - let bridge_user_id = appservice - .1 - .get("sender_localpart") - .and_then(|string| string.as_str()) - .and_then(|string| { - UserId::parse_with_server_name(string, services().globals.server_name()).ok() - }); + } else { + let bridge_user_id = UserId::parse_with_server_name( + appservice.registration.sender_localpart.as_str(), + services().globals.server_name(), + ) + .ok(); let in_room = bridge_user_id .map_or(false, |id| self.is_joined(&id, room_id).unwrap_or(false)) || self.room_members(room_id).any(|userid| { - userid.map_or(false, |userid| { - users.iter().any(|r| r.is_match(userid.as_str())) - }) + userid.map_or(false, |userid| appservice.users.is_match(userid.as_str())) }); self.appservice_in_room_cache @@ -231,11 +216,9 @@ impl service::rooms::state_cache::Data for KeyValueDatabase { .unwrap() .entry(room_id.to_owned()) .or_default() - .insert(appservice.0.clone(), in_room); + .insert(appservice.registration.id.clone(), in_room); Ok(in_room) - } else { - Ok(false) } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 425ef4e9..5b8588cf 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -8,7 +8,9 @@ use crate::{ use abstraction::{KeyValueDatabaseEngine, KvTree}; use directories::ProjectDirs; use lru_cache::LruCache; + use ruma::{ + api::appservice::Registration, events::{ push_rules::{PushRulesEvent, PushRulesEventContent}, room::message::RoomMessageEventContent, @@ -162,7 +164,7 @@ pub struct KeyValueDatabase { //pub pusher: pusher::PushData, pub(super) senderkey_pusher: Arc, - pub(super) cached_registrations: Arc>>, + pub(super) cached_registrations: Arc>>, pub(super) pdu_cache: Mutex>>, pub(super) shorteventid_cache: Mutex>>, pub(super) auth_chain_cache: Mutex, Arc>>>, @@ -967,6 +969,22 @@ impl KeyValueDatabase { ); } + // Inserting registrations into cache + for appservice in services().appservice.all()? { + services() + .appservice + .registration_info + .write() + .await + .insert( + appservice.0, + appservice + .1 + .try_into() + .expect("Should be validated on registration"), + ); + } + // This data is probably outdated db.presenceid_presence.clear()?; diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index d99be878..12bc1cf6 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -8,6 +8,7 @@ use std::{ use clap::Parser; use regex::Regex; use ruma::{ + api::appservice::Registration, events::{ room::{ canonical_alias::RoomCanonicalAliasEventContent, @@ -335,10 +336,9 @@ impl Service { if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```" { let appservice_config = body[1..body.len() - 1].join("\n"); - let parsed_config = - serde_yaml::from_str::(&appservice_config); + let parsed_config = serde_yaml::from_str::(&appservice_config); match parsed_config { - Ok(yaml) => match services().appservice.register_appservice(yaml) { + Ok(yaml) => match services().appservice.register_appservice(yaml).await { Ok(id) => RoomMessageEventContent::text_plain(format!( "Appservice registered with ID: {id}." )), @@ -361,6 +361,7 @@ impl Service { } => match services() .appservice .unregister_appservice(&appservice_identifier) + .await { Ok(()) => RoomMessageEventContent::text_plain("Appservice unregistered."), Err(e) => RoomMessageEventContent::text_plain(format!( diff --git a/src/service/appservice/data.rs b/src/service/appservice/data.rs index 744f0f94..ab19a50c 100644 --- a/src/service/appservice/data.rs +++ b/src/service/appservice/data.rs @@ -1,8 +1,10 @@ +use ruma::api::appservice::Registration; + use crate::Result; pub trait Data: Send + Sync { /// Registers an appservice and returns the ID to the caller - fn register_appservice(&self, yaml: serde_yaml::Value) -> Result; + fn register_appservice(&self, yaml: Registration) -> Result; /// Remove an appservice registration /// @@ -11,9 +13,9 @@ pub trait Data: Send + Sync { /// * `service_name` - the name you send to register the service previously fn unregister_appservice(&self, service_name: &str) -> Result<()>; - fn get_registration(&self, id: &str) -> Result>; + fn get_registration(&self, id: &str) -> Result>; fn iter_ids<'a>(&'a self) -> Result> + 'a>>; - fn all(&self) -> Result>; + fn all(&self) -> Result>; } diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 3052964d..40fa3ee8 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -1,16 +1,113 @@ mod data; +use std::collections::HashMap; + pub use data::Data; -use crate::Result; +use regex::RegexSet; +use ruma::api::appservice::{Namespace, Registration}; +use tokio::sync::RwLock; + +use crate::{services, Result}; + +/// Compiled regular expressions for a namespace +pub struct NamespaceRegex { + pub exclusive: Option, + pub non_exclusive: Option, +} + +impl NamespaceRegex { + /// Checks if this namespace has rights to a namespace + pub fn is_match(&self, heystack: &str) -> bool { + if self.is_exclusive_match(heystack) { + return true; + } + + if let Some(non_exclusive) = &self.non_exclusive { + if non_exclusive.is_match(heystack) { + return true; + } + } + false + } + + /// Checks if this namespace has exlusive rights to a namespace + pub fn is_exclusive_match(&self, heystack: &str) -> bool { + if let Some(exclusive) = &self.exclusive { + if exclusive.is_match(heystack) { + return true; + } + } + false + } +} + +impl TryFrom> for NamespaceRegex { + fn try_from(value: Vec) -> Result { + let mut exclusive = vec![]; + let mut non_exclusive = vec![]; + + for namespace in value { + if namespace.exclusive { + exclusive.push(namespace.regex); + } else { + non_exclusive.push(namespace.regex); + } + } + + Ok(NamespaceRegex { + exclusive: if exclusive.is_empty() { + None + } else { + Some(RegexSet::new(exclusive)?) + }, + non_exclusive: if non_exclusive.is_empty() { + None + } else { + Some(RegexSet::new(non_exclusive)?) + }, + }) + } + + type Error = regex::Error; +} + +/// Compiled regular expressions for an appservice +pub struct RegistrationInfo { + pub registration: Registration, + pub users: NamespaceRegex, + pub aliases: NamespaceRegex, + pub rooms: NamespaceRegex, +} + +impl TryFrom for RegistrationInfo { + fn try_from(value: Registration) -> Result { + Ok(RegistrationInfo { + users: value.namespaces.users.clone().try_into()?, + aliases: value.namespaces.aliases.clone().try_into()?, + rooms: value.namespaces.rooms.clone().try_into()?, + registration: value, + }) + } + + type Error = regex::Error; +} pub struct Service { pub db: &'static dyn Data, + pub registration_info: RwLock>, } impl Service { /// Registers an appservice and returns the ID to the caller - pub fn register_appservice(&self, yaml: serde_yaml::Value) -> Result { + pub async fn register_appservice(&self, yaml: Registration) -> Result { + services() + .appservice + .registration_info + .write() + .await + .insert(yaml.id.clone(), yaml.clone().try_into()?); + self.db.register_appservice(yaml) } @@ -19,11 +116,18 @@ impl Service { /// # Arguments /// /// * `service_name` - the name you send to register the service previously - pub fn unregister_appservice(&self, service_name: &str) -> Result<()> { + pub async fn unregister_appservice(&self, service_name: &str) -> Result<()> { + services() + .appservice + .registration_info + .write() + .await + .remove(service_name); + self.db.unregister_appservice(service_name) } - pub fn get_registration(&self, id: &str) -> Result> { + pub fn get_registration(&self, id: &str) -> Result> { self.db.get_registration(id) } @@ -31,7 +135,7 @@ impl Service { self.db.iter_ids() } - pub fn all(&self) -> Result> { + pub fn all(&self) -> Result> { self.db.all() } } diff --git a/src/service/mod.rs b/src/service/mod.rs index 8f9fb0a5..045ccd10 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -4,7 +4,7 @@ use std::{ }; use lru_cache::LruCache; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, RwLock}; use crate::{Config, Result}; @@ -56,7 +56,10 @@ impl Services { config: Config, ) -> Result { Ok(Self { - appservice: appservice::Service { db }, + appservice: appservice::Service { + db, + registration_info: RwLock::new(HashMap::new()), + }, pusher: pusher::Service { db }, rooms: rooms::Service { alias: rooms::alias::Service { db }, diff --git a/src/service/rooms/state_cache/data.rs b/src/service/rooms/state_cache/data.rs index 8921909f..b511919a 100644 --- a/src/service/rooms/state_cache/data.rs +++ b/src/service/rooms/state_cache/data.rs @@ -1,6 +1,6 @@ use std::{collections::HashSet, sync::Arc}; -use crate::Result; +use crate::{service::appservice::RegistrationInfo, Result}; use ruma::{ events::{AnyStrippedStateEvent, AnySyncStateEvent}, serde::Raw, @@ -22,11 +22,7 @@ pub trait Data: Send + Sync { fn get_our_real_users(&self, room_id: &RoomId) -> Result>>; - fn appservice_in_room( - &self, - room_id: &RoomId, - appservice: &(String, serde_yaml::Value), - ) -> Result; + fn appservice_in_room(&self, room_id: &RoomId, appservice: &RegistrationInfo) -> Result; /// Makes a user forget a room. fn forget(&self, room_id: &RoomId, user_id: &UserId) -> Result<()>; diff --git a/src/service/rooms/state_cache/mod.rs b/src/service/rooms/state_cache/mod.rs index ef1ad61e..c108695d 100644 --- a/src/service/rooms/state_cache/mod.rs +++ b/src/service/rooms/state_cache/mod.rs @@ -16,7 +16,7 @@ use ruma::{ }; use tracing::warn; -use crate::{services, Error, Result}; +use crate::{service::appservice::RegistrationInfo, services, Error, Result}; pub struct Service { pub db: &'static dyn Data, @@ -205,7 +205,7 @@ impl Service { pub fn appservice_in_room( &self, room_id: &RoomId, - appservice: &(String, serde_yaml::Value), + appservice: &RegistrationInfo, ) -> Result { self.db.appservice_in_room(room_id, appservice) } diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 097cc82f..1df1db50 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -7,7 +7,7 @@ use std::{ }; pub use data::Data; -use regex::Regex; + use ruma::{ api::{client::error::ErrorKind, federation}, canonical_json::to_canonical_value, @@ -21,8 +21,7 @@ use ruma::{ }, push::{Action, Ruleset, Tweak}, serde::Base64, - state_res, - state_res::{Event, RoomVersion}, + state_res::{self, Event, RoomVersion}, uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName, RoomId, ServerName, UserId, }; @@ -33,7 +32,10 @@ use tracing::{error, info, warn}; use crate::{ api::server_server, - service::pdu::{EventHash, PduBuilder}, + service::{ + appservice::NamespaceRegex, + pdu::{EventHash, PduBuilder}, + }, services, utils, Error, PduEvent, Result, }; @@ -522,15 +524,21 @@ impl Service { } } - for appservice in services().appservice.all()? { + for appservice in services() + .appservice + .registration_info + .read() + .await + .values() + { if services() .rooms .state_cache - .appservice_in_room(&pdu.room_id, &appservice)? + .appservice_in_room(&pdu.room_id, appservice)? { services() .sending - .send_pdu_appservice(appservice.0, pdu_id.clone())?; + .send_pdu_appservice(appservice.registration.id.clone(), pdu_id.clone())?; continue; } @@ -542,73 +550,41 @@ impl Service { .as_ref() .and_then(|state_key| UserId::parse(state_key.as_str()).ok()) { - if let Some(appservice_uid) = appservice - .1 - .get("sender_localpart") - .and_then(|string| string.as_str()) - .and_then(|string| { - UserId::parse_with_server_name(string, services().globals.server_name()) - .ok() - }) - { - if state_key_uid == &appservice_uid { - services() - .sending - .send_pdu_appservice(appservice.0, pdu_id.clone())?; - continue; - } + let appservice_uid = appservice.registration.sender_localpart.as_str(); + if state_key_uid == appservice_uid { + services().sending.send_pdu_appservice( + appservice.registration.id.clone(), + pdu_id.clone(), + )?; + continue; } } } - if let Some(namespaces) = appservice.1.get("namespaces") { - let users = namespaces - .get("users") - .and_then(|users| users.as_sequence()) - .map_or_else(Vec::new, |users| { - users - .iter() - .filter_map(|users| Regex::new(users.get("regex")?.as_str()?).ok()) - .collect::>() - }); - let aliases = namespaces - .get("aliases") - .and_then(|aliases| aliases.as_sequence()) - .map_or_else(Vec::new, |aliases| { - aliases - .iter() - .filter_map(|aliases| Regex::new(aliases.get("regex")?.as_str()?).ok()) - .collect::>() - }); - let rooms = namespaces - .get("rooms") - .and_then(|rooms| rooms.as_sequence()); - - let matching_users = |users: &Regex| { - users.is_match(pdu.sender.as_str()) - || pdu.kind == TimelineEventType::RoomMember - && pdu - .state_key - .as_ref() - .map_or(false, |state_key| users.is_match(state_key)) - }; - let matching_aliases = |aliases: &Regex| { - services() - .rooms - .alias - .local_aliases_for_room(&pdu.room_id) - .filter_map(|r| r.ok()) - .any(|room_alias| aliases.is_match(room_alias.as_str())) - }; - - if aliases.iter().any(matching_aliases) - || rooms.map_or(false, |rooms| rooms.contains(&pdu.room_id.as_str().into())) - || users.iter().any(matching_users) - { - services() - .sending - .send_pdu_appservice(appservice.0, pdu_id.clone())?; - } + let matching_users = |users: &NamespaceRegex| { + appservice.users.is_match(pdu.sender.as_str()) + || pdu.kind == TimelineEventType::RoomMember + && pdu + .state_key + .as_ref() + .map_or(false, |state_key| users.is_match(state_key)) + }; + let matching_aliases = |aliases: &NamespaceRegex| { + services() + .rooms + .alias + .local_aliases_for_room(&pdu.room_id) + .filter_map(|r| r.ok()) + .any(|room_alias| aliases.is_match(room_alias.as_str())) + }; + + if matching_aliases(&appservice.aliases) + || appservice.rooms.is_match(pdu.room_id.as_str()) + || matching_users(&appservice.users) + { + services() + .sending + .send_pdu_appservice(appservice.registration.id.clone(), pdu_id.clone())?; } } diff --git a/src/service/sending/mod.rs b/src/service/sending/mod.rs index f80c4f0a..bbacfdec 100644 --- a/src/service/sending/mod.rs +++ b/src/service/sending/mod.rs @@ -22,7 +22,7 @@ use base64::{engine::general_purpose, Engine as _}; use ruma::{ api::{ - appservice, + appservice::{self, Registration}, federation::{ self, transactions::edu::{ @@ -484,7 +484,7 @@ impl Service { let permit = services().sending.maximum_requests.acquire().await; - let response = appservice_server::send_request( + let response = match appservice_server::send_request( services() .appservice .get_registration(id) @@ -511,8 +511,12 @@ impl Service { }, ) .await - .map(|_response| kind.clone()) - .map_err(|e| (kind, e)); + { + None => Ok(kind.clone()), + Some(op_resp) => op_resp + .map(|_response| kind.clone()) + .map_err(|e| (kind.clone(), e)), + }; drop(permit); @@ -698,12 +702,15 @@ impl Service { response } + /// Sends a request to an appservice + /// + /// Only returns None if there is no url specified in the appservice registration file #[tracing::instrument(skip(self, registration, request))] pub async fn send_appservice_request( &self, - registration: serde_yaml::Value, + registration: Registration, request: T, - ) -> Result + ) -> Option> where T: Debug, { diff --git a/src/utils/error.rs b/src/utils/error.rs index 765a31bb..04390283 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -54,6 +54,11 @@ pub enum Error { #[from] source: reqwest::Error, }, + #[error("Could build regular expression: {source}")] + RegexError { + #[from] + source: regex::Error, + }, #[error("{0}")] FederationError(OwnedServerName, RumaError), #[error("Could not do this io: {source}")] From 10f3f9da494bf41899c83bdef62ebb83281ac363 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 28 Jan 2024 15:47:37 -0800 Subject: [PATCH 107/175] switch/update rocksdb crate This fork was created because the original seems de-facto unmaintained. --- Cargo.lock | 71 +++++++++++++++++++++++------------------------------- Cargo.toml | 12 ++++++--- flake.nix | 18 ++++++++++++-- 3 files changed, 55 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e99928e0..88217001 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,17 +204,16 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.65.1" +version = "0.69.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +checksum = "a4c69fae65a523209d34240b60abe0c42d33d1045d445c0839d8a4894a736e2d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "cexpr", "clang-sys", "lazy_static", "lazycell", "peeking_take_while", - "prettyplease", "proc-macro2", "quote", "regex", @@ -400,10 +399,10 @@ dependencies = [ "regex", "reqwest", "ring", - "rocksdb", "ruma", "rusqlite", "rust-argon2", + "rust-rocksdb", "sd-notify", "serde", "serde_html_form", @@ -1278,22 +1277,6 @@ dependencies = [ "redox_syscall", ] -[[package]] -name = "librocksdb-sys" -version = "0.11.0+8.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" -dependencies = [ - "bindgen", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", - "zstd-sys", -] - [[package]] name = "libsqlite3-sys" version = "0.26.0" @@ -1790,16 +1773,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "prettyplease" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" -dependencies = [ - "proc-macro2", - "syn 2.0.48", -] - [[package]] name = "proc-macro-crate" version = "2.0.0" @@ -2005,16 +1978,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "rocksdb" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" -dependencies = [ - "libc", - "librocksdb-sys", -] - [[package]] name = "ruma" version = "0.9.4" @@ -2230,6 +2193,32 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-librocksdb-sys" +version = "0.18.1+8.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef22f434855ceb8daf99073fcf909d957ad8705f5b530154e47978ae68e867c" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", +] + +[[package]] +name = "rust-rocksdb" +version = "0.22.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62223f035e676bb69da2ab9487e6f710da82be89473c658c51ed3b1a60c4b4a6" +dependencies = [ + "libc", + "rust-librocksdb-sys", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index e8c1c8bf..7bb3b5db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,8 +97,6 @@ threadpool = "1.8.1" # Used for ruma wrapper serde_html_form = "0.2.0" -rocksdb = { version = "0.21.0", default-features = true, features = ["multi-threaded-cf", "zstd"], optional = true } - thread_local = "1.1.7" # used for TURN server authentication hmac = "0.12.1" @@ -116,6 +114,14 @@ async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } +[dependencies.rust-rocksdb] +version = "0.22.7" +optional = true +features = [ + "multi-threaded-cf", + "zstd", +] + [target.'cfg(unix)'.dependencies] nix = { version = "0.26.2", features = ["resource"] } @@ -125,7 +131,7 @@ default = ["conduit_bin", "backend_sqlite", "backend_rocksdb", "systemd"] backend_persy = ["persy", "parking_lot"] backend_sqlite = ["sqlite"] #backend_heed = ["heed", "crossbeam"] -backend_rocksdb = ["rocksdb"] +backend_rocksdb = ["rust-rocksdb"] jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"] sqlite = ["rusqlite", "parking_lot", "tokio/signal"] conduit_bin = ["axum"] diff --git a/flake.nix b/flake.nix index cc95aecb..cdfe91f8 100644 --- a/flake.nix +++ b/flake.nix @@ -58,9 +58,23 @@ pkgs.pkgsBuildHost.rustPlatform.bindgenHook ]; + rocksdb' = pkgs: + let + version = "8.11.3"; + in + pkgs.rocksdb.overrideAttrs (old: { + inherit version; + src = pkgs.fetchFromGitHub { + owner = "facebook"; + repo = "rocksdb"; + rev = "v${version}"; + hash = "sha256-OpEiMwGxZuxb9o3RQuSrwZMQGLhe9xLT1aa3HpI4KPs="; + }; + }); + env = pkgs: { - ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; + ROCKSDB_INCLUDE_DIR = "${rocksdb' pkgs}/include"; + ROCKSDB_LIB_DIR = "${rocksdb' pkgs}/lib"; } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isStatic { ROCKSDB_STATIC = ""; From daed4cdddfcb84e9b648b15bcfcd89c4bbde834b Mon Sep 17 00:00:00 2001 From: tezlm Date: Sat, 14 Oct 2023 06:20:29 -0700 Subject: [PATCH 108/175] Remove log config modification --- src/main.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 524f6886..aaa34346 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,8 +65,6 @@ async fn main() { config.warn_deprecated(); - let log = format!("{},ruma_state_res=error,_=off,sled=off", config.log); - if config.allow_jaeger { opentelemetry::global::set_text_map_propagator(opentelemetry_jaeger::Propagator::new()); let tracer = opentelemetry_jaeger::new_agent_pipeline() @@ -76,7 +74,7 @@ async fn main() { .unwrap(); let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); - let filter_layer = match EnvFilter::try_new(&log) { + let filter_layer = match EnvFilter::try_new(&config.log) { Ok(s) => s, Err(e) => { eprintln!( @@ -103,7 +101,7 @@ async fn main() { } else { let registry = tracing_subscriber::Registry::default(); let fmt_layer = tracing_subscriber::fmt::Layer::new(); - let filter_layer = match EnvFilter::try_new(&log) { + let filter_layer = match EnvFilter::try_new(&config.log) { Ok(s) => s, Err(e) => { eprintln!("It looks like your config is invalid. The following error occured while parsing it: {e}"); From 9ff9e85ebe2b6358dd1e554a8ba5ce34f4faedf0 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 22:33:54 -0700 Subject: [PATCH 109/175] add newline to end of file Please, people. --- docker/docker-compose.with-traefik.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.with-traefik.yml b/docker/docker-compose.with-traefik.yml index fda942bc..e3289ba4 100644 --- a/docker/docker-compose.with-traefik.yml +++ b/docker/docker-compose.with-traefik.yml @@ -95,4 +95,4 @@ volumes: acme: networks: - proxy: \ No newline at end of file + proxy: From 5f053a93574e6bc2a36bd5b9a1c70c4bf6f5c8fa Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 22:34:25 -0700 Subject: [PATCH 110/175] link to example config instead of copying it DRY FTW --- DEPLOY.md | 53 ++++------------------------------------------------- 1 file changed, 4 insertions(+), 49 deletions(-) diff --git a/DEPLOY.md b/DEPLOY.md index dd279688..e87fca3b 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -139,57 +139,12 @@ $ sudo systemctl daemon-reload ## Creating the Conduit configuration file -Now we need to create the Conduit's config file in `/etc/matrix-conduit/conduit.toml`. Paste this in **and take a moment -to read it. You need to change at least the server name.** +Now we need to create the Conduit's config file in +`/etc/matrix-conduit/conduit.toml`. Paste in the contents of +[`conduit-example.toml`](./conduit-example.toml) **and take a moment to read it. +You need to change at least the server name.** You can also choose to use a different database backend, but right now only `rocksdb` and `sqlite` are recommended. -```toml -[global] -# The server_name is the pretty name of this server. It is used as a suffix for user -# and room ids. Examples: matrix.org, conduit.rs - -# The Conduit server needs all /_matrix/ requests to be reachable at -# https://your.server.name/ on port 443 (client-server) and 8448 (federation). - -# If that's not possible for you, you can create /.well-known files to redirect -# requests. See -# https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client -# and -# https://matrix.org/docs/spec/server_server/r0.1.4#get-well-known-matrix-server -# for more information - -# YOU NEED TO EDIT THIS -#server_name = "your.server.name" - -# This is the only directory where Conduit will save its data -database_path = "/var/lib/matrix-conduit/" -database_backend = "rocksdb" - -# The port Conduit will be running on. You need to set up a reverse proxy in -# your web server (e.g. apache or nginx), so all requests to /_matrix on port -# 443 and 8448 will be forwarded to the Conduit instance running on this port -# Docker users: Don't change this, you'll need to map an external port to this. -port = 6167 - -# Max size for uploads -max_request_size = 20_000_000 # in bytes - -# Enables registration. If set to false, no users can register on this server. -allow_registration = true - -allow_federation = true -allow_check_for_updates = true - -# Server to get public keys from. You probably shouldn't change this -trusted_servers = ["matrix.org"] - -#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time -#log = "warn,state_res=warn,rocket=off,_=off,sled=off" - -address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy -#address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it. -``` - ## Setting the correct file permissions As we are using a Conduit specific user we need to allow it to read the config. To do that you can run this command on From ed5bd2325596ae73a7e81e13aafdf774cc403449 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 22:36:48 -0700 Subject: [PATCH 111/175] remove explicit references to log config They're all stale. Sled was yote long ago. --- debian/postinst | 1 - docker/README.md | 1 - docker/docker-compose.for-traefik.yml | 1 - docker/docker-compose.with-traefik.yml | 1 - docker/docker-compose.yml | 1 - 5 files changed, 5 deletions(-) diff --git a/debian/postinst b/debian/postinst index 69a766a0..110f22d6 100644 --- a/debian/postinst +++ b/debian/postinst @@ -78,7 +78,6 @@ allow_check_for_updates = true trusted_servers = ["matrix.org"] #max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time -#log = "warn,state_res=warn,rocket=off,_=off,sled=off" EOF fi ;; diff --git a/docker/README.md b/docker/README.md index b34f9d87..2448e643 100644 --- a/docker/README.md +++ b/docker/README.md @@ -64,7 +64,6 @@ docker run -d -p 8448:6167 \ -e CONDUIT_MAX_REQUEST_SIZE="20_000_000" \ -e CONDUIT_TRUSTED_SERVERS="[\"matrix.org\"]" \ -e CONDUIT_MAX_CONCURRENT_REQUESTS="100" \ - -e CONDUIT_LOG="warn,rocket=off,_=off,sled=off" \ --name conduit ``` diff --git a/docker/docker-compose.for-traefik.yml b/docker/docker-compose.for-traefik.yml index bed734f1..82bb55b0 100644 --- a/docker/docker-compose.for-traefik.yml +++ b/docker/docker-compose.for-traefik.yml @@ -32,7 +32,6 @@ services: CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true' CONDUIT_TRUSTED_SERVERS: '["matrix.org"]' #CONDUIT_MAX_CONCURRENT_REQUESTS: 100 - #CONDUIT_LOG: warn,rocket=off,_=off,sled=off CONDUIT_ADDRESS: 0.0.0.0 CONDUIT_CONFIG: '' # Ignore this diff --git a/docker/docker-compose.with-traefik.yml b/docker/docker-compose.with-traefik.yml index e3289ba4..58603277 100644 --- a/docker/docker-compose.with-traefik.yml +++ b/docker/docker-compose.with-traefik.yml @@ -33,7 +33,6 @@ services: # CONDUIT_PORT: 6167 # CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string '' # Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging - # CONDUIT_LOG: info # default is: "warn,_=off,sled=off" # CONDUIT_ALLOW_JAEGER: 'false' # CONDUIT_ALLOW_ENCRYPTION: 'true' # CONDUIT_ALLOW_FEDERATION: 'true' diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 5bcf84f7..97f91daf 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -32,7 +32,6 @@ services: CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true' CONDUIT_TRUSTED_SERVERS: '["matrix.org"]' #CONDUIT_MAX_CONCURRENT_REQUESTS: 100 - #CONDUIT_LOG: warn,rocket=off,_=off,sled=off CONDUIT_ADDRESS: 0.0.0.0 CONDUIT_CONFIG: '' # Ignore this # From 516876f8ef5f88c42b44ef1c485dd9e69cb9659b Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 22:37:22 -0700 Subject: [PATCH 112/175] remove final reference to sled in log config --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index a4d7cca4..4605855f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -264,7 +264,7 @@ fn default_trusted_servers() -> Vec { } fn default_log() -> String { - "warn,state_res=warn,_=off,sled=off".to_owned() + "warn,state_res=warn,_=off".to_owned() } fn default_turn_ttl() -> u64 { From dc89fbed3ad6296e72c68f4209116cf05870fc27 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 22:38:02 -0700 Subject: [PATCH 113/175] document log config syntax, don't give example Because the old one was stale. Shocking! --- conduit-example.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/conduit-example.toml b/conduit-example.toml index 836db654..a52121ac 100644 --- a/conduit-example.toml +++ b/conduit-example.toml @@ -51,7 +51,11 @@ enable_lightning_bolt = true trusted_servers = ["matrix.org"] #max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time -#log = "warn,state_res=warn,rocket=off,_=off,sled=off" + +# Controls the log verbosity. See also [here][0]. +# +# [0]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives +#log = "..." address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy #address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it. From d1bc7fcfd2493b77a4f701e333d3eb0faf5e5109 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 10 Mar 2024 23:39:02 -0700 Subject: [PATCH 114/175] rename the `rust-rocksdb` crate to just `rocksdb` This way the old `cfg`s still work and we don't need to constantly remind ourselves what programming language we're using in `use` statements. Also fixes a problem where RocksDB users couldn't start Conduit because the old `cfg`s were using the original crate's name instead of the `backend_rocksdb` feature name for some reason. Maybe that should be changed, but I'm not sure. --- Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7bb3b5db..08188cb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,8 @@ async-trait = "0.1.68" sd-notify = { version = "0.4.1", optional = true } -[dependencies.rust-rocksdb] +[dependencies.rocksdb] +package = "rust-rocksdb" version = "0.22.7" optional = true features = [ @@ -131,7 +132,7 @@ default = ["conduit_bin", "backend_sqlite", "backend_rocksdb", "systemd"] backend_persy = ["persy", "parking_lot"] backend_sqlite = ["sqlite"] #backend_heed = ["heed", "crossbeam"] -backend_rocksdb = ["rust-rocksdb"] +backend_rocksdb = ["rocksdb"] jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"] sqlite = ["rusqlite", "parking_lot", "tokio/signal"] conduit_bin = ["axum"] From 4af691d737b29f6fa7e98d302279f5a85a2c879a Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Mon, 11 Mar 2024 11:43:05 +0100 Subject: [PATCH 115/175] fix(ci): avoid duplicate pipelines --- .gitlab-ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 348e7b19..3b7016fb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,15 @@ variables: # Makes some things print in color TERM: ansi +# Avoid duplicate pipelines +# See: https://docs.gitlab.com/ee/ci/yaml/workflow.html#switch-between-branch-pipelines-and-merge-request-pipelines +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS + when: never + - if: $CI + before_script: # Enable nix-command and flakes - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi @@ -52,10 +61,14 @@ ci: rules: # CI on upstream runners (only available for maintainers) - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $IS_UPSTREAM_CI == "true" + # Manual CI on unprotected branches that are not MRs + - if: $CI_PIPELINE_SOURCE != "merge_request_event" && $CI_COMMIT_REF_PROTECTED == "false" + when: manual # Manual CI on forks - if: $IS_UPSTREAM_CI != "true" when: manual - if: $CI + interruptible: true artifacts: stage: artifacts @@ -100,6 +113,7 @@ artifacts: when: manual allow_failure: true - if: $CI + interruptible: true .push-oci-image: stage: publish From 9a81a49c6ae1217928658dd1d6742868ec40931e Mon Sep 17 00:00:00 2001 From: Max Cohen Date: Sun, 25 Sep 2022 10:59:19 +0200 Subject: [PATCH 116/175] Add argument parser for the conduit executable Allow fetching the version with `conduit --version`. Fixes #285. --- src/clap.rs | 13 +++++++++++++ src/lib.rs | 1 + src/main.rs | 2 ++ 3 files changed, 16 insertions(+) create mode 100644 src/clap.rs diff --git a/src/clap.rs b/src/clap.rs new file mode 100644 index 00000000..444f21bf --- /dev/null +++ b/src/clap.rs @@ -0,0 +1,13 @@ +//! Integration with `clap` + +use clap::Parser; + +/// Command line arguments +#[derive(Parser)] +#[clap(about, version)] +pub struct Args {} + +/// Parse command line arguments into structured data +pub fn parse() -> Args { + Args::parse() +} diff --git a/src/lib.rs b/src/lib.rs index 70c6f373..5a89f805 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod api; +pub mod clap; mod config; mod database; mod service; diff --git a/src/main.rs b/src/main.rs index 524f6886..e5861846 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,8 @@ static GLOBAL: Jemalloc = Jemalloc; #[tokio::main] async fn main() { + clap::parse(); + // Initialize config let raw_config = Figment::new() From ac22b1bed13c298b566acf503cba47e7e9bc072a Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 11 Mar 2024 20:11:59 -0700 Subject: [PATCH 117/175] allow including extra info in `--version` output --- Cargo.toml | 2 +- flake.nix | 1 + src/clap.rs | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08188cb3..796791bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ thread_local = "1.1.7" hmac = "0.12.1" sha-1 = "0.10.1" # used for conduit's CLI and admin room command parsing -clap = { version = "4.3.0", default-features = false, features = ["std", "derive", "help", "usage", "error-context"] } +clap = { version = "4.3.0", default-features = false, features = ["std", "derive", "help", "usage", "error-context", "string"] } futures-util = { version = "0.3.28", default-features = false } # Used for reading the configuration from conduit.toml & environment variables figment = { version = "0.10.8", features = ["env", "toml"] } diff --git a/flake.nix b/flake.nix index cdfe91f8..97f68354 100644 --- a/flake.nix +++ b/flake.nix @@ -73,6 +73,7 @@ }); env = pkgs: { + CONDUIT_VERSION_EXTRA = self.shortRev or self.dirtyShortRev; ROCKSDB_INCLUDE_DIR = "${rocksdb' pkgs}/include"; ROCKSDB_LIB_DIR = "${rocksdb' pkgs}/lib"; } diff --git a/src/clap.rs b/src/clap.rs index 444f21bf..170d2a17 100644 --- a/src/clap.rs +++ b/src/clap.rs @@ -2,9 +2,23 @@ use clap::Parser; +/// Returns the current version of the crate with extra info if supplied +/// +/// Set the environment variable `CONDUIT_VERSION_EXTRA` to any UTF-8 string to +/// include it in parenthesis after the SemVer version. A common value are git +/// commit hashes. +fn version() -> String { + let cargo_pkg_version = env!("CARGO_PKG_VERSION"); + + match option_env!("CONDUIT_VERSION_EXTRA") { + Some(x) => format!("{} ({})", cargo_pkg_version, x), + None => cargo_pkg_version.to_owned(), + } +} + /// Command line arguments #[derive(Parser)] -#[clap(about, version)] +#[clap(about, version = version())] pub struct Args {} /// Parse command line arguments into structured data From 425660472cdbb66fd1bfea30f387598b680ed64a Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Wed, 13 Mar 2024 18:01:41 +0100 Subject: [PATCH 118/175] docs: build docs using mdBook --- .gitignore | 3 ++ .gitlab/route-map.yml | 3 ++ README.md | 29 ++++++++++--------- book.toml | 18 ++++++++++++ debian/README.md | 2 +- docs/SUMMARY.md | 12 ++++++++ APPSERVICES.md => docs/appservices.md | 0 docs/configuration.md | 5 ++++ docs/deploying.md | 8 +++++ docs/deploying/debian.md | 1 + .../deploying}/docker-compose.for-traefik.yml | 0 .../deploying}/docker-compose.override.yml | 0 .../docker-compose.with-traefik.yml | 0 {docker => docs/deploying}/docker-compose.yml | 0 docker/README.md => docs/deploying/docker.md | 7 ++--- nix/README.md => docs/deploying/nix.md | 0 DEPLOY.md => docs/deploying/simple.md | 10 ++++--- docs/introduction.md | 13 +++++++++ TURN.md => docs/turn.md | 2 +- 19 files changed, 89 insertions(+), 24 deletions(-) create mode 100644 .gitlab/route-map.yml create mode 100644 book.toml create mode 100644 docs/SUMMARY.md rename APPSERVICES.md => docs/appservices.md (100%) create mode 100644 docs/configuration.md create mode 100644 docs/deploying.md create mode 100644 docs/deploying/debian.md rename {docker => docs/deploying}/docker-compose.for-traefik.yml (100%) rename {docker => docs/deploying}/docker-compose.override.yml (100%) rename {docker => docs/deploying}/docker-compose.with-traefik.yml (100%) rename {docker => docs/deploying}/docker-compose.yml (100%) rename docker/README.md => docs/deploying/docker.md (97%) rename nix/README.md => docs/deploying/nix.md (100%) rename DEPLOY.md => docs/deploying/simple.md (97%) create mode 100644 docs/introduction.md rename TURN.md => docs/turn.md (97%) diff --git a/.gitignore b/.gitignore index a34d70ad..73ce2e1f 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ cached_target # Gitlab CI cache /.gitlab-ci.d + +# mdbook output +public/ \ No newline at end of file diff --git a/.gitlab/route-map.yml b/.gitlab/route-map.yml new file mode 100644 index 00000000..2c23079c --- /dev/null +++ b/.gitlab/route-map.yml @@ -0,0 +1,3 @@ +# Docs: Map markdown to html files +- source: /docs/(.+)\.md/ + public: '\1.html' \ No newline at end of file diff --git a/README.md b/README.md index bf7bde5e..0026f077 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,15 @@ # Conduit + + ### A Matrix homeserver written in Rust + + +Please visit the [Conduit documentation](https://famedly.gitlab.io/conduit) for more information. +Alternatively you can open [docs/introduction.md](docs/introduction.md) in this repository. + #### What is Matrix? + [Matrix](https://matrix.org) is an open network for secure and decentralized communication. Users from every Matrix homeserver can chat with users from all other Matrix servers. You can even use bridges (also called Matrix appservices) @@ -30,16 +38,9 @@ There are still a few important features missing: - E2EE emoji comparison over federation (E2EE chat works) - Outgoing read receipts, typing, presence over federation (incoming works) + -#### How can I deploy my own? - -- Simple install (this was tested the most): [DEPLOY.md](DEPLOY.md) -- Debian package: [debian/README.md](debian/README.md) -- Nix/NixOS: [nix/README.md](nix/README.md) -- Docker: [docker/README.md](docker/README.md) - -If you want to connect an Appservice to Conduit, take a look at [APPSERVICES.md](APPSERVICES.md). - + #### How can I contribute? 1. Look for an issue you would like to work on and make sure no one else is currently working on it. @@ -56,7 +57,6 @@ If you have any questions, feel free to - Send an direct message to `@timokoesters:fachschaften.org` on Matrix - [Open an issue on GitLab](https://gitlab.com/famedly/conduit/-/issues/new) - #### Thanks to Thanks to FUTO, Famedly, Prototype Fund (DLR and German BMBF) and all individuals for financially supporting this project. @@ -68,10 +68,11 @@ Thanks to the contributors to Conduit and all libraries we use, for example: #### Donate -Liberapay: \ -Bitcoin: `bc1qnnykf986tw49ur7wx9rpw2tevpsztvar5x8w4n` +- Liberapay: +- Bitcoin: `bc1qnnykf986tw49ur7wx9rpw2tevpsztvar5x8w4n` #### Logo -Lightning Bolt Logo: https://github.com/mozilla/fxemoji/blob/gh-pages/svgs/nature/u26A1-bolt.svg \ -Logo License: https://github.com/mozilla/fxemoji/blob/gh-pages/LICENSE.md +- Lightning Bolt Logo: +- Logo License: + diff --git a/book.toml b/book.toml new file mode 100644 index 00000000..e25746ca --- /dev/null +++ b/book.toml @@ -0,0 +1,18 @@ +[book] +title = "Conduit" +description = "Conduit is a simple, fast and reliable chat server for the Matrix protocol" +language = "en" +multilingual = false +src = "docs" + +[build] +build-dir = "public" +create-missing = true + +[output.html] +git-repository-url = "https://gitlab.com/famedly/conduit" +edit-url-template = "https://gitlab.com/famedly/conduit/-/edit/next/{path}" +git-repository-icon = "fa-git-square" + +[output.html.search] +limit-results = 15 diff --git a/debian/README.md b/debian/README.md index 443be76b..4ddb614d 100644 --- a/debian/README.md +++ b/debian/README.md @@ -5,7 +5,7 @@ Installation ------------ Information about downloading, building and deploying the Debian package, see -the "Installing Conduit" section in [DEPLOY.md](../DEPLOY.md). +the "Installing Conduit" section in the Deploying docs. All following sections until "Setting up the Reverse Proxy" be ignored because this is handled automatically by the packaging. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 00000000..e7ed05d7 --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,12 @@ +# Summary + +- [Introduction](introduction.md) + +- [Example configuration](configuration.md) +- [Deployment options](deploying.md) + - [Simple (Recommended)](deploying/simple.md) + - [Debian](deploying/debian.md) + - [Docker](deploying/docker.md) + - [Nix](deploying/nix.md) +- [TURN](turn.md) +- [Appservices](appservices.md) diff --git a/APPSERVICES.md b/docs/appservices.md similarity index 100% rename from APPSERVICES.md rename to docs/appservices.md diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 00000000..a47e5ff9 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,5 @@ +# Example configuration + +``` toml +{{#include ../conduit-example.toml}} +``` diff --git a/docs/deploying.md b/docs/deploying.md new file mode 100644 index 00000000..3694f6b2 --- /dev/null +++ b/docs/deploying.md @@ -0,0 +1,8 @@ +# Deployment options + +There are several ways to deploy a Conduit server. + +- [Simple (Recommended)](deploying/simple.md) - This is the recommended way to set up Conduit. +- [Debian](deploying/debian.md) - If you're using a debian-based system, you may find the `deb` package useful. +- [Docker](deploying/docker.md) - We provide multi-arch OCI images for Conduit. +- [Nix](deploying/nix.md) - Nix flake based setup. diff --git a/docs/deploying/debian.md b/docs/deploying/debian.md new file mode 100644 index 00000000..2e8a544a --- /dev/null +++ b/docs/deploying/debian.md @@ -0,0 +1 @@ +{{#include ../../debian/README.md}} diff --git a/docker/docker-compose.for-traefik.yml b/docs/deploying/docker-compose.for-traefik.yml similarity index 100% rename from docker/docker-compose.for-traefik.yml rename to docs/deploying/docker-compose.for-traefik.yml diff --git a/docker/docker-compose.override.yml b/docs/deploying/docker-compose.override.yml similarity index 100% rename from docker/docker-compose.override.yml rename to docs/deploying/docker-compose.override.yml diff --git a/docker/docker-compose.with-traefik.yml b/docs/deploying/docker-compose.with-traefik.yml similarity index 100% rename from docker/docker-compose.with-traefik.yml rename to docs/deploying/docker-compose.with-traefik.yml diff --git a/docker/docker-compose.yml b/docs/deploying/docker-compose.yml similarity index 100% rename from docker/docker-compose.yml rename to docs/deploying/docker-compose.yml diff --git a/docker/README.md b/docs/deploying/docker.md similarity index 97% rename from docker/README.md rename to docs/deploying/docker.md index 2448e643..4a38b30b 100644 --- a/docker/README.md +++ b/docs/deploying/docker.md @@ -69,7 +69,7 @@ docker run -d -p 8448:6167 \ or you can use [docker-compose](#docker-compose). -The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../conduit-example.toml). +The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../configuration.md). You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible values, please take a look at the `docker-compose.yml` file. @@ -87,8 +87,7 @@ Depending on your proxy setup, you can use one of the following files; When picking the traefik-related compose file, rename it so it matches `docker-compose.yml`, and rename the override file to `docker-compose.override.yml`. Edit the latter with the values you want for your server. - -Additional info about deploying Conduit can be found [here](../DEPLOY.md). +Additional info about deploying Conduit can be found [here](simple.md). ### Build @@ -130,7 +129,7 @@ So...step by step: 1. Copy [`docker-compose.for-traefik.yml`](docker-compose.for-traefik.yml) (or [`docker-compose.with-traefik.yml`](docker-compose.with-traefik.yml)) and [`docker-compose.override.yml`](docker-compose.override.yml) from the repository and remove `.for-traefik` (or `.with-traefik`) from the filename. 2. Open both files and modify/adjust them to your needs. Meaning, change the `CONDUIT_SERVER_NAME` and the volume host mappings according to your needs. -3. Create the `conduit.toml` config file, an example can be found [here](../conduit-example.toml), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars. +3. Create the `conduit.toml` config file, an example can be found [here](../configuration.md), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars. 4. Uncomment the `element-web` service if you want to host your own Element Web Client and create a `element_config.json`. 5. Create the files needed by the `well-known` service. diff --git a/nix/README.md b/docs/deploying/nix.md similarity index 100% rename from nix/README.md rename to docs/deploying/nix.md diff --git a/DEPLOY.md b/docs/deploying/simple.md similarity index 97% rename from DEPLOY.md rename to docs/deploying/simple.md index e87fca3b..9542bf1a 100644 --- a/DEPLOY.md +++ b/docs/deploying/simple.md @@ -1,4 +1,6 @@ -# Deploying Conduit +# Simple setup + +This is the recommended way to set up Conduit. It is the easiest way to get started and is suitable for most use cases. > ## Getting help > @@ -141,7 +143,7 @@ $ sudo systemctl daemon-reload Now we need to create the Conduit's config file in `/etc/matrix-conduit/conduit.toml`. Paste in the contents of -[`conduit-example.toml`](./conduit-example.toml) **and take a moment to read it. +[`conduit-example.toml`](../configuration.md) **and take a moment to read it. You need to change at least the server name.** You can also choose to use a different database backend, but right now only `rocksdb` and `sqlite` are recommended. @@ -305,8 +307,8 @@ $ curl https://your.server.name:8448/_matrix/client/versions ## Audio/Video calls -For Audio/Video call functionality see the [TURN Guide](TURN.md). +For Audio/Video call functionality see the [TURN Guide](../turn.md). ## Appservices -If you want to set up an appservice, take a look at the [Appservice Guide](APPSERVICES.md). +If you want to set up an appservice, take a look at the [Appservice Guide](../appservices.md). diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 00000000..da34ab6e --- /dev/null +++ b/docs/introduction.md @@ -0,0 +1,13 @@ +# Conduit + +{{#include ../README.md:catchphrase}} + +{{#include ../README.md:body}} + +#### How can I deploy my own? + +- [Deployment options](deploying.md) + +If you want to connect an Appservice to Conduit, take a look at the [appservices documentation](appservices.md). + +{{#include ../README.md:footer}} diff --git a/TURN.md b/docs/turn.md similarity index 97% rename from TURN.md rename to docs/turn.md index 63c1e99f..a61f1b13 100644 --- a/TURN.md +++ b/docs/turn.md @@ -22,4 +22,4 @@ turn_secret = "ADD SECRET HERE" ## Apply settings -Restart Conduit. \ No newline at end of file +Restart Conduit. From 4f8d3953b36e8a67deba44ef524e4e032453c575 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 14 Mar 2024 20:19:02 -0700 Subject: [PATCH 119/175] add nix output for the book --- flake.nix | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/flake.nix b/flake.nix index cdfe91f8..0e699e1d 100644 --- a/flake.nix +++ b/flake.nix @@ -207,6 +207,35 @@ packages = { default = package pkgsHost; oci-image = mkOciImage pkgsHost self.packages.${system}.default; + + book = + let + package = self.packages.${system}.default; + in + pkgsHost.stdenv.mkDerivation { + pname = "${package.pname}-book"; + version = package.version; + + src = nix-filter { + root = ./.; + include = [ + "book.toml" + "conduit-example.toml" + "README.md" + "debian/README.md" + "docs" + ]; + }; + + nativeBuildInputs = (with pkgsHost; [ + mdbook + ]); + + buildPhase = '' + mdbook build + mv public $out + ''; + }; } // builtins.listToAttrs From 6800e5fd185095ec84bdd692b2bd45502f94891a Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 14 Mar 2024 20:27:44 -0700 Subject: [PATCH 120/175] build book in ci, deploy it to gitlab pages --- .gitlab-ci.yml | 17 +++++++++++++++++ engage.toml | 10 ++++++++++ flake.nix | 3 +++ 3 files changed, 30 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3b7016fb..8c880b9c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -98,6 +98,10 @@ artifacts: - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl - cp result oci-image-arm64v8.tar.gz + + - ./bin/nix-build-and-cache .#book + # We can't just copy the symlink, we need to dereference it https://gitlab.com/gitlab-org/gitlab/-/issues/19746 + - cp -r --dereference result public artifacts: paths: - x86_64-unknown-linux-musl @@ -105,6 +109,7 @@ artifacts: - x86_64-unknown-linux-musl.deb - oci-image-amd64.tar.gz - oci-image-arm64v8.tar.gz + - public rules: # CI required for all MRs - if: $CI_PIPELINE_SOURCE == "merge_request_event" @@ -165,3 +170,15 @@ oci-image:push-dockerhub: IMAGE_NAME: matrixconduit/matrix-conduit before_script: - docker login -u $DOCKER_HUB_USER -p $DOCKER_HUB_PASSWORD + +pages: + stage: publish + dependencies: + - artifacts + only: + - next + script: + - "true" + artifacts: + paths: + - public diff --git a/engage.toml b/engage.toml index 3e8884eb..cb284167 100644 --- a/engage.toml +++ b/engage.toml @@ -30,6 +30,11 @@ name = "cargo-clippy" group = "versions" script = "cargo clippy -- --version" +[[task]] +name = "lychee" +group = "versions" +script = "lychee --version" + [[task]] name = "cargo-fmt" group = "lints" @@ -51,6 +56,11 @@ name = "cargo-clippy" group = "lints" script = "cargo clippy --workspace --all-targets --color=always -- -D warnings" +[[task]] +name = "lychee" +group = "lints" +script = "lychee --offline docs" + [[task]] name = "cargo" group = "tests" diff --git a/flake.nix b/flake.nix index 0e699e1d..9cd826b8 100644 --- a/flake.nix +++ b/flake.nix @@ -304,6 +304,9 @@ # Needed for our script for Complement jq + + # Needed for finding broken markdown links + lychee ]); }; }); From a3968725b4938fec2fcbd24e655f8b5ba2d53490 Mon Sep 17 00:00:00 2001 From: Samuel Meenzen Date: Fri, 15 Mar 2024 12:23:09 +0100 Subject: [PATCH 121/175] chore: add EditorConfig --- .editorconfig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..a4e9e432 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://EditorConfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +tab_width = 4 +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 + +[*.nix] +indent_size = 2 From 120035685b225a318844f8aed9b4088644fe9ff9 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 17 Mar 2024 17:13:34 +0000 Subject: [PATCH 122/175] docs: point people to the matrix client list instead of element --- README.md | 3 +-- docs/deploying/simple.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0026f077..474a5247 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,7 @@ friends or company. #### Can I try it out? -Yes! You can test our Conduit instance by opening a Matrix client ( or Element Android for -example) and registering on the `conduit.rs` homeserver. The registration token is "for_testing_only". Don't share personal information. +Yes! You can test our Conduit instance by opening a client that supports registration tokens such as [Element web](https://app.element.io/), [Nheko](https://matrix.org/ecosystem/clients/nheko/) or [SchildiChat web](https://app.schildi.chat/) and registering on the `conduit.rs` homeserver. The registration token is "for_testing_only". Don't share personal information. Once you have registered, you can use any other [Matrix client](https://matrix.org/ecosystem/clients) to login. Server hosting for conduit.rs is donated by the Matrix.org Foundation. diff --git a/docs/deploying/simple.md b/docs/deploying/simple.md index 9542bf1a..ea12a281 100644 --- a/docs/deploying/simple.md +++ b/docs/deploying/simple.md @@ -289,7 +289,7 @@ $ sudo systemctl enable conduit ## How do I know it works? -You can open , enter your homeserver and try to register. +You can open [a Matrix client](https://matrix.org/ecosystem/clients), enter your homeserver and try to register. If you are using a registration token, use [Element web](https://app.element.io/), [Nheko](https://matrix.org/ecosystem/clients/nheko/) or [SchildiChat web](https://app.schildi.chat/), as they support this feature. You can also use these commands as a quick health check. From 5f0bea69614de0bc0dac3b440fcb070274ccb9cb Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 16 Mar 2024 19:04:54 +0000 Subject: [PATCH 123/175] refactor: check if federation is disabled inside the authcheck where possible --- src/api/ruma_wrapper/axum.rs | 4 +++ src/api/server_server.rs | 68 ------------------------------------ 2 files changed, 4 insertions(+), 68 deletions(-) diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index bbd48614..c6a19578 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -149,6 +149,10 @@ where } } AuthScheme::ServerSignatures => { + if !services().globals.allow_federation() { + return Err(Error::bad_config("Federation is disabled.")); + } + let TypedHeader(Authorization(x_matrix)) = parts .extract::>>() .await diff --git a/src/api/server_server.rs b/src/api/server_server.rs index f946feaf..e0335493 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -601,10 +601,6 @@ pub async fn get_server_keys_deprecated_route() -> impl IntoResponse { pub async fn get_public_rooms_filtered_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let response = client_server::get_public_rooms_filtered_helper( None, body.limit, @@ -628,10 +624,6 @@ pub async fn get_public_rooms_filtered_route( pub async fn get_public_rooms_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let response = client_server::get_public_rooms_filtered_helper( None, body.limit, @@ -686,10 +678,6 @@ pub fn parse_incoming_pdu( pub async fn send_transaction_message_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -954,10 +942,6 @@ pub async fn send_transaction_message_route( pub async fn get_event_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1016,10 +1000,6 @@ pub async fn get_event_route( pub async fn get_backfill_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1092,10 +1072,6 @@ pub async fn get_backfill_route( pub async fn get_missing_events_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1181,10 +1157,6 @@ pub async fn get_missing_events_route( pub async fn get_event_authorization_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1243,10 +1215,6 @@ pub async fn get_event_authorization_route( pub async fn get_room_state_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1323,10 +1291,6 @@ pub async fn get_room_state_route( pub async fn get_room_state_ids_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1384,10 +1348,6 @@ pub async fn get_room_state_ids_route( pub async fn create_join_event_template_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if !services().rooms.metadata.exists(&body.room_id)? { return Err(Error::BadRequest( ErrorKind::NotFound, @@ -1495,10 +1455,6 @@ async fn create_join_event( room_id: &RoomId, pdu: &RawJsonValue, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if !services().rooms.metadata.exists(room_id)? { return Err(Error::BadRequest( ErrorKind::NotFound, @@ -1679,10 +1635,6 @@ pub async fn create_join_event_v2_route( pub async fn create_invite_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let sender_servername = body .sender_servername .as_ref() @@ -1796,10 +1748,6 @@ pub async fn create_invite_route( pub async fn get_devices_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if body.user_id.server_name() != services().globals.server_name() { return Err(Error::BadRequest( ErrorKind::InvalidParam, @@ -1852,10 +1800,6 @@ pub async fn get_devices_route( pub async fn get_room_information_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let room_id = services() .rooms .alias @@ -1877,10 +1821,6 @@ pub async fn get_room_information_route( pub async fn get_profile_information_route( body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if body.user_id.server_name() != services().globals.server_name() { return Err(Error::BadRequest( ErrorKind::InvalidParam, @@ -1920,10 +1860,6 @@ pub async fn get_profile_information_route( /// /// Gets devices and identity keys for the given users. pub async fn get_keys_route(body: Ruma) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if body .device_keys .iter() @@ -1953,10 +1889,6 @@ pub async fn get_keys_route(body: Ruma) -> Result, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - if body .one_time_keys .iter() From 879a8b969d4a6b664c2f00c219d8c18ca3d821da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Wed, 13 Mar 2024 12:52:11 +0100 Subject: [PATCH 124/175] improvement: use simpler rocksdb config --- Cargo.lock | 434 ++++++++++++------------ Cargo.toml | 1 + src/api/client_server/sync.rs | 4 +- src/api/client_server/user_directory.rs | 31 +- src/database/abstraction/rocksdb.rs | 73 ++-- 5 files changed, 288 insertions(+), 255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88217001..4d294c08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -46,15 +46,15 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" [[package]] name = "arrayref" @@ -88,7 +88,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -204,22 +204,22 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" -version = "0.69.2" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c69fae65a523209d34240b60abe0c42d33d1045d445c0839d8a4894a736e2d" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ "bitflags 2.4.2", "cexpr", "clang-sys", + "itertools 0.12.1", "lazy_static", "lazycell", - "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -256,15 +256,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytemuck" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" @@ -291,9 +291,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ "jobserver", "libc", @@ -327,9 +327,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" dependencies = [ "clap_builder", "clap_derive", @@ -337,9 +337,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstyle", "clap_lex", @@ -347,21 +347,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "color_quant" @@ -484,18 +484,18 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ "crossbeam-utils", ] @@ -518,9 +518,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", @@ -541,7 +541,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -625,9 +625,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -640,9 +640,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "encoding_rs" @@ -694,9 +694,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" [[package]] name = "figment" @@ -803,7 +803,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -861,9 +861,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" dependencies = [ "color_quant", "weezl", @@ -893,7 +893,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.1", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -957,9 +957,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hmac" @@ -983,9 +983,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1082,9 +1082,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.8" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", @@ -1107,9 +1107,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.1" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1155,6 +1155,15 @@ 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 = "itoa" version = "1.0.10" @@ -1163,9 +1172,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -1178,9 +1187,9 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1252,18 +1261,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.4", ] [[package]] @@ -1317,9 +1326,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru-cache" @@ -1402,9 +1411,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -1412,9 +1421,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1465,21 +1474,26 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1653,15 +1667,9 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.48", + "syn 2.0.52", ] -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "pem" version = "3.0.3" @@ -1680,9 +1688,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "persy" -version = "1.4.7" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd38c602b23c2f451842d89f27cd5e0d4b292176daf40feeda859c658dcdc76" +checksum = "9ef4b7250ab3a90ded0e284b2633469c23ef01ea868fe7cbb64e2f0a7d6f6d02" dependencies = [ "crc", "data-encoding", @@ -1696,22 +1704,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -1738,9 +1746,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" @@ -1750,9 +1758,9 @@ checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "png" -version = "0.17.11" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1775,18 +1783,19 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ - "toml_edit 0.20.7", + "toml_datetime", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1799,7 +1808,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", "version_check", "yansi", ] @@ -1877,7 +1886,7 @@ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.5", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -1892,9 +1901,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1915,9 +1924,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" dependencies = [ "base64", "bytes", @@ -1942,6 +1951,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls", @@ -1966,16 +1976,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2038,7 +2049,7 @@ dependencies = [ "bytes", "form_urlencoded", "http", - "indexmap 2.2.1", + "indexmap 2.2.5", "js_int", "konst", "percent-encoding", @@ -2062,7 +2073,7 @@ version = "0.27.11" source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ "as_variant", - "indexmap 2.2.1", + "indexmap 2.2.5", "js_int", "js_option", "percent-encoding", @@ -2120,7 +2131,7 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn 2.0.48", + "syn 2.0.52", "toml", ] @@ -2157,7 +2168,7 @@ name = "ruma-state-res" version = "0.10.0" source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" dependencies = [ - "itertools", + "itertools 0.11.0", "js_int", "ruma-common", "ruma-events", @@ -2291,9 +2302,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" @@ -2351,38 +2362,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "serde_html_form" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e1066e1cfa6692a722cf40386a2caec36da5ddc4a2c16df592f0f609677e8c" +checksum = "50437e6a58912eecc08865e35ea2e8d365fbb2db0debb1c8bb43bf1faf055f25" dependencies = [ "form_urlencoded", - "indexmap 2.2.1", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -2390,9 +2401,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -2401,9 +2412,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -2432,11 +2443,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.31" +version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -2544,12 +2555,12 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2596,9 +2607,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -2634,29 +2645,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2717,12 +2728,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -2737,10 +2749,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -2761,9 +2774,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -2785,7 +2798,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -2837,43 +2850,32 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +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 0.21.0", + "toml_edit", ] [[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.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.2.1", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", @@ -2947,7 +2949,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] @@ -3120,9 +3122,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -3135,9 +3137,9 @@ checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "unsigned-varint" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" [[package]] name = "untrusted" @@ -3200,9 +3202,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3210,24 +3212,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -3237,9 +3239,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3247,28 +3249,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3288,9 +3290,9 @@ checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "wildmatch" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495ec47bf3c1345005f40724f0269362c8556cbc43aed0526ed44cae1d35fceb" +checksum = "017f0a8ed8331210d91b7a4c30d4edef8f21a65c02f2540496e2e79725f6d8a8" [[package]] name = "winapi" @@ -3329,7 +3331,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -3349,17 +3351,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -3370,9 +3372,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -3382,9 +3384,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -3394,9 +3396,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -3406,9 +3408,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -3418,9 +3420,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -3430,9 +3432,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -3442,15 +3444,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.35" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -3467,9 +3469,9 @@ dependencies = [ [[package]] name = "yansi" -version = "1.0.0-rc.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -3488,7 +3490,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.52", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 08188cb3..ac334728 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,6 +121,7 @@ optional = true features = [ "multi-threaded-cf", "zstd", + "lz4", ] [target.'cfg(unix)'.dependencies] diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index c510f5f5..103daeb0 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -29,7 +29,7 @@ use std::{ time::Duration, }; use tokio::sync::watch::Sender; -use tracing::error; +use tracing::{error, info}; /// # `GET /_matrix/client/r0/sync` /// @@ -99,6 +99,8 @@ pub async fn sync_events_route( o.insert((body.since.clone(), rx.clone())); + info!("Sync started for {sender_user}"); + tokio::spawn(sync_helper_wrapper( sender_user.clone(), sender_device.clone(), diff --git a/src/api/client_server/user_directory.rs b/src/api/client_server/user_directory.rs index c30bac51..b4d11800 100644 --- a/src/api/client_server/user_directory.rs +++ b/src/api/client_server/user_directory.rs @@ -48,6 +48,9 @@ pub async fn search_users_route( return None; } + // It's a matching user, but is the sender allowed to see them? + let mut user_visible = false; + let user_is_in_public_rooms = services() .rooms .state_cache @@ -69,22 +72,26 @@ pub async fn search_users_route( }); if user_is_in_public_rooms { - return Some(user); - } + user_visible = true; + } else { + let user_is_in_shared_rooms = services() + .rooms + .user + .get_shared_rooms(vec![sender_user.clone(), user_id]) + .ok()? + .next() + .is_some(); - let user_is_in_shared_rooms = services() - .rooms - .user - .get_shared_rooms(vec![sender_user.clone(), user_id]) - .ok()? - .next() - .is_some(); + if user_is_in_shared_rooms { + user_visible = true; + } + } - if user_is_in_shared_rooms { - return Some(user); + if !user_visible { + return None; } - None + Some(user) }); let results = users.by_ref().take(limit).collect(); diff --git a/src/database/abstraction/rocksdb.rs b/src/database/abstraction/rocksdb.rs index 7a93d787..447ee038 100644 --- a/src/database/abstraction/rocksdb.rs +++ b/src/database/abstraction/rocksdb.rs @@ -23,29 +23,23 @@ pub struct RocksDbEngineTree<'a> { fn db_options(max_open_files: i32, rocksdb_cache: &rocksdb::Cache) -> rocksdb::Options { let mut block_based_options = rocksdb::BlockBasedOptions::default(); block_based_options.set_block_cache(rocksdb_cache); - - // "Difference of spinning disk" - // https://zhangyuchi.gitbooks.io/rocksdbbook/content/RocksDB-Tuning-Guide.html + block_based_options.set_bloom_filter(10.0, false); block_based_options.set_block_size(4 * 1024); block_based_options.set_cache_index_and_filter_blocks(true); + block_based_options.set_pin_l0_filter_and_index_blocks_in_cache(true); + block_based_options.set_optimize_filters_for_memory(true); let mut db_opts = rocksdb::Options::default(); db_opts.set_block_based_table_factory(&block_based_options); - db_opts.set_optimize_filters_for_hits(true); - db_opts.set_skip_stats_update_on_db_open(true); - db_opts.set_level_compaction_dynamic_level_bytes(true); - db_opts.set_target_file_size_base(256 * 1024 * 1024); - //db_opts.set_compaction_readahead_size(2 * 1024 * 1024); - //db_opts.set_use_direct_reads(true); - //db_opts.set_use_direct_io_for_flush_and_compaction(true); db_opts.create_if_missing(true); db_opts.increase_parallelism(num_cpus::get() as i32); db_opts.set_max_open_files(max_open_files); - db_opts.set_compression_type(rocksdb::DBCompressionType::Zstd); + db_opts.set_compression_type(rocksdb::DBCompressionType::Lz4); + db_opts.set_bottommost_compression_type(rocksdb::DBCompressionType::Zstd); db_opts.set_compaction_style(rocksdb::DBCompactionStyle::Level); - db_opts.optimize_level_style_compaction(10 * 1024 * 1024); // https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning + db_opts.set_level_compaction_dynamic_level_bytes(true); db_opts.set_max_background_jobs(6); db_opts.set_bytes_per_sync(1048576); @@ -59,9 +53,6 @@ fn db_options(max_open_files: i32, rocksdb_cache: &rocksdb::Cache) -> rocksdb::O // restored via federation. db_opts.set_wal_recovery_mode(rocksdb::DBRecoveryMode::TolerateCorruptedTailRecords); - let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(1); - db_opts.set_prefix_extractor(prefix_extractor); - db_opts } @@ -147,12 +138,17 @@ impl RocksDbEngineTree<'_> { impl KvTree for RocksDbEngineTree<'_> { fn get(&self, key: &[u8]) -> Result>> { - Ok(self.db.rocks.get_cf(&self.cf(), key)?) + let readoptions = rocksdb::ReadOptions::default(); + + Ok(self.db.rocks.get_cf_opt(&self.cf(), key, &readoptions)?) } fn insert(&self, key: &[u8], value: &[u8]) -> Result<()> { + let writeoptions = rocksdb::WriteOptions::default(); let lock = self.write_lock.read().unwrap(); - self.db.rocks.put_cf(&self.cf(), key, value)?; + self.db + .rocks + .put_cf_opt(&self.cf(), key, value, &writeoptions)?; drop(lock); self.watchers.wake(key); @@ -161,22 +157,31 @@ impl KvTree for RocksDbEngineTree<'_> { } fn insert_batch<'a>(&self, iter: &mut dyn Iterator, Vec)>) -> Result<()> { + let writeoptions = rocksdb::WriteOptions::default(); for (key, value) in iter { - self.db.rocks.put_cf(&self.cf(), key, value)?; + self.db + .rocks + .put_cf_opt(&self.cf(), key, value, &writeoptions)?; } Ok(()) } fn remove(&self, key: &[u8]) -> Result<()> { - Ok(self.db.rocks.delete_cf(&self.cf(), key)?) + let writeoptions = rocksdb::WriteOptions::default(); + Ok(self + .db + .rocks + .delete_cf_opt(&self.cf(), key, &writeoptions)?) } fn iter<'a>(&'a self) -> Box, Vec)> + 'a> { + let readoptions = rocksdb::ReadOptions::default(); + Box::new( self.db .rocks - .iterator_cf(&self.cf(), rocksdb::IteratorMode::Start) + .iterator_cf_opt(&self.cf(), readoptions, rocksdb::IteratorMode::Start) .map(|r| r.unwrap()) .map(|(k, v)| (Vec::from(k), Vec::from(v))), ) @@ -187,11 +192,14 @@ impl KvTree for RocksDbEngineTree<'_> { from: &[u8], backwards: bool, ) -> Box, Vec)> + 'a> { + let readoptions = rocksdb::ReadOptions::default(); + Box::new( self.db .rocks - .iterator_cf( + .iterator_cf_opt( &self.cf(), + readoptions, rocksdb::IteratorMode::From( from, if backwards { @@ -207,23 +215,33 @@ impl KvTree for RocksDbEngineTree<'_> { } fn increment(&self, key: &[u8]) -> Result> { + let readoptions = rocksdb::ReadOptions::default(); + let writeoptions = rocksdb::WriteOptions::default(); + let lock = self.write_lock.write().unwrap(); - let old = self.db.rocks.get_cf(&self.cf(), key)?; + let old = self.db.rocks.get_cf_opt(&self.cf(), key, &readoptions)?; let new = utils::increment(old.as_deref()).unwrap(); - self.db.rocks.put_cf(&self.cf(), key, &new)?; + self.db + .rocks + .put_cf_opt(&self.cf(), key, &new, &writeoptions)?; drop(lock); Ok(new) } fn increment_batch<'a>(&self, iter: &mut dyn Iterator>) -> Result<()> { + let readoptions = rocksdb::ReadOptions::default(); + let writeoptions = rocksdb::WriteOptions::default(); + let lock = self.write_lock.write().unwrap(); for key in iter { - let old = self.db.rocks.get_cf(&self.cf(), &key)?; + let old = self.db.rocks.get_cf_opt(&self.cf(), &key, &readoptions)?; let new = utils::increment(old.as_deref()).unwrap(); - self.db.rocks.put_cf(&self.cf(), key, new)?; + self.db + .rocks + .put_cf_opt(&self.cf(), key, new, &writeoptions)?; } drop(lock); @@ -235,11 +253,14 @@ impl KvTree for RocksDbEngineTree<'_> { &'a self, prefix: Vec, ) -> Box, Vec)> + 'a> { + let readoptions = rocksdb::ReadOptions::default(); + Box::new( self.db .rocks - .iterator_cf( + .iterator_cf_opt( &self.cf(), + readoptions, rocksdb::IteratorMode::From(&prefix, rocksdb::Direction::Forward), ) .map(|r| r.unwrap()) From 68a33862b3a0298f3e478d94a0255bd95cb54326 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:40:10 -0700 Subject: [PATCH 125/175] add mdbook to the devshell --- flake.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flake.nix b/flake.nix index 9cd826b8..fdaa0b67 100644 --- a/flake.nix +++ b/flake.nix @@ -307,6 +307,9 @@ # Needed for finding broken markdown links lychee + + # Useful for editing the book locally + mdbook ]); }; }); From 0a790686c57c087103ccbbaf9096d0eba6a2d753 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:31:57 -0700 Subject: [PATCH 126/175] avoid duplicating links in documentation Because one might forget to update them. I did, initially, which is why I'm making this change. --- docs/deploying.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/deploying.md b/docs/deploying.md index 3694f6b2..4c4b154a 100644 --- a/docs/deploying.md +++ b/docs/deploying.md @@ -1,8 +1,3 @@ # Deployment options -There are several ways to deploy a Conduit server. - -- [Simple (Recommended)](deploying/simple.md) - This is the recommended way to set up Conduit. -- [Debian](deploying/debian.md) - If you're using a debian-based system, you may find the `deb` package useful. -- [Docker](deploying/docker.md) - We provide multi-arch OCI images for Conduit. -- [Nix](deploying/nix.md) - Nix flake based setup. +This chapter describes various ways to deploy Conduit. From 2022efd2792034ab45a9e27db514744876009c93 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:36:08 -0700 Subject: [PATCH 127/175] remove section about cross compilation It is very stale. Please just use Nix. Trying to do it outside of Nix will be an exercise in frustration, I guarantee it. --- docs/deploying/simple.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/docs/deploying/simple.md b/docs/deploying/simple.md index ea12a281..ef5c15d1 100644 --- a/docs/deploying/simple.md +++ b/docs/deploying/simple.md @@ -61,26 +61,6 @@ Then, `cd` into the source tree of conduit-next and run: $ cargo build --release ``` -If you want to cross compile Conduit to another architecture, read the guide below. - -
-Cross compilation - -As easiest way to compile conduit for another platform [cross-rs](https://github.com/cross-rs/cross) is recommended, so install it first. - -In order to use RockDB as storage backend append `-latomic` to linker flags. - -For example, to build a binary for Raspberry Pi Zero W (ARMv6) you need `arm-unknown-linux-gnueabihf` as compilation -target. - -```bash -git clone https://gitlab.com/famedly/conduit.git -cd conduit -export RUSTFLAGS='-C link-arg=-lgcc -Clink-arg=-latomic -Clink-arg=-static-libgcc' -cross build --release --no-default-features --features conduit_bin,backend_rocksdb,jemalloc --target=arm-unknown-linux-gnueabihf -``` -
- ## Adding a Conduit user While Conduit can run as any user it is usually better to use dedicated users for different services. This also allows From f56abba21651f64bf1b4f970ad0ca97c807256e8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:22:53 -0700 Subject: [PATCH 128/175] rename "simple" deployment to "generic" The main thing this section is really useful for is explaining how to configure various reverse proxies, which applies to basically anything. Also, remove all the language about this being "recommended", because nothing in this documentation is actually tested in CI. --- docs/SUMMARY.md | 2 +- docs/deploying/docker.md | 2 +- docs/deploying/{simple.md => generic.md} | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) rename docs/deploying/{simple.md => generic.md} (98%) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index e7ed05d7..342d6957 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -4,7 +4,7 @@ - [Example configuration](configuration.md) - [Deployment options](deploying.md) - - [Simple (Recommended)](deploying/simple.md) + - [Generic](deploying/generic.md) - [Debian](deploying/debian.md) - [Docker](deploying/docker.md) - [Nix](deploying/nix.md) diff --git a/docs/deploying/docker.md b/docs/deploying/docker.md index 4a38b30b..20cd15f2 100644 --- a/docs/deploying/docker.md +++ b/docs/deploying/docker.md @@ -87,7 +87,7 @@ Depending on your proxy setup, you can use one of the following files; When picking the traefik-related compose file, rename it so it matches `docker-compose.yml`, and rename the override file to `docker-compose.override.yml`. Edit the latter with the values you want for your server. -Additional info about deploying Conduit can be found [here](simple.md). +Additional info about deploying Conduit can be found [here](generic.md). ### Build diff --git a/docs/deploying/simple.md b/docs/deploying/generic.md similarity index 98% rename from docs/deploying/simple.md rename to docs/deploying/generic.md index ef5c15d1..307de359 100644 --- a/docs/deploying/simple.md +++ b/docs/deploying/generic.md @@ -1,6 +1,4 @@ -# Simple setup - -This is the recommended way to set up Conduit. It is the easiest way to get started and is suitable for most use cases. +# Generic deployment documentation > ## Getting help > From f6bfba70146ea01ad00c526a022e6cad1c057e6c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:28:19 -0700 Subject: [PATCH 129/175] normalize headers to "Conduit for X" --- docs/deploying/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/deploying/docker.md b/docs/deploying/docker.md index 20cd15f2..c19ef51b 100644 --- a/docs/deploying/docker.md +++ b/docs/deploying/docker.md @@ -1,4 +1,4 @@ -# Deploy using Docker +# Conduit for Docker > **Note:** To run and use Conduit you should probably use it with a Domain or Subdomain behind a reverse proxy (like Nginx, Traefik, Apache, ...) with a Lets Encrypt certificate. From 3dd21456efe8c38aed4206f05042eddba1cbbc94 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:25:34 -0700 Subject: [PATCH 130/175] reduce scope of nixos documentation There are so many ways to do this we realistically shouldn't bother describing any of them, especially because people should be learning all the options and choosing the one that suits them best anyway. --- docs/SUMMARY.md | 2 +- docs/deploying/nix.md | 198 ---------------------------------------- docs/deploying/nixos.md | 18 ++++ 3 files changed, 19 insertions(+), 199 deletions(-) delete mode 100644 docs/deploying/nix.md create mode 100644 docs/deploying/nixos.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 342d6957..89f620ea 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -7,6 +7,6 @@ - [Generic](deploying/generic.md) - [Debian](deploying/debian.md) - [Docker](deploying/docker.md) - - [Nix](deploying/nix.md) + - [NixOS](deploying/nixos.md) - [TURN](turn.md) - [Appservices](appservices.md) diff --git a/docs/deploying/nix.md b/docs/deploying/nix.md deleted file mode 100644 index bd6f0962..00000000 --- a/docs/deploying/nix.md +++ /dev/null @@ -1,198 +0,0 @@ -# Conduit for Nix/NixOS - -This guide assumes you have a recent version of Nix (^2.4) installed. - -Since Conduit ships as a Nix flake, you'll first need to [enable -flakes][enable_flakes]. - -You can now use the usual Nix commands to interact with Conduit's flake. For -example, `nix run gitlab:famedly/conduit` will run Conduit (though you'll need -to provide configuration and such manually as usual). - -If your NixOS configuration is defined as a flake, you can depend on this flake -to provide a more up-to-date version than provided by `nixpkgs`. In your flake, -add the following to your `inputs`: - -```nix -conduit = { - url = "gitlab:famedly/conduit"; - - # Assuming you have an input for nixpkgs called `nixpkgs`. If you experience - # build failures while using this, try commenting/deleting this line. This - # will probably also require you to always build from source. - inputs.nixpkgs.follows = "nixpkgs"; -}; -``` - -Next, make sure you're passing your flake inputs to the `specialArgs` argument -of `nixpkgs.lib.nixosSystem` [as explained here][specialargs]. This guide will -assume you've named the group `flake-inputs`. - -Now you can configure Conduit and a reverse proxy for it. Add the following to -a new Nix file and include it in your configuration: - -```nix -{ config -, pkgs -, flake-inputs -, ... -}: - -let - # You'll need to edit these values - - # The hostname that will appear in your user and room IDs - server_name = "example.com"; - - # The hostname that Conduit actually runs on - # - # This can be the same as `server_name` if you want. This is only necessary - # when Conduit is running on a different machine than the one hosting your - # root domain. This configuration also assumes this is all running on a single - # machine, some tweaks will need to be made if this is not the case. - matrix_hostname = "matrix.${server_name}"; - - # An admin email for TLS certificate notifications - admin_email = "admin@${server_name}"; - - # These ones you can leave alone - - # Build a dervation that stores the content of `${server_name}/.well-known/matrix/server` - well_known_server = pkgs.writeText "well-known-matrix-server" '' - { - "m.server": "${matrix_hostname}" - } - ''; - - # Build a dervation that stores the content of `${server_name}/.well-known/matrix/client` - well_known_client = pkgs.writeText "well-known-matrix-client" '' - { - "m.homeserver": { - "base_url": "https://${matrix_hostname}" - } - } - ''; -in - -{ - # Configure Conduit itself - services.matrix-conduit = { - enable = true; - - # This causes NixOS to use the flake defined in this repository instead of - # the build of Conduit built into nixpkgs. - package = flake-inputs.conduit.packages.${pkgs.system}.default; - - settings.global = { - inherit server_name; - }; - }; - - # Configure automated TLS acquisition/renewal - security.acme = { - acceptTerms = true; - defaults = { - email = admin_email; - }; - }; - - # ACME data must be readable by the NGINX user - users.users.nginx.extraGroups = [ - "acme" - ]; - - # Configure NGINX as a reverse proxy - services.nginx = { - enable = true; - recommendedProxySettings = true; - - virtualHosts = { - "${matrix_hostname}" = { - forceSSL = true; - enableACME = true; - - listen = [ - { - addr = "0.0.0.0"; - port = 443; - ssl = true; - } - { - addr = "[::]"; - port = 443; - ssl = true; - } { - addr = "0.0.0.0"; - port = 8448; - ssl = true; - } - { - addr = "[::]"; - port = 8448; - ssl = true; - } - ]; - - locations."/_matrix/" = { - proxyPass = "http://backend_conduit$request_uri"; - proxyWebsockets = true; - extraConfig = '' - proxy_set_header Host $host; - proxy_buffering off; - ''; - }; - - extraConfig = '' - merge_slashes off; - ''; - }; - - "${server_name}" = { - forceSSL = true; - enableACME = true; - - locations."=/.well-known/matrix/server" = { - # Use the contents of the derivation built previously - alias = "${well_known_server}"; - - extraConfig = '' - # Set the header since by default NGINX thinks it's just bytes - default_type application/json; - ''; - }; - - locations."=/.well-known/matrix/client" = { - # Use the contents of the derivation built previously - alias = "${well_known_client}"; - - extraConfig = '' - # Set the header since by default NGINX thinks it's just bytes - default_type application/json; - - # https://matrix.org/docs/spec/client_server/r0.4.0#web-browser-clients - add_header Access-Control-Allow-Origin "*"; - ''; - }; - }; - }; - - upstreams = { - "backend_conduit" = { - servers = { - "[::1]:${toString config.services.matrix-conduit.settings.global.port}" = { }; - }; - }; - }; - }; - - # Open firewall ports for HTTP, HTTPS, and Matrix federation - networking.firewall.allowedTCPPorts = [ 80 443 8448 ]; - networking.firewall.allowedUDPPorts = [ 80 443 8448 ]; -} -``` - -Now you can rebuild your system configuration and you should be good to go! - -[enable_flakes]: https://nixos.wiki/wiki/Flakes#Enable_flakes - -[specialargs]: https://nixos.wiki/wiki/Flakes#Using_nix_flakes_with_NixOS diff --git a/docs/deploying/nixos.md b/docs/deploying/nixos.md new file mode 100644 index 00000000..bf9b1a11 --- /dev/null +++ b/docs/deploying/nixos.md @@ -0,0 +1,18 @@ +# Conduit for NixOS + +Conduit can be acquired by Nix from various places: + +* The `flake.nix` at the root of the repo +* The `default.nix` at the root of the repo +* From Nixpkgs + +The `flake.nix` and `default.nix` do not (currently) provide a NixOS module, so +(for now) [`services.matrix-conduit`][module] from Nixpkgs should be used to +configure Conduit. + +If you want to run the latest code, you should get Conduit from the `flake.nix` +or `default.nix` and set [`services.matrix-conduit.package`][package] +appropriately. + +[module]: https://search.nixos.org/options?channel=unstable&query=services.matrix-conduit +[package]: https://search.nixos.org/options?channel=unstable&query=services.matrix-conduit.package From 5a4ee9808abeee0eedb932e4c02568d192ebdfca Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 21 Mar 2024 15:42:36 -0700 Subject: [PATCH 131/175] make chapter name reflect file name Personally I think this makes more sense anyway. --- docs/SUMMARY.md | 2 +- docs/deploying.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 89f620ea..30316e27 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -3,7 +3,7 @@ - [Introduction](introduction.md) - [Example configuration](configuration.md) -- [Deployment options](deploying.md) +- [Deploying](deploying.md) - [Generic](deploying/generic.md) - [Debian](deploying/debian.md) - [Docker](deploying/docker.md) diff --git a/docs/deploying.md b/docs/deploying.md index 4c4b154a..136e6538 100644 --- a/docs/deploying.md +++ b/docs/deploying.md @@ -1,3 +1,3 @@ -# Deployment options +# Deploying This chapter describes various ways to deploy Conduit. From 6bd7ff4917978856613c464f813fff8cf2b7e6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Tue, 5 Mar 2024 23:48:36 +0100 Subject: [PATCH 132/175] improvement: do not save typing edus in db --- src/api/client_server/sync.rs | 4 +- src/api/client_server/typing.rs | 4 +- src/api/server_server.rs | 4 +- src/service/mod.rs | 3 +- src/service/rooms/edus/typing/mod.rs | 57 ++++++++++++++++++++-------- 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 103daeb0..ba2ceefa 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1055,10 +1055,10 @@ async fn load_joined_room( .map(|(_, _, v)| v) .collect(); - if services().rooms.edus.typing.last_typing_update(room_id)? > since { + if services().rooms.edus.typing.last_typing_update(room_id).await? > since { edus.push( serde_json::from_str( - &serde_json::to_string(&services().rooms.edus.typing.typings_all(room_id)?) + &serde_json::to_string(&services().rooms.edus.typing.typings_all(room_id).await?) .expect("event is valid, we just created it"), ) .expect("event is valid, we just created it"), diff --git a/src/api/client_server/typing.rs b/src/api/client_server/typing.rs index 43217e1a..eff84051 100644 --- a/src/api/client_server/typing.rs +++ b/src/api/client_server/typing.rs @@ -27,13 +27,13 @@ pub async fn create_typing_event_route( sender_user, &body.room_id, duration.as_millis() as u64 + utils::millis_since_unix_epoch(), - )?; + ).await?; } else { services() .rooms .edus .typing - .typing_remove(sender_user, &body.room_id)?; + .typing_remove(sender_user, &body.room_id).await?; } Ok(create_typing_event::v3::Response {}) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index e0335493..59724b03 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -830,13 +830,13 @@ pub async fn send_transaction_message_route( &typing.user_id, &typing.room_id, 3000 + utils::millis_since_unix_epoch(), - )?; + ).await?; } else { services() .rooms .edus .typing - .typing_remove(&typing.user_id, &typing.room_id)?; + .typing_remove(&typing.user_id, &typing.room_id).await?; } } } diff --git a/src/service/mod.rs b/src/service/mod.rs index 8f9fb0a5..8c97cdd0 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -7,6 +7,7 @@ use lru_cache::LruCache; use tokio::sync::Mutex; use crate::{Config, Result}; +use tokio::sync::RwLock; pub mod account_data; pub mod admin; @@ -65,7 +66,7 @@ impl Services { edus: rooms::edus::Service { presence: rooms::edus::presence::Service { db }, read_receipt: rooms::edus::read_receipt::Service { db }, - typing: rooms::edus::typing::Service { db }, + typing: rooms::edus::typing::Service { db, typing: RwLock::new(BTreeMap::new()), last_typing_update: RwLock::new(BTreeMap::new()) }, }, event_handler: rooms::event_handler::Service, lazy_loading: rooms::lazy_loading::Service { diff --git a/src/service/rooms/edus/typing/mod.rs b/src/service/rooms/edus/typing/mod.rs index 7d44f7d7..f3436741 100644 --- a/src/service/rooms/edus/typing/mod.rs +++ b/src/service/rooms/edus/typing/mod.rs @@ -1,48 +1,73 @@ mod data; pub use data::Data; -use ruma::{events::SyncEphemeralRoomEvent, RoomId, UserId}; +use ruma::{events::SyncEphemeralRoomEvent, RoomId, UserId, OwnedRoomId, OwnedUserId}; +use tokio::sync::RwLock; +use std::collections::BTreeMap; -use crate::Result; +use crate::{utils, services, Result}; pub struct Service { pub db: &'static dyn Data, + pub typing: RwLock>>, // u64 is unix timestamp of timeout + pub last_typing_update: RwLock>, // timestamp of the last change to typing users } impl Service { /// Sets a user as typing until the timeout timestamp is reached or roomtyping_remove is /// called. - pub fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()> { - self.db.typing_add(user_id, room_id, timeout) + pub async fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()> { + self.typing.write().await.entry(room_id.to_owned()).or_default().insert(user_id.to_owned(), timeout); + self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + Ok(()) } /// Removes a user from typing before the timeout is reached. - pub fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> { - self.db.typing_remove(user_id, room_id) + pub async fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> { + self.typing.write().await.entry(room_id.to_owned()).or_default().remove(user_id); + self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + Ok(()) } /// Makes sure that typing events with old timestamps get removed. - fn typings_maintain(&self, room_id: &RoomId) -> Result<()> { - self.db.typings_maintain(room_id) + async fn typings_maintain(&self, room_id: &RoomId) -> Result<()> { + let current_timestamp = utils::millis_since_unix_epoch(); + let mut removable = Vec::new(); + { + let typing = self.typing.read().await; + let Some(room) = typing.get(room_id) else { return Ok(()); }; + for (user, timeout) in room { + if *timeout < current_timestamp { + removable.push(user.clone()); + } + } + drop(typing); + } + if !removable.is_empty() { + let typing = &mut self.typing.write().await; + let room = typing.entry(room_id.to_owned()).or_default(); + for user in removable { + room.remove(&user); + } + self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + } + Ok(()) } /// Returns the count of the last typing update in this room. - pub fn last_typing_update(&self, room_id: &RoomId) -> Result { - self.typings_maintain(room_id)?; - - self.db.last_typing_update(room_id) + pub async fn last_typing_update(&self, room_id: &RoomId) -> Result { + self.typings_maintain(room_id).await?; + Ok(self.last_typing_update.read().await.get(room_id).copied().unwrap_or(0)) } /// Returns a new typing EDU. - pub fn typings_all( + pub async fn typings_all( &self, room_id: &RoomId, ) -> Result> { - let user_ids = self.db.typings_all(room_id)?; - Ok(SyncEphemeralRoomEvent { content: ruma::events::typing::TypingEventContent { - user_ids: user_ids.into_iter().collect(), + user_ids: self.typing.read().await.get(room_id).map(|m| m.keys().cloned().collect()).unwrap_or_default(), }, }) } From d2817679e59494a7944e1141e65dc236bcf7b061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Fri, 22 Mar 2024 08:22:15 +0100 Subject: [PATCH 133/175] refactor: remove previous typing implementation and add sync wakeup for new one --- src/api/client_server/sync.rs | 9 +- src/api/client_server/typing.rs | 18 ++- src/api/server_server.rs | 18 ++- src/database/key_value/globals.rs | 4 +- src/database/key_value/rooms/edus/mod.rs | 1 - src/database/key_value/rooms/edus/typing.rs | 127 -------------------- src/database/mod.rs | 4 - src/service/mod.rs | 8 +- src/service/rooms/edus/mod.rs | 2 +- src/service/rooms/edus/typing/data.rs | 21 ---- src/service/rooms/edus/typing/mod.rs | 74 +++++++++--- 11 files changed, 101 insertions(+), 185 deletions(-) delete mode 100644 src/database/key_value/rooms/edus/typing.rs delete mode 100644 src/service/rooms/edus/typing/data.rs diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index ba2ceefa..da603dcf 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1055,7 +1055,14 @@ async fn load_joined_room( .map(|(_, _, v)| v) .collect(); - if services().rooms.edus.typing.last_typing_update(room_id).await? > since { + if services() + .rooms + .edus + .typing + .last_typing_update(room_id) + .await? + > since + { edus.push( serde_json::from_str( &serde_json::to_string(&services().rooms.edus.typing.typings_all(room_id).await?) diff --git a/src/api/client_server/typing.rs b/src/api/client_server/typing.rs index eff84051..e9e93708 100644 --- a/src/api/client_server/typing.rs +++ b/src/api/client_server/typing.rs @@ -23,17 +23,23 @@ pub async fn create_typing_event_route( } if let Typing::Yes(duration) = body.state { - services().rooms.edus.typing.typing_add( - sender_user, - &body.room_id, - duration.as_millis() as u64 + utils::millis_since_unix_epoch(), - ).await?; + services() + .rooms + .edus + .typing + .typing_add( + sender_user, + &body.room_id, + duration.as_millis() as u64 + utils::millis_since_unix_epoch(), + ) + .await?; } else { services() .rooms .edus .typing - .typing_remove(sender_user, &body.room_id).await?; + .typing_remove(sender_user, &body.room_id) + .await?; } Ok(create_typing_event::v3::Response {}) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 59724b03..0fdf22fc 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -826,17 +826,23 @@ pub async fn send_transaction_message_route( .is_joined(&typing.user_id, &typing.room_id)? { if typing.typing { - services().rooms.edus.typing.typing_add( - &typing.user_id, - &typing.room_id, - 3000 + utils::millis_since_unix_epoch(), - ).await?; + services() + .rooms + .edus + .typing + .typing_add( + &typing.user_id, + &typing.room_id, + 3000 + utils::millis_since_unix_epoch(), + ) + .await?; } else { services() .rooms .edus .typing - .typing_remove(&typing.user_id, &typing.room_id).await?; + .typing_remove(&typing.user_id, &typing.room_id) + .await?; } } } diff --git a/src/database/key_value/globals.rs b/src/database/key_value/globals.rs index 7a70af18..2851ce53 100644 --- a/src/database/key_value/globals.rs +++ b/src/database/key_value/globals.rs @@ -94,7 +94,9 @@ impl service::globals::Data for KeyValueDatabase { futures.push(self.pduid_pdu.watch_prefix(&short_roomid)); // EDUs - futures.push(self.roomid_lasttypingupdate.watch_prefix(&roomid_bytes)); + futures.push(Box::into_pin(Box::new(async move { + let _result = services().rooms.edus.typing.wait_for_update(&room_id).await; + }))); futures.push(self.readreceiptid_readreceipt.watch_prefix(&roomid_prefix)); diff --git a/src/database/key_value/rooms/edus/mod.rs b/src/database/key_value/rooms/edus/mod.rs index 6c652918..7abf946f 100644 --- a/src/database/key_value/rooms/edus/mod.rs +++ b/src/database/key_value/rooms/edus/mod.rs @@ -1,6 +1,5 @@ mod presence; mod read_receipt; -mod typing; use crate::{database::KeyValueDatabase, service}; diff --git a/src/database/key_value/rooms/edus/typing.rs b/src/database/key_value/rooms/edus/typing.rs deleted file mode 100644 index 5709192c..00000000 --- a/src/database/key_value/rooms/edus/typing.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::{collections::HashSet, mem}; - -use ruma::{OwnedUserId, RoomId, UserId}; - -use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; - -impl service::rooms::edus::typing::Data for KeyValueDatabase { - fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let count = services().globals.next_count()?.to_be_bytes(); - - let mut room_typing_id = prefix; - room_typing_id.extend_from_slice(&timeout.to_be_bytes()); - room_typing_id.push(0xff); - room_typing_id.extend_from_slice(&count); - - self.typingid_userid - .insert(&room_typing_id, user_id.as_bytes())?; - - self.roomid_lasttypingupdate - .insert(room_id.as_bytes(), &count)?; - - Ok(()) - } - - fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let user_id = user_id.to_string(); - - let mut found_outdated = false; - - // Maybe there are multiple ones from calling roomtyping_add multiple times - for outdated_edu in self - .typingid_userid - .scan_prefix(prefix) - .filter(|(_, v)| &**v == user_id.as_bytes()) - { - self.typingid_userid.remove(&outdated_edu.0)?; - found_outdated = true; - } - - if found_outdated { - self.roomid_lasttypingupdate.insert( - room_id.as_bytes(), - &services().globals.next_count()?.to_be_bytes(), - )?; - } - - Ok(()) - } - - fn typings_maintain(&self, room_id: &RoomId) -> Result<()> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let current_timestamp = utils::millis_since_unix_epoch(); - - let mut found_outdated = false; - - // Find all outdated edus before inserting a new one - for outdated_edu in self - .typingid_userid - .scan_prefix(prefix) - .map(|(key, _)| { - Ok::<_, Error>(( - key.clone(), - utils::u64_from_bytes( - &key.splitn(2, |&b| b == 0xff).nth(1).ok_or_else(|| { - Error::bad_database("RoomTyping has invalid timestamp or delimiters.") - })?[0..mem::size_of::()], - ) - .map_err(|_| Error::bad_database("RoomTyping has invalid timestamp bytes."))?, - )) - }) - .filter_map(|r| r.ok()) - .take_while(|&(_, timestamp)| timestamp < current_timestamp) - { - // This is an outdated edu (time > timestamp) - self.typingid_userid.remove(&outdated_edu.0)?; - found_outdated = true; - } - - if found_outdated { - self.roomid_lasttypingupdate.insert( - room_id.as_bytes(), - &services().globals.next_count()?.to_be_bytes(), - )?; - } - - Ok(()) - } - - fn last_typing_update(&self, room_id: &RoomId) -> Result { - Ok(self - .roomid_lasttypingupdate - .get(room_id.as_bytes())? - .map(|bytes| { - utils::u64_from_bytes(&bytes).map_err(|_| { - Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.") - }) - }) - .transpose()? - .unwrap_or(0)) - } - - fn typings_all(&self, room_id: &RoomId) -> Result> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let mut user_ids = HashSet::new(); - - for (_, user_id) in self.typingid_userid.scan_prefix(prefix) { - let user_id = UserId::parse(utils::string_from_bytes(&user_id).map_err(|_| { - Error::bad_database("User ID in typingid_userid is invalid unicode.") - })?) - .map_err(|_| Error::bad_database("User ID in typingid_userid is invalid."))?; - - user_ids.insert(user_id); - } - - Ok(user_ids) - } -} diff --git a/src/database/mod.rs b/src/database/mod.rs index 425ef4e9..0960dc96 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -70,8 +70,6 @@ pub struct KeyValueDatabase { pub(super) readreceiptid_readreceipt: Arc, // ReadReceiptId = RoomId + Count + UserId pub(super) roomuserid_privateread: Arc, // RoomUserId = Room + User, PrivateRead = Count pub(super) roomuserid_lastprivatereadupdate: Arc, // LastPrivateReadUpdate = Count - pub(super) typingid_userid: Arc, // TypingId = RoomId + TimeoutTime + Count - pub(super) roomid_lasttypingupdate: Arc, // LastRoomTypingUpdate = Count pub(super) presenceid_presence: Arc, // PresenceId = RoomId + Count + UserId pub(super) userid_lastpresenceupdate: Arc, // LastPresenceUpdate = Count @@ -301,8 +299,6 @@ impl KeyValueDatabase { roomuserid_privateread: builder.open_tree("roomuserid_privateread")?, // "Private" read receipt roomuserid_lastprivatereadupdate: builder .open_tree("roomuserid_lastprivatereadupdate")?, - typingid_userid: builder.open_tree("typingid_userid")?, - roomid_lasttypingupdate: builder.open_tree("roomid_lasttypingupdate")?, presenceid_presence: builder.open_tree("presenceid_presence")?, userid_lastpresenceupdate: builder.open_tree("userid_lastpresenceupdate")?, pduid_pdu: builder.open_tree("pduid_pdu")?, diff --git a/src/service/mod.rs b/src/service/mod.rs index 8c97cdd0..ba1ae1c8 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -4,7 +4,7 @@ use std::{ }; use lru_cache::LruCache; -use tokio::sync::Mutex; +use tokio::sync::{broadcast, Mutex}; use crate::{Config, Result}; use tokio::sync::RwLock; @@ -66,7 +66,11 @@ impl Services { edus: rooms::edus::Service { presence: rooms::edus::presence::Service { db }, read_receipt: rooms::edus::read_receipt::Service { db }, - typing: rooms::edus::typing::Service { db, typing: RwLock::new(BTreeMap::new()), last_typing_update: RwLock::new(BTreeMap::new()) }, + typing: rooms::edus::typing::Service { + typing: RwLock::new(BTreeMap::new()), + last_typing_update: RwLock::new(BTreeMap::new()), + typing_update_sender: broadcast::channel(100).0, + }, }, event_handler: rooms::event_handler::Service, lazy_loading: rooms::lazy_loading::Service { diff --git a/src/service/rooms/edus/mod.rs b/src/service/rooms/edus/mod.rs index cf7a3591..a6bc3d5b 100644 --- a/src/service/rooms/edus/mod.rs +++ b/src/service/rooms/edus/mod.rs @@ -2,7 +2,7 @@ pub mod presence; pub mod read_receipt; pub mod typing; -pub trait Data: presence::Data + read_receipt::Data + typing::Data + 'static {} +pub trait Data: presence::Data + read_receipt::Data + 'static {} pub struct Service { pub presence: presence::Service, diff --git a/src/service/rooms/edus/typing/data.rs b/src/service/rooms/edus/typing/data.rs deleted file mode 100644 index 3b1eecfb..00000000 --- a/src/service/rooms/edus/typing/data.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::Result; -use ruma::{OwnedUserId, RoomId, UserId}; -use std::collections::HashSet; - -pub trait Data: Send + Sync { - /// Sets a user as typing until the timeout timestamp is reached or roomtyping_remove is - /// called. - fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()>; - - /// Removes a user from typing before the timeout is reached. - fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>; - - /// Makes sure that typing events with old timestamps get removed. - fn typings_maintain(&self, room_id: &RoomId) -> Result<()>; - - /// Returns the count of the last typing update in this room. - fn last_typing_update(&self, room_id: &RoomId) -> Result; - - /// Returns all user ids currently typing. - fn typings_all(&self, room_id: &RoomId) -> Result>; -} diff --git a/src/service/rooms/edus/typing/mod.rs b/src/service/rooms/edus/typing/mod.rs index f3436741..7546aa84 100644 --- a/src/service/rooms/edus/typing/mod.rs +++ b/src/service/rooms/edus/typing/mod.rs @@ -1,31 +1,57 @@ -mod data; - -pub use data::Data; -use ruma::{events::SyncEphemeralRoomEvent, RoomId, UserId, OwnedRoomId, OwnedUserId}; -use tokio::sync::RwLock; +use ruma::{events::SyncEphemeralRoomEvent, OwnedRoomId, OwnedUserId, RoomId, UserId}; use std::collections::BTreeMap; +use tokio::sync::{broadcast, RwLock}; -use crate::{utils, services, Result}; +use crate::{services, utils, Result}; pub struct Service { - pub db: &'static dyn Data, pub typing: RwLock>>, // u64 is unix timestamp of timeout pub last_typing_update: RwLock>, // timestamp of the last change to typing users + pub typing_update_sender: broadcast::Sender, } impl Service { /// Sets a user as typing until the timeout timestamp is reached or roomtyping_remove is /// called. pub async fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()> { - self.typing.write().await.entry(room_id.to_owned()).or_default().insert(user_id.to_owned(), timeout); - self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + self.typing + .write() + .await + .entry(room_id.to_owned()) + .or_default() + .insert(user_id.to_owned(), timeout); + self.last_typing_update + .write() + .await + .insert(room_id.to_owned(), services().globals.next_count()?); + let _ = self.typing_update_sender.send(room_id.to_owned()); Ok(()) } /// Removes a user from typing before the timeout is reached. pub async fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> { - self.typing.write().await.entry(room_id.to_owned()).or_default().remove(user_id); - self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + self.typing + .write() + .await + .entry(room_id.to_owned()) + .or_default() + .remove(user_id); + self.last_typing_update + .write() + .await + .insert(room_id.to_owned(), services().globals.next_count()?); + let _ = self.typing_update_sender.send(room_id.to_owned()); + Ok(()) + } + + pub async fn wait_for_update(&self, room_id: &RoomId) -> Result<()> { + let mut receiver = self.typing_update_sender.subscribe(); + while let Ok(next) = receiver.recv().await { + if next == room_id { + break; + } + } + Ok(()) } @@ -35,7 +61,9 @@ impl Service { let mut removable = Vec::new(); { let typing = self.typing.read().await; - let Some(room) = typing.get(room_id) else { return Ok(()); }; + let Some(room) = typing.get(room_id) else { + return Ok(()); + }; for (user, timeout) in room { if *timeout < current_timestamp { removable.push(user.clone()); @@ -49,7 +77,11 @@ impl Service { for user in removable { room.remove(&user); } - self.last_typing_update.write().await.insert(room_id.to_owned(), services().globals.next_count()?); + self.last_typing_update + .write() + .await + .insert(room_id.to_owned(), services().globals.next_count()?); + let _ = self.typing_update_sender.send(room_id.to_owned()); } Ok(()) } @@ -57,7 +89,13 @@ impl Service { /// Returns the count of the last typing update in this room. pub async fn last_typing_update(&self, room_id: &RoomId) -> Result { self.typings_maintain(room_id).await?; - Ok(self.last_typing_update.read().await.get(room_id).copied().unwrap_or(0)) + Ok(self + .last_typing_update + .read() + .await + .get(room_id) + .copied() + .unwrap_or(0)) } /// Returns a new typing EDU. @@ -67,7 +105,13 @@ impl Service { ) -> Result> { Ok(SyncEphemeralRoomEvent { content: ruma::events::typing::TypingEventContent { - user_ids: self.typing.read().await.get(room_id).map(|m| m.keys().cloned().collect()).unwrap_or_default(), + user_ids: self + .typing + .read() + .await + .get(room_id) + .map(|m| m.keys().cloned().collect()) + .unwrap_or_default(), }, }) } From 0bb28f60cfc68beaa521bb7dacdec7a9f92c2288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Fri, 22 Mar 2024 08:52:39 +0100 Subject: [PATCH 134/175] refactor: minor appservice code cleanup --- src/api/appservice_server.rs | 157 ++++++++++++++------------- src/api/client_server/alias.rs | 8 +- src/api/ruma_wrapper/axum.rs | 8 +- src/database/key_value/appservice.rs | 35 ++---- src/database/mod.rs | 19 ---- src/service/appservice/mod.rs | 39 +++++-- src/service/mod.rs | 7 +- src/service/rooms/timeline/mod.rs | 10 +- 8 files changed, 128 insertions(+), 155 deletions(-) diff --git a/src/api/appservice_server.rs b/src/api/appservice_server.rs index ab4da79f..841c32a1 100644 --- a/src/api/appservice_server.rs +++ b/src/api/appservice_server.rs @@ -17,95 +17,96 @@ pub(crate) async fn send_request( where T: Debug, { - if let Some(destination) = registration.url { - let hs_token = registration.hs_token.as_str(); + let Some(destination) = registration.url else { + return None; + }; - let mut http_request = request - .try_into_http_request::( - &destination, - SendAccessToken::IfRequired(hs_token), - &[MatrixVersion::V1_0], - ) - .unwrap() - .map(|body| body.freeze()); + let hs_token = registration.hs_token.as_str(); - let mut parts = http_request.uri().clone().into_parts(); - let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); - let symbol = if old_path_and_query.contains('?') { - "&" - } else { - "?" - }; + let mut http_request = request + .try_into_http_request::( + &destination, + SendAccessToken::IfRequired(hs_token), + &[MatrixVersion::V1_0], + ) + .unwrap() + .map(|body| body.freeze()); - parts.path_and_query = Some( - (old_path_and_query + symbol + "access_token=" + hs_token) - .parse() - .unwrap(), - ); - *http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid"); - - let mut reqwest_request = reqwest::Request::try_from(http_request) - .expect("all http requests are valid reqwest requests"); + let mut parts = http_request.uri().clone().into_parts(); + let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); + let symbol = if old_path_and_query.contains('?') { + "&" + } else { + "?" + }; - *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); + parts.path_and_query = Some( + (old_path_and_query + symbol + "access_token=" + hs_token) + .parse() + .unwrap(), + ); + *http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid"); - let url = reqwest_request.url().clone(); - let mut response = match services() - .globals - .default_client() - .execute(reqwest_request) - .await - { - Ok(r) => r, - Err(e) => { - warn!( - "Could not send request to appservice {:?} at {}: {}", - registration.id, destination, e - ); - return Some(Err(e.into())); - } - }; + let mut reqwest_request = reqwest::Request::try_from(http_request) + .expect("all http requests are valid reqwest requests"); - // reqwest::Response -> http::Response conversion - let status = response.status(); - let mut http_response_builder = http::Response::builder() - .status(status) - .version(response.version()); - mem::swap( - response.headers_mut(), - http_response_builder - .headers_mut() - .expect("http::response::Builder is usable"), - ); + *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); - let body = response.bytes().await.unwrap_or_else(|e| { - warn!("server error: {}", e); - Vec::new().into() - }); // TODO: handle timeout - - if status != 200 { + let url = reqwest_request.url().clone(); + let mut response = match services() + .globals + .default_client() + .execute(reqwest_request) + .await + { + Ok(r) => r, + Err(e) => { warn!( - "Appservice returned bad response {} {}\n{}\n{:?}", - destination, - status, - url, - utils::string_from_bytes(&body) + "Could not send request to appservice {:?} at {}: {}", + registration.id, destination, e ); + return Some(Err(e.into())); } + }; + + // reqwest::Response -> http::Response conversion + let status = response.status(); + let mut http_response_builder = http::Response::builder() + .status(status) + .version(response.version()); + mem::swap( + response.headers_mut(), + http_response_builder + .headers_mut() + .expect("http::response::Builder is usable"), + ); + + let body = response.bytes().await.unwrap_or_else(|e| { + warn!("server error: {}", e); + Vec::new().into() + }); // TODO: handle timeout - let response = T::IncomingResponse::try_from_http_response( - http_response_builder - .body(body) - .expect("reqwest body is valid http body"), + if status != 200 { + warn!( + "Appservice returned bad response {} {}\n{}\n{:?}", + destination, + status, + url, + utils::string_from_bytes(&body) ); - Some(response.map_err(|_| { - warn!( - "Appservice returned invalid response bytes {}\n{}", - destination, url - ); - Error::BadServerResponse("Server returned bad response.") - })) - } else { - None } + + let response = T::IncomingResponse::try_from_http_response( + http_response_builder + .body(body) + .expect("reqwest body is valid http body"), + ); + + Some(response.map_err(|_| { + warn!( + "Appservice returned invalid response bytes {}\n{}", + destination, url + ); + Error::BadServerResponse("Server returned bad response.") + })) } diff --git a/src/api/client_server/alias.rs b/src/api/client_server/alias.rs index d3a6e39a..00ee6c85 100644 --- a/src/api/client_server/alias.rs +++ b/src/api/client_server/alias.rs @@ -100,13 +100,7 @@ pub(crate) async fn get_alias_helper( match services().rooms.alias.resolve_local_alias(&room_alias)? { Some(r) => room_id = Some(r), None => { - for appservice in services() - .appservice - .registration_info - .read() - .await - .values() - { + for appservice in services().appservice.all().await { if appservice.aliases.is_match(room_alias.as_str()) && if let Some(opt_result) = services() .sending diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index e841f13a..6411ab9d 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -80,19 +80,19 @@ where let mut json_body = serde_json::from_slice::(&body).ok(); - let appservices = services().appservice.all().unwrap(); + let appservices = services().appservice.all().await; let appservice_registration = appservices .iter() - .find(|(_id, registration)| Some(registration.as_token.as_str()) == token); + .find(|info| Some(info.registration.as_token.as_str()) == token); let (sender_user, sender_device, sender_servername, from_appservice) = - if let Some((_id, registration)) = appservice_registration { + if let Some(info) = appservice_registration { match metadata.authentication { AuthScheme::AccessToken => { let user_id = query_params.user_id.map_or_else( || { UserId::parse_with_server_name( - registration.sender_localpart.as_str(), + info.registration.sender_localpart.as_str(), services().globals.server_name(), ) .unwrap() diff --git a/src/database/key_value/appservice.rs b/src/database/key_value/appservice.rs index 3243183d..b547e66a 100644 --- a/src/database/key_value/appservice.rs +++ b/src/database/key_value/appservice.rs @@ -10,10 +10,6 @@ impl service::appservice::Data for KeyValueDatabase { id.as_bytes(), serde_yaml::to_string(&yaml).unwrap().as_bytes(), )?; - self.cached_registrations - .write() - .unwrap() - .insert(id.to_owned(), yaml.to_owned()); Ok(id.to_owned()) } @@ -26,33 +22,18 @@ impl service::appservice::Data for KeyValueDatabase { fn unregister_appservice(&self, service_name: &str) -> Result<()> { self.id_appserviceregistrations .remove(service_name.as_bytes())?; - self.cached_registrations - .write() - .unwrap() - .remove(service_name); Ok(()) } fn get_registration(&self, id: &str) -> Result> { - self.cached_registrations - .read() - .unwrap() - .get(id) - .map_or_else( - || { - self.id_appserviceregistrations - .get(id.as_bytes())? - .map(|bytes| { - serde_yaml::from_slice(&bytes).map_err(|_| { - Error::bad_database( - "Invalid registration bytes in id_appserviceregistrations.", - ) - }) - }) - .transpose() - }, - |r| Ok(Some(r.clone())), - ) + self.id_appserviceregistrations + .get(id.as_bytes())? + .map(|bytes| { + serde_yaml::from_slice(&bytes).map_err(|_| { + Error::bad_database("Invalid registration bytes in id_appserviceregistrations.") + }) + }) + .transpose() } fn iter_ids<'a>(&'a self) -> Result> + 'a>> { diff --git a/src/database/mod.rs b/src/database/mod.rs index 5b8588cf..190e7e12 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -10,7 +10,6 @@ use directories::ProjectDirs; use lru_cache::LruCache; use ruma::{ - api::appservice::Registration, events::{ push_rules::{PushRulesEvent, PushRulesEventContent}, room::message::RoomMessageEventContent, @@ -164,7 +163,6 @@ pub struct KeyValueDatabase { //pub pusher: pusher::PushData, pub(super) senderkey_pusher: Arc, - pub(super) cached_registrations: Arc>>, pub(super) pdu_cache: Mutex>>, pub(super) shorteventid_cache: Mutex>>, pub(super) auth_chain_cache: Mutex, Arc>>>, @@ -374,7 +372,6 @@ impl KeyValueDatabase { global: builder.open_tree("global")?, server_signingkeys: builder.open_tree("server_signingkeys")?, - cached_registrations: Arc::new(RwLock::new(HashMap::new())), pdu_cache: Mutex::new(LruCache::new( config .pdu_cache_capacity @@ -969,22 +966,6 @@ impl KeyValueDatabase { ); } - // Inserting registrations into cache - for appservice in services().appservice.all()? { - services() - .appservice - .registration_info - .write() - .await - .insert( - appservice.0, - appservice - .1 - .try_into() - .expect("Should be validated on registration"), - ); - } - // This data is probably outdated db.presenceid_presence.clear()?; diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 40fa3ee8..6b9e21f1 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -10,7 +10,8 @@ use tokio::sync::RwLock; use crate::{services, Result}; -/// Compiled regular expressions for a namespace +/// Compiled regular expressions for a namespace. +#[derive(Clone, Debug)] pub struct NamespaceRegex { pub exclusive: Option, pub non_exclusive: Option, @@ -72,7 +73,8 @@ impl TryFrom> for NamespaceRegex { type Error = regex::Error; } -/// Compiled regular expressions for an appservice +/// Appservice registration combined with its compiled regular expressions. +#[derive(Clone, Debug)] pub struct RegistrationInfo { pub registration: Registration, pub users: NamespaceRegex, @@ -95,11 +97,29 @@ impl TryFrom for RegistrationInfo { pub struct Service { pub db: &'static dyn Data, - pub registration_info: RwLock>, + registration_info: RwLock>, } impl Service { - /// Registers an appservice and returns the ID to the caller + pub fn build(db: &'static dyn Data) -> Result { + let mut registration_info = HashMap::new(); + // Inserting registrations into cache + for appservice in db.all()? { + registration_info.insert( + appservice.0, + appservice + .1 + .try_into() + .expect("Should be validated on registration"), + ); + } + + Ok(Self { + db, + registration_info: RwLock::new(registration_info), + }) + } + /// Registers an appservice and returns the ID to the caller. pub async fn register_appservice(&self, yaml: Registration) -> Result { services() .appservice @@ -111,7 +131,7 @@ impl Service { self.db.register_appservice(yaml) } - /// Remove an appservice registration + /// Removes an appservice registration. /// /// # Arguments /// @@ -135,7 +155,12 @@ impl Service { self.db.iter_ids() } - pub fn all(&self) -> Result> { - self.db.all() + pub async fn all(&self) -> Vec { + self.registration_info + .read() + .await + .values() + .cloned() + .collect() } } diff --git a/src/service/mod.rs b/src/service/mod.rs index 045ccd10..0cbe6a82 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -4,7 +4,7 @@ use std::{ }; use lru_cache::LruCache; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::Mutex; use crate::{Config, Result}; @@ -56,10 +56,7 @@ impl Services { config: Config, ) -> Result { Ok(Self { - appservice: appservice::Service { - db, - registration_info: RwLock::new(HashMap::new()), - }, + appservice: appservice::Service::build(db)?, pusher: pusher::Service { db }, rooms: rooms::Service { alias: rooms::alias::Service { db }, diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 1df1db50..035513d6 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -524,17 +524,11 @@ impl Service { } } - for appservice in services() - .appservice - .registration_info - .read() - .await - .values() - { + for appservice in services().appservice.all().await { if services() .rooms .state_cache - .appservice_in_room(&pdu.room_id, appservice)? + .appservice_in_room(&pdu.room_id, &appservice)? { services() .sending From 34e0e710cb5faaa4a7cad62bf956267661eed2c2 Mon Sep 17 00:00:00 2001 From: lafleur Date: Thu, 26 Oct 2023 16:51:54 +0800 Subject: [PATCH 135/175] add registration_token in default cfg and README --- conduit-example.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/conduit-example.toml b/conduit-example.toml index a52121ac..1fb27416 100644 --- a/conduit-example.toml +++ b/conduit-example.toml @@ -38,6 +38,12 @@ max_request_size = 20_000_000 # in bytes # Enables registration. If set to false, no users can register on this server. allow_registration = true +# A static registration token that new users will have to provide when creating +# an account. YOU NEED TO EDIT THIS. +# - Insert a password that users will have to enter on registration +# - Comment out the line to remove the condition +registration_token = "" + allow_federation = true allow_check_for_updates = true From 1fb5bcf98fa7832ab6c5b78f3ef04caa54f5db1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Wed, 24 Jan 2024 18:44:00 +0100 Subject: [PATCH 136/175] improvement: registration token now only works when registration is enabled --- conduit-example.toml | 2 +- debian/postinst | 13 +++++ docs/deploying/docker-compose.for-traefik.yml | 1 + .../deploying/docker-compose.with-traefik.yml | 3 +- src/api/client_server/account.rs | 47 ++++++++++++------- 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/conduit-example.toml b/conduit-example.toml index 1fb27416..c83bce74 100644 --- a/conduit-example.toml +++ b/conduit-example.toml @@ -41,7 +41,7 @@ allow_registration = true # A static registration token that new users will have to provide when creating # an account. YOU NEED TO EDIT THIS. # - Insert a password that users will have to enter on registration -# - Comment out the line to remove the condition +# - Start the line with '#' to remove the condition registration_token = "" allow_federation = true diff --git a/debian/postinst b/debian/postinst index 110f22d6..0707b6f2 100644 --- a/debian/postinst +++ b/debian/postinst @@ -72,9 +72,22 @@ max_request_size = 20_000_000 # in bytes # Enables registration. If set to false, no users can register on this server. allow_registration = true +# A static registration token that new users will have to provide when creating +# an account. +# - Insert a password that users will have to enter on registration +# - Start the line with '#' to remove the condition +#registration_token = "" + allow_federation = true allow_check_for_updates = true +# Enable the display name lightning bolt on registration. +enable_lightning_bolt = true + +# Servers listed here will be used to gather public keys of other servers. +# Generally, copying this exactly should be enough. (Currently, Conduit doesn't +# support batched key requests, so this list should only contain Synapse +# servers.) trusted_servers = ["matrix.org"] #max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time diff --git a/docs/deploying/docker-compose.for-traefik.yml b/docs/deploying/docker-compose.for-traefik.yml index 82bb55b0..c0bb042e 100644 --- a/docs/deploying/docker-compose.for-traefik.yml +++ b/docs/deploying/docker-compose.for-traefik.yml @@ -28,6 +28,7 @@ services: CONDUIT_PORT: 6167 CONDUIT_MAX_REQUEST_SIZE: 20_000_000 # in bytes, ~20 MB CONDUIT_ALLOW_REGISTRATION: 'true' + #CONDUIT_REGISTRATION_TOKEN: '' # require password for registration CONDUIT_ALLOW_FEDERATION: 'true' CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true' CONDUIT_TRUSTED_SERVERS: '["matrix.org"]' diff --git a/docs/deploying/docker-compose.with-traefik.yml b/docs/deploying/docker-compose.with-traefik.yml index 58603277..8ce3ad46 100644 --- a/docs/deploying/docker-compose.with-traefik.yml +++ b/docs/deploying/docker-compose.with-traefik.yml @@ -31,14 +31,13 @@ services: ### Uncomment and change values as desired # CONDUIT_ADDRESS: 0.0.0.0 # CONDUIT_PORT: 6167 + # CONDUIT_REGISTRATION_TOKEN: '' # require password for registration # CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string '' # Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging - # CONDUIT_ALLOW_JAEGER: 'false' # CONDUIT_ALLOW_ENCRYPTION: 'true' # CONDUIT_ALLOW_FEDERATION: 'true' # CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true' # CONDUIT_DATABASE_PATH: /srv/conduit/.local/share/conduit - # CONDUIT_WORKERS: 10 # CONDUIT_MAX_REQUEST_SIZE: 20_000_000 # in bytes, ~20 MB # We need some way to server the client and server .well-known json. The simplest way is to use a nginx container diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index d4529a40..b39e6229 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -74,10 +74,7 @@ pub async fn get_register_available_route( /// - Creates a new account and populates it with default account data /// - If `inhibit_login` is false: Creates a device and returns device id and access_token pub async fn register_route(body: Ruma) -> Result { - if !services().globals.allow_registration() - && !body.from_appservice - && services().globals.config.registration_token.is_none() - { + if !services().globals.allow_registration() && !body.from_appservice { return Err(Error::BadRequest( ErrorKind::Forbidden, "Registration has been disabled.", @@ -122,21 +119,35 @@ pub async fn register_route(body: Ruma) -> Result Date: Fri, 22 Mar 2024 17:51:15 +0000 Subject: [PATCH 137/175] refactor: use BTreeMap for cached registration info --- src/service/appservice/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 6b9e21f1..d9ab9eb1 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -1,6 +1,6 @@ mod data; -use std::collections::HashMap; +use std::collections::BTreeMap; pub use data::Data; @@ -97,12 +97,12 @@ impl TryFrom for RegistrationInfo { pub struct Service { pub db: &'static dyn Data, - registration_info: RwLock>, + registration_info: RwLock>, } impl Service { pub fn build(db: &'static dyn Data) -> Result { - let mut registration_info = HashMap::new(); + let mut registration_info = BTreeMap::new(); // Inserting registrations into cache for appservice in db.all()? { registration_info.insert( From b20483aa13399822fe047349d1af7678f6777259 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 22 Mar 2024 18:27:14 +0000 Subject: [PATCH 138/175] refactor(appservices): avoid cloning frequently --- src/api/appservice_server.rs | 4 +--- src/api/client_server/alias.rs | 2 +- src/api/ruma_wrapper/axum.rs | 9 +++++---- src/service/admin/mod.rs | 26 +++++++----------------- src/service/appservice/mod.rs | 33 +++++++++++++++++++++++-------- src/service/rooms/timeline/mod.rs | 4 ++-- src/service/sending/mod.rs | 2 +- 7 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/api/appservice_server.rs b/src/api/appservice_server.rs index 841c32a1..213e4c09 100644 --- a/src/api/appservice_server.rs +++ b/src/api/appservice_server.rs @@ -17,9 +17,7 @@ pub(crate) async fn send_request( where T: Debug, { - let Some(destination) = registration.url else { - return None; - }; + let destination = registration.url?; let hs_token = registration.hs_token.as_str(); diff --git a/src/api/client_server/alias.rs b/src/api/client_server/alias.rs index 00ee6c85..bc3a5e25 100644 --- a/src/api/client_server/alias.rs +++ b/src/api/client_server/alias.rs @@ -100,7 +100,7 @@ pub(crate) async fn get_alias_helper( match services().rooms.alias.resolve_local_alias(&room_alias)? { Some(r) => room_id = Some(r), None => { - for appservice in services().appservice.all().await { + for appservice in services().appservice.read().await.values() { if appservice.aliases.is_match(room_alias.as_str()) && if let Some(opt_result) = services() .sending diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index 6411ab9d..8ba9fa52 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -80,10 +80,11 @@ where let mut json_body = serde_json::from_slice::(&body).ok(); - let appservices = services().appservice.all().await; - let appservice_registration = appservices - .iter() - .find(|info| Some(info.registration.as_token.as_str()) == token); + let appservice_registration = if let Some(token) = token { + services().appservice.find_from_token(token).await + } else { + None + }; let (sender_user, sender_device, sender_servername, from_appservice) = if let Some(info) = appservice_registration { diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 12bc1cf6..f2f60a7a 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -369,25 +369,13 @@ impl Service { )), }, AdminCommand::ListAppservices => { - if let Ok(appservices) = services() - .appservice - .iter_ids() - .map(|ids| ids.collect::>()) - { - let count = appservices.len(); - let output = format!( - "Appservices ({}): {}", - count, - appservices - .into_iter() - .filter_map(|r| r.ok()) - .collect::>() - .join(", ") - ); - RoomMessageEventContent::text_plain(output) - } else { - RoomMessageEventContent::text_plain("Failed to get appservices.") - } + let appservices = services().appservice.iter_ids().await; + let output = format!( + "Appservices ({}): {}", + appservices.len(), + appservices.join(", ") + ); + RoomMessageEventContent::text_plain(output) } AdminCommand::ListRooms => { let room_ids = services().rooms.metadata.iter_ids(); diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index d9ab9eb1..4bda8961 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -4,6 +4,7 @@ use std::collections::BTreeMap; pub use data::Data; +use futures_util::Future; use regex::RegexSet; use ruma::api::appservice::{Namespace, Registration}; use tokio::sync::RwLock; @@ -147,20 +148,36 @@ impl Service { self.db.unregister_appservice(service_name) } - pub fn get_registration(&self, id: &str) -> Result> { - self.db.get_registration(id) - } - - pub fn iter_ids(&self) -> Result> + '_> { - self.db.iter_ids() + pub async fn get_registration(&self, id: &str) -> Option { + self.registration_info + .read() + .await + .get(id) + .cloned() + .map(|info| info.registration) } - pub async fn all(&self) -> Vec { + pub async fn iter_ids(&self) -> Vec { self.registration_info .read() .await - .values() + .keys() .cloned() .collect() } + + pub async fn find_from_token(&self, token: &str) -> Option { + self.read() + .await + .values() + .find(|info| info.registration.as_token == token) + .cloned() + } + + pub fn read( + &self, + ) -> impl Future>> + { + self.registration_info.read() + } } diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 035513d6..379d97fe 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -524,11 +524,11 @@ impl Service { } } - for appservice in services().appservice.all().await { + for appservice in services().appservice.read().await.values() { if services() .rooms .state_cache - .appservice_in_room(&pdu.room_id, &appservice)? + .appservice_in_room(&pdu.room_id, appservice)? { services() .sending diff --git a/src/service/sending/mod.rs b/src/service/sending/mod.rs index bbacfdec..45cca173 100644 --- a/src/service/sending/mod.rs +++ b/src/service/sending/mod.rs @@ -488,7 +488,7 @@ impl Service { services() .appservice .get_registration(id) - .map_err(|e| (kind.clone(), e))? + .await .ok_or_else(|| { ( kind.clone(), From 8d70f69e621496796341eacf760918941728f0de Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 30 Mar 2024 12:40:58 +0000 Subject: [PATCH 139/175] fix: reject /register requests when there is no token and the type is appservice --- src/api/client_server/account.rs | 10 +++++++++- src/api/client_server/session.rs | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index d4529a40..9f98369b 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -3,7 +3,8 @@ use crate::{api::client_server, services, utils, Error, Result, Ruma}; use ruma::{ api::client::{ account::{ - change_password, deactivate, get_3pids, get_username_availability, register, + change_password, deactivate, get_3pids, get_username_availability, + register::{self, LoginType}, request_3pid_management_token_via_email, request_3pid_management_token_via_msisdn, whoami, ThirdPartyIdRemovalStatus, }, @@ -84,6 +85,13 @@ pub async fn register_route(body: Ruma) -> Result) -> Result { if !body.from_appservice { return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Forbidden login type.", + ErrorKind::MissingToken, + "Missing appservice token.", )); }; if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { From 5c634ceb6b755eaddeb1b854542d9e4a16d763f8 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 30 Mar 2024 11:02:39 +0000 Subject: [PATCH 140/175] fix: reject requests with authentication when not used --- Cargo.lock | 36 ++-- Cargo.toml | 2 +- src/api/ruma_wrapper/axum.rs | 322 +++++++++++++++++++---------------- 3 files changed, 198 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d294c08..bd83f2d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1992,7 +1992,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.9.4" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "assign", "js_int", @@ -2011,7 +2011,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.9.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "js_int", "ruma-common", @@ -2023,7 +2023,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.17.4" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "as_variant", "assign", @@ -2042,7 +2042,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.12.1" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "as_variant", "base64", @@ -2061,16 +2061,18 @@ dependencies = [ "serde_html_form", "serde_json", "thiserror", + "time", "tracing", "url", "uuid", + "web-time", "wildmatch", ] [[package]] name = "ruma-events" version = "0.27.11" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "as_variant", "indexmap 2.2.5", @@ -2092,7 +2094,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "js_int", "ruma-common", @@ -2104,7 +2106,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.3" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "js_int", "thiserror", @@ -2113,7 +2115,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "js_int", "ruma-common", @@ -2123,7 +2125,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.12.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "once_cell", "proc-macro-crate", @@ -2138,7 +2140,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.8.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "js_int", "ruma-common", @@ -2150,7 +2152,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.14.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "base64", "ed25519-dalek", @@ -2166,7 +2168,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.10.0" -source = "git+https://github.com/ruma/ruma?rev=1a1c61ee1e8f0936e956a3b69c931ce12ee28475#1a1c61ee1e8f0936e956a3b69c931ce12ee28475" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" dependencies = [ "itertools 0.11.0", "js_int", @@ -3276,6 +3278,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "weezl" version = "0.1.8" diff --git a/Cargo.toml b/Cargo.toml index ac334728..d2b828ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ tower-http = { version = "0.4.1", features = ["add-extension", "cors", "sensitiv # Used for matrix spec type definitions and helpers #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "1a1c61ee1e8f0936e956a3b69c931ce12ee28475", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } +ruma = { git = "https://github.com/ruma/ruma", rev = "5495b85aa311c2805302edb0a7de40399e22b397", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] } diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index a5ef7f7e..43e73c66 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -15,13 +15,20 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use http::{Request, StatusCode}; use ruma::{ api::{client::error::ErrorKind, AuthScheme, IncomingRequest, OutgoingResponse}, - CanonicalJsonValue, OwnedDeviceId, OwnedServerName, UserId, + CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, }; use serde::Deserialize; use tracing::{debug, error, warn}; use super::{Ruma, RumaResponse}; -use crate::{services, Error, Result}; +use crate::{service::appservice::RegistrationInfo, services, Error, Result}; + +enum Token { + Appservice(Box), + User((OwnedUserId, OwnedDeviceId)), + Invalid, + None, +} #[async_trait] impl FromRequest for Ruma @@ -78,177 +85,194 @@ where None => query_params.access_token.as_deref(), }; - let mut json_body = serde_json::from_slice::(&body).ok(); - - let appservice_registration = if let Some(token) = token { - services().appservice.find_from_token(token).await + let token = if let Some(token) = token { + if let Some(reg_info) = services().appservice.find_from_token(token).await { + Token::Appservice(Box::new(reg_info.clone())) + } else if let Some((user_id, device_id)) = services().users.find_from_token(token)? { + Token::User((user_id, OwnedDeviceId::from(device_id))) + } else { + Token::Invalid + } } else { - None + Token::None }; + let mut json_body = serde_json::from_slice::(&body).ok(); + let (sender_user, sender_device, sender_servername, from_appservice) = - if let Some(info) = appservice_registration { - match metadata.authentication { - AuthScheme::AccessToken => { - let user_id = query_params.user_id.map_or_else( + match (metadata.authentication, token) { + (_, Token::Invalid) => { + return Err(Error::BadRequest( + ErrorKind::UnknownToken { soft_logout: false }, + "Unknown access token.", + )) + } + ( + AuthScheme::AccessToken + | AuthScheme::AppserviceToken + | AuthScheme::AccessTokenOptional, + Token::Appservice(info), + ) => { + let user_id = query_params + .user_id + .map_or_else( || { UserId::parse_with_server_name( info.registration.sender_localpart.as_str(), services().globals.server_name(), ) - .unwrap() }, - |s| UserId::parse(s).unwrap(), - ); + UserId::parse, + ) + .map_err(|_| { + Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.") + })?; + if !services().users.exists(&user_id)? { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User does not exist.", + )); + } - if !services().users.exists(&user_id).unwrap() { + // TODO: Check if appservice is allowed to be that user + (Some(user_id), None, None, true) + } + (AuthScheme::AccessToken, Token::None) => { + return Err(Error::BadRequest( + ErrorKind::MissingToken, + "Missing access token.", + )); + } + ( + AuthScheme::AccessToken | AuthScheme::AccessTokenOptional, + Token::User((user_id, device_id)), + ) => (Some(user_id), Some(device_id), None, false), + (AuthScheme::ServerSignatures, Token::None) => { + if !services().globals.allow_federation() { + return Err(Error::bad_config("Federation is disabled.")); + } + + let TypedHeader(Authorization(x_matrix)) = parts + .extract::>>() + .await + .map_err(|e| { + warn!("Missing or invalid Authorization header: {}", e); + + let msg = match e.reason() { + TypedHeaderRejectionReason::Missing => { + "Missing Authorization header." + } + TypedHeaderRejectionReason::Error(_) => { + "Invalid X-Matrix signatures." + } + _ => "Unknown header-related error", + }; + + Error::BadRequest(ErrorKind::Forbidden, msg) + })?; + + let origin_signatures = BTreeMap::from_iter([( + x_matrix.key.clone(), + CanonicalJsonValue::String(x_matrix.sig), + )]); + + let signatures = BTreeMap::from_iter([( + x_matrix.origin.as_str().to_owned(), + CanonicalJsonValue::Object(origin_signatures), + )]); + + let mut request_map = BTreeMap::from_iter([ + ( + "method".to_owned(), + CanonicalJsonValue::String(parts.method.to_string()), + ), + ( + "uri".to_owned(), + CanonicalJsonValue::String(parts.uri.to_string()), + ), + ( + "origin".to_owned(), + CanonicalJsonValue::String(x_matrix.origin.as_str().to_owned()), + ), + ( + "destination".to_owned(), + CanonicalJsonValue::String( + services().globals.server_name().as_str().to_owned(), + ), + ), + ( + "signatures".to_owned(), + CanonicalJsonValue::Object(signatures), + ), + ]); + + if let Some(json_body) = &json_body { + request_map.insert("content".to_owned(), json_body.clone()); + }; + + let keys_result = services() + .rooms + .event_handler + .fetch_signing_keys(&x_matrix.origin, vec![x_matrix.key.to_owned()]) + .await; + + let keys = match keys_result { + Ok(b) => b, + Err(e) => { + warn!("Failed to fetch signing keys: {}", e); return Err(Error::BadRequest( ErrorKind::Forbidden, - "User does not exist.", + "Failed to fetch signing keys.", )); } + }; - // TODO: Check if appservice is allowed to be that user - (Some(user_id), None, None, true) - } - AuthScheme::ServerSignatures => (None, None, None, true), - AuthScheme::None => (None, None, None, true), - } - } else { - match metadata.authentication { - AuthScheme::AccessToken => { - let token = match token { - Some(token) => token, - _ => { - return Err(Error::BadRequest( - ErrorKind::MissingToken, - "Missing access token.", - )) - } - }; - - match services().users.find_from_token(token).unwrap() { - None => { - return Err(Error::BadRequest( - ErrorKind::UnknownToken { soft_logout: false }, - "Unknown access token.", - )) - } - Some((user_id, device_id)) => ( - Some(user_id), - Some(OwnedDeviceId::from(device_id)), - None, - false, - ), - } - } - AuthScheme::ServerSignatures => { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - - let TypedHeader(Authorization(x_matrix)) = parts - .extract::>>() - .await - .map_err(|e| { - warn!("Missing or invalid Authorization header: {}", e); - - let msg = match e.reason() { - TypedHeaderRejectionReason::Missing => { - "Missing Authorization header." - } - TypedHeaderRejectionReason::Error(_) => { - "Invalid X-Matrix signatures." - } - _ => "Unknown header-related error", - }; - - Error::BadRequest(ErrorKind::Forbidden, msg) - })?; - - let origin_signatures = BTreeMap::from_iter([( - x_matrix.key.clone(), - CanonicalJsonValue::String(x_matrix.sig), - )]); - - let signatures = BTreeMap::from_iter([( - x_matrix.origin.as_str().to_owned(), - CanonicalJsonValue::Object(origin_signatures), - )]); - - let mut request_map = BTreeMap::from_iter([ - ( - "method".to_owned(), - CanonicalJsonValue::String(parts.method.to_string()), - ), - ( - "uri".to_owned(), - CanonicalJsonValue::String(parts.uri.to_string()), - ), - ( - "origin".to_owned(), - CanonicalJsonValue::String(x_matrix.origin.as_str().to_owned()), - ), - ( - "destination".to_owned(), - CanonicalJsonValue::String( - services().globals.server_name().as_str().to_owned(), - ), - ), - ( - "signatures".to_owned(), - CanonicalJsonValue::Object(signatures), - ), - ]); - - if let Some(json_body) = &json_body { - request_map.insert("content".to_owned(), json_body.clone()); - }; - - let keys_result = services() - .rooms - .event_handler - .fetch_signing_keys(&x_matrix.origin, vec![x_matrix.key.to_owned()]) - .await; - - let keys = match keys_result { - Ok(b) => b, - Err(e) => { - warn!("Failed to fetch signing keys: {}", e); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Failed to fetch signing keys.", - )); - } - }; + let pub_key_map = + BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]); - let pub_key_map = - BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]); + match ruma::signatures::verify_json(&pub_key_map, &request_map) { + Ok(()) => (None, None, Some(x_matrix.origin), false), + Err(e) => { + warn!( + "Failed to verify json request from {}: {}\n{:?}", + x_matrix.origin, e, request_map + ); - match ruma::signatures::verify_json(&pub_key_map, &request_map) { - Ok(()) => (None, None, Some(x_matrix.origin), false), - Err(e) => { + if parts.uri.to_string().contains('@') { warn!( - "Failed to verify json request from {}: {}\n{:?}", - x_matrix.origin, e, request_map - ); - - if parts.uri.to_string().contains('@') { - warn!( - "Request uri contained '@' character. Make sure your \ + "Request uri contained '@' character. Make sure your \ reverse proxy gives Conduit the raw uri (apache: use \ nocanon)" - ); - } - - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Failed to verify X-Matrix signatures.", - )); + ); } + + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Failed to verify X-Matrix signatures.", + )); } } - AuthScheme::None => (None, None, None, false), + } + ( + AuthScheme::None + | AuthScheme::AppserviceToken + | AuthScheme::AccessTokenOptional, + Token::None, + ) => (None, None, None, false), + ( + AuthScheme::ServerSignatures | AuthScheme::None, + Token::Appservice(_) | Token::User(_), + ) => { + return Err(Error::BadRequest( + ErrorKind::Unauthorized, + "Access tokens should not be used on this endpoint.", + )); + } + (AuthScheme::AppserviceToken, Token::User(_)) => { + return Err(Error::BadRequest( + ErrorKind::Unauthorized, + "Only appservice access tokens should be used on this endpoint.", + )); } }; From 11612e347d01788fec0a6f524f899724341b3293 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 31 Mar 2024 13:25:04 +0100 Subject: [PATCH 141/175] fix: return error when trying to unregister unknown appservice id --- src/service/appservice/mod.rs | 3 ++- src/utils/error.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 4bda8961..7d2d46bd 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -143,7 +143,8 @@ impl Service { .registration_info .write() .await - .remove(service_name); + .remove(service_name) + .ok_or_else(|| crate::Error::AdminCommand("Appservice not found"))?; self.db.unregister_appservice(service_name) } diff --git a/src/utils/error.rs b/src/utils/error.rs index 04390283..899dfde6 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -85,6 +85,8 @@ pub enum Error { #[cfg(feature = "conduit_bin")] #[error("{0}")] PathError(#[from] axum::extract::rejection::PathRejection), + #[error("{0}")] + AdminCommand(&'static str), } impl Error { From 3ce3d13378dcb523c06ed914527ccc190c1d9457 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sun, 31 Mar 2024 21:30:26 +0100 Subject: [PATCH 142/175] fix: do not expect that all http requests are valid reqwest requests --- src/api/appservice_server.rs | 18 +++++++++++------- src/api/client_server/alias.rs | 26 ++++++++++++-------------- src/api/server_server.rs | 3 +-- src/service/pusher/mod.rs | 3 +-- src/service/sending/mod.rs | 8 +++----- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/api/appservice_server.rs b/src/api/appservice_server.rs index 213e4c09..3ec7a66e 100644 --- a/src/api/appservice_server.rs +++ b/src/api/appservice_server.rs @@ -13,11 +13,16 @@ use tracing::warn; pub(crate) async fn send_request( registration: Registration, request: T, -) -> Option> +) -> Result> where T: Debug, { - let destination = registration.url?; + let destination = match registration.url { + Some(url) => url, + None => { + return Ok(None); + } + }; let hs_token = registration.hs_token.as_str(); @@ -45,8 +50,7 @@ where ); *http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid"); - let mut reqwest_request = reqwest::Request::try_from(http_request) - .expect("all http requests are valid reqwest requests"); + let mut reqwest_request = reqwest::Request::try_from(http_request)?; *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); @@ -63,7 +67,7 @@ where "Could not send request to appservice {:?} at {}: {}", registration.id, destination, e ); - return Some(Err(e.into())); + return Err(e.into()); } }; @@ -100,11 +104,11 @@ where .expect("reqwest body is valid http body"), ); - Some(response.map_err(|_| { + response.map(Some).map_err(|_| { warn!( "Appservice returned invalid response bytes {}\n{}", destination, url ); Error::BadServerResponse("Server returned bad response.") - })) + }) } diff --git a/src/api/client_server/alias.rs b/src/api/client_server/alias.rs index bc3a5e25..b84c7c4e 100644 --- a/src/api/client_server/alias.rs +++ b/src/api/client_server/alias.rs @@ -102,20 +102,18 @@ pub(crate) async fn get_alias_helper( None => { for appservice in services().appservice.read().await.values() { if appservice.aliases.is_match(room_alias.as_str()) - && if let Some(opt_result) = services() - .sending - .send_appservice_request( - appservice.registration.clone(), - appservice::query::query_room_alias::v1::Request { - room_alias: room_alias.clone(), - }, - ) - .await - { - opt_result.is_ok() - } else { - false - } + && matches!( + services() + .sending + .send_appservice_request( + appservice.registration.clone(), + appservice::query::query_room_alias::v1::Request { + room_alias: room_alias.clone(), + }, + ) + .await, + Ok(Some(_opt_result)) + ) { room_id = Some( services() diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 0fdf22fc..c116e796 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -233,8 +233,7 @@ where } } - let reqwest_request = reqwest::Request::try_from(http_request) - .expect("all http requests are valid reqwest requests"); + let reqwest_request = reqwest::Request::try_from(http_request)?; let url = reqwest_request.url().clone(); diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index 418b7a8f..6ca86be7 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -66,8 +66,7 @@ impl Service { })? .map(|body| body.freeze()); - let reqwest_request = reqwest::Request::try_from(http_request) - .expect("all http requests are valid reqwest requests"); + let reqwest_request = reqwest::Request::try_from(http_request)?; // TODO: we could keep this very short and let expo backoff do it's thing... //*reqwest_request.timeout_mut() = Some(Duration::from_secs(5)); diff --git a/src/service/sending/mod.rs b/src/service/sending/mod.rs index 45cca173..7e54e8b4 100644 --- a/src/service/sending/mod.rs +++ b/src/service/sending/mod.rs @@ -512,10 +512,8 @@ impl Service { ) .await { - None => Ok(kind.clone()), - Some(op_resp) => op_resp - .map(|_response| kind.clone()) - .map_err(|e| (kind.clone(), e)), + Ok(_) => Ok(kind.clone()), + Err(e) => Err((kind.clone(), e)), }; drop(permit); @@ -710,7 +708,7 @@ impl Service { &self, registration: Registration, request: T, - ) -> Option> + ) -> Result> where T: Debug, { From 1c529529aa4c7f1f8d08f60b44487c0032cead62 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 1 Apr 2024 13:36:38 +0100 Subject: [PATCH 143/175] chore: upgrade nix to 0.28 needed for musl targets on s390x --- Cargo.lock | 24 ++++++++++-------------- Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd83f2d2..cc614a77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -314,6 +314,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "clang-sys" version = "1.7.0" @@ -1388,15 +1394,6 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -1432,15 +1429,14 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.4" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "cfg-if", + "cfg_aliases", "libc", - "memoffset", - "pin-utils", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d2b828ae..636f32e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,7 +125,7 @@ features = [ ] [target.'cfg(unix)'.dependencies] -nix = { version = "0.26.2", features = ["resource"] } +nix = { version = "0.28", features = ["resource"] } [features] default = ["conduit_bin", "backend_sqlite", "backend_rocksdb", "systemd"] From e38af9b7fc069a8929ead6542a8a16d2f1a48286 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 1 Apr 2024 20:55:13 +0100 Subject: [PATCH 144/175] feat: use _matrix-fed._tcp SRV record, fallback to _matrix._tcp --- src/api/server_server.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 0fdf22fc..fb0d31a6 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -476,12 +476,11 @@ async fn find_actual_destination(destination: &'_ ServerName) -> (FedDest, FedDe (actual_destination, hostname) } -async fn query_srv_record(hostname: &'_ str) -> Option { - let hostname = hostname.trim_end_matches('.'); - if let Ok(Some(host_port)) = services() +async fn query_given_srv_record(record: &str) -> Option { + services() .globals .dns_resolver() - .srv_lookup(format!("_matrix._tcp.{hostname}.")) + .srv_lookup(record) .await .map(|srv| { srv.iter().next().map(|result| { @@ -491,10 +490,17 @@ async fn query_srv_record(hostname: &'_ str) -> Option { ) }) }) + .unwrap_or(None) +} + +async fn query_srv_record(hostname: &'_ str) -> Option { + let hostname = hostname.trim_end_matches('.'); + + if let Some(host_port) = query_given_srv_record(&format!("_matrix-fed._tcp.{hostname}.")).await { Some(host_port) } else { - None + query_given_srv_record(&format!("_matrix._tcp.{hostname}.")).await } } From 0d62c9de7ce96d90356210084dc36449df59af0d Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 2 Apr 2024 17:19:59 +0100 Subject: [PATCH 145/175] fix: ignore access tokens where they are not needed --- src/api/ruma_wrapper/axum.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index 43e73c66..895b601d 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -110,7 +110,8 @@ where ( AuthScheme::AccessToken | AuthScheme::AppserviceToken - | AuthScheme::AccessTokenOptional, + | AuthScheme::AccessTokenOptional + | AuthScheme::None, Token::Appservice(info), ) => { let user_id = query_params @@ -144,7 +145,7 @@ where )); } ( - AuthScheme::AccessToken | AuthScheme::AccessTokenOptional, + AuthScheme::AccessToken | AuthScheme::AccessTokenOptional | AuthScheme::None, Token::User((user_id, device_id)), ) => (Some(user_id), Some(device_id), None, false), (AuthScheme::ServerSignatures, Token::None) => { @@ -259,13 +260,10 @@ where | AuthScheme::AccessTokenOptional, Token::None, ) => (None, None, None, false), - ( - AuthScheme::ServerSignatures | AuthScheme::None, - Token::Appservice(_) | Token::User(_), - ) => { + (AuthScheme::ServerSignatures, Token::Appservice(_) | Token::User(_)) => { return Err(Error::BadRequest( ErrorKind::Unauthorized, - "Access tokens should not be used on this endpoint.", + "Only server signatures should be used on this endpoint.", )); } (AuthScheme::AppserviceToken, Token::User(_)) => { From 0f6b771cdd55633af3bcdb706d48139532106412 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 3 Apr 2024 22:42:14 +0100 Subject: [PATCH 146/175] fix(membership): remove join_authorized_via_users_server field on state update --- src/api/client_server/membership.rs | 2 ++ src/api/client_server/profile.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index bc84b262..86ac5950 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -270,6 +270,7 @@ pub async fn ban_user_route(body: Ruma) -> Result Date: Fri, 5 Apr 2024 10:21:44 +0100 Subject: [PATCH 147/175] feat(membership): check if user already has the membership that is requested to be set --- src/api/client_server/membership.rs | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index bc84b262..beda8cf2 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -187,6 +187,14 @@ pub async fn kick_user_route( ) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + if let Ok(true) = services() + .rooms + .state_cache + .is_left(sender_user, &body.room_id) + { + return Ok(kick_user::v3::Response {}); + } + let mut event: RoomMemberEventContent = serde_json::from_str( services() .rooms @@ -247,6 +255,16 @@ pub async fn kick_user_route( pub async fn ban_user_route(body: Ruma) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + if let Ok(Some(membership_event)) = services() + .rooms + .state_accessor + .get_member(&body.room_id, sender_user) + { + if membership_event.membership == MembershipState::Ban { + return Ok(ban_user::v3::Response {}); + } + } + let event = services() .rooms .state_accessor @@ -317,6 +335,16 @@ pub async fn unban_user_route( ) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + if let Ok(Some(membership_event)) = services() + .rooms + .state_accessor + .get_member(&body.room_id, sender_user) + { + if membership_event.membership != MembershipState::Ban { + return Ok(unban_user::v3::Response {}); + } + } + let mut event: RoomMemberEventContent = serde_json::from_str( services() .rooms @@ -497,6 +525,12 @@ async fn join_room_by_id_helper( ) -> Result { let sender_user = sender_user.expect("user is authenticated"); + if let Ok(true) = services().rooms.state_cache.is_joined(sender_user, room_id) { + return Ok(join_room_by_id::v3::Response { + room_id: room_id.into(), + }); + } + let mutex_state = Arc::clone( services() .globals From 110b7e10e68e21037799e5e492aabb6f605c1e56 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 1 Apr 2024 13:04:36 +0100 Subject: [PATCH 148/175] fix: do not allow administration of remote users --- src/service/admin/mod.rs | 91 +++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 15 deletions(-) diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index f2f60a7a..408adf6f 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -555,6 +555,13 @@ impl Service { } }; + // Checks if user is local + if user_id.server_name() != services().globals.server_name() { + return Ok(RoomMessageEventContent::text_plain( + "The specified user is not from this server!", + )); + }; + // Check if the specified user is valid if !services().users.exists(&user_id)? || user_id @@ -658,7 +665,15 @@ impl Service { user_id, } => { let user_id = Arc::::from(user_id); - if services().users.exists(&user_id)? { + if !services().users.exists(&user_id)? { + RoomMessageEventContent::text_plain(format!( + "User {user_id} doesn't exist on this server" + )) + } else if user_id.server_name() != services().globals.server_name() { + RoomMessageEventContent::text_plain(format!( + "User {user_id} is not from this server" + )) + } else { RoomMessageEventContent::text_plain(format!( "Making {user_id} leave all rooms before deactivation..." )); @@ -672,30 +687,76 @@ impl Service { RoomMessageEventContent::text_plain(format!( "User {user_id} has been deactivated" )) - } else { - RoomMessageEventContent::text_plain(format!( - "User {user_id} doesn't exist on this server" - )) } } AdminCommand::DeactivateAll { leave_rooms, force } => { if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```" { - let usernames = body.clone().drain(1..body.len() - 1).collect::>(); - - let mut user_ids: Vec<&UserId> = Vec::new(); - - for &username in &usernames { - match <&UserId>::try_from(username) { - Ok(user_id) => user_ids.push(user_id), + let users = body.clone().drain(1..body.len() - 1).collect::>(); + + let mut user_ids = Vec::new(); + let mut remote_ids = Vec::new(); + let mut non_existant_ids = Vec::new(); + let mut invalid_users = Vec::new(); + + for &user in &users { + match <&UserId>::try_from(user) { + Ok(user_id) => { + if user_id.server_name() != services().globals.server_name() { + remote_ids.push(user_id) + } else if !services().users.exists(user_id)? { + non_existant_ids.push(user_id) + } else { + user_ids.push(user_id) + } + } Err(_) => { - return Ok(RoomMessageEventContent::text_plain(format!( - "{username} is not a valid username" - ))) + invalid_users.push(user); } } } + let mut markdown_message = String::new(); + let mut html_message = String::new(); + if !invalid_users.is_empty() { + markdown_message.push_str("The following user ids are not valid:\n```\n"); + html_message.push_str("The following user ids are not valid:\n
\n");
+                        for invalid_user in invalid_users {
+                            markdown_message.push_str(&format!("{invalid_user}\n"));
+                            html_message.push_str(&format!("{invalid_user}\n"));
+                        }
+                        markdown_message.push_str("```\n\n");
+                        html_message.push_str("
\n\n"); + } + if !remote_ids.is_empty() { + markdown_message + .push_str("The following users are not from this server:\n```\n"); + html_message + .push_str("The following users are not from this server:\n
\n");
+                        for remote_id in remote_ids {
+                            markdown_message.push_str(&format!("{remote_id}\n"));
+                            html_message.push_str(&format!("{remote_id}\n"));
+                        }
+                        markdown_message.push_str("```\n\n");
+                        html_message.push_str("
\n\n"); + } + if !non_existant_ids.is_empty() { + markdown_message.push_str("The following users do not exist:\n```\n"); + html_message.push_str("The following users do not exist:\n
\n");
+                        for non_existant_id in non_existant_ids {
+                            markdown_message.push_str(&format!("{non_existant_id}\n"));
+                            html_message.push_str(&format!("{non_existant_id}\n"));
+                        }
+                        markdown_message.push_str("```\n\n");
+                        html_message.push_str("
\n\n"); + } + if !markdown_message.is_empty() { + return Ok(RoomMessageEventContent::text_html( + markdown_message, + html_message, + )); + } + let mut deactivation_count = 0; let mut admins = Vec::new(); From 9497713a79243eb745a8e06032412a075efe2eec Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 6 Apr 2024 14:10:11 +0100 Subject: [PATCH 149/175] fix(membership): check if server is in room to decide whether to do remote leaves --- src/api/client_server/membership.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index bc84b262..c2ad61ad 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -1398,8 +1398,10 @@ pub async fn leave_all_rooms(user_id: &UserId) -> Result<()> { pub async fn leave_room(user_id: &UserId, room_id: &RoomId, reason: Option) -> Result<()> { // Ask a remote server if we don't have this room - if !services().rooms.metadata.exists(room_id)? - && room_id.server_name() != Some(services().globals.server_name()) + if !services() + .rooms + .state_cache + .server_in_room(services().globals.server_name(), room_id)? { if let Err(e) = remote_leave_room(user_id, room_id).await { warn!("Failed to leave room {} remotely: {}", user_id, e); From 2c73c3adbb1b326bdebcac856225bb93275287b8 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Sat, 6 Apr 2024 14:12:18 +0100 Subject: [PATCH 150/175] fix(sync): send phoney leave event where room state is unknown on invite rejection --- src/api/client_server/sync.rs | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index da603dcf..e0c6e0b9 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -1,5 +1,6 @@ use crate::{ - service::rooms::timeline::PduCount, services, Error, PduEvent, Result, Ruma, RumaResponse, + service::{pdu::EventHash, rooms::timeline::PduCount}, + services, utils, Error, PduEvent, Result, Ruma, RumaResponse, }; use ruma::{ @@ -21,7 +22,7 @@ use ruma::{ StateEventType, TimelineEventType, }, serde::Raw, - uint, DeviceId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, + uint, DeviceId, EventId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, }; use std::{ collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet}, @@ -296,8 +297,6 @@ async fn sync_helper( for result in all_left_rooms { let (room_id, _) = result?; - let mut left_state_events = Vec::new(); - { // Get and drop the lock to wait for remaining operations to finish let mutex_insert = Arc::clone( @@ -325,9 +324,48 @@ async fn sync_helper( if !services().rooms.metadata.exists(&room_id)? { // This is just a rejected invite, not a room we know + let event = PduEvent { + event_id: EventId::new(services().globals.server_name()).into(), + sender: sender_user.clone(), + origin_server_ts: utils::millis_since_unix_epoch() + .try_into() + .expect("Timestamp is valid js_int value"), + kind: TimelineEventType::RoomMember, + content: serde_json::from_str(r#"{ "membership": "leave"}"#).unwrap(), + state_key: Some(sender_user.to_string()), + unsigned: None, + // The following keys are dropped on conversion + room_id: room_id.clone(), + prev_events: vec![], + depth: uint!(1), + auth_events: vec![], + redacts: None, + hashes: EventHash { + sha256: String::new(), + }, + signatures: None, + }; + + left_rooms.insert( + room_id, + LeftRoom { + account_data: RoomAccountData { events: Vec::new() }, + timeline: Timeline { + limited: false, + prev_batch: Some(next_batch_string.clone()), + events: Vec::new(), + }, + state: State { + events: vec![event.to_sync_state_event()], + }, + }, + ); + continue; } + let mut left_state_events = Vec::new(); + let since_shortstatehash = services() .rooms .user From fe78cc8262d009a94efe8cdf11b2ad8fe10c48ad Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Thu, 4 Apr 2024 02:00:08 +0100 Subject: [PATCH 151/175] refactor(state_accessor): add method to check if a user can invite another user --- src/service/rooms/state_accessor/mod.rs | 40 +++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 903ad47b..c287edc5 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -18,9 +18,10 @@ use ruma::{ }, EventId, JsOption, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, }; -use tracing::error; +use serde_json::value::to_raw_value; +use tracing::{error, warn}; -use crate::{services, Error, PduEvent, Result}; +use crate::{service::pdu::PduBuilder, services, Error, PduEvent, Result}; pub struct Service { pub db: &'static dyn Data, @@ -301,6 +302,41 @@ impl Service { }) } + pub async fn user_can_invite( + &self, + room_id: &RoomId, + sender: &UserId, + target_user: &UserId, + ) -> Result { + let content = to_raw_value(&RoomMemberEventContent::new(MembershipState::Invite)) + .expect("Event content always serializes"); + + let new_event = PduBuilder { + event_type: ruma::events::TimelineEventType::RoomMember, + content, + unsigned: None, + state_key: Some(target_user.into()), + redacts: None, + }; + + let mutex_state = Arc::clone( + services() + .globals + .roomid_mutex_state + .write() + .await + .entry(room_id.to_owned()) + .or_default(), + ); + let state_lock = mutex_state.lock().await; + + Ok(services() + .rooms + .timeline + .create_hash_and_sign_event(new_event, sender, room_id, &state_lock) + .is_ok()) + } + pub fn get_member( &self, room_id: &RoomId, From e88d137bd71232d0cc9793757cf3d79a8fd8c998 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Thu, 11 Apr 2024 17:19:42 +0000 Subject: [PATCH 152/175] Replace panic!() with unreachable!() --- src/api/client_server/room.rs | 6 +++--- src/service/rooms/timeline/mod.rs | 12 ++---------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 128f84f9..ee89439d 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -147,7 +147,7 @@ pub async fn create_room_route( ); } RoomVersionId::V11 => {} // V11 removed the "creator" key - _ => panic!("Unexpected room version {}", room_version), + _ => unreachable!("Validity of room version already checked"), } content.insert( @@ -172,7 +172,7 @@ pub async fn create_room_route( | RoomVersionId::V9 | RoomVersionId::V10 => RoomCreateEventContent::new_v1(sender_user.clone()), RoomVersionId::V11 => RoomCreateEventContent::new_v11(), - _ => panic!("Unexpected room version {}", room_version), + _ => unreachable!("Validity of room version already checked"), }; let mut content = serde_json::from_str::( to_raw_value(&content) @@ -633,7 +633,7 @@ pub async fn upgrade_room_route( // "creator" key no longer exists in V11 rooms create_event_content.remove("creator"); } - _ => panic!("Unexpected room version {}", body.new_version) + _ => unreachable!("Validity of room version already checked") } create_event_content.insert( "room_version".into(), diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index d0943c9a..cb2e6494 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -400,11 +400,7 @@ impl Service { } } RoomVersionId::V11 => { - #[derive(Deserialize)] - struct Redaction { - redacts: Option, - } - let content = serde_json::from_str::(pdu.content.get()) + let content = serde_json::from_str::(pdu.content.get()) .map_err(|_| { Error::bad_database("Invalid content in redaction pdu.") })?; @@ -680,11 +676,7 @@ impl Service { .get_room_version(room_id) .or_else(|_| { if event_type == TimelineEventType::RoomCreate { - #[derive(Deserialize)] - struct RoomCreate { - room_version: RoomVersionId, - } - let content = serde_json::from_str::(content.get()) + let content = serde_json::from_str::(content.get()) .expect("Invalid content in RoomCreate pdu."); Ok(content.room_version) } else { From 9e6ce8326f88d12b6fe3d5cd7bfcc440fd684f9b Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Thu, 11 Apr 2024 17:21:00 +0000 Subject: [PATCH 153/175] Remove TODO --- src/api/client_server/room.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index ee89439d..df325059 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -159,7 +159,6 @@ pub async fn create_room_route( content } None => { - // TODO: Add correct value for v11 let content = match room_version { RoomVersionId::V1 | RoomVersionId::V2 From 561a103140325a537f248f9121163a56cd275257 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Thu, 11 Apr 2024 22:55:18 +0100 Subject: [PATCH 154/175] chore(config): bump default room version to v10 --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 4605855f..3ad73bc6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -273,5 +273,5 @@ fn default_turn_ttl() -> u64 { // I know, it's a great name pub fn default_default_room_version() -> RoomVersionId { - RoomVersionId::V9 + RoomVersionId::V10 } From ab8592526fe6f061756f730c349a0e575072f627 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 12 Apr 2024 05:14:39 +0000 Subject: [PATCH 155/175] Replace panic!() with unreachable!() --- src/service/admin/mod.rs | 2 +- src/service/globals/mod.rs | 2 +- src/service/rooms/timeline/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index c5f014cd..484fc134 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -978,7 +978,7 @@ impl Service { | RoomVersionId::V9 | RoomVersionId::V10 => RoomCreateEventContent::new_v1(conduit_user.clone()), RoomVersionId::V11 => RoomCreateEventContent::new_v11(), - _ => panic!("Unexpected room version {}", room_version), + _ => unreachable!("Validity of room version already checked"), }; content.federate = true; content.predecessor = None; diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index cab61c66..3eb49e10 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -178,13 +178,13 @@ impl Service { RoomVersionId::V8, RoomVersionId::V9, RoomVersionId::V10, + RoomVersionId::V11, ]; // Experimental, partially supported room versions let unstable_room_versions = vec![ RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5, - RoomVersionId::V11, ]; let mut s = Self { diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index dff727af..2aeffa60 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -407,7 +407,7 @@ impl Service { self.redact_pdu(redact_id, pdu)?; } } - _ => panic!("Unexpected room version {}", room_version_id) + _ => unreachable!("Validity of room version already checked") }; } TimelineEventType::SpaceChild => { From 92817213d5c828c7dc95920ded1562ec4b2003f3 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 12 Apr 2024 05:15:37 +0000 Subject: [PATCH 156/175] Add missing import --- src/service/rooms/timeline/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 2aeffa60..2887fdd7 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -15,7 +15,7 @@ use ruma::{ push_rules::PushRulesEvent, room::{ create::RoomCreateEventContent, encrypted::Relation, member::MembershipState, - power_levels::RoomPowerLevelsEventContent, + power_levels::RoomPowerLevelsEventContent, redaction::RoomRedactionEventContent, }, GlobalAccountDataEventType, StateEventType, TimelineEventType, }, From 475a68cbb93da208fed175a2868c97d4c44a8839 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Fri, 12 Apr 2024 20:52:14 +0100 Subject: [PATCH 157/175] refactor: disable federation at the router level --- src/api/ruma_wrapper/axum.rs | 4 -- src/api/server_server.rs | 8 ---- src/main.rs | 76 +++++++++++++++++++++--------------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index 895b601d..906904bf 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -149,10 +149,6 @@ where Token::User((user_id, device_id)), ) => (Some(user_id), Some(device_id), None, false), (AuthScheme::ServerSignatures, Token::None) => { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let TypedHeader(Authorization(x_matrix)) = parts .extract::>>() .await diff --git a/src/api/server_server.rs b/src/api/server_server.rs index fa7f1315..b25b1313 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -527,10 +527,6 @@ async fn request_well_known(destination: &str) -> Option { pub async fn get_server_version_route( _body: Ruma, ) -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - Ok(get_server_version::v1::Response { server: Some(get_server_version::v1::Server { name: Some("Conduit".to_owned()), @@ -547,10 +543,6 @@ pub async fn get_server_version_route( /// forever. // Response type for this endpoint is Json because we need to calculate a signature for the response pub async fn get_server_keys_route() -> Result { - if !services().globals.allow_federation() { - return Err(Error::bad_config("Federation is disabled.")); - } - let mut verify_keys: BTreeMap = BTreeMap::new(); verify_keys.insert( format!("ed25519:{}", services().globals.keypair().version()) diff --git a/src/main.rs b/src/main.rs index b5bf742d..7beeb8ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::{future::Future, io, net::SocketAddr, sync::atomic, time::Duration}; use axum::{ extract::{DefaultBodyLimit, FromRequestParts, MatchedPath}, response::IntoResponse, - routing::{get, on, MethodFilter}, + routing::{any, get, on, MethodFilter}, Router, }; use axum_server::{bind, bind_rustls, tls_rustls::RustlsConfig, Handle as ServerHandle}; @@ -188,7 +188,7 @@ async fn run_server() -> io::Result<()> { .expect("failed to convert max request size"), )); - let app = routes().layer(middlewares).into_make_service(); + let app = routes(config).layer(middlewares).into_make_service(); let handle = ServerHandle::new(); tokio::spawn(shutdown_signal(handle.clone())); @@ -249,8 +249,8 @@ async fn unrecognized_method( Ok(inner) } -fn routes() -> Router { - Router::new() +fn routes(config: &Config) -> Router { + let router = Router::new() .ruma_route(client_server::get_supported_versions_route) .ruma_route(client_server::get_register_available_route) .ruma_route(client_server::register_route) @@ -390,33 +390,6 @@ fn routes() -> Router { .ruma_route(client_server::get_relating_events_with_rel_type_route) .ruma_route(client_server::get_relating_events_route) .ruma_route(client_server::get_hierarchy_route) - .ruma_route(server_server::get_server_version_route) - .route( - "/_matrix/key/v2/server", - get(server_server::get_server_keys_route), - ) - .route( - "/_matrix/key/v2/server/:key_id", - get(server_server::get_server_keys_deprecated_route), - ) - .ruma_route(server_server::get_public_rooms_route) - .ruma_route(server_server::get_public_rooms_filtered_route) - .ruma_route(server_server::send_transaction_message_route) - .ruma_route(server_server::get_event_route) - .ruma_route(server_server::get_backfill_route) - .ruma_route(server_server::get_missing_events_route) - .ruma_route(server_server::get_event_authorization_route) - .ruma_route(server_server::get_room_state_route) - .ruma_route(server_server::get_room_state_ids_route) - .ruma_route(server_server::create_join_event_template_route) - .ruma_route(server_server::create_join_event_v1_route) - .ruma_route(server_server::create_join_event_v2_route) - .ruma_route(server_server::create_invite_route) - .ruma_route(server_server::get_devices_route) - .ruma_route(server_server::get_room_information_route) - .ruma_route(server_server::get_profile_information_route) - .ruma_route(server_server::get_keys_route) - .ruma_route(server_server::claim_keys_route) .route( "/_matrix/client/r0/rooms/:room_id/initialSync", get(initial_sync), @@ -426,7 +399,42 @@ fn routes() -> Router { get(initial_sync), ) .route("/", get(it_works)) - .fallback(not_found) + .fallback(not_found); + + if config.allow_federation { + router + .ruma_route(server_server::get_server_version_route) + .route( + "/_matrix/key/v2/server", + get(server_server::get_server_keys_route), + ) + .route( + "/_matrix/key/v2/server/:key_id", + get(server_server::get_server_keys_deprecated_route), + ) + .ruma_route(server_server::get_public_rooms_route) + .ruma_route(server_server::get_public_rooms_filtered_route) + .ruma_route(server_server::send_transaction_message_route) + .ruma_route(server_server::get_event_route) + .ruma_route(server_server::get_backfill_route) + .ruma_route(server_server::get_missing_events_route) + .ruma_route(server_server::get_event_authorization_route) + .ruma_route(server_server::get_room_state_route) + .ruma_route(server_server::get_room_state_ids_route) + .ruma_route(server_server::create_join_event_template_route) + .ruma_route(server_server::create_join_event_v1_route) + .ruma_route(server_server::create_join_event_v2_route) + .ruma_route(server_server::create_invite_route) + .ruma_route(server_server::get_devices_route) + .ruma_route(server_server::get_room_information_route) + .ruma_route(server_server::get_profile_information_route) + .ruma_route(server_server::get_keys_route) + .ruma_route(server_server::claim_keys_route) + } else { + router + .route("/_matrix/federation/*path", any(federation_disabled)) + .route("/_matrix/key/*path", any(federation_disabled)) + } } async fn shutdown_signal(handle: ServerHandle) { @@ -463,6 +471,10 @@ async fn shutdown_signal(handle: ServerHandle) { let _ = sd_notify::notify(true, &[sd_notify::NotifyState::Stopping]); } +async fn federation_disabled(_: Uri) -> impl IntoResponse { + Error::bad_config("Federation is disabled.") +} + async fn not_found(uri: Uri) -> impl IntoResponse { warn!("Not found: {uri}"); Error::BadRequest(ErrorKind::Unrecognized, "Unrecognized request") From 54e0e2a14c1446847d02b299d17f7c848abb2ead Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 15 Apr 2024 19:13:10 +0100 Subject: [PATCH 158/175] fix(appservices): don't use identity assertion on account management endpoints --- src/api/ruma_wrapper/axum.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index 895b601d..e721e80d 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -108,10 +108,7 @@ where )) } ( - AuthScheme::AccessToken - | AuthScheme::AppserviceToken - | AuthScheme::AccessTokenOptional - | AuthScheme::None, + AuthScheme::AccessToken | AuthScheme::AccessTokenOptional, Token::Appservice(info), ) => { let user_id = query_params @@ -138,6 +135,9 @@ where // TODO: Check if appservice is allowed to be that user (Some(user_id), None, None, true) } + (AuthScheme::None | AuthScheme::AppserviceToken, Token::Appservice(_)) => { + (None, None, None, true) + } (AuthScheme::AccessToken, Token::None) => { return Err(Error::BadRequest( ErrorKind::MissingToken, From 7a7c09785e4895336bb3559c05f8accf0c4c23ac Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 16 Apr 2024 22:45:04 +0100 Subject: [PATCH 159/175] feat(pdu): copy top level redact to content and vice versa --- src/api/client_server/room.rs | 2 +- src/service/globals/mod.rs | 6 +---- src/service/pdu.rs | 40 ++++++++++++++++++++++++------- src/service/rooms/timeline/mod.rs | 16 ++++++------- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 203a8b70..6f92e9f6 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -671,7 +671,7 @@ pub async fn upgrade_room_route( // "creator" key no longer exists in V11 rooms create_event_content.remove("creator"); } - _ => unreachable!("Validity of room version already checked") + _ => unreachable!("Validity of room version already checked"), } create_event_content.insert( "room_version".into(), diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 3eb49e10..798c725a 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -181,11 +181,7 @@ impl Service { RoomVersionId::V11, ]; // Experimental, partially supported room versions - let unstable_room_versions = vec![ - RoomVersionId::V3, - RoomVersionId::V4, - RoomVersionId::V5, - ]; + let unstable_room_versions = vec![RoomVersionId::V3, RoomVersionId::V4, RoomVersionId::V5]; let mut s = Self { db, diff --git a/src/service/pdu.rs b/src/service/pdu.rs index 0a9ea861..a10573be 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -2,7 +2,8 @@ use crate::Error; use ruma::{ canonical_json::redact_content_in_place, events::{ - room::member::RoomMemberEventContent, space::child::HierarchySpaceChildEvent, + room::{member::RoomMemberEventContent, redaction::RoomRedactionEventContent}, + space::child::HierarchySpaceChildEvent, AnyEphemeralRoomEvent, AnyMessageLikeEvent, AnyStateEvent, AnyStrippedStateEvent, AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent, StateEvent, TimelineEventType, }, @@ -25,7 +26,7 @@ pub struct EventHash { pub sha256: String, } -#[derive(Clone, Deserialize, Serialize, Debug)] +#[derive(Clone, Deserialize, Debug, Serialize)] pub struct PduEvent { pub event_id: Arc, pub room_id: OwnedRoomId, @@ -96,10 +97,31 @@ impl PduEvent { Ok(()) } + pub fn copy_redacts(&self) -> (Option>, Box) { + if self.kind == TimelineEventType::RoomRedaction { + if let Ok(mut content) = + serde_json::from_str::(self.content.get()) + { + if let Some(redacts) = content.redacts { + return (Some(redacts.into()), self.content.clone()); + } else if let Some(redacts) = self.redacts.clone() { + content.redacts = Some(redacts.into()); + return ( + self.redacts.clone(), + to_raw_value(&content).expect("Must be valid, we only added redacts field"), + ); + } + } + } + + (self.redacts.clone(), self.content.clone()) + } + #[tracing::instrument(skip(self))] pub fn to_sync_room_event(&self) -> Raw { + let (redacts, content) = self.copy_redacts(); let mut json = json!({ - "content": self.content, + "content": content, "type": self.kind, "event_id": self.event_id, "sender": self.sender, @@ -112,7 +134,7 @@ impl PduEvent { if let Some(state_key) = &self.state_key { json["state_key"] = json!(state_key); } - if let Some(redacts) = &self.redacts { + if let Some(redacts) = &redacts { json["redacts"] = json!(redacts); } @@ -146,8 +168,9 @@ impl PduEvent { #[tracing::instrument(skip(self))] pub fn to_room_event(&self) -> Raw { + let (redacts, content) = self.copy_redacts(); let mut json = json!({ - "content": self.content, + "content": content, "type": self.kind, "event_id": self.event_id, "sender": self.sender, @@ -161,7 +184,7 @@ impl PduEvent { if let Some(state_key) = &self.state_key { json["state_key"] = json!(state_key); } - if let Some(redacts) = &self.redacts { + if let Some(redacts) = &redacts { json["redacts"] = json!(redacts); } @@ -170,8 +193,9 @@ impl PduEvent { #[tracing::instrument(skip(self))] pub fn to_message_like_event(&self) -> Raw { + let (redacts, content) = self.copy_redacts(); let mut json = json!({ - "content": self.content, + "content": content, "type": self.kind, "event_id": self.event_id, "sender": self.sender, @@ -185,7 +209,7 @@ impl PduEvent { if let Some(state_key) = &self.state_key { json["state_key"] = json!(state_key); } - if let Some(redacts) = &self.redacts { + if let Some(redacts) = &redacts { json["redacts"] = json!(redacts); } diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 2887fdd7..8f713c45 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -399,15 +399,16 @@ impl Service { } } RoomVersionId::V11 => { - let content = serde_json::from_str::(pdu.content.get()) - .map_err(|_| { - Error::bad_database("Invalid content in redaction pdu.") - })?; + let content = + serde_json::from_str::(pdu.content.get()) + .map_err(|_| { + Error::bad_database("Invalid content in redaction pdu.") + })?; if let Some(redact_id) = &content.redacts { self.redact_pdu(redact_id, pdu)?; } } - _ => unreachable!("Validity of room version already checked") + _ => unreachable!("Validity of room version already checked"), }; } TimelineEventType::SpaceChild => { @@ -1015,10 +1016,7 @@ impl Service { let mut pdu = self .get_pdu_from_id(&pdu_id)? .ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?; - let room_version_id = services() - .rooms - .state - .get_room_version(&pdu.room_id)?; + let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?; pdu.redact(room_version_id, reason)?; self.replace_pdu( &pdu_id, From eb6801290b90e400b2c00c9275d6f90a2d3baad4 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Wed, 17 Apr 2024 19:37:32 +0200 Subject: [PATCH 160/175] Document copy_redacts --- src/service/pdu.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/service/pdu.rs b/src/service/pdu.rs index a10573be..b5c95981 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -97,6 +97,14 @@ impl PduEvent { Ok(()) } + /// Copies the `redacts` property of the event to the `content` dict + /// + /// This follows the specification's + /// [recommendation](https://spec.matrix.org/v1.10/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property): + /// + /// > For backwards-compatibility with older clients, servers should add a redacts + /// > property to the top level of m.room.redaction events in when serving such events + /// > over the Client-Server API. pub fn copy_redacts(&self) -> (Option>, Box) { if self.kind == TimelineEventType::RoomRedaction { if let Ok(mut content) = From 2d8c551cd5f23c8ab7ab24b0bdde9dd413a5fa20 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Wed, 17 Apr 2024 19:41:38 +0200 Subject: [PATCH 161/175] Fix doc --- src/service/pdu.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/service/pdu.rs b/src/service/pdu.rs index b5c95981..a51d7ec5 100644 --- a/src/service/pdu.rs +++ b/src/service/pdu.rs @@ -97,7 +97,7 @@ impl PduEvent { Ok(()) } - /// Copies the `redacts` property of the event to the `content` dict + /// Copies the `redacts` property of the event to the `content` dict and vice-versa. /// /// This follows the specification's /// [recommendation](https://spec.matrix.org/v1.10/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property): @@ -105,6 +105,10 @@ impl PduEvent { /// > For backwards-compatibility with older clients, servers should add a redacts /// > property to the top level of m.room.redaction events in when serving such events /// > over the Client-Server API. + /// > + /// > For improved compatibility with newer clients, servers should add a redacts property + /// > to the content of m.room.redaction events in older room versions when serving + /// > such events over the Client-Server API. pub fn copy_redacts(&self) -> (Option>, Box) { if self.kind == TimelineEventType::RoomRedaction { if let Ok(mut content) = From 4b288fd22f826990dfd614ce6bc05baeda59651c Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Thu, 18 Apr 2024 20:49:50 +0100 Subject: [PATCH 162/175] chore: remove default database backend has been sqlite for far too long, and having a default for this is just asking for trouble --- src/config/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 4605855f..ff05754d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -21,7 +21,6 @@ pub struct Config { pub tls: Option, pub server_name: OwnedServerName, - #[serde(default = "default_database_backend")] pub database_backend: String, pub database_path: String, #[serde(default = "default_db_cache_capacity_mb")] @@ -223,10 +222,6 @@ fn default_port() -> u16 { 8000 } -fn default_database_backend() -> String { - "sqlite".to_owned() -} - fn default_db_cache_capacity_mb() -> f64 { 300.0 } From b48e1300f2eea997b06e439504625909da5b4e88 Mon Sep 17 00:00:00 2001 From: Awiteb Date: Thu, 18 Apr 2024 02:35:14 +0300 Subject: [PATCH 163/175] chore(docs): Rename configuration section to `Configuration` --- docs/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 30316e27..2caca3ee 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,7 +2,7 @@ - [Introduction](introduction.md) -- [Example configuration](configuration.md) +- [Configuration](configuration.md) - [Deploying](deploying.md) - [Generic](deploying/generic.md) - [Debian](deploying/debian.md) From 2656f6f43546c81d19c24741910551f302fb1688 Mon Sep 17 00:00:00 2001 From: Awiteb Date: Thu, 18 Apr 2024 02:35:52 +0300 Subject: [PATCH 164/175] feat(docs): Document all configuration options Fixes: https://gitlab.com/famedly/conduit/-/issues/435 Suggested-by: Matthias Ahouansou Helped-by: Matthias Ahouansou Signed-off-by: Awiteb --- docs/configuration.md | 111 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index a47e5ff9..efa080dc 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,5 +1,110 @@ -# Example configuration +# Configuration -``` toml -{{#include ../conduit-example.toml}} +**Conduit** is configured using a TOML file. The configuration file is loaded from the path specified by the `CONDUIT_CONFIG` environment variable. + +> **Note:** The configuration file is required to run Conduit. If the `CONDUIT_CONFIG` environment variable is not set, Conduit will exit with an error. + +> **Note:** If you update the configuration file, you must restart Conduit for the changes to take effect + +Conduit's configuration file is divided into the following sections: + +- [Global](#global) + - [TLS](#tls) + - [Proxy](#proxy) + + +## Global + +The `global` section contains the following fields: + +> **Note:** The `*` symbol indicates that the field is required, and the values in **parentheses** are the possible values + +| Field | Type | Description | Default | +| --- | --- | --- | --- | +| `address` | `string` | The address to bind to | `"127.0.0.1"` | +| `port` | `integer` | The port to bind to | `8000` | +| `tls` | `table` | See the [TLS configuration](#tls) | N/A | +| `server_name`_*_ | `string` | The server name | N/A | +| `database_backend`_*_ | `string` | The database backend to use (`"rocksdb"` *recommended*, `"sqlite"`) | N/A | +| `database_path`_*_ | `string` | The path to the database file/dir | N/A | +| `db_cache_capacity_mb` | `float` | The cache capacity, in MB | `300.0` | +| `enable_lightning_bolt` | `boolean` | Add `⚡️` emoji to end of user's display name | `true` | +| `allow_check_for_updates` | `boolean` | Allow Conduit to check for updates | `true` | +| `conduit_cache_capacity_modifier` | `float` | The value to multiply the default cache capacity by | `1.0` | +| `rocksdb_max_open_files` | `integer` | The maximum number of open files | `1000` | +| `pdu_cache_capacity` | `integer` | The maximum number of Persisted Data Units (PDUs) to cache | `150000` | +| `cleanup_second_interval` | `integer` | How often conduit should clean up the database, in seconds | `60` | +| `max_request_size` | `integer` | The maximum request size, in bytes | `20971520` (20 MiB) | +| `max_concurrent_requests` | `integer` | The maximum number of concurrent requests | `100` | +| `max_fetch_prev_events` | `integer` | The maximum number of previous events to fetch per request if conduit notices events are missing | `100` | +| `allow_registration` | `boolean` | Opens your homeserver to public registration | `false` | +| `registration_token` | `string` | The token users need to have when registering to your homeserver | N/A | +| `allow_encryption` | `boolean` | Allow users to enable encryption in their rooms | `true` | +| `allow_federation` | `boolean` | Allow federation with other servers | `true` | +| `allow_room_creation` | `boolean` | Allow users to create rooms | `true` | +| `allow_unstable_room_versions` | `boolean` | Allow users to create and join rooms with unstable versions | `true` | +| `default_room_version` | `string` | The default room version (`"6"`-`"10"`)| `"10"` | +| `allow_jaeger` | `boolean` | Allow Jaeger tracing | `false` | +| `tracing_flame` | `boolean` | Enable flame tracing | `false` | +| `proxy` | `table` | See the [Proxy configuration](#proxy) | N/A | +| `jwt_secret` | `string` | The secret used in the JWT to enable JWT login without it a 400 error will be returned | N/A | +| `trusted_servers` | `array` | The list of trusted servers to gather public keys of offline servers | `["matrix.org"]` | +| `log` | `string` | The log verbosity to use | `"warn"` | +| `turn_username` | `string` | The TURN username | `""` | +| `turn_password` | `string` | The TURN password | `""` | +| `turn_uris` | `array` | The TURN URIs | `[]` | +| `turn_secret` | `string` | The TURN secret | `""` | +| `turn_ttl` | `integer` | The TURN TTL in seconds | `86400` | +| `emergency_password` | `string` | Set a password to login as the `conduit` user in case of emergency | N/A | + + +### TLS +The `tls` table contains the following fields: +- `certs`: The path to the public PEM certificate +- `key`: The path to the PEM private key + +#### Example +```toml +[global.tls] +certs = "/path/to/cert.pem" +key = "/path/to/key.pem" +``` + + +### Proxy +You can choose what requests conduit should proxy (if any). The `proxy` table contains the following fields + +#### Global +The global option will proxy all outgoing requests. The `global` table contains the following fields: +- `url`: The URL of the proxy server +##### Example +```toml +[global.proxy.global] +url = "https://example.com" +``` + +#### By domain +An array of tables that contain the following fields: +- `url`: The URL of the proxy server +- `include`: Domains that should be proxied (assumed to be `["*"]` if unset) +- `exclude`: Domains that should not be proxied (takes precedent over `include`) + +Both `include` and `exclude` allow for glob pattern matching. +##### Example +In this example, all requests to domains ending in `.onion` and `matrix.secretly-an-onion-domain.xyz` +will be proxied via `socks://localhost:9050`, except for domains ending in `.myspecial.onion`. You can add as many `by_domain` tables as you need. +```toml +[[global.proxy.by_domain]] +url = "socks5://localhost:9050" +include = ["*.onion", "matrix.secretly-an-onion-domain.xyz"] +exclude = ["*.clearnet.onion"] +``` + +### Example + +> **Note:** The following example is a minimal configuration file. You should replace the values with your own. + +```toml +[global] +{{#include ../conduit-example.toml:22:}} ``` From 8c6ffb6bfc5a517c2531cfd83f9fba16cb5381fd Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 21 Apr 2024 12:31:49 -0700 Subject: [PATCH 165/175] unpin crane because the bug was fixed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'crane': 'github:ipetkov/crane/2c653e4478476a52c6aa3ac0495e4dea7449ea0e?narHash=sha256-XoXRS%2B5whotelr1rHiZle5t5hDg9kpguS5yk8c8qzOc%3D' (2024-02-11) → 'github:ipetkov/crane/55f4939ac59ff8f89c6a4029730a2d49ea09105f?narHash=sha256-Vz1KRVTzU3ClBfyhOj8gOehZk21q58T1YsXC30V23PU%3D' (2024-04-21) --- flake.lock | 8 ++++---- flake.nix | 7 +------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 1c2142f2..1983d800 100644 --- a/flake.lock +++ b/flake.lock @@ -51,17 +51,17 @@ ] }, "locked": { - "lastModified": 1707685877, - "narHash": "sha256-XoXRS+5whotelr1rHiZle5t5hDg9kpguS5yk8c8qzOc=", + "lastModified": 1713721181, + "narHash": "sha256-Vz1KRVTzU3ClBfyhOj8gOehZk21q58T1YsXC30V23PU=", "owner": "ipetkov", "repo": "crane", - "rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e", + "rev": "55f4939ac59ff8f89c6a4029730a2d49ea09105f", "type": "github" }, "original": { "owner": "ipetkov", + "ref": "master", "repo": "crane", - "rev": "2c653e4478476a52c6aa3ac0495e4dea7449ea0e", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 4536f172..69dd520c 100644 --- a/flake.nix +++ b/flake.nix @@ -13,12 +13,7 @@ inputs.nixpkgs.follows = "nixpkgs"; }; crane = { - # Pin latest crane that's not affected by the following bugs: - # - # * - # * - # * - url = "github:ipetkov/crane?rev=2c653e4478476a52c6aa3ac0495e4dea7449ea0e"; + url = "github:ipetkov/crane?ref=master"; inputs.nixpkgs.follows = "nixpkgs"; }; attic.url = "github:zhaofengli/attic?ref=main"; From 61cb186b5b3e245f05928c54456489ca465c3437 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Sun, 21 Apr 2024 12:39:27 -0700 Subject: [PATCH 166/175] update rocksdb --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- flake.nix | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc614a77..6e870c06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2204,9 +2204,9 @@ dependencies = [ [[package]] name = "rust-librocksdb-sys" -version = "0.18.1+8.11.3" +version = "0.20.0+9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef22f434855ceb8daf99073fcf909d957ad8705f5b530154e47978ae68e867c" +checksum = "48b14f4848d8574c074bb26445b43e63735d802ef2fc5cc40c1b015134baee0c" dependencies = [ "bindgen", "bzip2-sys", @@ -2220,9 +2220,9 @@ dependencies = [ [[package]] name = "rust-rocksdb" -version = "0.22.7" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62223f035e676bb69da2ab9487e6f710da82be89473c658c51ed3b1a60c4b4a6" +checksum = "d36eae38b1d3d0018e273191f791343bd3eb030d7da63aaa20350e41c0182881" dependencies = [ "libc", "rust-librocksdb-sys", diff --git a/Cargo.toml b/Cargo.toml index b5be5055..cc5b37eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ sd-notify = { version = "0.4.1", optional = true } [dependencies.rocksdb] package = "rust-rocksdb" -version = "0.22.7" +version = "0.24.0" optional = true features = [ "multi-threaded-cf", diff --git a/flake.nix b/flake.nix index 69dd520c..114e221c 100644 --- a/flake.nix +++ b/flake.nix @@ -55,7 +55,7 @@ rocksdb' = pkgs: let - version = "8.11.3"; + version = "9.1.0"; in pkgs.rocksdb.overrideAttrs (old: { inherit version; @@ -63,7 +63,7 @@ owner = "facebook"; repo = "rocksdb"; rev = "v${version}"; - hash = "sha256-OpEiMwGxZuxb9o3RQuSrwZMQGLhe9xLT1aa3HpI4KPs="; + hash = "sha256-vRPyrXkXVVhP56n5FVYef8zbIsnnanQSpElmQLZ7mh8="; }; }); From 6c9c1b5afe23e136d20bcb121a0258559ce70d2f Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Mon, 22 Apr 2024 10:32:33 +0100 Subject: [PATCH 167/175] fix(appservices): don't perform identity assertion when auth is optional --- src/api/ruma_wrapper/axum.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index b3494721..af2dbeb6 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -107,10 +107,7 @@ where "Unknown access token.", )) } - ( - AuthScheme::AccessToken | AuthScheme::AccessTokenOptional, - Token::Appservice(info), - ) => { + (AuthScheme::AccessToken, Token::Appservice(info)) => { let user_id = query_params .user_id .map_or_else( @@ -135,9 +132,12 @@ where // TODO: Check if appservice is allowed to be that user (Some(user_id), None, None, true) } - (AuthScheme::None | AuthScheme::AppserviceToken, Token::Appservice(_)) => { - (None, None, None, true) - } + ( + AuthScheme::None + | AuthScheme::AppserviceToken + | AuthScheme::AccessTokenOptional, + Token::Appservice(_), + ) => (None, None, None, true), (AuthScheme::AccessToken, Token::None) => { return Err(Error::BadRequest( ErrorKind::MissingToken, From 00d6aeddb6c43660326277a675fadb08a1617c10 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 23 Apr 2024 21:42:01 +0100 Subject: [PATCH 168/175] refactor(redactions): move checks inside conduit ruma was already accidentally performing these checks for us, but this shouldn't be the case --- src/service/rooms/event_handler/mod.rs | 15 +++++++- src/service/rooms/state_accessor/mod.rs | 51 +++++++++++++++++++++++++ src/service/rooms/timeline/mod.rs | 35 ++++++++++++++++- 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index 1547d406..ada289fb 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -24,7 +24,7 @@ use ruma::{ }, events::{ room::{create::RoomCreateEventContent, server_acl::RoomServerAclEventContent}, - StateEventType, + StateEventType, TimelineEventType, }, int, serde::Base64, @@ -796,7 +796,18 @@ impl Service { None::, |k, s| auth_events.get(&(k.clone(), s.to_owned())), ) - .map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))?; + .map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))? + || if let Some(redact_id) = &incoming_pdu.redacts { + incoming_pdu.kind == TimelineEventType::RoomRedaction + && !services().rooms.state_accessor.user_can_redact( + redact_id, + &incoming_pdu.sender, + &incoming_pdu.room_id, + true, + )? + } else { + false + }; // 13. Use state resolution to find new room state diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index c287edc5..8ca1b778 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -13,9 +13,11 @@ use ruma::{ history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent}, member::{MembershipState, RoomMemberEventContent}, name::RoomNameEventContent, + power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent}, }, StateEventType, }, + state_res::Event, EventId, JsOption, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, }; use serde_json::value::to_raw_value; @@ -351,4 +353,53 @@ impl Service { .map_err(|_| Error::bad_database("Invalid room member event in database.")) }) } + + /// Checks if a given user can redact a given event + /// + /// If federation is true, it allows redaction events from any user of the same server as the original event sender + pub fn user_can_redact( + &self, + redacts: &EventId, + sender: &UserId, + room_id: &RoomId, + federation: bool, + ) -> Result { + self.room_state_get(room_id, &StateEventType::RoomPowerLevels, "")? + .map(|e| { + serde_json::from_str(e.content.get()) + .map(|c: RoomPowerLevelsEventContent| c.into()) + .map(|e: RoomPowerLevels| { + e.user_can_redact_event_of_other(sender) + || e.user_can_redact_own_event(sender) + && if let Ok(Some(pdu)) = services().rooms.timeline.get_pdu(redacts) + { + if federation { + pdu.sender().server_name() == sender.server_name() + } else { + pdu.sender == sender + } + } else { + false + } + }) + .map_err(|_| { + Error::bad_database("Invalid m.room.power_levels event in database") + }) + }) + // Falling back on m.room.create to judge power levels + .unwrap_or_else(|| { + if let Some(pdu) = self.room_state_get(room_id, &StateEventType::RoomCreate, "")? { + Ok(pdu.sender == sender + || if let Ok(Some(pdu)) = services().rooms.timeline.get_pdu(redacts) { + pdu.sender == sender + } else { + false + }) + } else { + Err(Error::bad_database( + "No m.room.power_levels or m.room.create events in database for room", + )) + } + }) + } } diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 8f713c45..2752abe4 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -395,7 +395,14 @@ impl Service { | RoomVersionId::V9 | RoomVersionId::V10 => { if let Some(redact_id) = &pdu.redacts { - self.redact_pdu(redact_id, pdu)?; + if services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + self.redact_pdu(redact_id, pdu)?; + } } } RoomVersionId::V11 => { @@ -405,7 +412,14 @@ impl Service { Error::bad_database("Invalid content in redaction pdu.") })?; if let Some(redact_id) = &content.redacts { - self.redact_pdu(redact_id, pdu)?; + if services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + self.redact_pdu(redact_id, pdu)?; + } } } _ => unreachable!("Validity of room version already checked"), @@ -885,6 +899,23 @@ impl Service { } } + // If redaction event is not authorized, do not append it to the timeline + if let Some(redact_id) = &pdu.redacts { + if pdu.kind == TimelineEventType::RoomRedaction + && !services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? + { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User cannot redact this event.", + )); + } + }; + // We append to state before appending the pdu, so we don't have a moment in time with the // pdu without it's state. This is okay because append_pdu can't fail. let statehashid = services().rooms.state.append_to_state(&pdu)?; From 89c1c2109cba0cef29b09201d6aa188889c2cfdd Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Wed, 24 Apr 2024 08:29:47 +0200 Subject: [PATCH 169/175] Link to the specification from user_can_redact's documentation --- src/service/rooms/state_accessor/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 8ca1b778..9a3580dd 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -356,7 +356,9 @@ impl Service { /// Checks if a given user can redact a given event /// - /// If federation is true, it allows redaction events from any user of the same server as the original event sender + /// If `federation` is `true`, it allows redaction events from any user of the same server + /// as the original event sender, [as required by room versions >= + /// v3](https://spec.matrix.org/v1.10/rooms/v11/#handling-redactions) pub fn user_can_redact( &self, redacts: &EventId, From 1c4ae8d268dc58829b5114ac2f0441c6f72e499d Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 24 Apr 2024 09:28:16 +0100 Subject: [PATCH 170/175] fix(redaction): use content.redacts when checking v11 events --- src/service/rooms/event_handler/mod.rs | 60 ++++++++++++++++++----- src/service/rooms/timeline/mod.rs | 68 ++++++++++++++++++++------ 2 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index ada289fb..b7817e50 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -23,7 +23,10 @@ use ruma::{ }, }, events::{ - room::{create::RoomCreateEventContent, server_acl::RoomServerAclEventContent}, + room::{ + create::RoomCreateEventContent, redaction::RoomRedactionEventContent, + server_acl::RoomServerAclEventContent, + }, StateEventType, TimelineEventType, }, int, @@ -797,17 +800,50 @@ impl Service { |k, s| auth_events.get(&(k.clone(), s.to_owned())), ) .map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))? - || if let Some(redact_id) = &incoming_pdu.redacts { - incoming_pdu.kind == TimelineEventType::RoomRedaction - && !services().rooms.state_accessor.user_can_redact( - redact_id, - &incoming_pdu.sender, - &incoming_pdu.room_id, - true, - )? - } else { - false - }; + || incoming_pdu.kind == TimelineEventType::RoomRedaction + && match room_version_id { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + if let Some(redact_id) = &incoming_pdu.redacts { + !services().rooms.state_accessor.user_can_redact( + redact_id, + &incoming_pdu.sender, + &incoming_pdu.room_id, + true, + )? + } else { + false + } + } + RoomVersionId::V11 => { + let content = serde_json::from_str::( + incoming_pdu.content.get(), + ) + .map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?; + + if let Some(redact_id) = &content.redacts { + !services().rooms.state_accessor.user_can_redact( + redact_id, + &incoming_pdu.sender, + &incoming_pdu.room_id, + true, + )? + } else { + false + } + } + _ => { + unreachable!("Validity of room version already checked") + } + }; // 13. Use state resolution to find new room state diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 2752abe4..acb00d01 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -900,21 +900,61 @@ impl Service { } // If redaction event is not authorized, do not append it to the timeline - if let Some(redact_id) = &pdu.redacts { - if pdu.kind == TimelineEventType::RoomRedaction - && !services().rooms.state_accessor.user_can_redact( - redact_id, - &pdu.sender, - &pdu.room_id, - false, - )? - { - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "User cannot redact this event.", - )); + if pdu.kind == TimelineEventType::RoomRedaction { + match services().rooms.state.get_room_version(&pdu.room_id)? { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + if let Some(redact_id) = &pdu.redacts { + if !services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User cannot redact this event.", + )); + } + }; + } + RoomVersionId::V11 => { + let content = + serde_json::from_str::(pdu.content.get()) + .map_err(|_| { + Error::bad_database("Invalid content in redaction pdu.") + })?; + + if let Some(redact_id) = &content.redacts { + if !services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User cannot redact this event.", + )); + } + } + } + _ => { + return Err(Error::BadRequest( + ErrorKind::UnsupportedRoomVersion, + "Unsupported room version", + )); + } } - }; + } // We append to state before appending the pdu, so we don't have a moment in time with the // pdu without it's state. This is okay because append_pdu can't fail. From 0c0c9549b937b28058bba6408e21001a91c8ab94 Mon Sep 17 00:00:00 2001 From: Paul van Tilburg Date: Wed, 24 Apr 2024 20:09:13 +0200 Subject: [PATCH 171/175] Sync up the generated Conduit config for Debian This applies changes made in the exampl config by commits dc89fbe and 844508b. --- debian/postinst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/postinst b/debian/postinst index 0707b6f2..6361af5a 100644 --- a/debian/postinst +++ b/debian/postinst @@ -91,6 +91,11 @@ enable_lightning_bolt = true trusted_servers = ["matrix.org"] #max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time + +# Controls the log verbosity. See also [here][0]. +# +# [0]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives +#log = "..." EOF fi ;; From e40aed3a7d362733ef22fb7176634c804917b1af Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 24 Apr 2024 19:17:00 +0100 Subject: [PATCH 172/175] fix(state-accessor): hold the state_lock when checking if a user can invite --- src/service/rooms/state_accessor/mod.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 9a3580dd..53e3176f 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -21,6 +21,7 @@ use ruma::{ EventId, JsOption, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, }; use serde_json::value::to_raw_value; +use tokio::sync::MutexGuard; use tracing::{error, warn}; use crate::{service::pdu::PduBuilder, services, Error, PduEvent, Result}; @@ -309,6 +310,7 @@ impl Service { room_id: &RoomId, sender: &UserId, target_user: &UserId, + state_lock: &MutexGuard<'_, ()>, ) -> Result { let content = to_raw_value(&RoomMemberEventContent::new(MembershipState::Invite)) .expect("Event content always serializes"); @@ -321,21 +323,10 @@ impl Service { redacts: None, }; - let mutex_state = Arc::clone( - services() - .globals - .roomid_mutex_state - .write() - .await - .entry(room_id.to_owned()) - .or_default(), - ); - let state_lock = mutex_state.lock().await; - Ok(services() .rooms .timeline - .create_hash_and_sign_event(new_event, sender, room_id, &state_lock) + .create_hash_and_sign_event(new_event, sender, room_id, state_lock) .is_ok()) } From 3086271139826902d05637682ae6e1ce6404627b Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Tue, 16 Apr 2024 15:53:38 +0100 Subject: [PATCH 173/175] feat(appservice): ensure users/aliases outside of namespaces are not accessed --- src/api/client_server/account.rs | 43 ++++++++++++------- src/api/client_server/alias.rs | 36 ++++++++++++++++ src/api/client_server/room.rs | 18 +++++++- src/api/client_server/session.rs | 73 +++++++++++++++++++++++++++----- src/api/ruma_wrapper/axum.rs | 25 +++++++---- src/api/ruma_wrapper/mod.rs | 4 +- src/service/appservice/mod.rs | 42 +++++++++++++++++- 7 files changed, 202 insertions(+), 39 deletions(-) diff --git a/src/api/client_server/account.rs b/src/api/client_server/account.rs index 9b6bb5f8..0226abc7 100644 --- a/src/api/client_server/account.rs +++ b/src/api/client_server/account.rs @@ -75,20 +75,13 @@ pub async fn get_register_available_route( /// - Creates a new account and populates it with default account data /// - If `inhibit_login` is false: Creates a device and returns device id and access_token pub async fn register_route(body: Ruma) -> Result { - if !services().globals.allow_registration() && !body.from_appservice { + if !services().globals.allow_registration() && body.appservice_info.is_none() { return Err(Error::BadRequest( ErrorKind::Forbidden, "Registration has been disabled.", )); } - if body.body.login_type == Some(LoginType::ApplicationService) && !body.from_appservice { - return Err(Error::BadRequest( - ErrorKind::MissingToken, - "Missing appservice token.", - )); - } - let is_guest = body.kind == RegistrationKind::Guest; let user_id = match (&body.username, is_guest) { @@ -126,10 +119,30 @@ pub async fn register_route(body: Ruma) -> Result) -> Result) -> Result) -> Result) -> Result { if services() diff --git a/src/api/client_server/session.rs b/src/api/client_server/session.rs index 54069c03..3e583fac 100644 --- a/src/api/client_server/session.rs +++ b/src/api/client_server/session.rs @@ -67,6 +67,13 @@ pub async fn login_route(body: Ruma) -> Result) -> Result) -> Result { - if !body.from_appservice { - return Err(Error::BadRequest( - ErrorKind::MissingToken, - "Missing appservice token.", - )); - }; - if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { + let user_id = if let Some(UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { UserId::parse_with_server_name( user_id.to_lowercase(), services().globals.server_name(), @@ -133,7 +145,23 @@ pub async fn login_route(body: Ruma) -> Result { warn!("Unsupported or unknown login type: {:?}", &body.login_info); @@ -199,6 +227,15 @@ pub async fn logout_route(body: Ruma) -> Result Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + if let Some(ref info) = body.appservice_info { + if !info.is_user_match(sender_user) { + return Err(Error::BadRequest( + ErrorKind::Exclusive, + "User is not in namespace.", + )); + } + } else { + return Err(Error::BadRequest( + ErrorKind::MissingToken, + "Missing appservice token.", + )); + } + for device_id in services().users.all_device_ids(sender_user).flatten() { services().users.remove_device(sender_user, &device_id)?; } diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index af2dbeb6..649c1f54 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -99,7 +99,7 @@ where let mut json_body = serde_json::from_slice::(&body).ok(); - let (sender_user, sender_device, sender_servername, from_appservice) = + let (sender_user, sender_device, sender_servername, appservice_info) = match (metadata.authentication, token) { (_, Token::Invalid) => { return Err(Error::BadRequest( @@ -122,6 +122,14 @@ where .map_err(|_| { Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.") })?; + + if !info.is_user_match(&user_id) { + return Err(Error::BadRequest( + ErrorKind::Exclusive, + "User is not in namespace.", + )); + } + if !services().users.exists(&user_id)? { return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -129,15 +137,14 @@ where )); } - // TODO: Check if appservice is allowed to be that user - (Some(user_id), None, None, true) + (Some(user_id), None, None, Some(*info)) } ( AuthScheme::None | AuthScheme::AppserviceToken | AuthScheme::AccessTokenOptional, - Token::Appservice(_), - ) => (None, None, None, true), + Token::Appservice(info), + ) => (None, None, None, Some(*info)), (AuthScheme::AccessToken, Token::None) => { return Err(Error::BadRequest( ErrorKind::MissingToken, @@ -147,7 +154,7 @@ where ( AuthScheme::AccessToken | AuthScheme::AccessTokenOptional | AuthScheme::None, Token::User((user_id, device_id)), - ) => (Some(user_id), Some(device_id), None, false), + ) => (Some(user_id), Some(device_id), None, None), (AuthScheme::ServerSignatures, Token::None) => { let TypedHeader(Authorization(x_matrix)) = parts .extract::>>() @@ -228,7 +235,7 @@ where BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]); match ruma::signatures::verify_json(&pub_key_map, &request_map) { - Ok(()) => (None, None, Some(x_matrix.origin), false), + Ok(()) => (None, None, Some(x_matrix.origin), None), Err(e) => { warn!( "Failed to verify json request from {}: {}\n{:?}", @@ -255,7 +262,7 @@ where | AuthScheme::AppserviceToken | AuthScheme::AccessTokenOptional, Token::None, - ) => (None, None, None, false), + ) => (None, None, None, None), (AuthScheme::ServerSignatures, Token::Appservice(_) | Token::User(_)) => { return Err(Error::BadRequest( ErrorKind::Unauthorized, @@ -318,7 +325,7 @@ where sender_user, sender_device, sender_servername, - from_appservice, + appservice_info, json_body, }) } diff --git a/src/api/ruma_wrapper/mod.rs b/src/api/ruma_wrapper/mod.rs index ac4c825a..862da1dc 100644 --- a/src/api/ruma_wrapper/mod.rs +++ b/src/api/ruma_wrapper/mod.rs @@ -1,4 +1,4 @@ -use crate::Error; +use crate::{service::appservice::RegistrationInfo, Error}; use ruma::{ api::client::uiaa::UiaaResponse, CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, @@ -16,7 +16,7 @@ pub struct Ruma { pub sender_servername: Option, // This is None when body is not a valid string pub json_body: Option, - pub from_appservice: bool, + pub appservice_info: Option, } impl Deref for Ruma { diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index 7d2d46bd..9db6609e 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -6,7 +6,10 @@ pub use data::Data; use futures_util::Future; use regex::RegexSet; -use ruma::api::appservice::{Namespace, Registration}; +use ruma::{ + api::appservice::{Namespace, Registration}, + RoomAliasId, RoomId, UserId, +}; use tokio::sync::RwLock; use crate::{services, Result}; @@ -83,6 +86,18 @@ pub struct RegistrationInfo { pub rooms: NamespaceRegex, } +impl RegistrationInfo { + pub fn is_user_match(&self, user_id: &UserId) -> bool { + self.users.is_match(user_id.as_str()) + || self.registration.sender_localpart == user_id.localpart() + } + + pub fn is_exclusive_user_match(&self, user_id: &UserId) -> bool { + self.users.is_exclusive_match(user_id.as_str()) + || self.registration.sender_localpart == user_id.localpart() + } +} + impl TryFrom for RegistrationInfo { fn try_from(value: Registration) -> Result { Ok(RegistrationInfo { @@ -122,6 +137,7 @@ impl Service { } /// Registers an appservice and returns the ID to the caller. pub async fn register_appservice(&self, yaml: Registration) -> Result { + //TODO: Check for collisions between exclusive appservice namespaces services() .appservice .registration_info @@ -175,6 +191,30 @@ impl Service { .cloned() } + // Checks if a given user id matches any exclusive appservice regex + pub async fn is_exclusive_user_id(&self, user_id: &UserId) -> bool { + self.read() + .await + .values() + .any(|info| info.is_exclusive_user_match(user_id)) + } + + // Checks if a given room alias matches any exclusive appservice regex + pub async fn is_exclusive_alias(&self, alias: &RoomAliasId) -> bool { + self.read() + .await + .values() + .any(|info| info.aliases.is_exclusive_match(alias.as_str())) + } + + // Checks if a given room id matches any exclusive appservice regex + pub async fn is_exclusive_room_id(&self, room_id: &RoomId) -> bool { + self.read() + .await + .values() + .any(|info| info.rooms.is_exclusive_match(room_id.as_str())) + } + pub fn read( &self, ) -> impl Future>> From 74db555336ca42684f985e6adf8fd30bea86453d Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 3 Apr 2024 23:27:02 +0100 Subject: [PATCH 174/175] fix(membership): perform stricter checks when choosing an authorized user --- src/api/client_server/membership.rs | 87 ++++++++++------------------- 1 file changed, 30 insertions(+), 57 deletions(-) diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index 60e03e4e..6fe1e0ea 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -15,7 +15,6 @@ use ruma::{ room::{ join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent}, member::{MembershipState, RoomMemberEventContent}, - power_levels::RoomPowerLevelsEventContent, }, StateEventType, TimelineEventType, }, @@ -858,11 +857,6 @@ async fn join_room_by_id_helper( &StateEventType::RoomJoinRules, "", )?; - let power_levels_event = services().rooms.state_accessor.room_state_get( - room_id, - &StateEventType::RoomPowerLevels, - "", - )?; let join_rules_event_content: Option = join_rules_event .as_ref() @@ -873,15 +867,6 @@ async fn join_room_by_id_helper( }) }) .transpose()?; - let power_levels_event_content: Option = power_levels_event - .as_ref() - .map(|power_levels_event| { - serde_json::from_str(power_levels_event.content.get()).map_err(|e| { - warn!("Invalid power levels event: {}", e); - Error::bad_database("Invalid power levels event in db.") - }) - }) - .transpose()?; let restriction_rooms = match join_rules_event_content { Some(RoomJoinRulesEventContent { @@ -900,47 +885,37 @@ async fn join_room_by_id_helper( _ => Vec::new(), }; - let authorized_user = restriction_rooms - .iter() - .find_map(|restriction_room_id| { - if !services() - .rooms - .state_cache - .is_joined(sender_user, restriction_room_id) - .ok()? + let authorized_user = if restriction_rooms.iter().any(|restriction_room_id| { + services() + .rooms + .state_cache + .is_joined(sender_user, restriction_room_id) + .unwrap_or(false) + }) { + let mut auth_user = None; + for user in services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(Result::ok) + .collect::>() + { + if user.server_name() == services().globals.server_name() + && services() + .rooms + .state_accessor + .user_can_invite(room_id, &user, sender_user, &state_lock) + .await + .unwrap_or(false) { - return None; + auth_user = Some(user); + break; } - let authorized_user = power_levels_event_content - .as_ref() - .and_then(|c| { - c.users - .iter() - .filter(|(uid, i)| { - uid.server_name() == services().globals.server_name() - && **i > ruma::int!(0) - && services() - .rooms - .state_cache - .is_joined(uid, restriction_room_id) - .unwrap_or(false) - }) - .max_by_key(|(_, i)| *i) - .map(|(u, _)| u.to_owned()) - }) - .or_else(|| { - // TODO: Check here if user is actually allowed to invite. Currently the auth - // check will just fail in this case. - services() - .rooms - .state_cache - .room_members(restriction_room_id) - .filter_map(|r| r.ok()) - .find(|uid| uid.server_name() == services().globals.server_name()) - }); - Some(authorized_user) - }) - .flatten(); + } + auth_user + } else { + None + }; let event = RoomMemberEventContent { membership: MembershipState::Join, @@ -978,9 +953,7 @@ async fn join_room_by_id_helper( if !restriction_rooms.is_empty() && servers .iter() - .filter(|s| *s != services().globals.server_name()) - .count() - > 0 + .any(|s| *s != services().globals.server_name()) { info!( "We couldn't do the join locally, maybe federation can help to satisfy the restricted join requirements" From a854a46c24e23c6f56ed18a27e0fd6ec337bc053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Wed, 24 Apr 2024 23:21:36 +0200 Subject: [PATCH 175/175] Bump version to v0.7.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e870c06..0063a3e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -377,7 +377,7 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "conduit" -version = "0.7.0-alpha" +version = "0.7.0" dependencies = [ "async-trait", "axum", diff --git a/Cargo.toml b/Cargo.toml index cc5b37eb..4dfc04f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ authors = ["timokoesters "] homepage = "https://conduit.rs" repository = "https://gitlab.com/famedly/conduit" readme = "README.md" -version = "0.7.0-alpha" +version = "0.7.0" edition = "2021" # See also `rust-toolchain.toml`