diff --git a/bindings/matrix-sdk-ffi/src/client_builder.rs b/bindings/matrix-sdk-ffi/src/client_builder.rs index 364b9a011..dd84d5c5f 100644 --- a/bindings/matrix-sdk-ffi/src/client_builder.rs +++ b/bindings/matrix-sdk-ffi/src/client_builder.rs @@ -10,6 +10,9 @@ use matrix_sdk::{ encryption::{BackupDownloadStrategy, EncryptionSettings}, reqwest::Certificate, ruma::{ServerName, UserId}, + sliding_sync::{ + Error as MatrixSlidingSyncError, VersionBuilder as MatrixSlidingSyncVersionBuilder, + }, Client as MatrixClient, ClientBuildError as MatrixClientBuildError, HttpError, IdParseError, RumaApiError, }; @@ -20,11 +23,8 @@ use zeroize::Zeroizing; use super::{client::Client, RUNTIME}; use crate::{ - authentication::OidcConfiguration, - client::{ClientSessionDelegate, SlidingSyncVersion}, - error::ClientError, - helpers::unwrap_or_clone_arc, - task_handle::TaskHandle, + authentication::OidcConfiguration, client::ClientSessionDelegate, error::ClientError, + helpers::unwrap_or_clone_arc, task_handle::TaskHandle, }; /// A list of bytes containing a certificate in DER or PEM form. @@ -82,7 +82,7 @@ pub enum HumanQrLoginError { Declined, #[error("An unknown error has happened.")] Unknown, - #[error("The homeserver doesn't provide a sliding sync proxy in its configuration.")] + #[error("The homeserver doesn't provide sliding sync in its configuration.")] SlidingSyncNotAvailable, #[error("Unable to use OIDC as the supplied client metadata is invalid.")] OidcMetadataInvalid, @@ -194,12 +194,10 @@ pub enum ClientBuildError { WellKnownLookupFailed(RumaApiError), #[error(transparent)] WellKnownDeserializationError(DeserializationError), - #[error("The homeserver doesn't provide a trusted sliding sync proxy in its well-known configuration.")] - SlidingSyncNotAvailable, - + #[error(transparent)] + SlidingSync(MatrixSlidingSyncError), #[error(transparent)] Sdk(MatrixClientBuildError), - #[error("Failed to build the client: {message}")] Generic { message: String }, } @@ -215,10 +213,7 @@ impl From for ClientBuildError { MatrixClientBuildError::AutoDiscovery(FromHttpResponseError::Deserialization(e)) => { ClientBuildError::WellKnownDeserializationError(e) } - MatrixClientBuildError::SlidingSyncNotAvailable => { - ClientBuildError::SlidingSyncNotAvailable - } - + MatrixClientBuildError::SlidingSync(e) => ClientBuildError::SlidingSync(e), _ => ClientBuildError::Sdk(e), } } @@ -255,7 +250,7 @@ pub struct ClientBuilder { homeserver_cfg: Option, passphrase: Zeroizing>, user_agent: Option, - sliding_sync_version: SlidingSyncVersion, + sliding_sync_version_builder: SlidingSyncVersionBuilder, proxy: Option, disable_ssl_verification: bool, disable_automatic_token_refresh: bool, @@ -278,7 +273,7 @@ impl ClientBuilder { homeserver_cfg: None, passphrase: Zeroizing::new(None), user_agent: None, - sliding_sync_version: SlidingSyncVersion::None, + sliding_sync_version_builder: SlidingSyncVersionBuilder::None, proxy: None, disable_ssl_verification: false, disable_automatic_token_refresh: false, @@ -365,9 +360,12 @@ impl ClientBuilder { Arc::new(builder) } - pub fn sliding_sync_version(self: Arc, version: SlidingSyncVersion) -> Arc { + pub fn sliding_sync_version_builder( + self: Arc, + version_builder: SlidingSyncVersionBuilder, + ) -> Arc { let mut builder = unwrap_or_clone_arc(self); - builder.sliding_sync_version = version; + builder.sliding_sync_version_builder = version_builder; Arc::new(builder) } @@ -546,15 +544,31 @@ impl ClientBuilder { .with_encryption_settings(builder.encryption_settings) .with_room_key_recipient_strategy(builder.room_key_recipient_strategy); - match builder.sliding_sync_version { - SlidingSyncVersion::None => {} - SlidingSyncVersion::Proxy { url } => { - inner_builder = inner_builder.sliding_sync_proxy( - Url::parse(&url) - .map_err(|e| ClientBuildError::Generic { message: e.to_string() })?, + match builder.sliding_sync_version_builder { + SlidingSyncVersionBuilder::None => { + inner_builder = inner_builder + .sliding_sync_version_builder(MatrixSlidingSyncVersionBuilder::None) + } + SlidingSyncVersionBuilder::Proxy { url } => { + inner_builder = inner_builder.sliding_sync_version_builder( + MatrixSlidingSyncVersionBuilder::Proxy { + url: Url::parse(&url) + .map_err(|e| ClientBuildError::Generic { message: e.to_string() })?, + }, ) } - SlidingSyncVersion::Native => inner_builder = inner_builder.sliding_sync_native(), + SlidingSyncVersionBuilder::Native => { + inner_builder = inner_builder + .sliding_sync_version_builder(MatrixSlidingSyncVersionBuilder::Native) + } + SlidingSyncVersionBuilder::DiscoverProxy => { + inner_builder = inner_builder + .sliding_sync_version_builder(MatrixSlidingSyncVersionBuilder::DiscoverProxy) + } + SlidingSyncVersionBuilder::DiscoverNative => { + inner_builder = inner_builder + .sliding_sync_version_builder(MatrixSlidingSyncVersionBuilder::DiscoverNative) + } } if let Some(config) = builder.request_config { @@ -615,7 +629,7 @@ impl ClientBuilder { let builder = self.server_name_or_homeserver_url(server_name.to_owned()); let client = builder.build().await.map_err(|e| match e { - ClientBuildError::SlidingSyncNotAvailable => HumanQrLoginError::SlidingSyncNotAvailable, + ClientBuildError::SlidingSync(_) => HumanQrLoginError::SlidingSyncNotAvailable, _ => { error!("Couldn't build the client {e:?}"); HumanQrLoginError::Unknown @@ -666,3 +680,12 @@ pub struct RequestConfig { /// Base delay between retries. retry_timeout: Option, } + +#[derive(Clone, uniffi::Enum)] +pub enum SlidingSyncVersionBuilder { + None, + Proxy { url: String }, + Native, + DiscoverProxy, + DiscoverNative, +} diff --git a/crates/matrix-sdk/src/client/builder.rs b/crates/matrix-sdk/src/client/builder.rs index 6c2b46ae2..56ffd6a2b 100644 --- a/crates/matrix-sdk/src/client/builder.rs +++ b/crates/matrix-sdk/src/client/builder.rs @@ -39,7 +39,7 @@ use crate::http_client::HttpSettings; #[cfg(feature = "experimental-oidc")] use crate::oidc::OidcCtx; #[cfg(feature = "experimental-sliding-sync")] -use crate::sliding_sync::Version as SlidingSyncVersion; +use crate::sliding_sync::VersionBuilder as SlidingSyncVersionBuilder; use crate::{ authentication::AuthCtx, client::ClientServerCapabilities, config::RequestConfig, error::RumaApiError, http_client::HttpClient, send_queue::SendQueueData, HttpError, @@ -89,7 +89,7 @@ use crate::{ pub struct ClientBuilder { homeserver_cfg: Option, #[cfg(feature = "experimental-sliding-sync")] - sliding_sync_version: SlidingSyncVersion, + sliding_sync_version_builder: SlidingSyncVersionBuilder, http_cfg: Option, store_config: BuilderStoreConfig, request_config: RequestConfig, @@ -108,7 +108,7 @@ impl ClientBuilder { Self { homeserver_cfg: None, #[cfg(feature = "experimental-sliding-sync")] - sliding_sync_version: SlidingSyncVersion::Native, + sliding_sync_version_builder: SlidingSyncVersionBuilder::Native, http_cfg: None, store_config: BuilderStoreConfig::Custom(StoreConfig::default()), request_config: Default::default(), @@ -136,30 +136,13 @@ impl ClientBuilder { self } - /// Set sliding sync to use the proxy, i.e. MSC3575. - /// - /// This value is always used no matter if the homeserver URL was defined - /// with [`Self::homeserver_url`] or auto-discovered via - /// [`Self::server_name`], [`Self::insecure_server_name_no_tls`], or - /// [`Self::server_name_or_homeserver_url`] - any proxy discovered via the - /// well-known lookup will be ignored. - #[cfg(feature = "experimental-sliding-sync")] - pub fn sliding_sync_proxy(mut self, url: Url) -> Self { - self.sliding_sync_version = SlidingSyncVersion::Proxy { url }; - self - } - - /// Set sliding sync to be native, i.e. Simplified MSC3575. - #[cfg(feature = "experimental-sliding-sync")] - pub fn sliding_sync_native(mut self) -> Self { - self.sliding_sync_version = SlidingSyncVersion::Native; - self - } - /// Set sliding sync to a specific version. #[cfg(feature = "experimental-sliding-sync")] - pub fn sliding_sync_version(mut self, version: SlidingSyncVersion) -> Self { - self.sliding_sync_version = version; + pub fn sliding_sync_version_builder( + mut self, + version_builder: SlidingSyncVersionBuilder, + ) -> Self { + self.sliding_sync_version_builder = version_builder; self } @@ -476,7 +459,7 @@ impl ClientBuilder { let http_client = HttpClient::new(inner_http_client.clone(), self.request_config); #[allow(unused_variables)] - let (homeserver, well_known, versions) = match homeserver_cfg { + let (homeserver, well_known, supported_versions) = match homeserver_cfg { HomeserverConfig::Url(url) => (Url::parse(&url)?, None, None), HomeserverConfig::ServerName { server: server_name, protocol } => { @@ -491,22 +474,24 @@ impl ClientBuilder { } }; - /* #[cfg(feature = "experimental-sliding-sync")] - if self.is_simplified_sliding_sync_enabled { - // When using Simplified MSC3575, don't use a sliding sync proxy, allow the - // requests to be sent directly to the homeserver. - tracing::info!("Simplified MSC3575 is enabled, ignoring any sliding sync proxy."); - sliding_sync_proxy = None; - } else if let Some(well_known) = well_known { - // Otherwise, if a proxy wasn't set, use the one discovered from the well-known. - if sliding_sync_proxy.is_none() { - sliding_sync_proxy = - well_known.sliding_sync_proxy.and_then(|p| Url::parse(&p.url).ok()) - } - } - */ + let sliding_sync_version = { + let supported_versions = match supported_versions { + Some(versions) => Some(versions), + None if self.sliding_sync_version_builder.needs_get_supported_versions() => { + Some(get_supported_versions(&homeserver, &http_client).await?) + } + None => None, + }; + let version = self + .sliding_sync_version_builder + .build(well_known.as_ref(), supported_versions.as_ref())?; + + tracing::info!(?version, "selected sliding sync version"); + + version + }; #[cfg(feature = "experimental-oidc")] let allow_insecure_oidc = homeserver.scheme() == "http"; @@ -535,7 +520,7 @@ impl ClientBuilder { auth_ctx, homeserver, #[cfg(feature = "experimental-sliding-sync")] - self.sliding_sync_version, + sliding_sync_version, http_client, base_client, server_capabilities, @@ -841,9 +826,10 @@ pub enum ClientBuildError { #[error("Error looking up the .well-known endpoint on auto-discovery")] AutoDiscovery(FromHttpResponseError), - /// The builder requires support for sliding sync but it isn't available. - #[error("The homeserver doesn't support sliding sync and a custom proxy wasn't configured.")] - SlidingSyncNotAvailable, + /// Error from sliding sync. + #[cfg(feature = "experimental-sliding-sync")] + #[error(transparent)] + SlidingSync(#[from] crate::sliding_sync::Error), /// An error encountered when trying to parse the homeserver url. #[error(transparent)] diff --git a/testing/matrix-sdk-integration-testing/src/helpers.rs b/testing/matrix-sdk-integration-testing/src/helpers.rs index 3b729097f..f18542fff 100644 --- a/testing/matrix-sdk-integration-testing/src/helpers.rs +++ b/testing/matrix-sdk-integration-testing/src/helpers.rs @@ -15,6 +15,7 @@ use matrix_sdk::{ api::client::{account::register::v3::Request as RegistrationRequest, uiaa}, RoomId, }, + sliding_sync::VersionBuilder, Client, ClientBuilder, Room, }; use once_cell::sync::Lazy; @@ -85,9 +86,10 @@ impl TestClientBuilder { .homeserver_url(homeserver_url) // Disable Simplified MSC3575 for the integration tests as, at the time of writing // (2024-07-15), we use a Synapse version that doesn't support Simplified MSC3575. - .sliding_sync_proxy( - Url::parse(&sliding_sync_proxy_url).expect("Sliding sync proxy URL is invalid"), - ) + .sliding_sync_version_builder(VersionBuilder::Proxy { + url: Url::parse(&sliding_sync_proxy_url) + .expect("Sliding sync proxy URL is invalid"), + }) .with_encryption_settings(self.encryption_settings) .request_config(RequestConfig::short_retry());