diff --git a/Cargo.lock b/Cargo.lock
index d7538e06..e157565e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -187,6 +187,7 @@ dependencies = [
"log",
"opentelemetry",
"opentelemetry-jaeger",
+ "pretty_env_logger",
"rand",
"regex",
"reqwest",
@@ -383,6 +384,19 @@ dependencies = [
"syn",
]
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
[[package]]
name = "figment"
version = "0.10.3"
@@ -664,6 +678,15 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error",
+]
+
[[package]]
name = "hyper"
version = "0.14.4"
@@ -688,6 +711,21 @@ dependencies = [
"want",
]
+[[package]]
+name = "hyper-rustls"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
+dependencies = [
+ "futures-util",
+ "hyper",
+ "log",
+ "rustls",
+ "tokio",
+ "tokio-rustls",
+ "webpki",
+]
+
[[package]]
name = "hyper-tls"
version = "0.5.0"
@@ -1259,6 +1297,16 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+[[package]]
+name = "pretty_env_logger"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
+dependencies = [
+ "env_logger",
+ "log",
+]
+
[[package]]
name = "proc-macro-crate"
version = "0.1.5"
@@ -1454,6 +1502,7 @@ dependencies = [
"http",
"http-body",
"hyper",
+ "hyper-rustls",
"hyper-tls",
"ipnet",
"js-sys",
@@ -1463,14 +1512,17 @@ dependencies = [
"native-tls",
"percent-encoding",
"pin-project-lite",
+ "rustls",
"serde",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
+ "tokio-rustls",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
+ "webpki-roots",
"winreg 0.7.0",
]
@@ -1570,7 +1622,6 @@ dependencies = [
[[package]]
name = "ruma"
version = "0.0.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"assign",
"js_int",
@@ -1590,7 +1641,6 @@ dependencies = [
[[package]]
name = "ruma-api"
version = "0.17.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"http",
"percent-encoding",
@@ -1605,7 +1655,6 @@ dependencies = [
[[package]]
name = "ruma-api-macros"
version = "0.17.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"proc-macro-crate",
"proc-macro2",
@@ -1616,7 +1665,6 @@ dependencies = [
[[package]]
name = "ruma-appservice-api"
version = "0.2.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"ruma-api",
"ruma-common",
@@ -1630,7 +1678,6 @@ dependencies = [
[[package]]
name = "ruma-client-api"
version = "0.10.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"assign",
"http",
@@ -1649,7 +1696,6 @@ dependencies = [
[[package]]
name = "ruma-common"
version = "0.3.0-alpha.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"js_int",
"maplit",
@@ -1662,7 +1708,6 @@ dependencies = [
[[package]]
name = "ruma-events"
version = "0.22.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"js_int",
"ruma-common",
@@ -1676,7 +1721,6 @@ dependencies = [
[[package]]
name = "ruma-events-macros"
version = "0.22.0-alpha.2"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"proc-macro-crate",
"proc-macro2",
@@ -1687,7 +1731,6 @@ dependencies = [
[[package]]
name = "ruma-federation-api"
version = "0.1.0-alpha.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"js_int",
"ruma-api",
@@ -1702,7 +1745,6 @@ dependencies = [
[[package]]
name = "ruma-identifiers"
version = "0.18.0-alpha.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"paste",
"rand",
@@ -1716,7 +1758,6 @@ dependencies = [
[[package]]
name = "ruma-identifiers-macros"
version = "0.18.0-alpha.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"proc-macro2",
"quote",
@@ -1727,12 +1768,10 @@ dependencies = [
[[package]]
name = "ruma-identifiers-validation"
version = "0.2.0"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
[[package]]
name = "ruma-identity-service-api"
version = "0.0.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"ruma-api",
"ruma-common",
@@ -1745,7 +1784,6 @@ dependencies = [
[[package]]
name = "ruma-push-gateway-api"
version = "0.0.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"js_int",
"ruma-api",
@@ -1760,7 +1798,6 @@ dependencies = [
[[package]]
name = "ruma-serde"
version = "0.3.0"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"form_urlencoded",
"itoa",
@@ -1773,7 +1810,6 @@ dependencies = [
[[package]]
name = "ruma-serde-macros"
version = "0.3.0"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"proc-macro-crate",
"proc-macro2",
@@ -1784,7 +1820,6 @@ dependencies = [
[[package]]
name = "ruma-signatures"
version = "0.6.0-alpha.1"
-source = "git+https://github.com/ruma/ruma?rev=0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc#0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc"
dependencies = [
"base64 0.13.0",
"ring",
@@ -2051,7 +2086,6 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
[[package]]
name = "state-res"
version = "0.1.0"
-source = "git+https://github.com/ruma/state-res?branch=main#d34a78c5b66de419862d9e592bde8e0007111ebd"
dependencies = [
"itertools",
"log",
@@ -2136,6 +2170,15 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "thiserror"
version = "1.0.24"
@@ -2656,6 +2699,15 @@ dependencies = [
"untrusted",
]
+[[package]]
+name = "webpki-roots"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82015b7e0b8bad8185994674a13a93306bea76cf5a16c5a181382fd3a5ec2376"
+dependencies = [
+ "webpki",
+]
+
[[package]]
name = "weezl"
version = "0.1.4"
@@ -2684,6 +2736,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
diff --git a/Cargo.toml b/Cargo.toml
index 2293b62d..9c087769 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,16 +18,16 @@ rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "93e62c86e
#rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", default-features = false, features = ["tls"] }
# Used for matrix spec type definitions and helpers
-ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "appservice-api", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks", "unstable-exhaustive-types"], rev = "0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc" }
+#ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "appservice-api", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks", "unstable-exhaustive-types"], rev = "0a10afe6dacc2b7a50a8002c953d10b7fb4e37bc" }
# ruma = { git = "https://github.com/DevinR528/ruma", features = ["rand", "client-api", "federation-api", "unstable-exhaustive-types", "unstable-pre-spec", "unstable-synapse-quirks"], branch = "verified-export" }
-# ruma = { path = "../ruma/ruma", features = ["unstable-exhaustive-types", "rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
+ruma = { path = "../ruma/ruma", features = ["unstable-exhaustive-types", "rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] }
# Used when doing state resolution
# state-res = { git = "https://github.com/timokoesters/state-res", branch = "timo-spec-comp", features = ["unstable-pre-spec"] }
# TODO: remove the gen-eventid feature
-state-res = { git = "https://github.com/ruma/state-res", branch = "main", features = ["unstable-pre-spec", "gen-eventid"] }
+#state-res = { git = "https://github.com/ruma/state-res", branch = "main", features = ["unstable-pre-spec", "gen-eventid"] }
# state-res = { git = "https://github.com/ruma/state-res", rev = "791c66d73cf064d09db0cdf767d5fef43a343425", features = ["unstable-pre-spec", "gen-eventid"] }
-# state-res = { path = "../../state-res", features = ["unstable-pre-spec", "gen-eventid"] }
+state-res = { path = "../state-res", features = ["unstable-pre-spec", "gen-eventid"] }
# Used for long polling and federation sender, should be the same as rocket::tokio
tokio = "1.2.0"
@@ -50,7 +50,7 @@ rand = "0.8.3"
# Used to hash passwords
rust-argon2 = "0.8.3"
# Used to send requests
-reqwest = "0.11.1"
+reqwest = { version = "0.11.1", features = ["rustls-tls"] }
# Used for conduit::Error type
thiserror = "1.0.24"
# Used to generate thumbnails for images
@@ -71,6 +71,7 @@ opentelemetry = "0.12.0"
tracing-subscriber = "0.2.16"
tracing-opentelemetry = "0.11.0"
opentelemetry-jaeger = "0.11.0"
+pretty_env_logger = "0.4.0"
[features]
default = ["conduit_bin"]
diff --git a/src/client_server/account.rs b/src/client_server/account.rs
index 7d3067e5..1c6f5178 100644
--- a/src/client_server/account.rs
+++ b/src/client_server/account.rs
@@ -455,16 +455,9 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMessage,
- content: serde_json::to_value(message::MessageEventContent::Text(
- message::TextMessageEventContent {
- body: "Thanks for trying out Conduit! This software is still in development, so expect many bugs and missing features. If you have federation enabled, you can join the Conduit chat room by typing `/join #conduit:matrix.org`. **Important: Please don't join any other Matrix rooms over federation without permission from the room's admins.** Some actions might trigger bugs in other server implementations, breaking the chat for everyone else.".to_owned(),
- formatted: Some(message::FormattedBody {
- format: message::MessageFormat::Html,
- body: "Thanks for trying out Conduit! This software is still in development, so expect many bugs and missing features. If you have federation enabled, you can join the Conduit chat room by typing /join #conduit:matrix.org
. Important: Please don't join any other Matrix rooms over federation without permission from the room's admins. Some actions might trigger bugs in other server implementations, breaking the chat for everyone else.".to_owned(),
- }),
- relates_to: None,
- new_content: None,
- },
+ content: serde_json::to_value(message::MessageEventContent::text_html(
+ "Thanks for trying out Conduit! This software is still in development, so expect many bugs and missing features. If you have federation enabled, you can join the Conduit chat room by typing `/join #conduit:matrix.org`. **Important: Please don't join any other Matrix rooms over federation without permission from the room's admins.** Some actions might trigger bugs in other server implementations, breaking the chat for everyone else.".to_owned(),
+ "Thanks for trying out Conduit! This software is still in development, so expect many bugs and missing features. If you have federation enabled, you can join the Conduit chat room by typing /join #conduit:matrix.org
. Important: Please don't join any other Matrix rooms over federation without permission from the room's admins. Some actions might trigger bugs in other server implementations, breaking the chat for everyone else.".to_owned(),
))
.expect("event is valid, we just created it"),
unsigned: None,
diff --git a/src/client_server/capabilities.rs b/src/client_server/capabilities.rs
index b4fdf690..a3c0db62 100644
--- a/src/client_server/capabilities.rs
+++ b/src/client_server/capabilities.rs
@@ -1,5 +1,10 @@
use crate::ConduitResult;
-use ruma::{api::client::r0::capabilities::get_capabilities, RoomVersionId};
+use ruma::{
+ api::client::r0::capabilities::{
+ get_capabilities, Capabilities, RoomVersionStability, RoomVersionsCapability,
+ },
+ RoomVersionId,
+};
use std::collections::BTreeMap;
#[cfg(feature = "conduit_bin")]
@@ -12,24 +17,14 @@ use rocket::get;
#[tracing::instrument]
pub async fn get_capabilities_route() -> ConduitResult {
let mut available = BTreeMap::new();
- available.insert(
- RoomVersionId::Version5,
- get_capabilities::RoomVersionStability::Stable,
- );
- available.insert(
- RoomVersionId::Version6,
- get_capabilities::RoomVersionStability::Stable,
- );
+ available.insert(RoomVersionId::Version5, RoomVersionStability::Stable);
+ available.insert(RoomVersionId::Version6, RoomVersionStability::Stable);
- Ok(get_capabilities::Response {
- capabilities: get_capabilities::Capabilities {
- change_password: get_capabilities::ChangePasswordCapability::default(), // enabled by default
- room_versions: get_capabilities::RoomVersionsCapability {
- default: RoomVersionId::Version6,
- available,
- },
- custom_capabilities: BTreeMap::new(),
- },
- }
- .into())
+ let mut capabilities = Capabilities::new();
+ capabilities.room_versions = RoomVersionsCapability {
+ default: RoomVersionId::Version6,
+ available,
+ };
+
+ Ok(get_capabilities::Response { capabilities }.into())
}
diff --git a/src/client_server/config.rs b/src/client_server/config.rs
index aece96e2..a53b7cd4 100644
--- a/src/client_server/config.rs
+++ b/src/client_server/config.rs
@@ -23,7 +23,7 @@ pub async fn set_global_account_data_route(
) -> ConduitResult {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
- let content = serde_json::from_str::(body.data.get())
+ let data = serde_json::from_str(body.data.get())
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Data is invalid."))?;
let event_type = body.event_type.to_string();
@@ -33,10 +33,7 @@ pub async fn set_global_account_data_route(
sender_user,
event_type.clone().into(),
&BasicEvent {
- content: CustomEventContent {
- event_type,
- json: content,
- },
+ content: CustomEventContent { event_type, data },
},
&db.globals,
)?;
diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs
index b7b2d4b0..d63fa029 100644
--- a/src/client_server/membership.rs
+++ b/src/client_server/membership.rs
@@ -4,7 +4,7 @@ use crate::{
pdu::{PduBuilder, PduEvent},
utils, ConduitResult, Database, Error, Result, Ruma,
};
-use log::warn;
+use log::{info, warn};
use ruma::{
api::{
client::{
@@ -21,11 +21,9 @@ use ruma::{
serde::{to_canonical_value, CanonicalJsonObject, Raw},
EventId, RoomId, RoomVersionId, ServerName, UserId,
};
-// use state_res::Event;
use std::{
- collections::{BTreeMap, HashSet},
+ collections::{BTreeMap, HashMap},
convert::TryFrom,
- iter,
sync::Arc,
};
@@ -439,6 +437,7 @@ pub async fn joined_members_route(
Ok(joined_members::Response { joined }.into())
}
+#[tracing::instrument(skip(db))]
async fn join_room_by_id_helper(
db: &Database,
sender_user: Option<&UserId>,
@@ -566,23 +565,22 @@ async fn join_room_by_id_helper(
Ok((event_id, value))
};
- let room_state = send_join_response.room_state.state.iter().map(add_event_id);
+ let count = db.globals.next_count()?;
- let _state_events = room_state
- .clone()
- .map(|pdu: Result<(EventId, CanonicalJsonObject)>| Ok(pdu?.0))
- .chain(iter::once(Ok(event_id.clone()))) // Add join event we just created
- .collect::>>()?;
+ let mut pdu_id = room_id.as_bytes().to_vec();
+ pdu_id.push(0xff);
+ pdu_id.extend_from_slice(&count.to_be_bytes());
- let auth_chain = send_join_response
+ let pdu = PduEvent::from_id_val(&event_id, join_event.clone())
+ .map_err(|_| Error::BadServerResponse("Invalid PDU in send_join response."))?;
+
+ let mut state = HashMap::new();
+
+ for pdu in send_join_response
.room_state
- .auth_chain
+ .state
.iter()
- .map(add_event_id);
-
- let mut event_map = room_state
- .chain(auth_chain)
- .chain(iter::once(Ok((event_id, join_event)))) // Add join event we just created
+ .map(add_event_id)
.map(|r| {
let (event_id, value) = r?;
PduEvent::from_id_val(&event_id, value.clone())
@@ -592,97 +590,78 @@ async fn join_room_by_id_helper(
Error::BadServerResponse("Invalid PDU in send_join response.")
})
})
- .collect::>>>()?;
-
- let control_events = event_map
- .values()
- .filter(|pdu| state_res::is_power_event(pdu))
- .map(|pdu| pdu.event_id.clone())
- .collect::>();
-
- // These events are not guaranteed to be sorted but they are resolved according to spec
- // we auth them anyways to weed out faulty/malicious server. The following is basically the
- // full state resolution algorithm.
- let event_ids = event_map.keys().cloned().collect::>();
-
- let sorted_control_events = state_res::StateResolution::reverse_topological_power_sort(
- &room_id,
- &control_events,
- &mut event_map,
- &event_ids,
- );
-
- // Auth check each event against the "partial" state created by the preceding events
- let resolved_control_events = state_res::StateResolution::iterative_auth_check(
- room_id,
- &RoomVersionId::Version6,
- &sorted_control_events,
- &BTreeMap::new(), // We have no "clean/resolved" events to add (these extend the `resolved_control_events`)
- &mut event_map,
- )
- .expect("iterative auth check failed on resolved events");
-
- // This removes the control events that failed auth, leaving the resolved
- // to be mainline sorted. In the actual `state_res::StateResolution::resolve`
- // function both are removed since these are all events we don't know of
- // we must keep track of everything to add to our DB.
- let events_to_sort = event_map
- .keys()
- .filter(|id| {
- !sorted_control_events.contains(id)
- || resolved_control_events.values().any(|rid| *id == rid)
- })
- .cloned()
- .collect::>();
-
- let power_level =
- resolved_control_events.get(&(EventType::RoomPowerLevels, Some("".to_string())));
- // Sort the remaining non control events
- let sorted_event_ids = state_res::StateResolution::mainline_sort(
- room_id,
- &events_to_sort,
- power_level,
- &mut event_map,
- );
-
- let resolved_events = state_res::StateResolution::iterative_auth_check(
- room_id,
- &RoomVersionId::Version6,
- &sorted_event_ids,
- &resolved_control_events,
- &mut event_map,
- )
- .expect("iterative auth check failed on resolved events");
-
- // filter the events that failed the auth check keeping the remaining events
- // sorted correctly
- for ev_id in sorted_event_ids
- .iter()
- .filter(|id| resolved_events.values().any(|rid| rid == *id))
{
- let pdu = event_map
- .get(ev_id)
- .expect("Found event_id in sorted events that is not in resolved state");
+ let (id, pdu) = pdu?;
+ info!("adding {} to outliers: {:#?}", id, pdu);
+ db.rooms.add_pdu_outlier(&pdu)?;
+ if let Some(state_key) = &pdu.state_key {
+ if pdu.kind == EventType::RoomMember {
+ let target_user_id = UserId::try_from(state_key.clone()).map_err(|_| {
+ Error::BadServerResponse("Invalid user id in send_join response.")
+ })?;
- // We do not rebuild the PDU in this case only insert to DB
- let count = db.globals.next_count()?;
- let mut pdu_id = room_id.as_bytes().to_vec();
- pdu_id.push(0xff);
- pdu_id.extend_from_slice(&count.to_be_bytes());
-
- let hash = db.rooms.append_to_state(&pdu_id, &pdu, &db.globals)?;
-
- db.rooms.append_pdu(
- &pdu,
- utils::to_canonical_object(&**pdu).expect("Pdu is valid canonical object"),
- count,
- pdu_id.clone().into(),
- &[pdu.event_id.clone()],
- &db,
- )?;
-
- db.rooms.set_room_state(room_id, &hash)?;
+ // Update our membership info, we do this here incase a user is invited
+ // and immediately leaves we need the DB to record the invite event for auth
+ db.rooms.update_membership(
+ &pdu.room_id,
+ &target_user_id,
+ serde_json::from_value::(pdu.content.clone())
+ .map_err(|_| {
+ Error::BadRequest(
+ ErrorKind::InvalidParam,
+ "Invalid member event content.",
+ )
+ })?,
+ &pdu.sender,
+ &db.account_data,
+ &db.globals,
+ )?;
+ }
+ let mut long_id = room_id.as_bytes().to_vec();
+ long_id.push(0xff);
+ long_id.extend_from_slice(id.as_bytes());
+ state.insert((pdu.kind.clone(), state_key.clone()), long_id);
+ }
}
+
+ state.insert(
+ (
+ pdu.kind.clone(),
+ pdu.state_key.clone().expect("join event has state key"),
+ ),
+ pdu_id.clone(),
+ );
+
+ db.rooms.force_state(room_id, state, &db.globals)?;
+
+ for pdu in send_join_response
+ .room_state
+ .auth_chain
+ .iter()
+ .map(add_event_id)
+ .map(|r| {
+ let (event_id, value) = r?;
+ PduEvent::from_id_val(&event_id, value.clone())
+ .map(|ev| (event_id, Arc::new(ev)))
+ .map_err(|e| {
+ warn!("{:?}: {}", value, e);
+ Error::BadServerResponse("Invalid PDU in send_join response.")
+ })
+ })
+ {
+ let (id, pdu) = pdu?;
+ info!("adding {} to outliers: {:#?}", id, pdu);
+ db.rooms.add_pdu_outlier(&pdu)?;
+ }
+
+ db.rooms.append_pdu(
+ &pdu,
+ utils::to_canonical_object(&pdu).expect("Pdu is valid canonical object"),
+ db.globals.next_count()?,
+ pdu_id.into(),
+ &[pdu.event_id.clone()],
+ db,
+ )?;
} else {
let event = member::MemberEventContent {
membership: member::MembershipState::Join,
diff --git a/src/client_server/sync.rs b/src/client_server/sync.rs
index fac6b155..f01eb390 100644
--- a/src/client_server/sync.rs
+++ b/src/client_server/sync.rs
@@ -102,9 +102,14 @@ pub async fn sync_events_route(
// since and the current room state, meaning there should be no updates.
// The inner Option is None when there is an event, but there is no state hash associated
// with it. This can happen for the RoomCreate event, so all updates should arrive.
- let first_pdu_after_since = db.rooms.pdus_after(sender_user, &room_id, since).next();
+ let first_pdu_before_since = db.rooms.pdus_until(sender_user, &room_id, since).next();
+ let pdus_after_since = db
+ .rooms
+ .pdus_after(sender_user, &room_id, since)
+ .next()
+ .is_some();
- let since_state_hash = first_pdu_after_since
+ let since_state_hash = first_pdu_before_since
.as_ref()
.map(|pdu| db.rooms.pdu_state_hash(&pdu.as_ref().ok()?.0).ok()?);
@@ -114,7 +119,7 @@ pub async fn sync_events_route(
invited_member_count,
joined_since_last_sync,
state_events,
- ) = if since_state_hash != None && Some(¤t_state_hash) != since_state_hash.as_ref() {
+ ) = if pdus_after_since && Some(¤t_state_hash) != since_state_hash.as_ref() {
let current_state = db.rooms.room_state_full(&room_id)?;
let current_members = current_state
.iter()
@@ -138,9 +143,9 @@ pub async fn sync_events_route(
// Calculations:
let new_encrypted_room =
- encrypted_room && since_encryption.map_or(false, |encryption| encryption.is_none());
+ encrypted_room && since_encryption.map_or(true, |encryption| encryption.is_none());
- let send_member_count = since_state.as_ref().map_or(false, |since_state| {
+ let send_member_count = since_state.as_ref().map_or(true, |since_state| {
since_state.as_ref().map_or(true, |since_state| {
current_members.len()
!= since_state
@@ -179,7 +184,7 @@ pub async fn sync_events_route(
let since_membership =
since_state
.as_ref()
- .map_or(MembershipState::Join, |since_state| {
+ .map_or(MembershipState::Leave, |since_state| {
since_state
.as_ref()
.and_then(|since_state| {
@@ -221,7 +226,7 @@ pub async fn sync_events_route(
}
}
- let joined_since_last_sync = since_sender_member.map_or(false, |member| {
+ let joined_since_last_sync = since_sender_member.map_or(true, |member| {
member.map_or(true, |member| member.membership != MembershipState::Join)
});
@@ -310,7 +315,7 @@ pub async fn sync_events_route(
(None, None, Vec::new())
};
- let state_events = if joined_since_last_sync {
+ let state_events = if dbg!(joined_since_last_sync) {
current_state
.into_iter()
.map(|(_, pdu)| pdu.to_sync_state_event())
diff --git a/src/database.rs b/src/database.rs
index bf3e0f0c..0f5e4b41 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -165,9 +165,8 @@ impl Database {
stateid_pduid: db.open_tree("stateid_pduid")?,
pduid_statehash: db.open_tree("pduid_statehash")?,
roomid_statehash: db.open_tree("roomid_statehash")?,
- roomeventid_outlierpdu: db.open_tree("roomeventid_outlierpdu")?,
+ eventid_outlierpdu: db.open_tree("roomeventid_outlierpdu")?,
prevevent_parent: db.open_tree("prevevent_parent")?,
- roomeventid_outlierpducount: db.open_tree("roomeventid_outlierpducount")?,
},
account_data: account_data::AccountData {
roomuserdataid_accountdata: db.open_tree("roomuserdataid_accountdata")?,
diff --git a/src/database/globals.rs b/src/database/globals.rs
index 8c0463d1..dd594c58 100644
--- a/src/database/globals.rs
+++ b/src/database/globals.rs
@@ -24,7 +24,7 @@ pub struct Globals {
reqwest_client: reqwest::Client,
dns_resolver: TokioAsyncResolver,
jwt_decoding_key: Option>,
- pub(super) servertimeout_signingkey: sled::Tree, // ServerName -> algorithm:key + pubkey
+ pub(super) servertimeout_signingkey: sled::Tree, // ServerName + Timeout Timestamp -> algorithm:key + pubkey
}
impl Globals {
@@ -157,37 +157,31 @@ impl Globals {
///
/// This doesn't actually check that the keys provided are newer than the old set.
pub fn add_signing_key(&self, origin: &ServerName, keys: &ServerSigningKeys) -> Result<()> {
- // Remove outdated keys
- let now = crate::utils::millis_since_unix_epoch();
- for item in self.servertimeout_signingkey.scan_prefix(origin.as_bytes()) {
- let (k, _) = item?;
- let valid_until = k
- .splitn(2, |&b| b == 0xff)
- .nth(1)
- .map(crate::utils::u64_from_bytes)
- .ok_or_else(|| Error::bad_database("Invalid signing keys."))?
- .map_err(|_| Error::bad_database("Invalid signing key valid until bytes"))?;
+ let mut key1 = origin.as_bytes().to_vec();
+ key1.push(0xff);
- if now > valid_until {
- self.servertimeout_signingkey.remove(k)?;
- }
- }
+ let mut key2 = key1.clone();
- let mut key = origin.as_bytes().to_vec();
- key.push(0xff);
- key.extend_from_slice(
- &(keys
- .valid_until_ts
- .duration_since(std::time::UNIX_EPOCH)
- .expect("time is valid")
- .as_millis() as u64)
- .to_be_bytes(),
- );
+ let ts = keys
+ .valid_until_ts
+ .duration_since(std::time::UNIX_EPOCH)
+ .expect("time is valid")
+ .as_millis() as u64;
+
+ key1.extend_from_slice(&ts.to_be_bytes());
+ key2.extend_from_slice(&(ts + 1).to_be_bytes());
self.servertimeout_signingkey.insert(
- key,
+ key1,
serde_json::to_vec(&keys.verify_keys).expect("ServerSigningKeys are a valid string"),
)?;
+
+ self.servertimeout_signingkey.insert(
+ key2,
+ serde_json::to_vec(&keys.old_verify_keys)
+ .expect("ServerSigningKeys are a valid string"),
+ )?;
+
Ok(())
}
@@ -196,7 +190,10 @@ impl Globals {
&self,
origin: &ServerName,
) -> Result> {
+ let mut response = BTreeMap::new();
+
let now = crate::utils::millis_since_unix_epoch();
+
for item in self.servertimeout_signingkey.scan_prefix(origin.as_bytes()) {
let (k, bytes) = item?;
let valid_until = k
@@ -207,10 +204,11 @@ impl Globals {
.map_err(|_| Error::bad_database("Invalid signing key valid until bytes"))?;
// If these keys are still valid use em!
if valid_until > now {
- return serde_json::from_slice(&bytes)
- .map_err(|_| Error::bad_database("Invalid BTreeMap<> of signing keys"));
+ let btree: BTreeMap<_, _> = serde_json::from_slice(&bytes)
+ .map_err(|_| Error::bad_database("Invalid BTreeMap<> of signing keys"))?;
+ response.extend(btree);
}
}
- Ok(BTreeMap::default())
+ Ok(response)
}
}
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index d48494b6..2a88628f 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -3,7 +3,7 @@ mod edus;
pub use edus::RoomEdus;
use crate::{pdu::PduBuilder, utils, Database, Error, PduEvent, Result};
-use log::error;
+use log::{error, info, warn};
use regex::Regex;
use ring::digest;
use ruma::{
@@ -71,10 +71,7 @@ pub struct Rooms {
/// RoomId + EventId -> outlier PDU.
/// Any pdu that has passed the steps 1-8 in the incoming event /federation/send/txn.
- pub(super) roomeventid_outlierpdu: sled::Tree,
- /// RoomId + EventId -> count of the last known pdu when the outlier was inserted.
- /// This allows us to skip any state snapshots that would for sure not have the outlier.
- pub(super) roomeventid_outlierpducount: sled::Tree,
+ pub(super) eventid_outlierpdu: sled::Tree,
/// RoomId + EventId -> Parent PDU EventId.
pub(super) prevevent_parent: sled::Tree,
@@ -89,19 +86,21 @@ impl Rooms {
room_id: &RoomId,
state_hash: &StateHashId,
) -> Result> {
- self.stateid_pduid
+ let r = self
+ .stateid_pduid
.scan_prefix(&state_hash)
.values()
- .map(|pduid_short| {
- let mut pduid = room_id.as_bytes().to_vec();
- pduid.push(0xff);
- pduid.extend_from_slice(&pduid_short?);
- match self.pduid_pdu.get(&pduid)? {
+ .map(|short_id| {
+ let short_id = short_id?;
+ let mut long_id = room_id.as_bytes().to_vec();
+ long_id.push(0xff);
+ long_id.extend_from_slice(&short_id);
+ match self.pduid_pdu.get(&long_id)? {
Some(b) => serde_json::from_slice::(&b)
.map_err(|_| Error::bad_database("Invalid PDU in db.")),
None => self
- .roomeventid_outlierpdu
- .get(pduid)?
+ .eventid_outlierpdu
+ .get(short_id)?
.map(|b| {
serde_json::from_slice::(&b)
.map_err(|_| Error::bad_database("Invalid PDU in db."))
@@ -124,7 +123,9 @@ impl Rooms {
pdu,
))
})
- .collect()
+ .collect();
+
+ r
}
/// Returns a single PDU from `room_id` with key (`event_type`, `state_key`).
@@ -140,6 +141,8 @@ impl Rooms {
key.push(0xff);
key.extend_from_slice(&state_key.as_bytes());
+ info!("Looking for {} {:?}", event_type, state_key);
+
let short = self.statekey_short.get(&key)?;
if let Some(short) = short {
@@ -147,32 +150,40 @@ impl Rooms {
stateid.push(0xff);
stateid.extend_from_slice(&short);
+ info!("trying to find pduid/eventid. short: {:?}", stateid);
self.stateid_pduid
.get(&stateid)?
- .map_or(Ok(None), |pdu_id_short| {
- let mut pdu_id = room_id.as_bytes().to_vec();
- pdu_id.push(0xff);
- pdu_id.extend_from_slice(&pdu_id_short);
+ .map_or(Ok(None), |short_id| {
+ info!("found in stateid_pduid");
+ let mut long_id = room_id.as_bytes().to_vec();
+ long_id.push(0xff);
+ long_id.extend_from_slice(&short_id);
- Ok::<_, Error>(Some((
- pdu_id.clone().into(),
- match self.pduid_pdu.get(&pdu_id)? {
- Some(b) => serde_json::from_slice::(&b)
+ Ok::<_, Error>(Some(match self.pduid_pdu.get(&long_id)? {
+ Some(b) => (
+ long_id.clone().into(),
+ serde_json::from_slice::(&b)
.map_err(|_| Error::bad_database("Invalid PDU in db."))?,
- None => self
- .roomeventid_outlierpdu
- .get(pdu_id)?
- .map(|b| {
- serde_json::from_slice::(&b)
- .map_err(|_| Error::bad_database("Invalid PDU in db."))
- })
- .ok_or_else(|| {
- Error::bad_database("Event is not in pdu tree or outliers.")
- })??,
- },
- )))
+ ),
+ None => {
+ info!("looking in outliers");
+ (
+ short_id.clone().into(),
+ self.eventid_outlierpdu
+ .get(&short_id)?
+ .map(|b| {
+ serde_json::from_slice::(&b)
+ .map_err(|_| Error::bad_database("Invalid PDU in db."))
+ })
+ .ok_or_else(|| {
+ Error::bad_database("Event is not in pdu tree or outliers.")
+ })??,
+ )
+ }
+ }))
})
} else {
+ info!("short id not found");
Ok(None)
}
}
@@ -215,6 +226,8 @@ impl Rooms {
.ok_or_else(|| Error::bad_database("Saved auth event with no state key."))?,
)? {
events.insert((event_type, state_key), pdu);
+ } else {
+ warn!("Could not find {} {:?} in state", event_type, state_key);
}
}
Ok(events)
@@ -253,11 +266,11 @@ impl Rooms {
globals: &super::globals::Globals,
) -> Result<()> {
let state_hash =
- self.calculate_hash(&state.values().map(|pdu_id| &**pdu_id).collect::>())?;
+ self.calculate_hash(&state.values().map(|long_id| &**long_id).collect::>())?;
let mut prefix = state_hash.to_vec();
prefix.push(0xff);
- for ((event_type, state_key), id_long) in state {
+ for ((event_type, state_key), long_id) in state {
let mut statekey = event_type.as_ref().as_bytes().to_vec();
statekey.push(0xff);
statekey.extend_from_slice(&state_key.as_bytes());
@@ -273,16 +286,13 @@ impl Rooms {
}
};
- // Because of outliers this could also be an eventID but that
- // is handled by `state_full`
- let pdu_id_short = id_long
- .splitn(2, |&b| b == 0xff)
- .nth(1)
- .ok_or_else(|| Error::bad_database("Invalid pduid in state."))?;
+ // If it's a pdu id we remove the room id, if it's an event id we leave it the same
+ let short_id = long_id.splitn(2, |&b| b == 0xff).nth(1).unwrap_or(&long_id);
let mut state_id = prefix.clone();
state_id.extend_from_slice(&short.to_be_bytes());
- self.stateid_pduid.insert(state_id, pdu_id_short)?;
+ info!("inserting {:?} into {:?}", short_id, state_id);
+ self.stateid_pduid.insert(state_id, short_id)?;
}
self.roomid_statehash
@@ -348,20 +358,19 @@ impl Rooms {
pub fn get_pdu_json(&self, event_id: &EventId) -> Result