This commit is contained in:
timedout committed 2026-11-11 14:36:24 +00:00
1 parent 302f535e66
commit 7e81918639
9 files changed
+76 -86

No files matched your search

@@ -10,7 +10,6 @@ use conduwuit::error;
use conduwuit::{
Err, Event, PduEvent, Result, debug, debug_info, debug_warn, err,
result::{FlatOk, LogErr},
state_res::lexicographical_topological_sort,
trace,
utils::{IterStream, math::Expected, stream::BroadbandExt},
warn,
@@ -23,7 +22,9 @@ use ruma::{
int,
room_version_rules::RoomVersionRules,
};
use ruma::events::room::power_levels::UserPowerLevel;
use ruma::state_res::utils::event_id_map::EventIdMap;
use conduwuit::debug::DebugInspect;
use super::get_room_version_rules;
use crate::rooms::event_handler::parse_incoming_pdu::expect_event_id_array;
@@ -64,8 +65,7 @@ pub async fn build_local_dag(
return Ok(pdu_map.keys().cloned().collect());
}
let mut dag: HashMap<OwnedEventId, HashSet<OwnedEventId>> =
HashMap::with_capacity(pdu_map.len());
let mut dag = EventIdMap::with_capacity(pdu_map.len());
let mut id_origin_ts: HashMap<OwnedEventId, _> = HashMap::with_capacity(pdu_map.len());
for (event_id, value) in pdu_map {
@@ -94,17 +94,16 @@ pub async fn build_local_dag(
}
debug!(count = dag.len(), "Sorting incoming events with partial graph");
lexicographical_topological_sort(&dag, &async |node_id| {
ruma::state_res::reverse_topological_power_sort(&dag, |node_id| {
// Note: we don't bother fetching power levels because that would
// massively slow this function down. This is a best-effort attempt to
// order events correctly for processing, however ultimately that
// should be the sender's job.
let ts = id_origin_ts.get(&node_id).copied().unwrap_or_default();
Ok((int!(0), MilliSecondsSinceUnixEpoch(ts)))
let ts = id_origin_ts.get(node_id).copied().unwrap_or_default();
Ok((UserPowerLevel::Infinite, MilliSecondsSinceUnixEpoch(ts)))
})
.await
.inspect(|sorted| {
debug_assert_eq!(
.debug_inspect(|sorted| {
assert_eq!(
sorted.len(),
pdu_map.len(),
"Sorted graph was not the same size as the input graph"
@@ -1,7 +1,7 @@
use std::collections::{HashMap, hash_map};
use conduwuit::{
Err, Event, EventTypeExt, PduEvent, Result, debug_info, err, utils::TryFutureExtExt, warn,
Err, Event, EventTypeExt, PduEvent, Result, debug_info, err, warn,
};
use ruma::{
OwnedEventId, ServerName, api::federation::authorization::get_event_authorization,
@@ -5,10 +5,8 @@
use std::{collections::BTreeMap, time::Duration};
use conduwuit::{
Err, Error, Event, PduEvent, Result, debug, debug_error, debug_info, debug_warn, err, error,
info, state_res::EventTypeExt, trace, utils::to_canonical_object, warn,
};
use conduwuit::{debug, debug_error, debug_info, debug_warn, err, error,
info, trace, utils::to_canonical_object, warn, Err, Error, Event, EventTypeExt, PduEvent, Result};
use http::StatusCode;
use ruma::{
CanonicalJsonObject, CanonicalJsonValue, KeyId, RoomId, ServerName, SigningKeyAlgorithm,
@@ -6,7 +6,6 @@ use std::{
use conduwuit::{
Error, Result, err,
state_res::{self, StateMap},
trace,
utils::stream::{IterStream, ReadyExt, TryWidebandExt, WidebandExt},
warn,
@@ -115,7 +114,7 @@ impl super::Service {
auth_chain_sets: Vec<EventIdSet<OwnedEventId>>,
) -> Result<ruma::state_res::StateMap<OwnedEventId>> {
let event_fetch = |event_id| self.event_fetch(event_id);
let calc_subgraph = |ss| self.calculate_conflicted_state_subgraph(ss);
let calc_subgraph = |ss| self.calculate_conflicted_state_subgraph(ss).ok();
ruma::state_res::resolve(
&room_version_rules.authorization,
&room_version_rules
@@ -6,13 +6,13 @@ use std::{
use conduwuit::{
Result, debug, debug_error, err, error,
matrix::{Event, StateMap},
trace,
utils::stream::{BroadbandExt, IterStream, ReadyExt, TryBroadbandExt, TryWidebandExt},
};
use futures::{FutureExt, StreamExt, TryFutureExt, TryStreamExt, future::try_join};
use ruma::{OwnedEventId, RoomId, room_version_rules::RoomVersionRules};
use ruma::{room_version_rules::RoomVersionRules, EventId, OwnedEventId, RoomId};
use ruma::state_res::{Event, StateMap};
use ruma::state_res::utils::event_id_set::EventIdSet;
use crate::rooms::short::ShortStateHash;
#[cfg(test)]
@@ -30,7 +30,7 @@ impl super::Service {
room_version_rules: &RoomVersionRules,
) -> Result<Option<HashMap<u64, OwnedEventId>>>
where
Pdu: Event + Send + Sync,
Pdu: Event<Id = EventId> + Send + Sync,
{
if incoming_pdu.prev_events().count() == 1 {
self.state_before_incoming_degree_one(incoming_pdu).await
@@ -48,7 +48,7 @@ impl super::Service {
incoming_pdu: &Pdu,
) -> Result<Option<HashMap<u64, OwnedEventId>>>
where
Pdu: Event + Send + Sync,
Pdu: Event<Id = EventId> + Send + Sync,
{
let prev_event = incoming_pdu
.prev_events()
@@ -109,8 +109,11 @@ impl super::Service {
room_version_rules: &RoomVersionRules,
) -> Result<Option<HashMap<u64, OwnedEventId>>>
where
Pdu: Event + Send + Sync,
Pdu: Event<Id = EventId> + Send + Sync,
{
if incoming_pdu.prev_events().count() == 0 {
return Ok(None);
}
trace!("Calculating extremity statehashes...");
let Ok(extremity_sstatehashes) = incoming_pdu
.prev_events()
@@ -135,8 +138,8 @@ impl super::Service {
};
trace!("Calculating fork states...");
let room_id = &incoming_pdu.room_id_or_hash();
let (fork_states, auth_chain_sets): (Vec<StateMap<_>>, Vec<HashSet<_>>) =
let room_id = incoming_pdu.room_id().unwrap();
let (fork_states, auth_chain_sets): (Vec<StateMap<_>>, Vec<EventIdSet<_>>) =
extremity_sstatehashes
.into_iter()
.try_stream()
@@ -149,9 +152,7 @@ impl super::Service {
.await?;
let Ok(new_state) = self
.state_resolution(room_version_rules, fork_states.iter(), &auth_chain_sets)
.boxed()
.await
.state_resolution(room_version_rules, fork_states.as_slice(), auth_chain_sets)
.inspect_err(|e| error!("State resolution failed: {e:?}"))
else {
return Ok(None);
@@ -182,7 +183,7 @@ impl super::Service {
prev_event: Pdu,
) -> Result<(StateMap<OwnedEventId>, HashSet<OwnedEventId>)>
where
Pdu: Event,
Pdu: Event<Id = OwnedEventId>,
{
let mut leaf_state: HashMap<_, _> = self
.services
@@ -195,7 +196,7 @@ impl super::Service {
let shortstatekey = self
.services
.short
.get_or_create_shortstatekey(&prev_event.kind().to_string().into(), state_key)
.get_or_create_shortstatekey(&prev_event.event_type().to_string().into(), state_key)
.await;
let event_id = prev_event.event_id();
@@ -216,11 +217,10 @@ impl super::Service {
self.services
.short
.get_statekey_from_short(*k)
.map_ok(|(ty, sk)| ((ty, sk), id.clone()))
.map_ok(|(ty, sk)| ((ty, sk.to_string()), id.clone()))
})
.ready_filter_map(Result::ok)
.collect()
.map(Ok);
.collect();
try_join(fork_state, auth_chain).await
}
+30 -17
View File
@@ -7,7 +7,7 @@ use conduwuit::{
event::{gen_event_id, gen_event_id_canonical_json},
},
pdu::PartialPdu,
state_res, trace,
trace,
utils::{self, IterStream, ReadyExt, to_canonical_object},
warn,
};
@@ -25,7 +25,7 @@ use ruma::{
StateEventType, StaticEventContent,
room::member::{MembershipState, RoomMemberEventContent},
},
room::{AllowRule, JoinRule, Restricted, RoomMembership},
room::{AllowRule, JoinRule, RoomMembership},
};
use crate::{
@@ -591,13 +591,17 @@ impl Service {
debug!("Running send_join auth check");
let fetch_state = &state;
let state_fetch = |k: StateEventType, s: StateKey| async move {
let shortstatekey = self.services.short.get_shortstatekey(&k, &s).await.ok()?;
let state_fetch = |k: StateEventType, s: StateKey| {
let shortstatekey = self
.services
.short
.get_shortstatekey_blocking(&k, &s)
.ok()?;
let event_id = fetch_state.get(&shortstatekey)?;
self.services.timeline.get_pdu(event_id).await.ok()
self.services.timeline.get_pdu_blocking(event_id).ok()
};
let Some(create_event) = state_fetch(StateEventType::RoomCreate, "".into()).await else {
if state_fetch(StateEventType::RoomCreate, "".into()).is_none() {
let in_auth_chain = send_join_auth_chain
.iter()
.any(|(t, s)| t == "m.room.create" && s.is_empty());
@@ -614,20 +618,29 @@ impl Service {
};
drop(send_join_auth_chain);
let auth_check = state_res::event_auth::auth_check(
&room_version.rules().unwrap(),
// TODO: These calls should be in a thread to avoid blocking the main
// event loop.
ruma::state_res::check_state_independent_auth_rules(
&room_version.rules().unwrap().authorization,
&parsed_join_pdu,
|event_id| self.services.timeline.get_pdu_blocking(event_id).ok(),
)
.map_err(|e| {
err!(Request(Forbidden(
"Join event returned by {remote_server} is not self-authorised (try again?): {e}"
)))
})?;
ruma::state_res::check_state_dependent_auth_rules(
&room_version.rules().unwrap().authorization,
&parsed_join_pdu,
|k, s| state_fetch(k.clone(), s.into()),
&create_event,
)
.await
.map_err(|e| err!(Request(Forbidden(warn!("Auth check failed: {e:?}")))))?;
.map_err(|e| {
err!(Request(Forbidden(
"Join event returned by {remote_server} is not self-authorised (try again?): {e}"
)))
})?;
if !auth_check {
return Err!(Request(Forbidden(
"Join event returned by {remote_server} is not self-authorised (try again?)"
)));
}
let resident_before = self
.services
.state_cache
@@ -845,7 +858,7 @@ impl Service {
&self,
room_id: &RoomId,
entity: JoinConditionEntity<'_>,
conditions: &Restricted,
conditions: &ruma::room::Restricted,
) -> JoinConditionResult {
if conditions.allow.is_empty() {
// This will never be authorisable, return forbidden.
+1 -1
View File
@@ -160,7 +160,7 @@ impl Service {
state_key: &str,
) -> Result<ShortStateKey> {
let key = (event_type, state_key);
self.db.shortstatekey_statekey.qry()
self.db.shortstatekey_statekey.qry_blocking(&key).deserialized()
}
/// Gets a full event ID from a short event ID.
+1 -1
View File
@@ -1,7 +1,7 @@
use std::{collections::HashMap, fmt::Write, sync::Arc};
use async_trait::async_trait;
use conduwuit::{debug, matrix::StateKey, smallstr::SmallString, utils::stream::WidebandExt};
use conduwuit::{debug, utils::stream::WidebandExt};
use conduwuit_core::{
Event, PduEvent, Result, err,
result::FlatOk,
+15 -34
View File
@@ -6,18 +6,11 @@ use conduwuit_core::{
matrix::{
event::{Event, gen_event_id},
pdu::{EventHash, PartialPdu, PduEvent},
state_res,
},
utils::{self, IterStream, ReadyExt, stream::TryIgnore},
};
use futures::{StreamExt, TryStreamExt, future, future::ready};
use ruma::{
CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId,
UserId,
events::{StateEventType, TimelineEventType, room::create::RoomCreateEventContent},
room_version_rules::RoomVersionRules,
uint,
};
use ruma::{events::{StateEventType, TimelineEventType, room::create::RoomCreateEventContent}, room_version_rules::RoomVersionRules, state_res, uint, CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId};
use serde_json::value::{RawValue, to_raw_value};
use super::RoomMutexGuard;
@@ -142,7 +135,7 @@ impl super::Service {
| None => Vec::new(),
};
let auth_events: HashMap<(StateEventType, SmallString<[u8; 48]>), PduEvent> =
let auth_events: HashMap<(StateEventType, String), PduEvent> =
match room_id {
| Some(room_id) =>
self.services
@@ -231,39 +224,27 @@ impl super::Service {
},
hashes: EventHash { sha256: String::new() },
signatures: None,
rejected: false,
};
let auth_fetch = |k: &StateEventType, s: &str| {
let key = (k.clone(), s.into());
ready(auth_events.get(&key).map(ToOwned::to_owned))
auth_events.get(&key).map(ToOwned::to_owned)
};
let room_id_or_hash = pdu.room_id_or_hash();
let create_pdu = match &pdu.kind {
| TimelineEventType::RoomCreate => None,
| _ => Some(
self.services
.state_accessor
.room_state_get(&room_id_or_hash, &StateEventType::RoomCreate, "")
.await
.map_err(|e| {
err!(Request(Forbidden(warn!("Failed to fetch room create event: {e}"))))
})?,
),
};
let create_event = match &pdu.kind {
| TimelineEventType::RoomCreate => &pdu,
| _ => create_pdu.as_ref().unwrap().as_pdu(),
};
let auth_check =
state_res::auth_check(&room_version_rules, &pdu, auth_fetch, create_event)
.await
.map_err(|e| err!(Request(Forbidden(warn!("Auth check failed: {e:?}")))))?;
if !auth_check {
return Err!(Request(Forbidden("Event is not authorized.")));
}
state_res::check_state_independent_auth_rules(
&room_version_rules.authorization,
&pdu,
|event_id| self.get_pdu_blocking(event_id).ok(),
)
.map_err(|e| err!(Request(Forbidden("{e}"))))?;
state_res::check_state_dependent_auth_rules(
&room_version_rules.authorization,
&pdu,
auth_fetch
).map_err(|e| err!(Request(Forbidden("{e}"))))?;
trace!(
"Event {} in room {} is authorized",
pdu.event_id,