2023-06-26 08:33:31 +02:00
#![ allow(deprecated) ]
2023-11-27 00:39:50 -05:00
// Conduit implements the older APIs
2023-06-26 08:33:31 +02:00
2021-05-20 23:46:52 +02:00
use crate ::{
2022-09-06 23:15:09 +02:00
api ::client_server ::{ self , claim_keys_helper , get_keys_helper } ,
2022-10-05 20:34:31 +02:00
service ::pdu ::{ gen_event_id_canonical_json , PduBuilder } ,
services , utils , Error , PduEvent , Result , Ruma ,
2021-05-20 23:46:52 +02:00
} ;
2022-01-20 11:51:31 +01:00
use axum ::{ response ::IntoResponse , Json } ;
2023-09-02 17:53:46 -04:00
use futures_util ::future ::TryFutureExt ;
2020-10-05 22:19:22 +02:00
use get_profile_information ::v1 ::ProfileField ;
2021-08-26 23:11:13 +02:00
use http ::header ::{ HeaderValue , AUTHORIZATION } ;
2022-10-05 20:41:05 +02:00
2024-01-21 22:59:06 -05:00
use ipaddress ::IPAddress ;
2020-09-12 22:41:33 +02:00
use ruma ::{
api ::{
2021-06-17 20:12:36 +02:00
client ::error ::{ Error as RumaError , ErrorKind } ,
2020-09-12 22:41:33 +02:00
federation ::{
2021-06-14 11:36:18 +02:00
authorization ::get_event_authorization ,
2023-02-18 13:20:20 +01:00
backfill ::get_backfill ,
2021-04-21 10:51:34 +02:00
device ::get_devices ::{ self , v1 ::UserDevice } ,
2020-09-25 12:26:29 +02:00
directory ::{ get_public_rooms , get_public_rooms_filtered } ,
2022-10-08 13:03:07 +02:00
discovery ::{ get_server_keys , get_server_version , ServerSigningKeys , VerifyKey } ,
2021-06-14 10:52:27 +02:00
event ::{ get_event , get_missing_events , get_room_state , get_room_state_ids } ,
2021-05-28 13:44:40 +02:00
keys ::{ claim_keys , get_keys } ,
2023-02-26 16:29:06 +01:00
membership ::{ create_invite , create_join_event , prepare_join_event } ,
2021-04-16 18:18:29 +02:00
query ::{ get_profile_information , get_room_information } ,
2021-05-28 13:44:40 +02:00
transactions ::{
2022-03-05 10:16:21 +08:00
edu ::{ DeviceListUpdateContent , DirectDeviceContent , Edu , SigningKeyUpdateContent } ,
2021-05-28 13:44:40 +02:00
send_transaction_message ,
} ,
2020-08-06 08:29:59 -04:00
} ,
2022-02-12 21:04:38 +01:00
EndpointError , IncomingResponse , MatrixVersion , OutgoingRequest , OutgoingResponse ,
SendAccessToken ,
2020-08-14 11:29:32 +02:00
} ,
2022-12-14 13:09:10 +01:00
directory ::{ Filter , RoomNetwork } ,
2021-04-11 21:01:27 +02:00
events ::{
2022-10-09 17:25:06 +02:00
receipt ::{ ReceiptEvent , ReceiptEventContent , ReceiptType } ,
2021-04-16 18:18:29 +02:00
room ::{
2022-01-18 16:53:25 +01:00
join_rules ::{ JoinRule , RoomJoinRulesEventContent } ,
2021-10-13 10:16:45 +02:00
member ::{ MembershipState , RoomMemberEventContent } ,
2021-04-16 18:18:29 +02:00
} ,
2023-02-26 16:29:06 +01:00
StateEventType , TimelineEventType ,
2021-04-11 21:01:27 +02:00
} ,
2022-02-18 15:33:14 +01:00
serde ::{ Base64 , JsonObject , Raw } ,
2022-10-08 13:03:07 +02:00
to_device ::DeviceIdOrAllDevices ,
2023-02-18 13:20:20 +01:00
uint , user_id , CanonicalJsonObject , CanonicalJsonValue , EventId , MilliSecondsSinceUnixEpoch ,
OwnedEventId , OwnedRoomId , OwnedServerName , OwnedServerSigningKeyId , OwnedUserId , RoomId ,
ServerName ,
2020-05-26 10:27:51 +02:00
} ;
2021-10-13 10:16:45 +02:00
use serde_json ::value ::{ to_raw_value , RawValue as RawJsonValue } ;
2020-04-22 20:55:11 +02:00
use std ::{
2022-10-08 13:03:07 +02:00
collections ::BTreeMap ,
2020-08-14 11:31:31 +02:00
fmt ::Debug ,
2021-04-29 20:58:05 +02:00
mem ,
2020-12-08 12:34:46 +01:00
net ::{ IpAddr , SocketAddr } ,
2022-10-05 20:41:05 +02:00
sync ::{ Arc , RwLock } ,
2021-05-20 23:46:52 +02:00
time ::{ Duration , Instant , SystemTime } ,
2020-04-22 20:55:11 +02:00
} ;
2023-09-02 17:53:46 -04:00
use trust_dns_resolver ::{ error ::ResolveError , lookup ::SrvLookup } ;
2022-10-05 20:41:05 +02:00
2023-09-02 17:53:46 -04:00
use tracing ::{ debug , error , info , warn } ;
2020-04-19 14:14:47 +02:00
2021-04-21 00:35:44 -03:00
/// Wraps either an literal IP address plus port, or a hostname plus complement
/// (colon-plus-port if it was specified).
///
/// Note: A `FedDest::Named` might contain an IP address in string form if there
/// was no port specified to construct a SocketAddr with.
///
/// # Examples:
2022-04-14 16:42:08 +02:00
/// ```rust
2022-10-12 14:39:58 -07:00
/// # use conduit::api::server_server::FedDest;
2022-04-14 16:42:08 +02:00
/// # fn main() -> Result<(), std::net::AddrParseError> {
2021-04-21 00:35:44 -03:00
/// FedDest::Literal("198.51.100.3:8448".parse()?);
/// FedDest::Literal("[2001:db8::4:5]:443".parse()?);
/// FedDest::Named("matrix.example.org".to_owned(), "".to_owned());
/// FedDest::Named("matrix.example.org".to_owned(), ":8448".to_owned());
/// FedDest::Named("198.51.100.5".to_owned(), "".to_owned());
2022-04-14 16:42:08 +02:00
/// # Ok(())
/// # }
2021-04-21 00:35:44 -03:00
/// ```
2022-10-10 14:09:11 +02:00
#[ derive(Clone, Debug, PartialEq, Eq) ]
2021-08-26 23:11:13 +02:00
pub enum FedDest {
2021-04-16 00:27:26 -03:00
Literal ( SocketAddr ) ,
Named ( String , String ) ,
}
2021-04-16 12:18:22 -03:00
impl FedDest {
2021-04-21 00:35:44 -03:00
fn into_https_string ( self ) -> String {
2021-04-16 00:27:26 -03:00
match self {
2022-12-21 10:42:12 +01:00
Self ::Literal ( addr ) = > format! ( " https:// {addr} " ) ,
Self ::Named ( host , port ) = > format! ( " https:// {host} {port} " ) ,
2021-04-16 00:27:26 -03:00
}
}
2021-04-21 00:35:44 -03:00
fn into_uri_string ( self ) -> String {
2021-04-16 00:27:26 -03:00
match self {
Self ::Literal ( addr ) = > addr . to_string ( ) ,
2024-01-14 22:39:08 -05:00
Self ::Named ( host , port ) = > host + & port ,
2021-04-16 00:27:26 -03:00
}
}
2021-04-21 00:35:44 -03:00
fn hostname ( & self ) -> String {
2021-04-16 00:27:26 -03:00
match & self {
Self ::Literal ( addr ) = > addr . ip ( ) . to_string ( ) ,
2021-04-16 12:18:22 -03:00
Self ::Named ( host , _ ) = > host . clone ( ) ,
2021-04-16 00:27:26 -03:00
}
}
2021-08-26 23:11:13 +02:00
fn port ( & self ) -> Option < u16 > {
match & self {
Self ::Literal ( addr ) = > Some ( addr . port ( ) ) ,
Self ::Named ( _ , port ) = > port [ 1 .. ] . parse ( ) . ok ( ) ,
}
}
2021-04-16 00:27:26 -03:00
}
2024-03-02 16:53:19 -05:00
pub ( crate ) async fn send_request < T > (
2021-01-14 14:39:56 -05:00
destination : & ServerName ,
2020-04-19 14:14:47 +02:00
request : T ,
2020-08-14 11:31:31 +02:00
) -> Result < T ::IncomingResponse >
where
2024-03-02 16:53:19 -05:00
T : OutgoingRequest + Debug ,
2020-08-14 11:31:31 +02:00
{
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2023-07-10 16:26:36 +02:00
if destination = = services ( ) . globals . server_name ( ) {
return Err ( Error ::bad_config (
" Won't send federation request to ourselves " ,
) ) ;
}
2024-01-24 18:34:41 -05:00
if destination . is_ip_literal ( ) | | IPAddress ::is_valid ( destination . host ( ) ) {
2024-01-24 15:51:13 -05:00
info! (
" Destination {} is an IP literal, checking against IP range denylist. " ,
destination
) ;
2024-01-21 22:59:06 -05:00
let ip = IPAddress ::parse ( destination . host ( ) ) . map_err ( | e | {
warn! ( " Failed to parse IP literal from string: {} " , e ) ;
Error ::BadServerResponse ( " Invalid IP address " )
} ) ? ;
let cidr_ranges_s = services ( ) . globals . ip_range_denylist ( ) . to_vec ( ) ;
let mut cidr_ranges : Vec < IPAddress > = Vec ::new ( ) ;
for cidr in cidr_ranges_s {
cidr_ranges . push ( IPAddress ::parse ( cidr ) . expect ( " we checked this at startup " ) ) ;
}
2024-01-24 15:51:13 -05:00
debug! ( " List of pushed CIDR ranges: {:?} " , cidr_ranges ) ;
2024-01-21 22:59:06 -05:00
for cidr in cidr_ranges {
2024-01-24 15:51:13 -05:00
if cidr . includes ( & ip ) {
2024-01-21 22:59:06 -05:00
return Err ( Error ::BadServerResponse (
" Not allowed to send requests to this IP " ,
) ) ;
}
}
2024-01-24 15:51:13 -05:00
info! ( " IP literal {} is allowed. " , destination ) ;
2024-01-21 22:59:06 -05:00
}
2023-03-13 08:27:59 +01:00
debug! ( " Preparing to send request to {destination} " ) ;
2023-02-23 11:20:40 +01:00
2021-08-26 23:11:13 +02:00
let mut write_destination_to_cache = false ;
2022-10-05 20:34:31 +02:00
let cached_result = services ( )
. globals
2020-12-06 11:05:51 +01:00
. actual_destination_cache
. read ( )
. unwrap ( )
2021-01-14 14:39:56 -05:00
. get ( destination )
2020-12-06 11:05:51 +01:00
. cloned ( ) ;
2020-09-23 12:03:08 +02:00
2021-08-26 23:11:13 +02:00
let ( actual_destination , host ) = if let Some ( result ) = cached_result {
2020-12-06 11:05:51 +01:00
result
} else {
2021-08-26 23:11:13 +02:00
write_destination_to_cache = true ;
2022-09-06 23:15:09 +02:00
let result = find_actual_destination ( destination ) . await ;
2021-08-26 23:11:13 +02:00
2021-08-31 21:20:03 +02:00
( result . 0 , result . 1. into_uri_string ( ) )
2020-12-06 11:05:51 +01:00
} ;
2020-08-14 11:31:31 +02:00
2021-08-26 23:11:13 +02:00
let actual_destination_str = actual_destination . clone ( ) . into_https_string ( ) ;
2020-08-14 11:31:31 +02:00
let mut http_request = request
2022-02-12 21:04:38 +01:00
. try_into_http_request ::< Vec < u8 > > (
& actual_destination_str ,
SendAccessToken ::IfRequired ( " " ) ,
2024-01-13 18:08:23 -05:00
& [ MatrixVersion ::V1_5 ] ,
2022-02-12 21:04:38 +01:00
)
2020-09-15 08:55:02 +02:00
. map_err ( | e | {
2021-08-26 23:11:13 +02:00
warn! (
" Failed to find destination {}: {} " ,
actual_destination_str , e
) ;
2020-09-15 08:55:02 +02:00
Error ::BadServerResponse ( " Invalid destination " )
} ) ? ;
2020-04-22 11:53:06 +02:00
2020-04-22 21:14:40 +02:00
let mut request_map = serde_json ::Map ::new ( ) ;
2020-04-19 14:14:47 +02:00
2020-04-22 21:14:40 +02:00
if ! http_request . body ( ) . is_empty ( ) {
2020-04-25 11:47:32 +02:00
request_map . insert (
" content " . to_owned ( ) ,
2020-09-15 08:55:02 +02:00
serde_json ::from_slice ( http_request . body ( ) )
. expect ( " body is valid json, we just created it " ) ,
2020-04-25 11:47:32 +02:00
) ;
2020-04-22 21:14:40 +02:00
} ;
2020-04-19 14:14:47 +02:00
2020-04-22 11:53:06 +02:00
request_map . insert ( " method " . to_owned ( ) , T ::METADATA . method . to_string ( ) . into ( ) ) ;
2020-08-14 11:31:31 +02:00
request_map . insert (
" uri " . to_owned ( ) ,
http_request
. uri ( )
. path_and_query ( )
. expect ( " all requests have a path " )
. to_string ( )
. into ( ) ,
) ;
2022-10-05 20:34:31 +02:00
request_map . insert (
" origin " . to_owned ( ) ,
services ( ) . globals . server_name ( ) . as_str ( ) . into ( ) ,
) ;
2020-09-14 11:00:31 +02:00
request_map . insert ( " destination " . to_owned ( ) , destination . as_str ( ) . into ( ) ) ;
2020-04-22 21:14:40 +02:00
2020-10-27 19:10:09 -04:00
let mut request_json =
serde_json ::from_value ( request_map . into ( ) ) . expect ( " valid JSON is valid BTreeMap " ) ;
2020-06-05 18:19:26 +02:00
ruma ::signatures ::sign_json (
2022-09-06 23:15:09 +02:00
services ( ) . globals . server_name ( ) . as_str ( ) ,
services ( ) . globals . keypair ( ) ,
2020-12-31 21:07:05 +01:00
& mut request_json ,
2020-05-09 21:47:09 +02:00
)
2020-09-15 08:55:02 +02:00
. expect ( " our request json is what ruma expects " ) ;
2020-04-19 14:14:47 +02:00
2020-10-27 19:10:09 -04:00
let request_json : serde_json ::Map < String , serde_json ::Value > =
serde_json ::from_slice ( & serde_json ::to_vec ( & request_json ) . unwrap ( ) ) . unwrap ( ) ;
2020-04-22 11:53:06 +02:00
let signatures = request_json [ " signatures " ]
. as_object ( )
. unwrap ( )
. values ( )
2020-08-14 11:31:31 +02:00
. map ( | v | {
v . as_object ( )
. unwrap ( )
. iter ( )
. map ( | ( k , v ) | ( k , v . as_str ( ) . unwrap ( ) ) )
} ) ;
for signature_server in signatures {
for s in signature_server {
http_request . headers_mut ( ) . insert (
AUTHORIZATION ,
HeaderValue ::from_str ( & format! (
" X-Matrix origin={},key= \" {} \" ,sig= \" {} \" " ,
2022-09-06 23:15:09 +02:00
services ( ) . globals . server_name ( ) ,
2020-08-14 11:31:31 +02:00
s . 0 ,
s . 1
) )
. unwrap ( ) ,
) ;
}
2020-04-22 11:53:06 +02:00
}
2023-10-26 20:11:19 -04:00
let reqwest_request = reqwest ::Request ::try_from ( http_request ) ? ;
2020-08-14 11:31:31 +02:00
2020-09-23 15:23:29 +02:00
let url = reqwest_request . url ( ) . clone ( ) ;
2021-08-26 23:11:13 +02:00
2023-03-13 08:27:59 +01:00
debug! ( " Sending request to {destination} at {url} " ) ;
2022-10-05 20:34:31 +02:00
let response = services ( )
. globals
. federation_client ( )
. execute ( reqwest_request )
. await ;
2023-03-13 08:27:59 +01:00
debug! ( " Received response from {destination} at {url} " ) ;
2020-04-22 11:53:06 +02:00
2021-04-29 20:58:05 +02:00
match response {
Ok ( mut response ) = > {
// reqwest::Response -> http::Response conversion
let status = response . status ( ) ;
let mut http_response_builder = http ::Response ::builder ( )
. status ( status )
. version ( response . version ( ) ) ;
mem ::swap (
response . headers_mut ( ) ,
http_response_builder
. headers_mut ( )
. expect ( " http::response::Builder is usable " ) ,
) ;
2020-12-05 21:03:43 +01:00
2023-03-13 08:27:59 +01:00
debug! ( " Getting response bytes from {destination} " ) ;
2021-04-29 20:58:05 +02:00
let body = response . bytes ( ) . await . unwrap_or_else ( | e | {
2023-10-28 23:40:44 -04:00
info! ( " server error {} " , e ) ;
2021-04-13 15:00:45 +02:00
Vec ::new ( ) . into ( )
} ) ; // TODO: handle timeout
2023-03-13 08:27:59 +01:00
debug! ( " Got response bytes from {destination} " ) ;
2020-12-05 21:03:43 +01:00
2023-10-28 22:36:47 -04:00
if ! status . is_success ( ) {
2023-10-28 23:40:44 -04:00
debug! (
" Response not successful \n {} {}: {} " ,
2021-03-26 11:10:45 +01:00
url ,
status ,
2021-03-26 13:41:05 +01:00
String ::from_utf8_lossy ( & body )
. lines ( )
. collect ::< Vec < _ > > ( )
. join ( " " )
2021-03-26 11:10:45 +01:00
) ;
2020-12-05 21:03:43 +01:00
}
2020-09-12 21:30:07 +02:00
2021-05-23 16:45:32 +02:00
let http_response = http_response_builder
. body ( body )
. expect ( " reqwest body is valid http body " ) ;
2023-10-28 22:36:47 -04:00
if status . is_success ( ) {
2023-03-13 08:27:59 +01:00
debug! ( " Parsing response bytes from {destination} " ) ;
2021-05-23 16:45:32 +02:00
let response = T ::IncomingResponse ::try_from_http_response ( http_response ) ;
2021-08-26 23:11:13 +02:00
if response . is_ok ( ) & & write_destination_to_cache {
2022-10-05 20:34:31 +02:00
services ( )
. globals
. actual_destination_cache
. write ( )
. unwrap ( )
. insert (
2022-10-09 17:25:06 +02:00
OwnedServerName ::from ( destination ) ,
2022-10-05 20:34:31 +02:00
( actual_destination , host ) ,
) ;
2021-08-26 23:11:13 +02:00
}
2021-08-04 22:55:03 +02:00
response . map_err ( | e | {
2021-08-17 16:06:09 +02:00
warn! (
" Invalid 200 response from {} on: {} {} " ,
& destination , url , e
) ;
2021-08-04 22:55:03 +02:00
Error ::BadServerResponse ( " Server returned bad 200 response. " )
} )
2021-05-23 16:45:32 +02:00
} else {
2023-03-13 08:27:59 +01:00
debug! ( " Returning error from {destination} " ) ;
2024-01-14 00:52:34 -05:00
// remove potentially dead destinations from our cache that may be from modified well-knowns
if ! write_destination_to_cache {
info! ( " Evicting {destination} from our true destination cache due to failed request. " ) ;
services ( )
. globals
. actual_destination_cache
. write ( )
. unwrap ( )
. remove ( destination ) ;
}
2021-05-23 16:45:32 +02:00
Err ( Error ::FederationError (
destination . to_owned ( ) ,
2022-12-14 13:09:10 +01:00
RumaError ::from_http_response ( http_response ) ,
2021-05-23 16:45:32 +02:00
) )
}
2020-04-22 11:53:06 +02:00
}
2022-10-13 10:14:52 +02:00
Err ( e ) = > {
2023-10-28 23:40:44 -04:00
// we do not need to log that servers in a room are dead, this is normal in public rooms and just spams the logs.
match e . is_timeout ( ) {
true = > info! (
2023-10-21 16:15:42 -04:00
" Timed out sending request to {} at {}: {} " ,
destination , actual_destination_str , e
2023-10-28 23:40:44 -04:00
) ,
false = > match e . is_connect ( ) {
true = > info! (
" Failed to connect to {} at {}: {} " ,
destination , actual_destination_str , e
) ,
false = > match e . is_redirect ( ) {
true = > info! (
" Redirect loop sending request to {} at {}: {} \n Final URL: {:?} " ,
destination ,
actual_destination_str ,
e ,
e . url ( )
) ,
false = > warn! (
" Could not send request to {} at {}: {} " ,
destination , actual_destination_str , e
) ,
} ,
} ,
2023-10-21 16:15:42 -04:00
}
2022-10-13 10:14:52 +02:00
Err ( e . into ( ) )
2022-10-15 00:28:43 +02:00
}
2020-04-22 11:53:06 +02:00
}
2020-04-19 14:14:47 +02:00
}
2020-04-22 20:55:11 +02:00
2021-04-16 12:18:22 -03:00
fn get_ip_with_port ( destination_str : & str ) -> Option < FedDest > {
2021-04-16 00:27:26 -03:00
if let Ok ( destination ) = destination_str . parse ::< SocketAddr > ( ) {
2021-04-16 12:18:22 -03:00
Some ( FedDest ::Literal ( destination ) )
2020-12-08 12:34:46 +01:00
} else if let Ok ( ip_addr ) = destination_str . parse ::< IpAddr > ( ) {
2021-04-16 12:18:22 -03:00
Some ( FedDest ::Literal ( SocketAddr ::new ( ip_addr , 8448 ) ) )
2020-12-08 12:34:46 +01:00
} else {
None
}
}
2021-04-16 12:18:22 -03:00
fn add_port_to_hostname ( destination_str : & str ) -> FedDest {
2021-04-16 00:27:26 -03:00
let ( host , port ) = match destination_str . find ( ':' ) {
None = > ( destination_str , " :8448 " ) ,
Some ( pos ) = > destination_str . split_at ( pos ) ,
} ;
2021-10-13 10:24:39 +02:00
FedDest ::Named ( host . to_owned ( ) , port . to_owned ( ) )
2020-12-08 12:34:46 +01:00
}
2020-12-06 11:05:51 +01:00
/// Returns: actual_destination, host header
2023-12-20 16:27:40 -08:00
/// Implemented according to the specification at <https://matrix.org/docs/spec/server_server/r0.1.4#resolving-server-names>
2020-12-08 12:34:46 +01:00
/// Numbers in comments below refer to bullet points in linked section of specification
2022-10-05 20:34:31 +02:00
async fn find_actual_destination ( destination : & '_ ServerName ) -> ( FedDest , FedDest ) {
2023-03-13 08:27:59 +01:00
debug! ( " Finding actual destination for {destination} " ) ;
2020-12-08 12:34:46 +01:00
let destination_str = destination . as_str ( ) . to_owned ( ) ;
2021-04-16 00:27:26 -03:00
let mut hostname = destination_str . clone ( ) ;
let actual_destination = match get_ip_with_port ( & destination_str ) {
2021-04-16 12:18:22 -03:00
Some ( host_port ) = > {
2023-03-13 08:27:59 +01:00
debug! ( " 1: IP literal with provided or default port " ) ;
2021-04-16 12:18:22 -03:00
host_port
}
None = > {
if let Some ( pos ) = destination_str . find ( ':' ) {
2023-03-13 08:27:59 +01:00
debug! ( " 2: Hostname with included port " ) ;
2021-04-16 12:18:22 -03:00
let ( host , port ) = destination_str . split_at ( pos ) ;
2021-10-13 10:24:39 +02:00
FedDest ::Named ( host . to_owned ( ) , port . to_owned ( ) )
2021-04-16 12:18:22 -03:00
} else {
2023-03-13 08:27:59 +01:00
debug! ( " Requesting well known for {destination} " ) ;
2022-09-06 23:15:09 +02:00
match request_well_known ( destination . as_str ( ) ) . await {
2021-04-16 12:18:22 -03:00
Some ( delegated_hostname ) = > {
2023-03-13 08:27:59 +01:00
debug! ( " 3: A .well-known file is available " ) ;
2021-08-26 23:11:13 +02:00
hostname = add_port_to_hostname ( & delegated_hostname ) . into_uri_string ( ) ;
2021-04-16 12:18:22 -03:00
match get_ip_with_port ( & delegated_hostname ) {
Some ( host_and_port ) = > host_and_port , // 3.1: IP literal in .well-known file
None = > {
2021-08-26 19:00:08 +02:00
if let Some ( pos ) = delegated_hostname . find ( ':' ) {
2023-03-13 08:27:59 +01:00
debug! ( " 3.2: Hostname with port in .well-known file " ) ;
2021-08-26 19:00:08 +02:00
let ( host , port ) = delegated_hostname . split_at ( pos ) ;
2021-10-13 10:24:39 +02:00
FedDest ::Named ( host . to_owned ( ) , port . to_owned ( ) )
2021-04-16 12:18:22 -03:00
} else {
2023-03-13 08:27:59 +01:00
debug! ( " Delegated hostname has no port in this branch " ) ;
2021-08-26 23:11:13 +02:00
if let Some ( hostname_override ) =
2022-09-06 23:15:09 +02:00
query_srv_record ( & delegated_hostname ) . await
2021-08-26 23:11:13 +02:00
{
2023-03-13 08:27:59 +01:00
debug! ( " 3.3: SRV lookup successful " ) ;
2021-08-26 23:11:13 +02:00
let force_port = hostname_override . port ( ) ;
2022-10-05 20:34:31 +02:00
if let Ok ( override_ip ) = services ( )
. globals
2021-08-26 23:11:13 +02:00
. dns_resolver ( )
. lookup_ip ( hostname_override . hostname ( ) )
. await
{
2022-10-05 20:34:31 +02:00
services ( )
. globals
. tls_name_override
. write ( )
. unwrap ( )
. insert (
delegated_hostname . clone ( ) ,
(
override_ip . iter ( ) . collect ( ) ,
force_port . unwrap_or ( 8448 ) ,
) ,
) ;
2021-08-26 23:11:13 +02:00
} else {
2023-10-28 23:40:44 -04:00
debug! (
" Using SRV record {}, but could not resolve to IP " ,
hostname_override . hostname ( )
) ;
2021-08-26 23:11:13 +02:00
}
if let Some ( port ) = force_port {
2022-12-21 10:42:12 +01:00
FedDest ::Named ( delegated_hostname , format! ( " : {port} " ) )
2021-08-26 23:11:13 +02:00
} else {
add_port_to_hostname ( & delegated_hostname )
}
} else {
2023-03-13 08:27:59 +01:00
debug! ( " 3.4: No SRV records, just use the hostname from .well-known " ) ;
2021-08-26 23:11:13 +02:00
add_port_to_hostname ( & delegated_hostname )
2020-12-08 12:34:46 +01:00
}
}
}
}
2021-04-16 12:18:22 -03:00
}
None = > {
2023-03-13 08:27:59 +01:00
debug! ( " 4: No .well-known or an error occured " ) ;
2022-09-06 23:15:09 +02:00
match query_srv_record ( & destination_str ) . await {
2021-08-26 23:11:13 +02:00
Some ( hostname_override ) = > {
2023-03-13 08:27:59 +01:00
debug! ( " 4: SRV record found " ) ;
2021-08-26 23:11:13 +02:00
let force_port = hostname_override . port ( ) ;
2022-10-05 20:34:31 +02:00
if let Ok ( override_ip ) = services ( )
. globals
2021-08-26 23:11:13 +02:00
. dns_resolver ( )
. lookup_ip ( hostname_override . hostname ( ) )
. await
{
2022-10-05 20:34:31 +02:00
services ( )
. globals
. tls_name_override
. write ( )
. unwrap ( )
. insert (
hostname . clone ( ) ,
(
override_ip . iter ( ) . collect ( ) ,
force_port . unwrap_or ( 8448 ) ,
) ,
) ;
2021-08-26 23:11:13 +02:00
} else {
2023-10-28 23:40:44 -04:00
debug! (
" Using SRV record {}, but could not resolve to IP " ,
hostname_override . hostname ( )
) ;
2021-08-26 23:11:13 +02:00
}
if let Some ( port ) = force_port {
2022-12-21 10:42:12 +01:00
FedDest ::Named ( hostname . clone ( ) , format! ( " : {port} " ) )
2021-08-26 23:11:13 +02:00
} else {
add_port_to_hostname ( & hostname )
}
}
2023-02-23 12:28:15 +01:00
None = > {
2023-03-13 08:27:59 +01:00
debug! ( " 5: No SRV record found " ) ;
2023-02-23 12:28:15 +01:00
add_port_to_hostname ( & destination_str )
}
2020-12-08 12:34:46 +01:00
}
}
}
2020-12-06 11:05:51 +01:00
}
2021-04-16 00:27:26 -03:00
}
2021-04-16 12:18:22 -03:00
} ;
2023-03-13 08:27:59 +01:00
debug! ( " Actual destination: {actual_destination:?} " ) ;
2020-12-06 11:05:51 +01:00
2021-04-21 00:35:44 -03:00
// Can't use get_ip_with_port here because we don't want to add a port
// to an IP address if it wasn't specified
2021-04-16 12:18:22 -03:00
let hostname = if let Ok ( addr ) = hostname . parse ::< SocketAddr > ( ) {
FedDest ::Literal ( addr )
} else if let Ok ( addr ) = hostname . parse ::< IpAddr > ( ) {
2021-10-13 10:24:39 +02:00
FedDest ::Named ( addr . to_string ( ) , " :8448 " . to_owned ( ) )
2021-04-16 12:18:22 -03:00
} else if let Some ( pos ) = hostname . find ( ':' ) {
let ( host , port ) = hostname . split_at ( pos ) ;
2021-10-13 10:24:39 +02:00
FedDest ::Named ( host . to_owned ( ) , port . to_owned ( ) )
2021-04-16 12:18:22 -03:00
} else {
2021-10-13 10:24:39 +02:00
FedDest ::Named ( hostname , " :8448 " . to_owned ( ) )
2021-04-16 12:18:22 -03:00
} ;
2021-04-16 00:27:26 -03:00
( actual_destination , hostname )
2020-12-06 11:05:51 +01:00
}
2022-10-05 20:34:31 +02:00
async fn query_srv_record ( hostname : & '_ str ) -> Option < FedDest > {
2023-09-02 17:53:46 -04:00
fn handle_successful_srv ( srv : SrvLookup ) -> Option < FedDest > {
srv . iter ( ) . next ( ) . map ( | result | {
FedDest ::Named (
result . target ( ) . to_string ( ) . trim_end_matches ( '.' ) . to_owned ( ) ,
format! ( " : {} " , result . port ( ) ) ,
)
2020-12-08 12:34:46 +01:00
} )
}
2023-09-02 17:53:46 -04:00
async fn lookup_srv ( hostname : & str ) -> Result < SrvLookup , ResolveError > {
debug! ( " querying SRV for {:?} " , hostname ) ;
let hostname = hostname . trim_end_matches ( '.' ) ;
services ( )
. globals
. dns_resolver ( )
2023-11-27 00:39:50 -05:00
. srv_lookup ( hostname . to_owned ( ) )
2023-09-02 17:53:46 -04:00
. await
}
let first_hostname = format! ( " _matrix-fed._tcp. {hostname} . " ) ;
let second_hostname = format! ( " _matrix._tcp. {hostname} . " ) ;
lookup_srv ( & first_hostname )
. or_else ( | _ | {
info! (
" Querying deprecated _matrix SRV record for host {:?} " ,
hostname
) ;
lookup_srv ( & second_hostname )
} )
. and_then ( | srv_lookup | async { Ok ( handle_successful_srv ( srv_lookup ) ) } )
. await
. ok ( )
. flatten ( )
2020-12-08 12:34:46 +01:00
}
2022-10-05 20:34:31 +02:00
async fn request_well_known ( destination : & str ) -> Option < String > {
2023-02-23 12:28:15 +01:00
let response = services ( )
. globals
. default_client ( )
. get ( & format! ( " https:// {destination} /.well-known/matrix/server " ) )
. send ( )
. await ;
2023-03-13 08:27:59 +01:00
debug! ( " Got well known response " ) ;
2024-01-13 18:08:50 -05:00
debug! ( " Well known response: {:?} " , response ) ;
2024-01-24 21:07:53 -05:00
2023-06-25 19:31:40 +02:00
if let Err ( e ) = & response {
2023-07-28 16:26:40 +01:00
debug! ( " Well known error: {e:?} " ) ;
return None ;
2023-06-25 19:31:40 +02:00
}
2024-01-24 21:07:53 -05:00
2023-02-23 12:28:15 +01:00
let text = response . ok ( ) ? . text ( ) . await ;
2024-01-24 21:07:53 -05:00
2023-03-13 08:27:59 +01:00
debug! ( " Got well known response text " ) ;
2024-01-13 18:08:50 -05:00
debug! ( " Well known response text: {:?} " , text ) ;
2024-01-24 21:07:53 -05:00
if text . as_ref ( ) . ok ( ) ? . len ( ) > 10000 {
info! ( " Well known response for destination '{destination}' exceeded past 10000 characters, assuming no well-known. " ) ;
return None ;
}
2023-02-23 12:28:15 +01:00
let body : serde_json ::Value = serde_json ::from_str ( & text . ok ( ) ? ) . ok ( ) ? ;
2024-01-24 21:07:53 -05:00
debug! ( " serde_json body of well known text: {} " , body ) ;
2020-12-08 12:34:46 +01:00
Some ( body . get ( " m.server " ) ? . as_str ( ) ? . to_owned ( ) )
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/version`
///
/// Get version information on this server.
2022-01-20 11:51:31 +01:00
pub async fn get_server_version_route (
_body : Ruma < get_server_version ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_server_version ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2021-04-11 21:01:27 +02:00
Ok ( get_server_version ::v1 ::Response {
server : Some ( get_server_version ::v1 ::Server {
2024-03-02 00:29:21 +00:00
name : Some ( " Conduwuit " . to_owned ( ) ) ,
2020-04-22 20:55:11 +02:00
version : Some ( env! ( " CARGO_PKG_VERSION " ) . to_owned ( ) ) ,
2020-04-28 20:03:14 +02:00
} ) ,
2022-01-22 16:58:32 +01:00
} )
2020-04-22 20:55:11 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `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.
2021-04-13 15:00:45 +02:00
// Response type for this endpoint is Json because we need to calculate a signature for the response
2022-09-06 23:15:09 +02:00
pub async fn get_server_keys_route ( ) -> Result < impl IntoResponse > {
if ! services ( ) . globals . allow_federation ( ) {
2022-01-22 13:32:21 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2022-10-09 17:25:06 +02:00
let mut verify_keys : BTreeMap < OwnedServerSigningKeyId , VerifyKey > = BTreeMap ::new ( ) ;
2020-04-22 20:55:11 +02:00
verify_keys . insert (
2022-09-06 23:15:09 +02:00
format! ( " ed25519: {} " , services ( ) . globals . keypair ( ) . version ( ) )
2021-11-27 00:30:28 +01:00
. try_into ( )
. expect ( " found invalid server signing keys in DB " ) ,
2020-08-14 11:31:31 +02:00
VerifyKey {
2022-09-06 23:15:09 +02:00
key : Base64 ::new ( services ( ) . globals . keypair ( ) . public_key ( ) . to_vec ( ) ) ,
2020-04-22 20:55:11 +02:00
} ,
) ;
let mut response = serde_json ::from_slice (
2021-04-13 15:00:45 +02:00
get_server_keys ::v2 ::Response {
2022-02-18 15:33:14 +01:00
server_key : Raw ::new ( & ServerSigningKeys {
2022-09-06 23:15:09 +02:00
server_name : services ( ) . globals . server_name ( ) . to_owned ( ) ,
2020-08-14 11:31:31 +02:00
verify_keys ,
old_verify_keys : BTreeMap ::new ( ) ,
signatures : BTreeMap ::new ( ) ,
2021-05-20 23:46:52 +02:00
valid_until_ts : MilliSecondsSinceUnixEpoch ::from_system_time (
2021-08-25 16:06:35 +02:00
SystemTime ::now ( ) + Duration ::from_secs ( 86400 * 7 ) ,
2021-05-20 23:46:52 +02:00
)
. expect ( " time is valid " ) ,
2022-02-18 15:33:14 +01:00
} )
. expect ( " static conversion, no errors " ) ,
2021-04-13 15:00:45 +02:00
}
2021-04-23 18:45:06 +02:00
. try_into_http_response ::< Vec < u8 > > ( )
2020-04-22 20:55:11 +02:00
. unwrap ( )
. body ( ) ,
)
. unwrap ( ) ;
2020-11-15 16:48:43 -05:00
2020-06-05 18:19:26 +02:00
ruma ::signatures ::sign_json (
2022-09-06 23:15:09 +02:00
services ( ) . globals . server_name ( ) . as_str ( ) ,
services ( ) . globals . keypair ( ) ,
2020-05-17 19:56:40 +02:00
& mut response ,
)
. unwrap ( ) ;
2020-11-15 16:48:43 -05:00
2022-01-22 13:32:21 +01:00
Ok ( Json ( response ) )
2020-04-22 20:55:11 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `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.
2022-09-06 23:15:09 +02:00
pub async fn get_server_keys_deprecated_route ( ) -> impl IntoResponse {
get_server_keys_route ( ) . await
2020-04-22 20:55:11 +02:00
}
2020-08-14 11:29:32 +02:00
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/federation/v1/publicRooms`
///
/// Lists the public rooms on this server.
2020-09-14 11:42:16 +02:00
pub async fn get_public_rooms_filtered_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_public_rooms_filtered ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_public_rooms_filtered ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2023-09-10 02:32:37 -04:00
if ! services ( )
. globals
. allow_public_room_directory_over_federation ( )
{
return Err ( Error ::bad_config ( " Room directory is not public. " ) ) ;
}
2020-09-14 11:42:16 +02:00
let response = client_server ::get_public_rooms_filtered_helper (
None ,
body . limit ,
body . since . as_deref ( ) ,
& body . filter ,
& body . room_network ,
)
2022-01-22 16:58:32 +01:00
. await ? ;
2020-09-14 11:42:16 +02:00
Ok ( get_public_rooms_filtered ::v1 ::Response {
2022-02-18 11:52:00 +01:00
chunk : response . chunk ,
2020-09-14 11:42:16 +02:00
prev_batch : response . prev_batch ,
next_batch : response . next_batch ,
total_room_count_estimate : response . total_room_count_estimate ,
2022-01-22 16:58:32 +01:00
} )
2020-09-14 11:42:16 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/publicRooms`
///
/// Lists the public rooms on this server.
2020-08-14 11:29:32 +02:00
pub async fn get_public_rooms_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_public_rooms ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_public_rooms ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2023-09-10 02:32:37 -04:00
if ! services ( )
. globals
. allow_public_room_directory_over_federation ( )
{
return Err ( Error ::bad_config ( " Room directory is not public. " ) ) ;
}
2020-09-14 11:42:16 +02:00
let response = client_server ::get_public_rooms_filtered_helper (
2020-08-23 08:32:43 -04:00
None ,
2020-09-14 11:42:16 +02:00
body . limit ,
body . since . as_deref ( ) ,
2022-12-14 13:09:10 +01:00
& Filter ::default ( ) ,
& RoomNetwork ::Matrix ,
2020-08-14 11:29:32 +02:00
)
2022-01-22 16:58:32 +01:00
. await ? ;
2020-08-14 11:29:32 +02:00
Ok ( get_public_rooms ::v1 ::Response {
2022-02-18 11:52:00 +01:00
chunk : response . chunk ,
2020-09-14 11:42:16 +02:00
prev_batch : response . prev_batch ,
next_batch : response . next_batch ,
total_room_count_estimate : response . total_room_count_estimate ,
2022-01-22 16:58:32 +01:00
} )
2020-08-14 11:29:32 +02:00
}
2023-02-20 22:59:45 +01:00
pub fn parse_incoming_pdu (
pdu : & RawJsonValue ,
) -> Result < ( OwnedEventId , CanonicalJsonObject , OwnedRoomId ) > {
let value : CanonicalJsonObject = serde_json ::from_str ( pdu . get ( ) ) . map_err ( | e | {
warn! ( " Error parsing incoming event {:?}: {:?} " , pdu , e ) ;
Error ::BadServerResponse ( " Invalid PDU in server response " )
} ) ? ;
let room_id : OwnedRoomId = value
. get ( " room_id " )
. and_then ( | id | RoomId ::parse ( id . as_str ( ) ? ) . ok ( ) )
. ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Invalid room id in pdu " ,
) ) ? ;
let room_version_id = services ( ) . rooms . state . get_room_version ( & room_id ) ? ;
2023-11-27 00:39:50 -05:00
let ( event_id , value ) = match gen_event_id_canonical_json ( pdu , & room_version_id ) {
2023-02-20 22:59:45 +01:00
Ok ( t ) = > t ,
Err ( _ ) = > {
// Event could not be converted to canonical json
return Err ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Could not convert event to canonical json. " ,
) ) ;
}
} ;
Ok ( ( event_id , value , room_id ) )
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/federation/v1/send/{txnId}`
///
/// Push EDUs and PDUs to this server.
2021-06-08 18:10:00 +02:00
pub async fn send_transaction_message_route (
2022-12-14 13:09:10 +01:00
body : Ruma < send_transaction_message ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < send_transaction_message ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2022-04-06 19:08:23 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2021-02-01 17:02:56 -05:00
let mut resolved_map = BTreeMap ::new ( ) ;
2021-04-13 21:34:31 +02:00
let pub_key_map = RwLock ::new ( BTreeMap ::new ( ) ) ;
2021-03-26 11:10:45 +01:00
// This is all the auth_events that have been recursively fetched so they don't have to be
// deserialized over and over again.
// TODO: make this persist across requests but not in a DB Tree (in globals?)
// TODO: This could potentially also be some sort of trie (suffix tree) like structure so
// that once an auth event is known it would know (using indexes maybe) all of the auth
// events that it references.
2021-06-29 20:18:52 -04:00
// let mut auth_cache = EventMap::new();
2021-03-26 11:10:45 +01:00
2023-11-24 20:05:42 +00:00
let mut parsed_pdus = vec! [ ] ;
2021-04-05 21:46:10 +02:00
for pdu in & body . pdus {
2023-08-11 10:48:48 +02:00
let value : CanonicalJsonObject = serde_json ::from_str ( pdu . get ( ) ) . map_err ( | e | {
warn! ( " Error parsing incoming event {:?}: {:?} " , pdu , e ) ;
Error ::BadServerResponse ( " Invalid PDU in server response " )
} ) ? ;
let room_id : OwnedRoomId = value
. get ( " room_id " )
. and_then ( | id | RoomId ::parse ( id . as_str ( ) ? ) . ok ( ) )
. ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Invalid room id in pdu " ,
) ) ? ;
if services ( ) . rooms . state . get_room_version ( & room_id ) . is_err ( ) {
debug! ( " Server is not in room {room_id} " ) ;
continue ;
}
2023-11-27 00:39:50 -05:00
let r = parse_incoming_pdu ( pdu ) ;
2023-02-22 09:32:47 +01:00
let ( event_id , value , room_id ) = match r {
Ok ( t ) = > t ,
Err ( e ) = > {
2023-07-28 23:40:10 +00:00
warn! ( " Could not parse PDU: {e} " ) ;
warn! ( " Full PDU: {:?} " , & pdu ) ;
2023-02-22 09:32:47 +01:00
continue ;
}
} ;
2023-11-24 20:05:42 +00:00
parsed_pdus . push ( ( event_id , value , room_id ) ) ;
2022-11-27 23:25:42 +01:00
// We do not add the event_id field to the pdu here because of signature and hashes checks
2023-11-24 20:05:42 +00:00
}
// We go through all the signatures we see on the PDUs and fetch the corresponding
// signing keys
services ( )
. rooms
. event_handler
. fetch_required_signing_keys (
parsed_pdus . iter ( ) . map ( | ( _event_id , event , _room_id ) | event ) ,
& pub_key_map ,
)
. await
. unwrap_or_else ( | e | {
warn! (
" Could not fetch all signatures for PDUs from {}: {:?} " ,
sender_servername , e
2024-03-02 20:55:02 -05:00
) ;
2023-11-24 20:05:42 +00:00
} ) ;
2022-11-27 23:25:42 +01:00
2023-11-24 20:05:42 +00:00
for ( event_id , value , room_id ) in parsed_pdus {
2021-07-01 19:55:26 +02:00
let mutex = Arc ::clone (
2022-10-05 20:34:31 +02:00
services ( )
. globals
2021-07-13 15:44:25 +02:00
. roomid_mutex_federation
2021-07-01 19:55:26 +02:00
. write ( )
. unwrap ( )
2024-03-02 20:55:02 -05:00
. entry ( room_id . clone ( ) )
2021-07-01 19:55:26 +02:00
. or_default ( ) ,
) ;
let mutex_lock = mutex . lock ( ) . await ;
2021-05-20 23:46:52 +02:00
let start_time = Instant ::now ( ) ;
2021-05-27 13:59:40 -03:00
resolved_map . insert (
event_id . clone ( ) ,
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
. handle_incoming_pdu (
2022-10-10 14:09:11 +02:00
sender_servername ,
2022-10-05 20:34:31 +02:00
& event_id ,
& room_id ,
value ,
true ,
& pub_key_map ,
)
. await
. map ( | _ | ( ) ) ,
2021-05-27 13:59:40 -03:00
) ;
2021-07-01 19:55:26 +02:00
drop ( mutex_lock ) ;
2021-05-20 23:46:52 +02:00
let elapsed = start_time . elapsed ( ) ;
2022-11-21 21:48:06 +02:00
debug! (
2021-08-12 17:55:16 +02:00
" Handling transaction of event {} took {}m{}s " ,
2021-08-06 20:00:08 +02:00
event_id ,
elapsed . as_secs ( ) / 60 ,
elapsed . as_secs ( ) % 60
) ;
2021-03-25 23:55:40 +01:00
}
2021-03-26 11:10:45 +01:00
for pdu in & resolved_map {
if let Err ( e ) = pdu . 1 {
2022-10-05 12:45:54 +02:00
if matches! ( e , Error ::BadRequest ( ErrorKind ::NotFound , _ ) ) {
2021-03-26 11:10:45 +01:00
warn! ( " Incoming PDU failed {:?} " , pdu ) ;
}
}
2021-03-25 23:55:40 +01:00
}
2021-05-12 20:04:28 +02:00
for edu in body
. edus
. iter ( )
2021-06-11 15:47:53 -04:00
. filter_map ( | edu | serde_json ::from_str ::< Edu > ( edu . json ( ) . get ( ) ) . ok ( ) )
2021-05-12 20:04:28 +02:00
{
match edu {
2023-07-10 16:41:00 +02:00
Edu ::Presence ( presence ) = > {
2023-09-08 14:36:39 +02:00
if ! services ( ) . globals . allow_incoming_presence ( ) {
continue ;
}
2023-07-10 16:41:00 +02:00
for update in presence . push {
for room_id in services ( ) . rooms . state_cache . rooms_joined ( & update . user_id ) {
services ( ) . rooms . edus . presence . set_presence (
& room_id ? ,
& update . user_id ,
update . presence . clone ( ) ,
Some ( update . currently_active ) ,
Some ( update . last_active_ago ) ,
update . status_msg . clone ( ) ,
) ? ;
}
}
}
2021-05-12 20:04:28 +02:00
Edu ::Receipt ( receipt ) = > {
for ( room_id , room_updates ) in receipt . receipts {
for ( user_id , user_updates ) in room_updates . read {
if let Some ( ( event_id , _ ) ) = user_updates
. event_ids
. iter ( )
. filter_map ( | id | {
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. timeline
. get_pdu_count ( id )
. ok ( )
. flatten ( )
. map ( | r | ( id , r ) )
2021-05-12 20:04:28 +02:00
} )
. max_by_key ( | ( _ , count ) | * count )
{
let mut user_receipts = BTreeMap ::new ( ) ;
user_receipts . insert ( user_id . clone ( ) , user_updates . data ) ;
2021-05-20 23:46:52 +02:00
let mut receipts = BTreeMap ::new ( ) ;
receipts . insert ( ReceiptType ::Read , user_receipts ) ;
2021-05-12 20:04:28 +02:00
let mut receipt_content = BTreeMap ::new ( ) ;
2021-05-20 23:46:52 +02:00
receipt_content . insert ( event_id . to_owned ( ) , receipts ) ;
2021-05-12 20:04:28 +02:00
2022-02-12 01:58:36 +01:00
let event = ReceiptEvent {
2021-05-20 23:46:52 +02:00
content : ReceiptEventContent ( receipt_content ) ,
room_id : room_id . clone ( ) ,
2022-02-12 01:58:36 +01:00
} ;
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. edus
. read_receipt
. readreceipt_update ( & user_id , & room_id , event ) ? ;
2021-05-12 20:04:28 +02:00
} else {
2021-08-11 21:17:01 +02:00
// TODO fetch missing events
2023-07-31 16:18:23 +02:00
debug! ( " No known event ids in read receipt: {:?} " , user_updates ) ;
2021-05-12 20:04:28 +02:00
}
}
}
}
Edu ::Typing ( typing ) = > {
2022-10-05 20:34:31 +02:00
if services ( )
. rooms
. state_cache
. is_joined ( & typing . user_id , & typing . room_id ) ?
{
2022-03-23 11:05:41 +01:00
if typing . typing {
2022-10-05 09:34:25 +02:00
services ( ) . rooms . edus . typing . typing_add (
2022-03-23 11:05:41 +01:00
& typing . user_id ,
& typing . room_id ,
3000 + utils ::millis_since_unix_epoch ( ) ,
) ? ;
} else {
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. edus
. typing
. typing_remove ( & typing . user_id , & typing . room_id ) ? ;
2022-03-23 11:05:41 +01:00
}
2021-05-12 20:04:28 +02:00
}
}
2021-08-24 19:10:31 +02:00
Edu ::DeviceListUpdate ( DeviceListUpdateContent { user_id , .. } ) = > {
2022-10-05 20:34:31 +02:00
services ( ) . users . mark_device_key_update ( & user_id ) ? ;
2021-05-28 13:44:40 +02:00
}
Edu ::DirectToDevice ( DirectDeviceContent {
sender ,
ev_type ,
message_id ,
messages ,
} ) = > {
// Check if this is a new transaction id
2022-09-06 23:15:09 +02:00
if services ( )
2021-05-28 13:44:40 +02:00
. transaction_ids
2022-02-12 15:03:07 +01:00
. existing_txnid ( & sender , None , & message_id ) ?
2021-05-28 13:44:40 +02:00
. is_some ( )
{
continue ;
}
for ( target_user_id , map ) in & messages {
for ( target_device_id_maybe , event ) in map {
match target_device_id_maybe {
2021-06-17 20:12:36 +02:00
DeviceIdOrAllDevices ::DeviceId ( target_device_id ) = > {
2022-09-06 23:15:09 +02:00
services ( ) . users . add_to_device_event (
2021-05-28 13:44:40 +02:00
& sender ,
2021-09-13 19:45:56 +02:00
target_user_id ,
target_device_id ,
2021-06-17 20:12:36 +02:00
& ev_type . to_string ( ) ,
2022-10-13 10:14:52 +02:00
event . deserialize_as ( ) . map_err ( | e | {
warn! ( " To-Device event is invalid: {event:?} {e} " ) ;
2021-05-28 13:44:40 +02:00
Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Event is invalid " ,
)
} ) ? ,
2024-03-02 20:55:02 -05:00
) ? ;
2021-05-28 13:44:40 +02:00
}
2021-06-17 20:12:36 +02:00
DeviceIdOrAllDevices ::AllDevices = > {
2022-10-05 20:34:31 +02:00
for target_device_id in
services ( ) . users . all_device_ids ( target_user_id )
{
2022-09-06 23:15:09 +02:00
services ( ) . users . add_to_device_event (
2021-05-28 13:44:40 +02:00
& sender ,
2021-09-13 19:45:56 +02:00
target_user_id ,
2021-05-28 13:44:40 +02:00
& target_device_id ? ,
2021-06-17 20:12:36 +02:00
& ev_type . to_string ( ) ,
event . deserialize_as ( ) . map_err ( | _ | {
2021-05-28 13:44:40 +02:00
Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Event is invalid " ,
)
} ) ? ,
) ? ;
}
}
}
}
}
// Save transaction id with empty data
2022-10-05 20:34:31 +02:00
services ( )
. transaction_ids
2022-02-12 15:03:07 +01:00
. add_txnid ( & sender , None , & message_id , & [ ] ) ? ;
2021-05-28 13:44:40 +02:00
}
2022-03-05 10:16:21 +08:00
Edu ::SigningKeyUpdate ( SigningKeyUpdateContent {
user_id ,
master_key ,
self_signing_key ,
} ) = > {
2022-04-06 19:08:23 +02:00
if user_id . server_name ( ) ! = sender_servername {
continue ;
}
2022-03-05 10:16:21 +08:00
if let Some ( master_key ) = master_key {
2022-09-06 23:15:09 +02:00
services ( ) . users . add_cross_signing_keys (
2022-03-05 10:16:21 +08:00
& user_id ,
& master_key ,
& self_signing_key ,
& None ,
2023-08-07 13:55:44 +02:00
true ,
2022-03-05 10:16:21 +08:00
) ? ;
}
}
2021-05-12 20:04:28 +02:00
Edu ::_Custom ( _ ) = > { }
}
}
2022-10-05 20:34:31 +02:00
Ok ( send_transaction_message ::v1 ::Response {
pdus : resolved_map
. into_iter ( )
2023-07-30 17:30:16 +00:00
. map ( | ( e , r ) | ( e , r . map_err ( | e | e . sanitized_error ( ) ) ) )
2022-10-05 20:34:31 +02:00
. collect ( ) ,
} )
2021-01-03 17:26:17 -05:00
}
2021-01-15 15:46:47 -05:00
2021-08-31 19:14:37 +02:00
/// # `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
2022-01-20 11:51:31 +01:00
pub async fn get_event_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_event ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_event ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-07 15:56:57 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2021-08-31 19:14:37 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-09-06 23:15:09 +02:00
let event = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. timeline
2021-08-31 19:14:37 +02:00
. get_pdu_json ( & body . event_id ) ?
2023-07-29 19:17:12 +00:00
. ok_or_else ( | | {
2023-07-28 23:40:10 +00:00
warn! ( " Event not found, event ID: {:?} " , & body . event_id ) ;
2023-07-29 14:30:48 +00:00
Error ::BadRequest ( ErrorKind ::NotFound , " Event not found. " )
} ) ? ;
2021-08-31 19:14:37 +02:00
let room_id_str = event
. get ( " room_id " )
. and_then ( | val | val . as_str ( ) )
. ok_or_else ( | | Error ::bad_database ( " Invalid event in database " ) ) ? ;
2021-11-27 00:30:28 +01:00
let room_id = < & RoomId > ::try_from ( room_id_str )
2021-08-31 19:14:37 +02:00
. map_err ( | _ | Error ::bad_database ( " Invalid room id field in event in database " ) ) ? ;
2022-10-05 20:34:31 +02:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , room_id ) ?
{
2022-01-17 14:35:38 +01:00
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room " ,
) ) ;
2021-08-31 19:14:37 +02:00
}
2023-02-22 15:49:55 +01:00
if ! services ( ) . rooms . state_accessor . server_can_see_event (
sender_servername ,
2023-11-27 00:39:50 -05:00
room_id ,
2023-02-22 15:49:55 +01:00
& body . event_id ,
) ? {
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not allowed to see event. " ,
) ) ;
}
2021-04-07 15:56:57 +02:00
Ok ( get_event ::v1 ::Response {
2022-09-06 23:15:09 +02:00
origin : services ( ) . globals . server_name ( ) . to_owned ( ) ,
2021-05-20 23:46:52 +02:00
origin_server_ts : MilliSecondsSinceUnixEpoch ::now ( ) ,
2021-08-31 19:14:37 +02:00
pdu : PduEvent ::convert_to_outgoing_federation_event ( event ) ,
2022-01-22 16:58:32 +01:00
} )
2021-04-07 15:56:57 +02:00
}
2023-02-18 13:20:20 +01:00
/// # `GET /_matrix/federation/v1/backfill/<room_id>`
///
/// Retrieves events from before the sender joined the room, if the room's
/// history visibility allows.
pub async fn get_backfill_route (
body : Ruma < get_backfill ::v1 ::Request > ,
) -> Result < get_backfill ::v1 ::Response > {
if ! services ( ) . globals . allow_federation ( ) {
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2023-07-31 16:18:23 +02:00
debug! ( " Got backfill request from: {} " , sender_servername ) ;
2023-02-18 13:20:20 +01:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , & body . room_id ) ?
{
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room. " ,
) ) ;
}
services ( )
. rooms
. event_handler
. acl_check ( sender_servername , & body . room_id ) ? ;
let until = body
. v
. iter ( )
. map ( | eventid | services ( ) . rooms . timeline . get_pdu_count ( eventid ) )
. filter_map ( | r | r . ok ( ) . flatten ( ) )
. max ( )
. ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" No known eventid in v " ,
) ) ? ;
let limit = body . limit . min ( uint! ( 100 ) ) ;
let all_events = services ( )
. rooms
. timeline
2023-11-27 00:39:50 -05:00
. pdus_until ( user_id! ( " @doesntmatter:conduit.rs " ) , & body . room_id , until ) ?
2023-02-18 13:20:20 +01:00
. take ( limit . try_into ( ) . unwrap ( ) ) ;
let events = all_events
2024-03-02 20:55:02 -05:00
. filter_map ( std ::result ::Result ::ok )
2023-02-18 13:20:20 +01:00
. filter ( | ( _ , e ) | {
matches! (
services ( ) . rooms . state_accessor . server_can_see_event (
sender_servername ,
& e . room_id ,
& e . event_id ,
) ,
Ok ( true ) ,
)
} )
2023-02-20 22:59:45 +01:00
. map ( | ( _ , pdu ) | services ( ) . rooms . timeline . get_pdu_json ( & pdu . event_id ) )
2023-02-18 13:20:20 +01:00
. filter_map ( | r | r . ok ( ) . flatten ( ) )
2023-11-27 00:39:50 -05:00
. map ( PduEvent ::convert_to_outgoing_federation_event )
2023-02-18 13:20:20 +01:00
. collect ( ) ;
Ok ( get_backfill ::v1 ::Response {
origin : services ( ) . globals . server_name ( ) . to_owned ( ) ,
origin_server_ts : MilliSecondsSinceUnixEpoch ::now ( ) ,
pdus : events ,
} )
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
///
/// Retrieves events that the sender is missing.
2022-01-20 11:51:31 +01:00
pub async fn get_missing_events_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_missing_events ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_missing_events ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2021-08-31 19:14:37 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , & body . room_id ) ?
{
2021-08-31 19:14:37 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room " ,
) ) ;
}
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-01-17 14:35:38 +01:00
2020-09-25 12:26:29 +02:00
let mut queued_events = body . latest_events . clone ( ) ;
let mut events = Vec ::new ( ) ;
let mut i = 0 ;
while i < queued_events . len ( ) & & events . len ( ) < u64 ::from ( body . limit ) as usize {
2022-10-05 09:34:25 +02:00
if let Some ( pdu ) = services ( ) . rooms . timeline . get_pdu_json ( & queued_events [ i ] ) ? {
2021-08-31 19:14:37 +02:00
let room_id_str = pdu
. get ( " room_id " )
. and_then ( | val | val . as_str ( ) )
. ok_or_else ( | | Error ::bad_database ( " Invalid event in database " ) ) ? ;
2021-11-27 00:30:28 +01:00
let event_room_id = < & RoomId > ::try_from ( room_id_str )
2021-08-31 19:14:37 +02:00
. map_err ( | _ | Error ::bad_database ( " Invalid room id field in event in database " ) ) ? ;
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 " ,
) ) ;
}
2021-04-14 10:43:31 +02:00
2021-08-31 19:14:37 +02:00
if body . earliest_events . contains ( & queued_events [ i ] ) {
2020-09-25 12:26:29 +02:00
i + = 1 ;
continue ;
}
2023-02-22 15:49:55 +01:00
if ! services ( ) . rooms . state_accessor . server_can_see_event (
sender_servername ,
& body . room_id ,
& queued_events [ i ] ,
) ? {
i + = 1 ;
continue ;
}
2020-09-25 12:26:29 +02:00
queued_events . extend_from_slice (
2022-10-09 17:25:06 +02:00
& serde_json ::from_value ::< Vec < OwnedEventId > > (
2021-04-11 21:01:27 +02:00
serde_json ::to_value ( pdu . get ( " prev_events " ) . cloned ( ) . ok_or_else ( | | {
Error ::bad_database ( " Event in db has no prev_events field. " )
} ) ? )
. expect ( " canonical json is valid json value " ) ,
2020-09-25 12:26:29 +02:00
)
. map_err ( | _ | Error ::bad_database ( " Invalid prev_events content in pdu in db. " ) ) ? ,
) ;
2021-04-11 21:01:27 +02:00
events . push ( PduEvent ::convert_to_outgoing_federation_event ( pdu ) ) ;
2020-09-25 12:26:29 +02:00
}
i + = 1 ;
}
2022-01-22 16:58:32 +01:00
Ok ( get_missing_events ::v1 ::Response { events } )
2020-09-25 12:26:29 +02:00
}
2020-10-05 22:19:22 +02:00
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}`
///
/// Retrieves the auth chain for a given event.
///
/// - This does not include the event itself
2022-01-20 11:51:31 +01:00
pub async fn get_event_authorization_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_event_authorization ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_event_authorization ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-06-14 11:36:18 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2021-08-31 19:14:37 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , & body . room_id ) ?
{
2022-01-17 14:35:38 +01:00
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room. " ,
) ) ;
}
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-01-17 14:35:38 +01:00
2022-09-06 23:15:09 +02:00
let event = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. timeline
2021-08-31 19:14:37 +02:00
. get_pdu_json ( & body . event_id ) ?
2023-07-29 19:17:12 +00:00
. ok_or_else ( | | {
2023-07-28 23:40:10 +00:00
warn! ( " Event not found, event ID: {:?} " , & body . event_id ) ;
2023-07-29 14:30:48 +00:00
Error ::BadRequest ( ErrorKind ::NotFound , " Event not found. " )
} ) ? ;
2021-08-31 19:14:37 +02:00
let room_id_str = event
. get ( " room_id " )
. and_then ( | val | val . as_str ( ) )
. ok_or_else ( | | Error ::bad_database ( " Invalid event in database " ) ) ? ;
2021-11-27 00:30:28 +01:00
let room_id = < & RoomId > ::try_from ( room_id_str )
2021-08-31 19:14:37 +02:00
. map_err ( | _ | Error ::bad_database ( " Invalid room id field in event in database " ) ) ? ;
2022-10-05 20:34:31 +02:00
let auth_chain_ids = services ( )
. rooms
. auth_chain
. get_auth_chain ( room_id , vec! [ Arc ::from ( & * body . event_id ) ] )
. await ? ;
2021-06-14 11:36:18 +02:00
2021-07-18 20:43:39 +02:00
Ok ( get_event_authorization ::v1 ::Response {
auth_chain : auth_chain_ids
2022-10-05 09:34:25 +02:00
. filter_map ( | id | services ( ) . rooms . timeline . get_pdu_json ( & id ) . ok ( ) ? )
2021-08-26 17:58:32 -04:00
. map ( PduEvent ::convert_to_outgoing_federation_event )
2021-07-18 20:43:39 +02:00
. collect ( ) ,
2022-01-22 16:58:32 +01:00
} )
2021-06-14 11:36:18 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/state/{roomId}`
///
/// Retrieves the current state of the room.
2022-01-20 11:51:31 +01:00
pub async fn get_room_state_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_room_state ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_room_state ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-06-14 10:52:27 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2021-08-31 19:14:37 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , & body . room_id ) ?
{
2021-08-31 19:14:37 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room. " ,
) ) ;
}
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-01-17 14:35:38 +01:00
2022-09-06 23:15:09 +02:00
let shortstatehash = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. state_accessor
2021-06-14 10:52:27 +02:00
. pdu_shortstatehash ( & body . event_id ) ?
. ok_or ( Error ::BadRequest (
ErrorKind ::NotFound ,
" Pdu state not found. " ,
) ) ? ;
2022-09-06 23:15:09 +02:00
let pdus = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. state_accessor
2022-06-18 16:38:41 +02:00
. state_full_ids ( shortstatehash )
. await ?
2022-10-10 14:09:11 +02:00
. into_values ( )
. map ( | id | {
2021-06-14 10:52:27 +02:00
PduEvent ::convert_to_outgoing_federation_event (
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. timeline
. get_pdu_json ( & id )
. unwrap ( )
. unwrap ( ) ,
2021-06-14 10:52:27 +02:00
)
} )
. collect ( ) ;
2022-10-05 20:34:31 +02:00
let auth_chain_ids = services ( )
. rooms
. auth_chain
. get_auth_chain ( & body . room_id , vec! [ Arc ::from ( & * body . event_id ) ] )
. await ? ;
2021-06-14 10:52:27 +02:00
2021-07-18 20:43:39 +02:00
Ok ( get_room_state ::v1 ::Response {
auth_chain : auth_chain_ids
2022-10-11 18:10:51 +02:00
. filter_map (
| id | match services ( ) . rooms . timeline . get_pdu_json ( & id ) . ok ( ) ? {
Some ( json ) = > Some ( PduEvent ::convert_to_outgoing_federation_event ( json ) ) ,
None = > {
error! ( " Could not find event json for {id} in db. " ) ;
None
2022-10-11 17:59:49 +02:00
}
2022-10-11 18:10:51 +02:00
} ,
)
2021-07-18 20:43:39 +02:00
. collect ( ) ,
pdus ,
2022-01-22 16:58:32 +01:00
} )
2021-06-14 10:52:27 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/state_ids/{roomId}`
///
/// Retrieves the current state of the room.
2022-01-20 11:51:31 +01:00
pub async fn get_room_state_ids_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_room_state_ids ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_room_state_ids ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-03-18 00:09:57 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2021-08-31 19:14:37 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
if ! services ( )
. rooms
. state_cache
. server_in_room ( sender_servername , & body . room_id ) ?
{
2021-08-31 19:14:37 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" Server is not in room. " ,
) ) ;
}
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-01-17 14:35:38 +01:00
2022-09-06 23:15:09 +02:00
let shortstatehash = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. state_accessor
2021-03-18 00:09:57 +01:00
. pdu_shortstatehash ( & body . event_id ) ?
. ok_or ( Error ::BadRequest (
ErrorKind ::NotFound ,
" Pdu state not found. " ,
) ) ? ;
2022-09-06 23:15:09 +02:00
let pdu_ids = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. state_accessor
2022-06-18 16:38:41 +02:00
. state_full_ids ( shortstatehash )
. await ?
2022-10-10 14:09:11 +02:00
. into_values ( )
. map ( | id | ( * id ) . to_owned ( ) )
2021-07-01 19:55:26 +02:00
. collect ( ) ;
2021-03-18 00:09:57 +01:00
2022-10-05 20:34:31 +02:00
let auth_chain_ids = services ( )
. rooms
. auth_chain
. get_auth_chain ( & body . room_id , vec! [ Arc ::from ( & * body . event_id ) ] )
. await ? ;
2021-03-18 00:09:57 +01:00
Ok ( get_room_state_ids ::v1 ::Response {
2021-11-26 20:36:40 +01:00
auth_chain_ids : auth_chain_ids . map ( | id | ( * id ) . to_owned ( ) ) . collect ( ) ,
2021-03-18 00:09:57 +01:00
pdu_ids ,
2022-01-22 16:58:32 +01:00
} )
2021-03-18 00:09:57 +01:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
///
/// Creates a join template.
2022-01-20 11:51:31 +01:00
pub async fn create_join_event_template_route (
2022-12-14 13:09:10 +01:00
body : Ruma < prepare_join_event ::v1 ::Request > ,
2022-02-18 15:33:14 +01:00
) -> Result < prepare_join_event ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-16 18:18:29 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2022-10-05 09:34:25 +02:00
if ! services ( ) . rooms . metadata . exists ( & body . room_id ) ? {
2021-04-16 18:18:29 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::NotFound ,
2022-01-17 14:35:38 +01:00
" Room is unknown to this server. " ,
2021-04-16 18:18:29 +02:00
) ) ;
}
2022-01-17 14:35:38 +01:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-09-06 23:15:09 +02:00
let mutex_state = Arc ::clone (
2022-10-05 20:34:31 +02:00
services ( )
. globals
2022-09-06 23:15:09 +02:00
. roomid_mutex_state
. write ( )
. unwrap ( )
2024-03-02 20:55:02 -05:00
. entry ( body . room_id . clone ( ) )
2022-09-06 23:15:09 +02:00
. or_default ( ) ,
) ;
let state_lock = mutex_state . lock ( ) . await ;
2022-01-17 14:35:38 +01:00
2022-01-18 16:53:25 +01:00
// TODO: Conduit does not implement restricted join rules yet, we always reject
2022-10-05 20:34:31 +02:00
let join_rules_event = services ( ) . rooms . state_accessor . room_state_get (
& body . room_id ,
& StateEventType ::RoomJoinRules ,
" " ,
) ? ;
2022-01-18 16:53:25 +01:00
let join_rules_event_content : Option < RoomJoinRulesEventContent > = join_rules_event
. as_ref ( )
. map ( | join_rules_event | {
serde_json ::from_str ( join_rules_event . content . get ( ) ) . map_err ( | e | {
warn! ( " Invalid join rules event: {} " , e ) ;
Error ::bad_database ( " Invalid join rules event in db. " )
} )
} )
. transpose ( ) ? ;
if let Some ( join_rules_event_content ) = join_rules_event_content {
if matches! (
join_rules_event_content . join_rule ,
2022-10-11 11:53:13 +02:00
JoinRule ::Restricted { .. } | JoinRule ::KnockRestricted { .. }
2022-01-18 16:53:25 +01:00
) {
return Err ( Error ::BadRequest (
2022-10-11 11:53:13 +02:00
ErrorKind ::UnableToAuthorizeJoin ,
2022-01-18 16:53:25 +01:00
" Conduit does not support restricted rooms yet. " ,
) ) ;
}
}
2022-10-05 09:34:25 +02:00
let room_version_id = services ( ) . rooms . state . get_room_version ( & body . room_id ) ? ;
if ! body . ver . contains ( & room_version_id ) {
2021-07-21 11:29:13 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::IncompatibleRoomVersion {
room_version : room_version_id ,
} ,
" Room version not supported. " ,
) ) ;
}
2021-04-16 18:18:29 +02:00
2021-10-13 10:16:45 +02:00
let content = to_raw_value ( & RoomMemberEventContent {
2021-04-16 18:18:29 +02:00
avatar_url : None ,
2021-07-15 23:17:58 +02:00
blurhash : None ,
2021-04-16 18:18:29 +02:00
displayname : None ,
is_direct : None ,
membership : MembershipState ::Join ,
third_party_invite : None ,
2021-08-19 11:01:18 +02:00
reason : None ,
2021-11-27 17:44:52 +01:00
join_authorized_via_users_server : None ,
2021-04-16 18:18:29 +02:00
} )
. expect ( " member event is valid value " ) ;
2022-10-12 10:57:54 +02:00
let ( _pdu , mut pdu_json ) = services ( ) . rooms . timeline . create_hash_and_sign_event (
2022-10-05 20:34:31 +02:00
PduBuilder {
2023-02-26 16:29:06 +01:00
event_type : TimelineEventType ::RoomMember ,
2022-10-05 20:34:31 +02:00
content ,
unsigned : None ,
state_key : Some ( body . user_id . to_string ( ) ) ,
redacts : None ,
} ,
& body . user_id ,
& body . room_id ,
& state_lock ,
) ? ;
2021-04-16 18:18:29 +02:00
2022-09-06 23:15:09 +02:00
drop ( state_lock ) ;
2021-04-16 18:18:29 +02:00
2022-10-12 10:57:54 +02:00
pdu_json . remove ( " event_id " ) ;
2022-02-18 15:33:14 +01:00
Ok ( prepare_join_event ::v1 ::Response {
2021-07-21 11:29:13 +02:00
room_version : Some ( room_version_id ) ,
2021-10-13 10:16:45 +02:00
event : to_raw_value ( & pdu_json ) . expect ( " CanonicalJson can be serialized to JSON " ) ,
2022-01-22 16:58:32 +01:00
} )
2021-04-16 18:18:29 +02:00
}
2021-07-25 19:28:54 +02:00
async fn create_join_event (
2022-01-17 14:35:38 +01:00
sender_servername : & ServerName ,
2021-07-25 19:28:54 +02:00
room_id : & RoomId ,
2021-10-13 10:16:45 +02:00
pdu : & RawJsonValue ,
2023-02-26 16:29:06 +01:00
) -> Result < create_join_event ::v1 ::RoomState > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-16 18:18:29 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2022-10-05 09:34:25 +02:00
if ! services ( ) . rooms . metadata . exists ( room_id ) ? {
2022-01-17 14:35:38 +01:00
return Err ( Error ::BadRequest (
ErrorKind ::NotFound ,
" Room is unknown to this server. " ,
) ) ;
}
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , room_id ) ? ;
2022-01-17 14:35:38 +01:00
2022-01-18 16:53:25 +01:00
// TODO: Conduit does not implement restricted join rules yet, we always reject
2022-10-05 20:34:31 +02:00
let join_rules_event = services ( ) . rooms . state_accessor . room_state_get (
room_id ,
& StateEventType ::RoomJoinRules ,
" " ,
) ? ;
2022-01-18 16:53:25 +01:00
let join_rules_event_content : Option < RoomJoinRulesEventContent > = join_rules_event
. as_ref ( )
. map ( | join_rules_event | {
serde_json ::from_str ( join_rules_event . content . get ( ) ) . map_err ( | e | {
warn! ( " Invalid join rules event: {} " , e ) ;
Error ::bad_database ( " Invalid join rules event in db. " )
} )
} )
. transpose ( ) ? ;
if let Some ( join_rules_event_content ) = join_rules_event_content {
if matches! (
join_rules_event_content . join_rule ,
2022-10-11 11:53:13 +02:00
JoinRule ::Restricted { .. } | JoinRule ::KnockRestricted { .. }
2022-01-18 16:53:25 +01:00
) {
return Err ( Error ::BadRequest (
2022-10-11 11:53:13 +02:00
ErrorKind ::UnableToAuthorizeJoin ,
2022-01-18 16:53:25 +01:00
" Conduit does not support restricted rooms yet. " ,
) ) ;
}
}
2021-04-16 18:18:29 +02:00
// We need to return the state prior to joining, let's keep a reference to that here
2022-09-06 23:15:09 +02:00
let shortstatehash = services ( )
2022-10-05 20:34:31 +02:00
. rooms
. state
2022-10-05 09:34:25 +02:00
. get_room_shortstatehash ( room_id ) ?
2021-07-25 19:28:54 +02:00
. ok_or ( Error ::BadRequest (
ErrorKind ::NotFound ,
" Pdu state not found. " ,
) ) ? ;
2021-04-16 18:18:29 +02:00
let pub_key_map = RwLock ::new ( BTreeMap ::new ( ) ) ;
2021-06-29 20:18:52 -04:00
// let mut auth_cache = EventMap::new();
2021-04-16 18:18:29 +02:00
// We do not add the event_id field to the pdu here because of signature and hashes checks
2022-11-27 23:25:42 +01:00
let room_version_id = services ( ) . rooms . state . get_room_version ( room_id ) ? ;
let ( event_id , value ) = match gen_event_id_canonical_json ( pdu , & room_version_id ) {
2021-04-16 18:18:29 +02:00
Ok ( t ) = > t ,
Err ( _ ) = > {
// Event could not be converted to canonical json
return Err ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Could not convert event to canonical json. " ,
) ) ;
}
} ;
2022-10-09 17:25:06 +02:00
let origin : OwnedServerName = serde_json ::from_value (
2021-04-16 18:18:29 +02:00
serde_json ::to_value ( value . get ( " origin " ) . ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Event needs an origin field. " ,
) ) ? )
. expect ( " CanonicalJson is valid json value " ) ,
)
. map_err ( | _ | Error ::BadRequest ( ErrorKind ::InvalidParam , " Origin field is invalid. " ) ) ? ;
2023-12-12 18:41:06 +00:00
services ( )
. rooms
. event_handler
. fetch_required_signing_keys ( [ & value ] , & pub_key_map )
. await ? ;
2021-07-01 19:55:26 +02:00
let mutex = Arc ::clone (
2022-10-05 20:34:31 +02:00
services ( )
. globals
2021-07-13 15:44:25 +02:00
. roomid_mutex_federation
2021-07-01 19:55:26 +02:00
. write ( )
. unwrap ( )
2021-11-26 20:36:40 +01:00
. entry ( room_id . to_owned ( ) )
2021-07-01 19:55:26 +02:00
. or_default ( ) ,
) ;
let mutex_lock = mutex . lock ( ) . await ;
2022-10-05 20:34:31 +02:00
let pdu_id : Vec < u8 > = services ( )
. rooms
. event_handler
. handle_incoming_pdu ( & origin , & event_id , room_id , value , true , & pub_key_map )
2022-10-05 09:34:25 +02:00
. await ?
2021-07-25 19:28:54 +02:00
. ok_or ( Error ::BadRequest (
2021-04-16 18:18:29 +02:00
ErrorKind ::InvalidParam ,
2021-07-25 19:28:54 +02:00
" Could not accept incoming PDU as timeline event. " ,
) ) ? ;
2021-07-01 19:55:26 +02:00
drop ( mutex_lock ) ;
2021-04-16 18:18:29 +02:00
2022-10-05 20:34:31 +02:00
let state_ids = services ( )
. rooms
. state_accessor
. state_full_ids ( shortstatehash )
. await ? ;
let auth_chain_ids = services ( )
. rooms
. auth_chain
2022-10-10 14:09:11 +02:00
. get_auth_chain ( room_id , state_ids . values ( ) . cloned ( ) . collect ( ) )
2022-10-05 20:34:31 +02:00
. await ? ;
2021-04-16 18:18:29 +02:00
2022-09-06 23:15:09 +02:00
let servers = services ( )
2021-04-16 18:18:29 +02:00
. rooms
2022-10-05 09:34:25 +02:00
. state_cache
2021-09-13 19:45:56 +02:00
. room_servers ( room_id )
2024-03-02 20:55:02 -05:00
. filter_map ( std ::result ::Result ::ok )
2022-09-06 23:15:09 +02:00
. filter ( | server | & * * server ! = services ( ) . globals . server_name ( ) ) ;
2021-04-16 18:18:29 +02:00
2022-09-06 23:15:09 +02:00
services ( ) . sending . send_pdu ( servers , & pdu_id ) ? ;
2021-07-14 07:07:08 +00:00
2023-02-26 16:29:06 +01:00
Ok ( create_join_event ::v1 ::RoomState {
2021-07-25 19:28:54 +02:00
auth_chain : auth_chain_ids
2022-10-05 09:34:25 +02:00
. filter_map ( | id | services ( ) . rooms . timeline . get_pdu_json ( & id ) . ok ( ) . flatten ( ) )
2021-07-25 19:28:54 +02:00
. map ( PduEvent ::convert_to_outgoing_federation_event )
. collect ( ) ,
state : state_ids
. iter ( )
2022-10-05 09:34:25 +02:00
. filter_map ( | ( _ , id ) | services ( ) . rooms . timeline . get_pdu_json ( id ) . ok ( ) . flatten ( ) )
2021-07-25 19:28:54 +02:00
. map ( PduEvent ::convert_to_outgoing_federation_event )
. collect ( ) ,
2022-11-09 18:46:10 +01:00
event : None , // TODO: handle restricted joins
2021-07-25 19:28:54 +02:00
} )
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}`
///
/// Submits a signed join event.
2021-07-25 19:28:54 +02:00
pub async fn create_join_event_v1_route (
2022-12-14 13:09:10 +01:00
body : Ruma < create_join_event ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < create_join_event ::v1 ::Response > {
2022-01-17 14:35:38 +01:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-09-06 23:15:09 +02:00
let room_state = create_join_event ( sender_servername , & body . room_id , & body . pdu ) . await ? ;
2021-07-25 19:28:54 +02:00
2022-01-22 16:58:32 +01:00
Ok ( create_join_event ::v1 ::Response { room_state } )
2021-07-25 19:28:54 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`
///
/// Submits a signed join event.
2021-07-25 19:28:54 +02:00
pub async fn create_join_event_v2_route (
2022-12-14 13:09:10 +01:00
body : Ruma < create_join_event ::v2 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < create_join_event ::v2 ::Response > {
2022-01-17 14:35:38 +01:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2023-02-26 16:29:06 +01:00
let create_join_event ::v1 ::RoomState {
auth_chain ,
state ,
event ,
} = create_join_event ( sender_servername , & body . room_id , & body . pdu ) . await ? ;
let room_state = create_join_event ::v2 ::RoomState {
members_omitted : false ,
auth_chain ,
state ,
event ,
servers_in_room : None ,
} ;
2021-07-25 19:28:54 +02:00
2022-01-22 16:58:32 +01:00
Ok ( create_join_event ::v2 ::Response { room_state } )
2021-04-16 18:18:29 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`
///
/// Invites a remote user to a room.
2021-06-08 18:10:00 +02:00
pub async fn create_invite_route (
2022-12-14 13:09:10 +01:00
body : Ruma < create_invite ::v2 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < create_invite ::v2 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-16 18:18:29 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2022-01-17 14:35:38 +01:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2022-10-05 20:34:31 +02:00
services ( )
. rooms
. event_handler
2022-10-10 14:09:11 +02:00
. acl_check ( sender_servername , & body . room_id ) ? ;
2022-01-17 14:35:38 +01:00
2022-10-05 20:34:31 +02:00
if ! services ( )
. globals
. supported_room_versions ( )
. contains ( & body . room_version )
{
2021-04-11 21:01:27 +02:00
return Err ( Error ::BadRequest (
ErrorKind ::IncompatibleRoomVersion {
room_version : body . room_version . clone ( ) ,
} ,
" Server does not support this room version. " ,
) ) ;
}
2024-01-17 22:07:43 -05:00
let mut signed_event = utils ::to_canonical_object ( & body . event ) . map_err ( | e | {
error! ( " Failed to convert invite event to canonical JSON: {} " , e ) ;
Error ::BadRequest ( ErrorKind ::InvalidParam , " Invite event is invalid. " )
} ) ? ;
2021-04-11 21:01:27 +02:00
ruma ::signatures ::hash_and_sign_event (
2022-09-06 23:15:09 +02:00
services ( ) . globals . server_name ( ) . as_str ( ) ,
services ( ) . globals . keypair ( ) ,
2021-04-11 21:01:27 +02:00
& mut signed_event ,
& body . room_version ,
)
. map_err ( | _ | Error ::BadRequest ( ErrorKind ::InvalidParam , " Failed to sign event. " ) ) ? ;
2021-04-13 21:34:31 +02:00
// Generate event id
2021-11-27 00:30:28 +01:00
let event_id = EventId ::parse ( format! (
2021-04-13 21:34:31 +02:00
" ${} " ,
ruma ::signatures ::reference_hash ( & signed_event , & body . room_version )
. expect ( " ruma can calculate reference hashes " )
) )
. expect ( " ruma's reference hashes are valid event ids " ) ;
// Add event_id back
signed_event . insert (
" event_id " . to_owned ( ) ,
2022-10-09 17:25:06 +02:00
CanonicalJsonValue ::String ( event_id . to_string ( ) ) ,
2021-04-13 21:34:31 +02:00
) ;
2022-10-09 17:25:06 +02:00
let sender : OwnedUserId = serde_json ::from_value (
2021-04-26 18:20:20 +02:00
signed_event
. get ( " sender " )
. ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Event had no sender field. " ,
) ) ?
. clone ( )
. into ( ) ,
2021-04-11 21:01:27 +02:00
)
. map_err ( | _ | Error ::BadRequest ( ErrorKind ::InvalidParam , " sender is not a user id. " ) ) ? ;
2021-04-26 18:20:20 +02:00
2021-11-26 20:36:40 +01:00
let invited_user : Box < _ > = serde_json ::from_value (
2021-04-26 18:20:20 +02:00
signed_event
. get ( " state_key " )
. ok_or ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Event had no state_key field. " ,
) ) ?
. clone ( )
. into ( ) ,
2021-04-11 21:01:27 +02:00
)
. map_err ( | _ | Error ::BadRequest ( ErrorKind ::InvalidParam , " state_key is not a user id. " ) ) ? ;
2024-03-02 21:54:16 -05:00
if services ( ) . rooms . metadata . is_banned ( & body . room_id ) ?
& & ! services ( ) . users . is_admin ( & invited_user ) ?
{
2024-03-02 21:49:04 -05:00
info! (
" Received remote invite from server {} for room {} and for user {invited_user}, but room is banned by us. " ,
& sender_servername , & body . room_id
) ;
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" This room is banned on this homeserver. " ,
) ) ;
}
2024-03-02 21:54:16 -05:00
if services ( ) . globals . block_non_admin_invites ( ) & & ! services ( ) . users . is_admin ( & invited_user ) ? {
info! ( " Received remote invite from server {} for room {} and for user {invited_user} who is not an admin, but \" block_non_admin_invites \" is enabled, rejecting. " , & sender_servername , & body . room_id ) ;
return Err ( Error ::BadRequest (
ErrorKind ::Forbidden ,
" This server does not allow room invites. " ,
) ) ;
}
2021-04-11 21:01:27 +02:00
let mut invite_state = body . invite_room_state . clone ( ) ;
2021-10-13 11:51:30 +02:00
let mut event : JsonObject = serde_json ::from_str ( body . event . get ( ) )
. map_err ( | _ | Error ::BadRequest ( ErrorKind ::InvalidParam , " Invalid invite event bytes. " ) ) ? ;
2021-04-11 21:01:27 +02:00
event . insert ( " event_id " . to_owned ( ) , " $dummy " . into ( ) ) ;
2021-10-13 11:51:30 +02:00
let pdu : PduEvent = serde_json ::from_value ( event . into ( ) ) . map_err ( | e | {
2021-04-13 21:34:31 +02:00
warn! ( " Invalid invite event: {} " , e ) ;
Error ::BadRequest ( ErrorKind ::InvalidParam , " Invalid invite event. " )
} ) ? ;
invite_state . push ( pdu . to_stripped_state_event ( ) ) ;
2022-11-27 23:25:42 +01:00
// If we are active in the room, the remote server will notify us about the join via /send
if ! services ( )
. rooms
. state_cache
. server_in_room ( services ( ) . globals . server_name ( ) , & body . room_id ) ?
{
2023-11-25 18:29:38 -05:00
services ( )
. rooms
. state_cache
. update_membership (
& body . room_id ,
& invited_user ,
2024-01-11 20:39:37 -05:00
RoomMemberEventContent ::new ( MembershipState ::Invite ) ,
2023-11-25 18:29:38 -05:00
& sender ,
Some ( invite_state ) ,
true ,
)
. await ? ;
2021-04-13 21:34:31 +02:00
}
2021-04-11 21:01:27 +02:00
Ok ( create_invite ::v2 ::Response {
event : PduEvent ::convert_to_outgoing_federation_event ( signed_event ) ,
2022-01-22 16:58:32 +01:00
} )
2021-04-11 21:01:27 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
///
/// Gets information on all devices of the user.
2022-01-20 11:51:31 +01:00
pub async fn get_devices_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_devices ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_devices ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-21 10:51:34 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2024-02-01 12:05:59 +01:00
if body . user_id . server_name ( ) ! = services ( ) . globals . server_name ( ) {
return Err ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Tried to access user from other server. " ,
) ) ;
}
2022-04-06 18:49:46 +02:00
let sender_servername = body
. sender_servername
. as_ref ( )
. expect ( " server is authenticated " ) ;
2021-04-21 10:51:34 +02:00
Ok ( get_devices ::v1 ::Response {
user_id : body . user_id . clone ( ) ,
2022-09-06 23:15:09 +02:00
stream_id : services ( )
2021-04-21 10:51:34 +02:00
. users
. get_devicelist_version ( & body . user_id ) ?
. unwrap_or ( 0 )
. try_into ( )
. expect ( " version will not grow that large " ) ,
2022-09-06 23:15:09 +02:00
devices : services ( )
2021-04-21 10:51:34 +02:00
. users
. all_devices_metadata ( & body . user_id )
2024-03-02 20:55:02 -05:00
. filter_map ( std ::result ::Result ::ok )
2021-04-21 10:51:34 +02:00
. filter_map ( | metadata | {
2023-11-27 00:39:50 -05:00
let device_id_string = metadata . device_id . as_str ( ) . to_owned ( ) ;
2023-09-10 15:40:00 -04:00
let device_display_name = match services ( ) . globals . allow_device_name_federation ( ) {
2023-10-21 12:19:21 -04:00
true = > metadata . display_name ,
2023-12-03 20:20:25 -05:00
false = > Some ( device_id_string ) ,
2023-09-10 15:40:00 -04:00
} ;
2021-04-21 10:51:34 +02:00
Some ( UserDevice {
2022-09-06 23:15:09 +02:00
keys : services ( )
2021-04-21 10:51:34 +02:00
. users
. get_device_keys ( & body . user_id , & metadata . device_id )
. ok ( ) ? ? ,
device_id : metadata . device_id ,
2023-11-27 00:39:50 -05:00
device_display_name ,
2021-04-21 10:51:34 +02:00
} )
} )
. collect ( ) ,
2023-07-16 16:50:03 +02:00
master_key : services ( ) . users . get_master_key ( None , & body . user_id , & | u | {
u . server_name ( ) = = sender_servername
} ) ? ,
2022-09-06 23:15:09 +02:00
self_signing_key : services ( )
2022-03-05 10:16:21 +08:00
. users
2023-07-16 16:50:03 +02:00
. get_self_signing_key ( None , & body . user_id , & | u | {
u . server_name ( ) = = sender_servername
} ) ? ,
2022-01-22 16:58:32 +01:00
} )
2021-04-21 10:51:34 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/query/directory`
///
/// Resolve a room alias to a room id.
2022-01-20 11:51:31 +01:00
pub async fn get_room_information_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_room_information ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_room_information ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-04-16 18:18:29 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2022-09-06 23:15:09 +02:00
let room_id = services ( )
2021-04-16 18:18:29 +02:00
. rooms
2022-10-05 20:34:31 +02:00
. alias
. resolve_local_alias ( & body . room_alias ) ?
2021-04-21 14:06:39 +02:00
. ok_or ( Error ::BadRequest (
ErrorKind ::NotFound ,
" Room alias not found. " ,
) ) ? ;
2021-04-16 18:18:29 +02:00
Ok ( get_room_information ::v1 ::Response {
room_id ,
2022-09-06 23:15:09 +02:00
servers : vec ! [ services ( ) . globals . server_name ( ) . to_owned ( ) ] ,
2022-01-22 16:58:32 +01:00
} )
2021-04-16 18:18:29 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `GET /_matrix/federation/v1/query/profile`
///
/// Gets information on a profile.
2022-01-20 11:51:31 +01:00
pub async fn get_profile_information_route (
2022-12-14 13:09:10 +01:00
body : Ruma < get_profile_information ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < get_profile_information ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2020-11-14 23:13:06 +01:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
2020-10-06 21:04:51 +02:00
}
2023-09-13 21:16:31 -04:00
if body . user_id . server_name ( ) ! = services ( ) . globals . server_name ( ) {
return Err ( Error ::BadRequest (
2024-02-01 12:05:59 +01:00
ErrorKind ::InvalidParam ,
2023-09-13 21:16:31 -04:00
" User does not belong to this server " ,
) ) ;
}
2020-10-05 22:19:22 +02:00
let mut displayname = None ;
let mut avatar_url = None ;
2021-07-15 23:17:58 +02:00
let mut blurhash = None ;
2020-10-05 22:19:22 +02:00
2020-12-04 18:16:17 -05:00
match & body . field {
2022-10-05 20:34:31 +02:00
Some ( ProfileField ::DisplayName ) = > {
2024-03-02 20:55:02 -05:00
displayname = services ( ) . users . displayname ( & body . user_id ) ? ;
2022-10-05 20:34:31 +02:00
}
2021-07-15 23:17:58 +02:00
Some ( ProfileField ::AvatarUrl ) = > {
2022-09-06 23:15:09 +02:00
avatar_url = services ( ) . users . avatar_url ( & body . user_id ) ? ;
2024-03-02 20:55:02 -05:00
blurhash = services ( ) . users . blurhash ( & body . user_id ) ? ;
2021-07-15 23:17:58 +02:00
}
2021-07-15 19:54:04 +02:00
// TODO: what to do with custom
Some ( _ ) = > { }
2020-10-05 22:19:22 +02:00
None = > {
2022-09-06 23:15:09 +02:00
displayname = services ( ) . users . displayname ( & body . user_id ) ? ;
avatar_url = services ( ) . users . avatar_url ( & body . user_id ) ? ;
blurhash = services ( ) . users . blurhash ( & body . user_id ) ? ;
2020-10-05 22:19:22 +02:00
}
}
Ok ( get_profile_information ::v1 ::Response {
2021-07-15 23:17:58 +02:00
blurhash ,
2020-10-05 22:19:22 +02:00
displayname ,
avatar_url ,
2022-01-22 16:58:32 +01:00
} )
2020-10-05 22:19:22 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/federation/v1/user/keys/query`
///
/// Gets devices and identity keys for the given users.
2022-10-05 20:34:31 +02:00
pub async fn get_keys_route ( body : Ruma < get_keys ::v1 ::Request > ) -> Result < get_keys ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-05-20 23:46:52 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2024-02-01 12:05:59 +01:00
if body
. device_keys
. iter ( )
. any ( | ( u , _ ) | u . server_name ( ) ! = services ( ) . globals . server_name ( ) )
{
return Err ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" User does not belong to this server. " ,
) ) ;
}
2023-09-10 15:40:00 -04:00
let result = get_keys_helper (
None ,
& body . device_keys ,
| u | Some ( u . server_name ( ) ) = = body . sender_servername . as_deref ( ) ,
services ( ) . globals . allow_device_name_federation ( ) ,
)
2021-07-20 19:40:25 +02:00
. await ? ;
2021-05-20 23:46:52 +02:00
Ok ( get_keys ::v1 ::Response {
device_keys : result . device_keys ,
master_keys : result . master_keys ,
self_signing_keys : result . self_signing_keys ,
2022-01-22 16:58:32 +01:00
} )
2021-05-20 23:46:52 +02:00
}
2021-08-31 19:14:37 +02:00
/// # `POST /_matrix/federation/v1/user/keys/claim`
///
/// Claims one-time keys.
2021-06-08 18:10:00 +02:00
pub async fn claim_keys_route (
2021-05-28 13:44:40 +02:00
body : Ruma < claim_keys ::v1 ::Request > ,
2022-01-22 16:58:32 +01:00
) -> Result < claim_keys ::v1 ::Response > {
2022-09-06 23:15:09 +02:00
if ! services ( ) . globals . allow_federation ( ) {
2021-05-28 13:44:40 +02:00
return Err ( Error ::bad_config ( " Federation is disabled. " ) ) ;
}
2024-02-01 12:05:59 +01:00
if body
. one_time_keys
. iter ( )
. any ( | ( u , _ ) | u . server_name ( ) ! = services ( ) . globals . server_name ( ) )
{
return Err ( Error ::BadRequest (
ErrorKind ::InvalidParam ,
" Tried to access user from other server. " ,
) ) ;
}
2022-09-06 23:15:09 +02:00
let result = claim_keys_helper ( & body . one_time_keys ) . await ? ;
2021-05-28 13:44:40 +02:00
Ok ( claim_keys ::v1 ::Response {
one_time_keys : result . one_time_keys ,
2022-01-22 16:58:32 +01:00
} )
2021-05-28 13:44:40 +02:00
}
2024-01-07 21:24:55 -05:00
/// # `GET /.well-known/matrix/server`
pub async fn well_known_server_route ( ) -> Result < impl IntoResponse > {
let server_url = match services ( ) . globals . well_known_server ( ) {
Some ( url ) = > url . clone ( ) ,
None = > return Err ( Error ::BadRequest ( ErrorKind ::NotFound , " Not found. " ) ) ,
} ;
Ok ( Json ( serde_json ::json! ( {
" m.server " : server_url
} ) ) )
}
2020-12-08 12:34:46 +01:00
#[ cfg(test) ]
mod tests {
2021-04-24 12:27:46 +02:00
use super ::{ add_port_to_hostname , get_ip_with_port , FedDest } ;
2020-12-08 12:34:46 +01:00
#[ test ]
fn ips_get_default_ports ( ) {
assert_eq! (
2021-04-21 00:35:44 -03:00
get_ip_with_port ( " 1.1.1.1 " ) ,
Some ( FedDest ::Literal ( " 1.1.1.1:8448 " . parse ( ) . unwrap ( ) ) )
2020-12-08 12:34:46 +01:00
) ;
assert_eq! (
2021-04-21 00:35:44 -03:00
get_ip_with_port ( " dead:beef:: " ) ,
Some ( FedDest ::Literal ( " [dead:beef::]:8448 " . parse ( ) . unwrap ( ) ) )
2020-12-08 12:34:46 +01:00
) ;
}
#[ test ]
fn ips_keep_custom_ports ( ) {
assert_eq! (
2021-04-21 00:35:44 -03:00
get_ip_with_port ( " 1.1.1.1:1234 " ) ,
Some ( FedDest ::Literal ( " 1.1.1.1:1234 " . parse ( ) . unwrap ( ) ) )
2020-12-08 12:34:46 +01:00
) ;
assert_eq! (
2021-04-21 00:35:44 -03:00
get_ip_with_port ( " [dead::beef]:8933 " ) ,
Some ( FedDest ::Literal ( " [dead::beef]:8933 " . parse ( ) . unwrap ( ) ) )
2020-12-08 12:34:46 +01:00
) ;
}
#[ test ]
fn hostnames_get_default_ports ( ) {
assert_eq! (
2021-04-21 00:35:44 -03:00
add_port_to_hostname ( " example.com " ) ,
FedDest ::Named ( String ::from ( " example.com " ) , String ::from ( " :8448 " ) )
2020-12-08 12:34:46 +01:00
)
}
#[ test ]
fn hostnames_keep_custom_ports ( ) {
assert_eq! (
2021-04-21 00:35:44 -03:00
add_port_to_hostname ( " example.com:1337 " ) ,
FedDest ::Named ( String ::from ( " example.com " ) , String ::from ( " :1337 " ) )
2020-12-08 12:34:46 +01:00
)
}
}