tuwunel_admin/debug/
get_remote_pdu.rs1use futures::FutureExt;
2use ruma::{CanonicalJsonObject, OwnedEventId, OwnedServerName};
3use serde_json::value::RawValue as RawJsonValue;
4use tuwunel_core::{Err, Result, err, info, warn};
5use tuwunel_service::fetcher::{Op, Opts};
6
7use crate::admin_command;
8
9#[admin_command]
10pub(super) async fn get_remote_pdu(
11 &self,
12 event_id: OwnedEventId,
13 server: OwnedServerName,
14) -> Result {
15 if !self.services.server.config.allow_federation {
16 return Err!("Federation is disabled on this homeserver.");
17 }
18
19 if server == self.services.globals.server_name() {
20 return Err!(
21 "Not allowed to send federation requests to ourselves. Please use `get-pdu` for \
22 fetching local PDUs.",
23 );
24 }
25
26 let opts = Opts::unscoped(Op::Event)
27 .event_id(event_id.clone())
28 .hint(server.clone())
29 .checks(false);
30
31 let outcome = self
32 .services
33 .fetcher
34 .fetch(opts)
35 .await
36 .map_err(|e| {
37 err!("Remote server did not have PDU or failed sending request to remote server: {e}")
38 })?;
39
40 let pdu: Box<RawJsonValue> = serde_json::from_slice(&outcome.bytes).map_err(|e| {
41 warn!(
42 "Requested event ID {event_id} from {server} but failed to parse the response as a \
43 PDU (malformed event/response?): {e}"
44 );
45 err!(Request(Unknown("Received response from server but failed to parse PDU")))
46 })?;
47
48 let json: CanonicalJsonObject = serde_json::from_slice(&outcome.bytes).map_err(|e| {
49 err!(
50 "Got a PDU from {server} but could not convert it to canonical JSON for display: {e}"
51 )
52 })?;
53
54 let (room_id, ..) = self
55 .services
56 .event_handler
57 .parse_incoming_pdu(&pdu)
58 .boxed()
59 .await
60 .map_err(|e| {
61 warn!("Failed to parse PDU: {e}");
62 info!("Full PDU: {pdu:?}");
63 err!("Failed to parse PDU remote server {server} sent us: {e}")
64 })?;
65
66 info!("Attempting to handle event ID {event_id} as backfilled PDU");
67 self.services
68 .timeline
69 .backfill_pdu(&room_id, &outcome.origin, pdu)
70 .await?;
71
72 let text = serde_json::to_string_pretty(&json)?;
73 let msg = "Got PDU from specified server and handled as backfilled";
74 write!(self, "{msg}. Event body:\n```json\n{text}\n```").await
75}