diff --git a/src/api/client_server/membership.rs b/src/api/client_server/membership.rs index a94b9f86..e6b1462a 100644 --- a/src/api/client_server/membership.rs +++ b/src/api/client_server/membership.rs @@ -30,7 +30,7 @@ use ruma::{ }; use serde_json::value::{to_raw_value, RawValue as RawJsonValue}; use tokio::sync::RwLock; -use tracing::{debug, error, info, warn}; +use tracing::{debug, error, info, trace, warn}; use super::get_alias_helper; use crate::{ @@ -1144,11 +1144,14 @@ async fn make_join_request( ) -> Result<(federation::membership::prepare_join_event::v1::Response, OwnedServerName)> { let mut make_join_response_and_server = Err(Error::BadServerResponse("No server available to assist in joining.")); + let mut make_join_counter = 0; + let mut incompatible_room_version_count = 0; + for remote_server in servers { if remote_server == services().globals.server_name() { continue; } - info!("Asking {remote_server} for make_join"); + info!("Asking {remote_server} for make_join ({make_join_counter})"); let make_join_response = services() .sending .send_federation_request( @@ -1161,6 +1164,34 @@ async fn make_join_request( ) .await; + trace!("make_join response: {:?}", make_join_response); + make_join_counter += 1; + + if let Err(ref e) = make_join_response { + trace!("make_join ErrorKind string: {:?}", e.error_code().to_string()); + // converting to a string is necessary (i think) because ruma is forcing us to + // fill in the struct for M_INCOMPATIBLE_ROOM_VERSION + if e.error_code() + .to_string() + .contains("M_INCOMPATIBLE_ROOM_VERSION") + || e.error_code() + .to_string() + .contains("M_UNSUPPORTED_ROOM_VERSION") + { + incompatible_room_version_count += 1; + } + + if incompatible_room_version_count > 15 { + info!( + "15 servers have responded with M_INCOMPATIBLE_ROOM_VERSION or M_UNSUPPORTED_ROOM_VERSION, \ + assuming that Conduwuit does not support the room {room_id}: {e}" + ); + make_join_response_and_server = + Err(Error::BadServerResponse("Room version is not supported by Conduwuit")); + return make_join_response_and_server; + } + } + make_join_response_and_server = make_join_response.map(|r| (r, remote_server.clone())); if make_join_response_and_server.is_ok() { diff --git a/src/utils/error.rs b/src/utils/error.rs index 48d18990..fd14caeb 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -101,7 +101,7 @@ impl Error { if let Self::FederationError(origin, error) = self { let mut error = error.clone(); error.body = ErrorBody::Standard { - kind: Unknown, + kind: error.error_kind().unwrap_or(&Unknown).clone(), message: format!("Answer from {origin}: {error}"), }; return RumaResponse(UiaaResponse::MatrixError(error)); @@ -138,7 +138,7 @@ impl Error { _ => (Unknown, StatusCode::INTERNAL_SERVER_ERROR), }; - info!("Returning an error: {}: {}", status_code, message); + info!("Returning an error: {status_code}: {message}"); RumaResponse(UiaaResponse::MatrixError(RumaError { body: ErrorBody::Standard { @@ -149,6 +149,18 @@ impl Error { })) } + /// Returns the Matrix error code / error kind + pub fn error_code(&self) -> ErrorKind { + if let Self::FederationError(_, error) = self { + return error.error_kind().unwrap_or(&Unknown).clone(); + } + + match self { + Self::BadRequest(kind, _) => kind.clone(), + _ => Unknown, + } + } + /// Sanitizes public-facing errors that can leak sensitive information. pub fn sanitized_error(&self) -> String { let db_error = String::from("Database or I/O error occurred.");