diff --git a/Cargo.toml b/Cargo.toml index d1eaba49..33a45fbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -349,6 +349,7 @@ features = [ "unstable-msc4121", "unstable-msc4125", "unstable-msc4133", + "unstable-msc4143", "unstable-msc4186", "unstable-msc4203", # sending to-device events to appservices "unstable-msc4310", diff --git a/src/api/client/capabilities.rs b/src/api/client/capabilities.rs index 7983c168..5cae8a1a 100644 --- a/src/api/client/capabilities.rs +++ b/src/api/client/capabilities.rs @@ -51,16 +51,5 @@ pub(crate) async fn get_capabilities_route( json!({"enabled": services.config.forget_forced_upon_leave}), )?; - // MSC4143: MatrixRTC - advertise RTC transport support - if !services - .server - .config - .well_known - .rtc_transports - .is_empty() - { - capabilities.set("org.matrix.msc4143.rtc_foci", json!({"supported": true}))?; - } - Ok(get_capabilities::v3::Response { capabilities }) } diff --git a/src/api/client/well_known.rs b/src/api/client/well_known.rs index 8ab1c0e0..a727aa03 100644 --- a/src/api/client/well_known.rs +++ b/src/api/client/well_known.rs @@ -1,7 +1,10 @@ use axum::{Json, extract::State, response::IntoResponse}; -use ruma::api::client::discovery::discover_support::{self, Contact}; -use serde_json::{Value, json}; -use tuwunel_core::{Err, Result}; +use ruma::api::client::discovery::{ + discover_homeserver::{self, HomeserverInfo, RtcFocusInfo}, + discover_support::{self, Contact}, +}; +use serde_json::Value as JsonValue; +use tuwunel_core::{Err, Result, err, error::inspect_log}; use crate::Ruma; @@ -11,55 +14,47 @@ use crate::Ruma; /// Also includes RTC transport configuration for Element Call (MSC4143). pub(crate) async fn well_known_client( State(services): State, -) -> Result> { - let client_url = match services.server.config.well_known.client.as_ref() { - | Some(url) => url.to_string(), - | None => return Err!(Request(NotFound("Not found."))), + _body: Ruma, +) -> Result { + let homeserver = HomeserverInfo { + base_url: match services.server.config.well_known.client.as_ref() { + | Some(url) => url.to_string(), + | None => return Err!(Request(NotFound("Not found."))), + }, }; - let mut response = json!({ - "m.homeserver": { - "base_url": client_url - } - }); - // Add RTC transport configuration if available (MSC4143 / Element Call) // Element Call has evolved through several versions with different field // expectations - if !services + let rtc_foci = services .server .config .well_known .rtc_transports - .is_empty() - { - if let Some(obj) = response.as_object_mut() { - // Element Call expects "org.matrix.msc4143.rtc_foci" (not rtc_foci_preferred) - // with an array of transport objects - obj.insert( - "org.matrix.msc4143.rtc_foci".to_owned(), - json!(services.server.config.well_known.rtc_transports), - ); + .iter() + .map(|transport| { + let focus_type = transport + .get("type") + .and_then(JsonValue::as_str) + .ok_or_else(|| err!("`type` is not a valid string"))?; - // Also add the LiveKit URL directly for backward compatibility - if let Some(first_transport) = services - .server - .config - .well_known - .rtc_transports - .first() - { - if let Some(livekit_url) = first_transport.get("livekit_service_url") { - obj.insert( - "org.matrix.msc4143.livekit_service_url".to_owned(), - livekit_url.clone(), - ); - } - } - } - } + let transport = transport + .as_object() + .cloned() + .ok_or_else(|| err!("`rtc_transport` is not a valid object"))?; - Ok(Json(response)) + RtcFocusInfo::new(focus_type, transport).map_err(Into::into) + }) + .collect::>() + .map_err(|e| { + err!(Config("global.well_known.rtc_transports", "Malformed value(s): {e:?}")) + }) + .inspect_err(inspect_log)?; + + Ok(discover_homeserver::Response { + rtc_foci, + ..discover_homeserver::Response::new(homeserver) + }) } /// # `GET /.well-known/matrix/support` diff --git a/src/api/router.rs b/src/api/router.rs index 196192a9..05eb0530 100644 --- a/src/api/router.rs +++ b/src/api/router.rs @@ -190,8 +190,7 @@ pub fn build(router: Router, server: &Server) -> Router { get(client::get_room_summary_legacy) ) .ruma_route(&client::well_known_support) - // this is the only thing currently needed to support Element Video Rooms / Calls. - .route("/.well-known/matrix/client", get(client::well_known_client)) + .ruma_route(&client::well_known_client) .route("/_tuwunel/server_version", get(client::tuwunel_server_version)) .ruma_route(&client::room_initial_sync_route) .route("/client/server.json", get(client::syncv3_client_server_json));