tuwunel_api/client/membership/
join.rs1use axum::extract::State;
2use futures::FutureExt;
3use ruma::{
4 RoomId,
5 api::client::membership::{join_room_by_id, join_room_by_id_or_alias},
6};
7use tuwunel_core::{Result, warn};
8
9use super::banned_room_check;
10use crate::{ClientIp, Ruma};
11
12#[tracing::instrument(skip_all, fields(%client), name = "join")]
21pub(crate) async fn join_room_by_id_route(
22 State(services): State<crate::State>,
23 ClientIp(client): ClientIp,
24 body: Ruma<join_room_by_id::v3::Request>,
25) -> Result<join_room_by_id::v3::Response> {
26 let sender_user = body.sender_user();
27
28 let room_id: &RoomId = &body.room_id;
29
30 banned_room_check(&services, sender_user, room_id, None, client).await?;
31
32 let mut errors = 0_usize;
33 while let Err(e) = services
34 .membership
35 .join(
36 sender_user,
37 room_id,
38 None,
39 body.reason.clone(),
40 &[],
41 body.appservice_info.is_some(),
42 )
43 .boxed()
44 .await
45 {
46 errors = errors.saturating_add(1);
47 if errors >= services.config.max_join_attempts_per_join_request {
48 warn!(
49 "Several servers failed. Giving up for this request. Try again for different \
50 server selection."
51 );
52 return Err(e);
53 }
54 }
55
56 Ok(join_room_by_id::v3::Response { room_id: room_id.to_owned() })
57}
58
59#[tracing::instrument(skip_all, fields(%client), name = "join")]
69pub(crate) async fn join_room_by_id_or_alias_route(
70 State(services): State<crate::State>,
71 ClientIp(client): ClientIp,
72 body: Ruma<join_room_by_id_or_alias::v3::Request>,
73) -> Result<join_room_by_id_or_alias::v3::Response> {
74 let sender_user = body.sender_user();
75 let appservice_info = &body.appservice_info;
76
77 let (room_id, servers) = services
78 .alias
79 .maybe_resolve_with_servers(&body.room_id_or_alias, Some(&body.via))
80 .await?;
81
82 banned_room_check(&services, sender_user, &room_id, Some(&body.room_id_or_alias), client)
83 .await?;
84
85 let mut errors = 0_usize;
86 while let Err(e) = services
87 .membership
88 .join(
89 sender_user,
90 &room_id,
91 Some(&body.room_id_or_alias),
92 body.reason.clone(),
93 &servers,
94 appservice_info.is_some(),
95 )
96 .boxed()
97 .await
98 {
99 errors = errors.saturating_add(1);
100 if errors >= services.config.max_join_attempts_per_join_request {
101 warn!(
102 "Several servers failed. Giving up for this request. Try again for different \
103 server selection."
104 );
105 return Err(e);
106 }
107 }
108
109 Ok(join_room_by_id_or_alias::v3::Response { room_id: room_id.clone() })
110}