diff --git a/src/admin/debug/commands.rs b/src/admin/debug/commands.rs index eaa72352..00ded5f4 100644 --- a/src/admin/debug/commands.rs +++ b/src/admin/debug/commands.rs @@ -304,7 +304,7 @@ pub(super) async fn get_remote_pdu( #[admin_command] pub(super) async fn get_room_state(&self, room: OwnedRoomOrAliasId) -> Result { - let room_id = self.services.alias.resolve(&room).await?; + let room_id = self.services.alias.maybe_resolve(&room).await?; let room_state: Vec> = self .services .state_accessor diff --git a/src/admin/query/room_timeline.rs b/src/admin/query/room_timeline.rs index 354ad273..0ee5019d 100644 --- a/src/admin/query/room_timeline.rs +++ b/src/admin/query/room_timeline.rs @@ -25,7 +25,11 @@ pub(crate) enum RoomTimelineCommand { #[admin_command] pub(super) async fn last(&self, room_id: OwnedRoomOrAliasId) -> Result { - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; let result = self .services @@ -43,7 +47,11 @@ pub(super) async fn pdus( from: Option, limit: Option, ) -> Result { - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; let from: Option = from.as_deref().map(str::parse).transpose()?; diff --git a/src/admin/query/short.rs b/src/admin/query/short.rs index e66d054f..192e6a74 100644 --- a/src/admin/query/short.rs +++ b/src/admin/query/short.rs @@ -30,7 +30,11 @@ pub(super) async fn short_event_id(&self, event_id: OwnedEventId) -> Result { #[admin_command] pub(super) async fn short_room_id(&self, room_id: OwnedRoomOrAliasId) -> Result { - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; let shortid = self .services diff --git a/src/admin/room/moderation.rs b/src/admin/room/moderation.rs index 0a68868a..68a90efe 100644 --- a/src/admin/room/moderation.rs +++ b/src/admin/room/moderation.rs @@ -105,7 +105,7 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result { match self .services .alias - .resolve_alias(room_alias, None) + .resolve_alias(room_alias) .await { | Ok((room_id, servers)) => { @@ -260,7 +260,7 @@ async fn ban_list_of_rooms(&self) -> Result { match self .services .alias - .resolve_alias(room_alias, None) + .resolve_alias(room_alias) .await { | Ok((room_id, servers)) => { @@ -423,7 +423,7 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result { match self .services .alias - .resolve_alias(room_alias, None) + .resolve_alias(room_alias) .await { | Ok((room_id, servers)) => { diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index b5b9261b..6d385e05 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -119,7 +119,7 @@ pub(super) async fn create_user(&self, username: String, password: Option Result { let user_id = parse_local_user_id(self.services, &user_id)?; - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; assert!( self.services.globals.user_is_local(&user_id), @@ -678,7 +682,11 @@ pub(super) async fn force_leave_room( #[admin_command] pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAliasId) -> Result { let user_id = parse_local_user_id(self.services, &user_id)?; - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; assert!( self.services.globals.user_is_local(&user_id), @@ -744,7 +752,11 @@ pub(super) async fn force_promote( room_id: OwnedRoomOrAliasId, ) -> Result { let target_id = parse_user_id(self.services, &target_id)?; - let room_id = self.services.alias.resolve(&room_id).await?; + let room_id = self + .services + .alias + .maybe_resolve(&room_id) + .await?; let state_lock = self.services.state.mutex.lock(&room_id).await; diff --git a/src/api/client/alias.rs b/src/api/client/alias.rs index d775f801..9e022536 100644 --- a/src/api/client/alias.rs +++ b/src/api/client/alias.rs @@ -5,7 +5,7 @@ use ruma::{ OwnedServerName, RoomAliasId, RoomId, api::client::alias::{create_alias, delete_alias, get_alias}, }; -use tuwunel_core::{Err, Result, debug}; +use tuwunel_core::{Err, Result, debug, err}; use tuwunel_service::Services; use crate::Ruma; @@ -83,13 +83,11 @@ pub(crate) async fn get_alias_route( ) -> Result { let room_alias = body.body.room_alias; - let Ok((room_id, servers)) = services + let (room_id, servers) = services .alias - .resolve_alias(&room_alias, None) + .resolve_alias(&room_alias) .await - else { - return Err!(Request(NotFound("Room with alias not found."))); - }; + .map_err(|_| err!(Request(NotFound("Room with alias not found."))))?; let servers = room_available_servers(&services, &room_id, &room_alias, servers).await; debug!(?room_alias, ?room_id, "available servers: {servers:?}"); diff --git a/src/api/client/membership/mod.rs b/src/api/client/membership/mod.rs index 20c3a317..cc3d6ca3 100644 --- a/src/api/client/membership/mod.rs +++ b/src/api/client/membership/mod.rs @@ -165,10 +165,7 @@ async fn get_join_params( }, // ... if room alias, resolve and don't shuffle ... | Err(room_alias) => { - let (room_id, servers) = services - .alias - .resolve_alias(&room_alias, Some(via.to_vec())) - .await?; + let (room_id, servers) = services.alias.resolve_alias(&room_alias).await?; (room_id, servers, Vec::new()) }, diff --git a/src/api/client/register.rs b/src/api/client/register.rs index e87ab36a..6e40b7f0 100644 --- a/src/api/client/register.rs +++ b/src/api/client/register.rs @@ -535,7 +535,7 @@ pub(crate) async fn register_route( && (services.config.allow_guests_auto_join_rooms || !is_guest) { for room in &services.server.config.auto_join_rooms { - let Ok(room_id) = services.alias.resolve(room).await else { + let Ok(room_id) = services.alias.maybe_resolve(room).await else { error!( "Failed to resolve room alias to room ID when attempting to auto join \ {room}, skipping" diff --git a/src/api/client/room/summary.rs b/src/api/client/room/summary.rs index a2d21bc3..127b73eb 100644 --- a/src/api/client/room/summary.rs +++ b/src/api/client/room/summary.rs @@ -55,7 +55,7 @@ pub(crate) async fn get_room_summary( ) -> Result { let (room_id, servers) = services .alias - .resolve_with_servers(&body.room_id_or_alias, Some(body.via.clone())) + .maybe_resolve_with_servers(&body.room_id_or_alias, Some(body.via.clone())) .await?; if services.metadata.is_banned(&room_id).await { diff --git a/src/api/client/state.rs b/src/api/client/state.rs index ea06045f..812b883d 100644 --- a/src/api/client/state.rs +++ b/src/api/client/state.rs @@ -328,7 +328,7 @@ async fn allowed_to_send_state_event( for alias in aliases { let (alias_room_id, _servers) = services .alias - .resolve_alias(&alias, None) + .resolve_alias(&alias) .await .map_err(|e| { err!(Request(BadAlias("Failed resolving alias \"{alias}\": {e}"))) diff --git a/src/service/rooms/alias/mod.rs b/src/service/rooms/alias/mod.rs index 0579eb6a..0b053e8d 100644 --- a/src/service/rooms/alias/mod.rs +++ b/src/service/rooms/alias/mod.rs @@ -1,11 +1,9 @@ -mod remote; - use std::sync::Arc; use futures::{Stream, StreamExt}; use ruma::{ OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId, UserId, - events::StateEventType, + api::federation::query::get_room_information::v1::Request, events::StateEventType, }; use tuwunel_core::{ Err, Result, err, @@ -99,23 +97,21 @@ impl Service { } #[inline] - pub async fn resolve(&self, room: &RoomOrAliasId) -> Result { - self.resolve_with_servers(room, None) - .await - .map(|(room_id, _)| room_id) + pub async fn maybe_resolve(&self, room: &RoomOrAliasId) -> Result { + match <&RoomId>::try_from(room) { + | Ok(room_id) => Ok(room_id.to_owned()), + | Err(alias) => Ok(self.resolve_alias(alias).await?.0), + } } - pub async fn resolve_with_servers( + pub async fn maybe_resolve_with_servers( &self, room: &RoomOrAliasId, servers: Option>, ) -> Result<(OwnedRoomId, Vec)> { - if room.is_room_id() { - let room_id: &RoomId = room.try_into().expect("valid RoomId"); - Ok((room_id.to_owned(), servers.unwrap_or_default())) - } else { - let alias: &RoomAliasId = room.try_into().expect("valid RoomAliasId"); - self.resolve_alias(alias, servers).await + match <&RoomId>::try_from(room) { + | Ok(room_id) => Ok((room_id.to_owned(), servers.unwrap_or_default())), + | Err(alias) => self.resolve_alias(alias).await, } } @@ -123,7 +119,6 @@ impl Service { pub async fn resolve_alias( &self, room_alias: &RoomAliasId, - servers: Option>, ) -> Result<(OwnedRoomId, Vec)> { if self .services @@ -141,9 +136,24 @@ impl Service { return Err!(Request(NotFound("Room with alias not found."))); } - return self - .remote_resolve(room_alias, servers.unwrap_or_default()) - .await; + return self.remote_resolve(room_alias).await; + } + + async fn remote_resolve( + &self, + room_alias: &RoomAliasId, + ) -> Result<(OwnedRoomId, Vec)> { + let server = room_alias.server_name(); + + let request = Request { room_alias: room_alias.to_owned() }; + + let response = self + .services + .sending + .send_federation_request(server, request) + .await?; + + Ok((response.room_id, response.servers)) } #[tracing::instrument(skip(self), level = "trace")] diff --git a/src/service/rooms/alias/remote.rs b/src/service/rooms/alias/remote.rs deleted file mode 100644 index ca2857c8..00000000 --- a/src/service/rooms/alias/remote.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::iter::once; - -use federation::query::get_room_information::v1::Response; -use ruma::{OwnedRoomId, OwnedServerName, RoomAliasId, ServerName, api::federation}; -use tuwunel_core::{Result, debug, debug_error, err, implement}; - -#[implement(super::Service)] -pub(super) async fn remote_resolve( - &self, - room_alias: &RoomAliasId, - servers: Vec, -) -> Result<(OwnedRoomId, Vec)> { - debug!(?room_alias, servers = ?servers, "resolve"); - let servers = once(room_alias.server_name()) - .map(ToOwned::to_owned) - .chain(servers.into_iter()); - - let mut resolved_servers = Vec::new(); - let mut resolved_room_id: Option = None; - for server in servers { - match self.remote_request(room_alias, &server).await { - | Err(e) => debug_error!("Failed to query for {room_alias:?} from {server}: {e}"), - | Ok(Response { room_id, servers }) => { - debug!( - "Server {server} answered with {room_id:?} for {room_alias:?} servers: \ - {servers:?}" - ); - - resolved_room_id.get_or_insert(room_id); - add_server(&mut resolved_servers, server); - - if !servers.is_empty() { - add_servers(&mut resolved_servers, servers); - break; - } - }, - } - } - - resolved_room_id - .map(|room_id| (room_id, resolved_servers)) - .ok_or_else(|| { - err!(Request(NotFound("No servers could assist in resolving the room alias"))) - }) -} - -#[implement(super::Service)] -async fn remote_request( - &self, - room_alias: &RoomAliasId, - server: &ServerName, -) -> Result { - use federation::query::get_room_information::v1::Request; - - let request = Request { room_alias: room_alias.to_owned() }; - - self.services - .sending - .send_federation_request(server, request) - .await -} - -fn add_servers(servers: &mut Vec, new: Vec) { - for server in new { - add_server(servers, server); - } -} - -fn add_server(servers: &mut Vec, server: OwnedServerName) { - if !servers.contains(&server) { - servers.push(server); - } -}