Skip to main content

tuwunel_api/client/appservice/
ping.rs

1use axum::extract::State;
2use ruma::api::{
3	appservice::ping::send_ping::v1::Request as SendPing,
4	client::appservice::request_ping::v1::{Request, Response},
5};
6use tuwunel_core::{Err, Result, err, utils::result::LogErr};
7
8use crate::Ruma;
9
10/// # `POST /_matrix/client/v1/appservice/{appserviceId}/ping`
11///
12/// Ask the homeserver to ping the application service to ensure the connection
13/// works.
14pub(crate) async fn appservice_ping(
15	State(services): State<crate::State>,
16	body: Ruma<Request>,
17) -> Result<Response> {
18	let appservice_info = body.appservice_info.as_ref().ok_or_else(|| {
19		err!(Request(Forbidden("This endpoint can only be called by appservices.")))
20	})?;
21
22	if body.appservice_id != appservice_info.registration.id {
23		return Err!(Request(Forbidden(
24			"Appservices can only ping themselves (wrong appservice ID)."
25		)));
26	}
27
28	if appservice_info.registration.url.is_none()
29		|| appservice_info
30			.registration
31			.url
32			.as_ref()
33			.is_some_and(|url| url.is_empty() || url == "null")
34	{
35		return Err!(Request(UrlNotSet(
36			"Appservice does not have a URL set, there is nothing to ping."
37		)));
38	}
39
40	let timer = tokio::time::Instant::now();
41
42	services
43		.appservice
44		.ping(appservice_info.registration.clone(), SendPing {
45			transaction_id: body.transaction_id.clone(),
46		})
47		.await?;
48
49	let duration = timer.elapsed();
50
51	services
52		.sending
53		.flush_appservice(appservice_info.registration.id.clone())
54		.log_err()
55		.ok();
56
57	Ok(Response { duration })
58}