|
|
|
@ -119,7 +119,7 @@ impl FedDest { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(globals, request))] |
|
|
|
#[tracing::instrument(skip(globals, request))] |
|
|
|
pub async fn send_request<T: OutgoingRequest>( |
|
|
|
pub(crate) async fn send_request<T: OutgoingRequest>( |
|
|
|
globals: &crate::database::globals::Globals, |
|
|
|
globals: &crate::database::globals::Globals, |
|
|
|
destination: &ServerName, |
|
|
|
destination: &ServerName, |
|
|
|
request: T, |
|
|
|
request: T, |
|
|
|
@ -487,7 +487,7 @@ async fn query_srv_record( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(globals))] |
|
|
|
#[tracing::instrument(skip(globals))] |
|
|
|
pub async fn request_well_known( |
|
|
|
async fn request_well_known( |
|
|
|
globals: &crate::database::globals::Globals, |
|
|
|
globals: &crate::database::globals::Globals, |
|
|
|
destination: &str, |
|
|
|
destination: &str, |
|
|
|
) -> Option<String> { |
|
|
|
) -> Option<String> { |
|
|
|
@ -512,6 +512,9 @@ pub async fn request_well_known( |
|
|
|
Some(body.get("m.server")?.as_str()?.to_owned()) |
|
|
|
Some(body.get("m.server")?.as_str()?.to_owned()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/version`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Get version information on this server.
|
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))] |
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
pub fn get_server_version_route( |
|
|
|
pub fn get_server_version_route( |
|
|
|
@ -530,6 +533,12 @@ pub fn get_server_version_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/key/v2/server`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Gets the public signing keys of this server.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
|
|
|
|
|
|
|
/// forever.
|
|
|
|
// Response type for this endpoint is Json because we need to calculate a signature for the response
|
|
|
|
// Response type for this endpoint is Json because we need to calculate a signature for the response
|
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server"))] |
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server"))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
@ -578,12 +587,21 @@ pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> { |
|
|
|
Json(serde_json::to_string(&response).expect("JSON is canonical")) |
|
|
|
Json(serde_json::to_string(&response).expect("JSON is canonical")) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/key/v2/server/{keyId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Gets the public signing keys of this server.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
|
|
|
|
|
|
|
/// forever.
|
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))] |
|
|
|
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
#[tracing::instrument(skip(db))] |
|
|
|
pub fn get_server_keys_deprecated_route(db: DatabaseGuard) -> Json<String> { |
|
|
|
pub fn get_server_keys_deprecated_route(db: DatabaseGuard) -> Json<String> { |
|
|
|
get_server_keys_route(db) |
|
|
|
get_server_keys_route(db) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/publicRooms`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Lists the public rooms on this server.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
post("/_matrix/federation/v1/publicRooms", data = "<body>") |
|
|
|
post("/_matrix/federation/v1/publicRooms", data = "<body>") |
|
|
|
@ -628,6 +646,9 @@ pub async fn get_public_rooms_filtered_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/publicRooms`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Lists the public rooms on this server.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/publicRooms", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/publicRooms", data = "<body>") |
|
|
|
@ -672,6 +693,9 @@ pub async fn get_public_rooms_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Push EDUs and PDUs to this server.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
put("/_matrix/federation/v1/send/<_>", data = "<body>") |
|
|
|
put("/_matrix/federation/v1/send/<_>", data = "<body>") |
|
|
|
@ -921,7 +945,7 @@ type AsyncRecursiveType<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>; |
|
|
|
/// 14. Use state resolution to find new room state
|
|
|
|
/// 14. Use state resolution to find new room state
|
|
|
|
// We use some AsyncRecursiveType hacks here so we can call this async funtion recursively
|
|
|
|
// We use some AsyncRecursiveType hacks here so we can call this async funtion recursively
|
|
|
|
#[tracing::instrument(skip(value, is_timeline_event, db, pub_key_map))] |
|
|
|
#[tracing::instrument(skip(value, is_timeline_event, db, pub_key_map))] |
|
|
|
pub async fn handle_incoming_pdu<'a>( |
|
|
|
pub(crate) async fn handle_incoming_pdu<'a>( |
|
|
|
origin: &'a ServerName, |
|
|
|
origin: &'a ServerName, |
|
|
|
event_id: &'a EventId, |
|
|
|
event_id: &'a EventId, |
|
|
|
room_id: &'a RoomId, |
|
|
|
room_id: &'a RoomId, |
|
|
|
@ -1397,7 +1421,11 @@ async fn upgrade_outlier_to_timeline_pdu( |
|
|
|
let mut auth_chain_sets = Vec::new(); |
|
|
|
let mut auth_chain_sets = Vec::new(); |
|
|
|
for state in fork_states { |
|
|
|
for state in fork_states { |
|
|
|
auth_chain_sets.push( |
|
|
|
auth_chain_sets.push( |
|
|
|
get_auth_chain(state.iter().map(|(_, id)| id.clone()).collect(), db) |
|
|
|
get_auth_chain( |
|
|
|
|
|
|
|
&room_id, |
|
|
|
|
|
|
|
state.iter().map(|(_, id)| id.clone()).collect(), |
|
|
|
|
|
|
|
db, |
|
|
|
|
|
|
|
) |
|
|
|
.map_err(|_| "Failed to load auth chain.".to_owned())? |
|
|
|
.map_err(|_| "Failed to load auth chain.".to_owned())? |
|
|
|
.collect(), |
|
|
|
.collect(), |
|
|
|
); |
|
|
|
); |
|
|
|
@ -1745,7 +1773,11 @@ async fn upgrade_outlier_to_timeline_pdu( |
|
|
|
let mut auth_chain_sets = Vec::new(); |
|
|
|
let mut auth_chain_sets = Vec::new(); |
|
|
|
for state in fork_states { |
|
|
|
for state in fork_states { |
|
|
|
auth_chain_sets.push( |
|
|
|
auth_chain_sets.push( |
|
|
|
get_auth_chain(state.iter().map(|(_, id)| id.clone()).collect(), db) |
|
|
|
get_auth_chain( |
|
|
|
|
|
|
|
&room_id, |
|
|
|
|
|
|
|
state.iter().map(|(_, id)| id.clone()).collect(), |
|
|
|
|
|
|
|
db, |
|
|
|
|
|
|
|
) |
|
|
|
.map_err(|_| "Failed to load auth chain.".to_owned())? |
|
|
|
.map_err(|_| "Failed to load auth chain.".to_owned())? |
|
|
|
.collect(), |
|
|
|
.collect(), |
|
|
|
); |
|
|
|
); |
|
|
|
@ -2187,10 +2219,11 @@ fn append_incoming_pdu( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(starting_events, db))] |
|
|
|
#[tracing::instrument(skip(starting_events, db))] |
|
|
|
pub fn get_auth_chain( |
|
|
|
pub(crate) fn get_auth_chain<'a>( |
|
|
|
|
|
|
|
room_id: &RoomId, |
|
|
|
starting_events: Vec<Arc<EventId>>, |
|
|
|
starting_events: Vec<Arc<EventId>>, |
|
|
|
db: &Database, |
|
|
|
db: &'a Database, |
|
|
|
) -> Result<impl Iterator<Item = Arc<EventId>> + '_> { |
|
|
|
) -> Result<impl Iterator<Item = Arc<EventId>> + 'a> { |
|
|
|
const NUM_BUCKETS: usize = 50; |
|
|
|
const NUM_BUCKETS: usize = 50; |
|
|
|
|
|
|
|
|
|
|
|
let mut buckets = vec![BTreeSet::new(); NUM_BUCKETS]; |
|
|
|
let mut buckets = vec![BTreeSet::new(); NUM_BUCKETS]; |
|
|
|
@ -2231,7 +2264,7 @@ pub fn get_auth_chain( |
|
|
|
chunk_cache.extend(cached.iter().cloned()); |
|
|
|
chunk_cache.extend(cached.iter().cloned()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
misses2 += 1; |
|
|
|
misses2 += 1; |
|
|
|
let auth_chain = Arc::new(get_auth_chain_inner(&event_id, db)?); |
|
|
|
let auth_chain = Arc::new(get_auth_chain_inner(&room_id, &event_id, db)?); |
|
|
|
db.rooms |
|
|
|
db.rooms |
|
|
|
.cache_auth_chain(vec![sevent_id], Arc::clone(&auth_chain))?; |
|
|
|
.cache_auth_chain(vec![sevent_id], Arc::clone(&auth_chain))?; |
|
|
|
println!( |
|
|
|
println!( |
|
|
|
@ -2267,13 +2300,20 @@ pub fn get_auth_chain( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(event_id, db))] |
|
|
|
#[tracing::instrument(skip(event_id, db))] |
|
|
|
fn get_auth_chain_inner(event_id: &EventId, db: &Database) -> Result<HashSet<u64>> { |
|
|
|
fn get_auth_chain_inner( |
|
|
|
|
|
|
|
room_id: &RoomId, |
|
|
|
|
|
|
|
event_id: &EventId, |
|
|
|
|
|
|
|
db: &Database, |
|
|
|
|
|
|
|
) -> Result<HashSet<u64>> { |
|
|
|
let mut todo = vec![event_id.clone()]; |
|
|
|
let mut todo = vec![event_id.clone()]; |
|
|
|
let mut found = HashSet::new(); |
|
|
|
let mut found = HashSet::new(); |
|
|
|
|
|
|
|
|
|
|
|
while let Some(event_id) = todo.pop() { |
|
|
|
while let Some(event_id) = todo.pop() { |
|
|
|
match db.rooms.get_pdu(&event_id) { |
|
|
|
match db.rooms.get_pdu(&event_id) { |
|
|
|
Ok(Some(pdu)) => { |
|
|
|
Ok(Some(pdu)) => { |
|
|
|
|
|
|
|
if &pdu.room_id != room_id { |
|
|
|
|
|
|
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Evil event in db")); |
|
|
|
|
|
|
|
} |
|
|
|
for auth_event in &pdu.auth_events { |
|
|
|
for auth_event in &pdu.auth_events { |
|
|
|
let sauthevent = db |
|
|
|
let sauthevent = db |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
@ -2297,6 +2337,11 @@ fn get_auth_chain_inner(event_id: &EventId, db: &Database) -> Result<HashSet<u64 |
|
|
|
Ok(found) |
|
|
|
Ok(found) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/event/{eventId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Retrieves a single event from the server.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// - Only works if a user of this server is currently invited or joined the room
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/event/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/event/<_>", data = "<body>") |
|
|
|
@ -2310,18 +2355,39 @@ pub fn get_event_route( |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sender_servername = body |
|
|
|
|
|
|
|
.sender_servername |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
|
|
|
|
.expect("server is authenticated"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let event = db |
|
|
|
|
|
|
|
.rooms |
|
|
|
|
|
|
|
.get_pdu_json(&body.event_id)? |
|
|
|
|
|
|
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Event not found."))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let room_id_str = event |
|
|
|
|
|
|
|
.get("room_id") |
|
|
|
|
|
|
|
.and_then(|val| val.as_str()) |
|
|
|
|
|
|
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let room_id = RoomId::try_from(room_id_str) |
|
|
|
|
|
|
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !db.rooms.server_in_room(sender_servername, &room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found.")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ok(get_event::v1::Response { |
|
|
|
Ok(get_event::v1::Response { |
|
|
|
origin: db.globals.server_name().to_owned(), |
|
|
|
origin: db.globals.server_name().to_owned(), |
|
|
|
origin_server_ts: MilliSecondsSinceUnixEpoch::now(), |
|
|
|
origin_server_ts: MilliSecondsSinceUnixEpoch::now(), |
|
|
|
pdu: PduEvent::convert_to_outgoing_federation_event( |
|
|
|
pdu: PduEvent::convert_to_outgoing_federation_event(event), |
|
|
|
db.rooms |
|
|
|
|
|
|
|
.get_pdu_json(&body.event_id)? |
|
|
|
|
|
|
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Event not found."))?, |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Retrieves events that the sender is missing.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
post("/_matrix/federation/v1/get_missing_events/<_>", data = "<body>") |
|
|
|
post("/_matrix/federation/v1/get_missing_events/<_>", data = "<body>") |
|
|
|
@ -2335,22 +2401,44 @@ pub fn get_missing_events_route( |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sender_servername = body |
|
|
|
|
|
|
|
.sender_servername |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
|
|
|
|
.expect("server is authenticated"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !db.rooms.server_in_room(sender_servername, &body.room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::Forbidden, |
|
|
|
|
|
|
|
"Server is not in room", |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut queued_events = body.latest_events.clone(); |
|
|
|
let mut queued_events = body.latest_events.clone(); |
|
|
|
let mut events = Vec::new(); |
|
|
|
let mut events = Vec::new(); |
|
|
|
|
|
|
|
|
|
|
|
let mut i = 0; |
|
|
|
let mut i = 0; |
|
|
|
while i < queued_events.len() && events.len() < u64::from(body.limit) as usize { |
|
|
|
while i < queued_events.len() && events.len() < u64::from(body.limit) as usize { |
|
|
|
if let Some(pdu) = db.rooms.get_pdu_json(&queued_events[i])? { |
|
|
|
if let Some(pdu) = db.rooms.get_pdu_json(&queued_events[i])? { |
|
|
|
let event_id = |
|
|
|
let room_id_str = pdu |
|
|
|
serde_json::from_value( |
|
|
|
.get("room_id") |
|
|
|
serde_json::to_value(pdu.get("event_id").cloned().ok_or_else(|| { |
|
|
|
.and_then(|val| val.as_str()) |
|
|
|
Error::bad_database("Event in db has no event_id field.") |
|
|
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?; |
|
|
|
})?) |
|
|
|
|
|
|
|
.expect("canonical json is valid json value"), |
|
|
|
let event_room_id = RoomId::try_from(room_id_str) |
|
|
|
) |
|
|
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?; |
|
|
|
.map_err(|_| Error::bad_database("Invalid event_id field in pdu in db."))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if body.earliest_events.contains(&event_id) { |
|
|
|
if event_room_id != body.room_id { |
|
|
|
|
|
|
|
warn!( |
|
|
|
|
|
|
|
"Evil event detected: Event {} found while searching in room {}", |
|
|
|
|
|
|
|
queued_events[i], body.room_id |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::InvalidParam, |
|
|
|
|
|
|
|
"Evil event detected", |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if body.earliest_events.contains(&queued_events[i]) { |
|
|
|
i += 1; |
|
|
|
i += 1; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2371,6 +2459,11 @@ pub fn get_missing_events_route( |
|
|
|
Ok(get_missing_events::v1::Response { events }.into()) |
|
|
|
Ok(get_missing_events::v1::Response { events }.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Retrieves the auth chain for a given event.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// - This does not include the event itself
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/event_auth/<_>/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/event_auth/<_>/<_>", data = "<body>") |
|
|
|
@ -2384,7 +2477,29 @@ pub fn get_event_authorization_route( |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let auth_chain_ids = get_auth_chain(vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
let sender_servername = body |
|
|
|
|
|
|
|
.sender_servername |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
|
|
|
|
.expect("server is authenticated"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let event = db |
|
|
|
|
|
|
|
.rooms |
|
|
|
|
|
|
|
.get_pdu_json(&body.event_id)? |
|
|
|
|
|
|
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Event not found."))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let room_id_str = event |
|
|
|
|
|
|
|
.get("room_id") |
|
|
|
|
|
|
|
.and_then(|val| val.as_str()) |
|
|
|
|
|
|
|
.ok_or_else(|| Error::bad_database("Invalid event in database"))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let room_id = RoomId::try_from(room_id_str) |
|
|
|
|
|
|
|
.map_err(|_| Error::bad_database("Invalid room id field in event in database"))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !db.rooms.server_in_room(sender_servername, &room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Event not found.")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let auth_chain_ids = get_auth_chain(&room_id, vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(get_event_authorization::v1::Response { |
|
|
|
Ok(get_event_authorization::v1::Response { |
|
|
|
auth_chain: auth_chain_ids |
|
|
|
auth_chain: auth_chain_ids |
|
|
|
@ -2395,6 +2510,9 @@ pub fn get_event_authorization_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/state/{roomId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Retrieves the current state of the room.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/state/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/state/<_>", data = "<body>") |
|
|
|
@ -2408,6 +2526,18 @@ pub fn get_room_state_route( |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sender_servername = body |
|
|
|
|
|
|
|
.sender_servername |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
|
|
|
|
.expect("server is authenticated"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !db.rooms.server_in_room(sender_servername, &body.room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::Forbidden, |
|
|
|
|
|
|
|
"Server is not in room.", |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let shortstatehash = db |
|
|
|
let shortstatehash = db |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
.pdu_shortstatehash(&body.event_id)? |
|
|
|
.pdu_shortstatehash(&body.event_id)? |
|
|
|
@ -2427,7 +2557,7 @@ pub fn get_room_state_route( |
|
|
|
}) |
|
|
|
}) |
|
|
|
.collect(); |
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
|
|
let auth_chain_ids = get_auth_chain(vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(get_room_state::v1::Response { |
|
|
|
Ok(get_room_state::v1::Response { |
|
|
|
auth_chain: auth_chain_ids |
|
|
|
auth_chain: auth_chain_ids |
|
|
|
@ -2443,6 +2573,9 @@ pub fn get_room_state_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/state_ids/{roomId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Retrieves the current state of the room.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/state_ids/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/state_ids/<_>", data = "<body>") |
|
|
|
@ -2456,6 +2589,18 @@ pub fn get_room_state_ids_route( |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sender_servername = body |
|
|
|
|
|
|
|
.sender_servername |
|
|
|
|
|
|
|
.as_ref() |
|
|
|
|
|
|
|
.expect("server is authenticated"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !db.rooms.server_in_room(sender_servername, &body.room_id)? { |
|
|
|
|
|
|
|
return Err(Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::Forbidden, |
|
|
|
|
|
|
|
"Server is not in room.", |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let shortstatehash = db |
|
|
|
let shortstatehash = db |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
.pdu_shortstatehash(&body.event_id)? |
|
|
|
.pdu_shortstatehash(&body.event_id)? |
|
|
|
@ -2471,7 +2616,7 @@ pub fn get_room_state_ids_route( |
|
|
|
.map(|(_, id)| (*id).clone()) |
|
|
|
.map(|(_, id)| (*id).clone()) |
|
|
|
.collect(); |
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
|
|
let auth_chain_ids = get_auth_chain(vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
let auth_chain_ids = get_auth_chain(&body.room_id, vec![Arc::new(body.event_id.clone())], &db)?; |
|
|
|
|
|
|
|
|
|
|
|
Ok(get_room_state_ids::v1::Response { |
|
|
|
Ok(get_room_state_ids::v1::Response { |
|
|
|
auth_chain_ids: auth_chain_ids.map(|id| (*id).clone()).collect(), |
|
|
|
auth_chain_ids: auth_chain_ids.map(|id| (*id).clone()).collect(), |
|
|
|
@ -2480,6 +2625,9 @@ pub fn get_room_state_ids_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Creates a join template.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/make_join/<_>/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/make_join/<_>/<_>", data = "<body>") |
|
|
|
@ -2719,7 +2867,11 @@ async fn create_join_event( |
|
|
|
drop(mutex_lock); |
|
|
|
drop(mutex_lock); |
|
|
|
|
|
|
|
|
|
|
|
let state_ids = db.rooms.state_full_ids(shortstatehash)?; |
|
|
|
let state_ids = db.rooms.state_full_ids(shortstatehash)?; |
|
|
|
let auth_chain_ids = get_auth_chain(state_ids.iter().map(|(_, id)| id.clone()).collect(), &db)?; |
|
|
|
let auth_chain_ids = get_auth_chain( |
|
|
|
|
|
|
|
&room_id, |
|
|
|
|
|
|
|
state_ids.iter().map(|(_, id)| id.clone()).collect(), |
|
|
|
|
|
|
|
&db, |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
for server in db |
|
|
|
for server in db |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
@ -2745,6 +2897,9 @@ async fn create_join_event( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Submits a signed join event.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
put("/_matrix/federation/v1/send_join/<_>/<_>", data = "<body>") |
|
|
|
put("/_matrix/federation/v1/send_join/<_>/<_>", data = "<body>") |
|
|
|
@ -2759,6 +2914,9 @@ pub async fn create_join_event_v1_route( |
|
|
|
Ok(create_join_event::v1::Response { room_state }.into()) |
|
|
|
Ok(create_join_event::v1::Response { room_state }.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Submits a signed join event.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
put("/_matrix/federation/v2/send_join/<_>/<_>", data = "<body>") |
|
|
|
put("/_matrix/federation/v2/send_join/<_>/<_>", data = "<body>") |
|
|
|
@ -2773,6 +2931,9 @@ pub async fn create_join_event_v2_route( |
|
|
|
Ok(create_join_event::v2::Response { room_state }.into()) |
|
|
|
Ok(create_join_event::v2::Response { room_state }.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Invites a remote user to a room.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
put("/_matrix/federation/v2/invite/<_>/<_>", data = "<body>") |
|
|
|
put("/_matrix/federation/v2/invite/<_>/<_>", data = "<body>") |
|
|
|
@ -2882,6 +3043,9 @@ pub async fn create_invite_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Gets information on all devices of the user.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/user/devices/<_>", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/user/devices/<_>", data = "<body>") |
|
|
|
@ -2922,6 +3086,9 @@ pub fn get_devices_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/query/directory`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Resolve a room alias to a room id.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/query/directory", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/query/directory", data = "<body>") |
|
|
|
@ -2950,6 +3117,9 @@ pub fn get_room_information_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `GET /_matrix/federation/v1/query/profile`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Gets information on a profile.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
get("/_matrix/federation/v1/query/profile", data = "<body>") |
|
|
|
get("/_matrix/federation/v1/query/profile", data = "<body>") |
|
|
|
@ -2990,6 +3160,9 @@ pub fn get_profile_information_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/user/keys/query`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Gets devices and identity keys for the given users.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
post("/_matrix/federation/v1/user/keys/query", data = "<body>") |
|
|
|
post("/_matrix/federation/v1/user/keys/query", data = "<body>") |
|
|
|
@ -3021,6 +3194,9 @@ pub async fn get_keys_route( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/federation/v1/user/keys/claim`
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// Claims one-time keys.
|
|
|
|
#[cfg_attr(
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "conduit_bin", |
|
|
|
feature = "conduit_bin", |
|
|
|
post("/_matrix/federation/v1/user/keys/claim", data = "<body>") |
|
|
|
post("/_matrix/federation/v1/user/keys/claim", data = "<body>") |
|
|
|
@ -3045,7 +3221,7 @@ pub async fn claim_keys_route( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(event, pub_key_map, db))] |
|
|
|
#[tracing::instrument(skip(event, pub_key_map, db))] |
|
|
|
pub async fn fetch_required_signing_keys( |
|
|
|
pub(crate) async fn fetch_required_signing_keys( |
|
|
|
event: &BTreeMap<String, CanonicalJsonValue>, |
|
|
|
event: &BTreeMap<String, CanonicalJsonValue>, |
|
|
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>, |
|
|
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>, |
|
|
|
db: &Database, |
|
|
|
db: &Database, |
|
|
|
|