Skip to main content

tuwunel_api/client/
rtc.rs

1use axum::extract::State;
2use ruma::api::client::rtc::{RtcTransport, transports};
3use tuwunel_core::{Result, err, error::inspect_log};
4use tuwunel_service::Services;
5
6use crate::Ruma;
7
8/// # `GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports`
9///
10/// Get MatrixRTC transports for MSC4143.
11pub(crate) async fn get_transports_route(
12	State(services): State<crate::State>,
13	_body: Ruma<transports::v1::Request>,
14) -> Result<transports::v1::Response> {
15	Ok(transports::v1::Response {
16		rtc_transports: get_transports(&services)?,
17	})
18}
19
20/// Build the configured RTC transports as `RtcTransport` values, the typed
21/// form shared between `.well-known/matrix/client.rtc_foci` and the
22/// `/rtc/transports` endpoint.
23pub(crate) fn get_transports(services: &Services) -> Result<Vec<RtcTransport>> {
24	let custom = services
25		.server
26		.config
27		.well_known
28		.rtc_transports
29		.iter()
30		.map(|item| {
31			let mut data = item
32				.as_object()
33				.cloned()
34				.ok_or_else(|| err!("`rtc_transport` is not a valid object"))?;
35
36			let transport_type = data
37				.remove("type")
38				.and_then(|v| v.as_str().map(str::to_owned))
39				.ok_or_else(|| err!("`type` is not a valid string"))?;
40
41			RtcTransport::new(&transport_type, data).map_err(|e| {
42				err!(Config("global.well_known.rtc_transports", "Malformed value(s): {e:?}"))
43			})
44		});
45
46	let livekit_url = services
47		.config
48		.well_known
49		.livekit_url
50		.iter()
51		.cloned()
52		.map(|url| Ok(RtcTransport::livekit(url)));
53
54	custom
55		.chain(livekit_url)
56		.collect::<Result<Vec<_>>>()
57		.inspect_err(inspect_log)
58}