2024-07-16 08:05:25 +00:00
|
|
|
use axum::extract::State;
|
2025-04-02 22:44:44 -04:00
|
|
|
use conduwuit::{
|
|
|
|
|
Result, debug, debug_info, debug_warn,
|
|
|
|
|
utils::{self},
|
|
|
|
|
warn,
|
2024-06-05 04:32:58 +00:00
|
|
|
};
|
2025-04-02 22:44:44 -04:00
|
|
|
use ruma::api::federation::event::get_missing_events;
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2024-10-30 07:01:50 +00:00
|
|
|
use super::AccessCheck;
|
2024-07-03 21:05:24 +00:00
|
|
|
use crate::Ruma;
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
/// arbitrary number but synapse's is 20 and we can handle lots of these anyways
|
|
|
|
|
const LIMIT_MAX: usize = 50;
|
|
|
|
|
/// spec says default is 10
|
|
|
|
|
const LIMIT_DEFAULT: usize = 10;
|
|
|
|
|
|
2024-06-05 04:32:58 +00:00
|
|
|
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
|
|
|
|
|
///
|
|
|
|
|
/// Retrieves events that the sender is missing.
|
|
|
|
|
pub(crate) async fn get_missing_events_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
body: Ruma<get_missing_events::v1::Request>,
|
2024-06-05 04:32:58 +00:00
|
|
|
) -> Result<get_missing_events::v1::Response> {
|
2024-10-30 07:01:50 +00:00
|
|
|
AccessCheck {
|
|
|
|
|
services: &services,
|
|
|
|
|
origin: body.origin(),
|
|
|
|
|
room_id: &body.room_id,
|
|
|
|
|
event_id: None,
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|
2024-10-30 07:01:50 +00:00
|
|
|
.check()
|
|
|
|
|
.await?;
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
let limit = body
|
|
|
|
|
.limit
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap_or(LIMIT_DEFAULT)
|
|
|
|
|
.min(LIMIT_MAX);
|
2024-06-05 04:32:58 +00:00
|
|
|
|
|
|
|
|
let mut queued_events = body.latest_events.clone();
|
|
|
|
|
// the vec will never have more entries the limit
|
|
|
|
|
let mut events = Vec::with_capacity(limit);
|
|
|
|
|
|
|
|
|
|
let mut i: usize = 0;
|
|
|
|
|
while i < queued_events.len() && events.len() < limit {
|
2025-04-02 22:44:44 -04:00
|
|
|
let Ok(pdu) = services.rooms.timeline.get_pdu(&queued_events[i]).await else {
|
|
|
|
|
debug_info!(?body.origin, "Event {} does not exist locally, skipping", &queued_events[i]);
|
|
|
|
|
i = i.saturating_add(1);
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
if pdu.room_id != body.room_id {
|
|
|
|
|
warn!(?body.origin,
|
|
|
|
|
"Got an event for the wrong room in database. Found {:?} in {:?}, server requested events in {:?}. Skipping.",
|
|
|
|
|
pdu.event_id, pdu.room_id, body.room_id
|
|
|
|
|
);
|
|
|
|
|
i = i.saturating_add(1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
if body.earliest_events.contains(&queued_events[i]) {
|
|
|
|
|
i = i.saturating_add(1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
if !services
|
|
|
|
|
.rooms
|
|
|
|
|
.state_accessor
|
|
|
|
|
.server_can_see_event(body.origin(), &body.room_id, &queued_events[i])
|
|
|
|
|
.await
|
|
|
|
|
{
|
|
|
|
|
debug!(?body.origin, "Server cannot see {:?} in {:?}, skipping", pdu.event_id, pdu.room_id);
|
|
|
|
|
i = i.saturating_add(1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-06-05 04:32:58 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
let Ok(pdu_json) = utils::to_canonical_object(&pdu) else {
|
|
|
|
|
debug_warn!(?body.origin, "Failed to convert PDU in database to canonical JSON: {pdu:?}");
|
|
|
|
|
i = i.saturating_add(1);
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2024-10-03 09:57:43 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
queued_events.extend(pdu.prev_events.iter().map(ToOwned::to_owned));
|
2024-10-03 09:57:43 +00:00
|
|
|
|
2025-04-02 22:44:44 -04:00
|
|
|
events.push(
|
|
|
|
|
services
|
|
|
|
|
.sending
|
|
|
|
|
.convert_to_outgoing_federation_event(pdu_json)
|
|
|
|
|
.await,
|
|
|
|
|
);
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
2024-12-15 00:05:47 -05:00
|
|
|
Ok(get_missing_events::v1::Response { events })
|
2024-06-05 04:32:58 +00:00
|
|
|
}
|