From e28c9b2e01144671c8977f44ea770000c406df1d Mon Sep 17 00:00:00 2001 From: nexy7574 Date: Tue, 2 Sep 2025 01:08:53 +0100 Subject: [PATCH] fix(hydra): Unable to parse backfilled incoming create events --- src/api/client/membership/join.rs | 3 +- .../rooms/event_handler/parse_incoming_pdu.rs | 49 +++++++++++++++---- src/service/rooms/timeline/backfill.rs | 2 + 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index 5f1ced7a..e6d2643d 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -604,6 +604,7 @@ async fn join_room_by_id_helper_remote( }) .ready_filter_map(Result::ok) .ready_for_each(|(event_id, value)| { + trace!(%event_id, "Adding PDU as an outlier from send_join auth_chain"); services.rooms.outlier.add_pdu_outlier(&event_id, &value); }) .await; @@ -661,7 +662,7 @@ async fn join_room_by_id_helper_remote( .force_state(room_id, statehash_before_join, added, removed, &state_lock) .await?; - info!("Updating joined counts for new room"); + debug!("Updating joined counts for new room"); services .rooms .state_cache diff --git a/src/service/rooms/event_handler/parse_incoming_pdu.rs b/src/service/rooms/event_handler/parse_incoming_pdu.rs index 65cf1752..e18ffe6a 100644 --- a/src/service/rooms/event_handler/parse_incoming_pdu.rs +++ b/src/service/rooms/event_handler/parse_incoming_pdu.rs @@ -1,7 +1,8 @@ use conduwuit::{ - Result, err, implement, matrix::event::gen_event_id_canonical_json, result::FlatOk, + Result, RoomVersion, err, implement, matrix::event::gen_event_id_canonical_json, + result::FlatOk, }; -use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId}; +use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, RoomVersionId}; use serde_json::value::RawValue as RawJsonValue; type Parsed = (OwnedRoomId, OwnedEventId, CanonicalJsonObject); @@ -11,12 +12,44 @@ pub async fn parse_incoming_pdu(&self, pdu: &RawJsonValue) -> Result { let value = serde_json::from_str::(pdu.get()).map_err(|e| { err!(BadServerResponse(debug_warn!("Error parsing incoming event {e:?}"))) })?; - - let room_id: OwnedRoomId = value - .get("room_id") + let event_type = value + .get("type") .and_then(CanonicalJsonValue::as_str) - .map(OwnedRoomId::parse) - .flat_ok_or(err!(Request(InvalidParam("Invalid room_id in pdu"))))?; + .ok_or_else(|| err!(Request(InvalidParam("Missing or invalid type in pdu"))))?; + + let room_id: OwnedRoomId = if event_type != "m.room.create" { + value + .get("room_id") + .and_then(CanonicalJsonValue::as_str) + .map(OwnedRoomId::parse) + .flat_ok_or(err!(Request(InvalidParam("Invalid room_id in pdu"))))? + } else { + // v12 rooms might have no room_id in the create event. We'll need to check the + // content.room_version + let content = value + .get("content") + .and_then(CanonicalJsonValue::as_object) + .ok_or_else(|| err!(Request(InvalidParam("Missing or invalid content in pdu"))))?; + let room_version = content + .get("room_version") + .and_then(CanonicalJsonValue::as_str) + .unwrap_or("1"); + let vi = RoomVersionId::try_from(room_version).unwrap_or(RoomVersionId::V1); + let vf = RoomVersion::new(&vi).expect("supported room version"); + if vf.room_ids_as_hashes { + let (event_id, _) = gen_event_id_canonical_json(pdu, &vi).map_err(|e| { + err!(Request(InvalidParam("Could not convert event to canonical json: {e}"))) + })?; + OwnedRoomId::parse(event_id.as_str().replace('$', "!")).expect("valid room ID") + } else { + // V11 or below room, room_id must be present + value + .get("room_id") + .and_then(CanonicalJsonValue::as_str) + .map(OwnedRoomId::parse) + .flat_ok_or(err!(Request(InvalidParam("Invalid or missing room_id in pdu"))))? + } + }; let room_version_id = self .services @@ -24,10 +57,8 @@ pub async fn parse_incoming_pdu(&self, pdu: &RawJsonValue) -> Result { .get_room_version(&room_id) .await .map_err(|_| err!("Server is not in room {room_id}"))?; - let (event_id, value) = gen_event_id_canonical_json(pdu, &room_version_id).map_err(|e| { err!(Request(InvalidParam("Could not convert event to canonical json: {e}"))) })?; - Ok((room_id, event_id, value)) } diff --git a/src/service/rooms/timeline/backfill.rs b/src/service/rooms/timeline/backfill.rs index e976981e..391e7545 100644 --- a/src/service/rooms/timeline/backfill.rs +++ b/src/service/rooms/timeline/backfill.rs @@ -38,6 +38,7 @@ pub async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Re .await { // Room is empty (1 user or none), there is no one that can backfill + debug_warn!("Room {room_id} is empty, skipping backfill"); return Ok(()); } @@ -48,6 +49,7 @@ pub async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Re if first_pdu.0 < from { // No backfill required, there are still events between them + debug!("No backfill required in room {room_id}, {:?} < {from}", first_pdu.0); return Ok(()); }