Skip to main content

tuwunel_api_client/
tuwunel.rs

1use std::time::Instant;
2
3use axum::{Json, extract::State, response::IntoResponse};
4use futures::StreamExt;
5use ruma::api::{client::tuwunel::get_remote_version, federation::discovery::get_server_version};
6use tuwunel_core::Result;
7
8use crate::Ruma;
9
10/// # `GET /_tuwunel/server_version`
11///
12/// Tuwunel-specific API to get the server version, results akin to
13/// `/_matrix/federation/v1/version`
14pub(crate) async fn tuwunel_server_version() -> Result<impl IntoResponse> {
15	Ok(Json(serde_json::json!({
16		"name": tuwunel_core::version::name(),
17		"version": tuwunel_core::version::version(),
18	})))
19}
20
21/// # `GET /_tuwunel/local_user_count`
22///
23/// Tuwunel-specific API to return the amount of users registered on this
24/// homeserver. Endpoint is disabled if federation is disabled for privacy. This
25/// only includes active users (not deactivated, no guests, etc)
26pub(crate) async fn tuwunel_local_user_count(
27	State(services): State<crate::State>,
28) -> Result<impl IntoResponse> {
29	let user_count = services.users.list_local_users().count().await;
30
31	Ok(Json(serde_json::json!({
32		"count": user_count
33	})))
34}
35
36/// # `GET /_tuwunel/remote_version/{server_name}`
37///
38/// Tuwunel-specific API to probe a remote server's
39/// `/_matrix/federation/v1/version` endpoint, returning that response body
40/// along with the round-trip time of the probe.
41pub(crate) async fn tuwunel_remote_version(
42	State(services): State<crate::State>,
43	body: Ruma<get_remote_version::unstable::Request>,
44) -> Result<get_remote_version::unstable::Response> {
45	let timer = Instant::now();
46
47	let server = if services.globals.server_is_ours(&body.server_name) {
48		Some(get_server_version::v1::Server {
49			name: Some(tuwunel_core::version::name().into()),
50			version: Some(tuwunel_core::version::version().into()),
51			compiler: tuwunel_core::info::rustc::version().map(Into::into),
52			..Default::default()
53		})
54	} else {
55		services
56			.federation
57			.execute(&body.server_name, get_server_version::v1::Request {})
58			.await?
59			.server
60	};
61
62	let elapsed = timer.elapsed();
63
64	Ok(get_remote_version::unstable::Response {
65		data: serde_json::value::to_raw_value(&server)?,
66		rtt_ms: elapsed,
67	})
68}