diff --git a/src/automatic_relay_management.rs b/src/autorelay.rs similarity index 83% rename from src/automatic_relay_management.rs rename to src/autorelay.rs index 542a4da77d..4037da380c 100644 --- a/src/automatic_relay_management.rs +++ b/src/autorelay.rs @@ -1,3 +1,18 @@ +//! # Automatic relay handling (experimental, still in development) +//! +//! Chatmail relays create an account on first login, +//! so a profile can add further transports on its own without user interaction. +//! Candidate hosts come from the `relay_candidates` table, +//! which migrations seed with a list of known chatmail relays. +//! +//! Status of implementation: +//! Additions are attempted right before going into IMAP IDLE, +//! i.e. only while connected and with nothing more important to do, +//! and only if a UI opted in via [`Config::Autorelay`]. +//! Once a profile has reached `NUM_TRANSPORTS_TARGET` transports, +//! [`Config::AutorelayFinished`] is set and nothing is ever added again, +//! so deleting a transport later does not pull in a replacement. + use std::pin::Pin; use anyhow::Result; @@ -46,9 +61,7 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool // Housekeeping or automatic relay management is already running in another thread, do nothing. return Ok(false); }; - let last_timestamp = context - .get_config_i64(Config::LastAutomaticRelayManagement) - .await?; + let last_timestamp = context.get_config_i64(Config::LastAutorelay).await?; if last_timestamp > now { warn!( context, @@ -57,22 +70,16 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool } else if last_timestamp > now.saturating_sub(AUTOMATIC_ADDITION_DEBOUNCE_SECONDS) { return Ok(false); } - if !context - .get_config_bool(Config::AutomaticRelayManagement) - .await? - { + if !context.get_config_bool(Config::Autorelay).await? { return Ok(false); } - if context - .get_config_bool(Config::AutomaticRelayManagementFinished) - .await? - { + if context.get_config_bool(Config::AutorelayFinished).await? { return Ok(false); } // Set the config at the beginning to avoid endless loops. // Race conditions are not a concern because we locked the mutex. context - .set_config_internal(Config::LastAutomaticRelayManagement, Some(&now.to_string())) + .set_config_internal(Config::LastAutorelay, Some(&now.to_string())) .await?; let mut relay_added = false; @@ -80,10 +87,7 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool for _ in 0..NUM_TRANSPORTS_TARGET { if context.count_transports().await? >= NUM_TRANSPORTS_TARGET { context - .set_config_internal( - Config::AutomaticRelayManagementFinished, - config::from_bool(true), - ) + .set_config_internal(Config::AutorelayFinished, config::from_bool(true)) .await?; return Ok(relay_added); @@ -175,4 +179,4 @@ pub(crate) fn login_param_from_host(host: &str) -> EnteredLoginParam { } #[cfg(test)] -mod automatic_relay_management_tests; +mod autorelay_tests; diff --git a/src/automatic_relay_management/automatic_relay_management_tests.rs b/src/autorelay/autorelay_tests.rs similarity index 86% rename from src/automatic_relay_management/automatic_relay_management_tests.rs rename to src/autorelay/autorelay_tests.rs index ba37c3bb8d..a74bd3f6f9 100644 --- a/src/automatic_relay_management/automatic_relay_management_tests.rs +++ b/src/autorelay/autorelay_tests.rs @@ -73,12 +73,9 @@ async fn test_load_relay_candidates_multiple() -> Result<()> { Ok(()) } -async fn assert_automatic_relay_management_does_nothing(t: &TestContext) { +async fn assert_autorelay_does_nothing(t: &TestContext) { let transports_before = t.count_transports().await.unwrap(); - let config_before = t - .get_config_i64(Config::LastAutomaticRelayManagement) - .await - .unwrap(); + let config_before = t.get_config_i64(Config::LastAutorelay).await.unwrap(); let skip_network = false; // No need to skip network, nothing is supposed to happen let relay_added = maybe_add_additional_relays_inner(t, skip_network) @@ -86,10 +83,7 @@ async fn assert_automatic_relay_management_does_nothing(t: &TestContext) { .unwrap(); assert_eq!(relay_added, false); - let config_after = t - .get_config_i64(Config::LastAutomaticRelayManagement) - .await - .unwrap(); + let config_after = t.get_config_i64(Config::LastAutorelay).await.unwrap(); let transports_after = t.count_transports().await.unwrap(); assert_eq!(config_after, config_before); @@ -105,7 +99,7 @@ async fn test_maybe_add_additional_relays_mutex_held() -> Result<()> { // already running housekeeping or relay management. let _lock = t.background_task_mutex.lock().await; - assert_automatic_relay_management_does_nothing(t).await; + assert_autorelay_does_nothing(t).await; Ok(()) } @@ -117,13 +111,10 @@ async fn test_maybe_add_additional_relays_debounce() -> Result<()> { let some_seconds_ago = time() - 10; // Pretend automatic relay management just ran. - t.set_config_internal( - Config::LastAutomaticRelayManagement, - Some(&some_seconds_ago.to_string()), - ) - .await?; + t.set_config_internal(Config::LastAutorelay, Some(&some_seconds_ago.to_string())) + .await?; - assert_automatic_relay_management_does_nothing(t).await; + assert_autorelay_does_nothing(t).await; Ok(()) } @@ -132,7 +123,7 @@ async fn test_maybe_add_additional_relays_debounce() -> Result<()> { async fn test_maybe_add_additional_relays_disabled() { // By default, automatic relay management is disabled: let t = &TestContext::new_alice().await; - assert_automatic_relay_management_does_nothing(t).await; + assert_autorelay_does_nothing(t).await; } /// Runs maybe_add_additional_relays_inner(), then deletes one of the transports. @@ -158,11 +149,8 @@ async fn test_maybe_add_additional_relays_does_nothing_after_finishing_once() -> let transports_count = t.count_transports().await?; assert_eq!(transports_count, NUM_TRANSPORTS_TARGET - 1); - assert!( - t.get_config_bool(Config::AutomaticRelayManagementFinished) - .await? - ); - assert_automatic_relay_management_does_nothing(t).await; + assert!(t.get_config_bool(Config::AutorelayFinished).await?); + assert_autorelay_does_nothing(t).await; Ok(()) } @@ -187,9 +175,7 @@ async fn test_maybe_add_additional_relays_add_one() -> Result<()> { let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?; assert!(relay_added); - let config_after = t - .get_config_i64(Config::LastAutomaticRelayManagement) - .await?; + let config_after = t.get_config_i64(Config::LastAutorelay).await?; assert!(config_after >= now); let transports_after = t.count_transports().await?; @@ -218,9 +204,7 @@ async fn test_maybe_add_additional_relays_add_multiple() -> Result<()> { let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?; assert!(relay_added); - let config_after = t - .get_config_i64(Config::LastAutomaticRelayManagement) - .await?; + let config_after = t.get_config_i64(Config::LastAutorelay).await?; assert!(config_after >= now); let transports_after = t.count_transports().await?; @@ -253,9 +237,7 @@ async fn test_maybe_add_additional_relays_failure() -> Result<()> { assert_eq!(relay_added, false); // The config is still updated: - let config_after = t - .get_config_i64(Config::LastAutomaticRelayManagement) - .await?; + let config_after = t.get_config_i64(Config::LastAutorelay).await?; assert!(config_after >= now); let transports_after = t.count_transports().await?; @@ -286,7 +268,7 @@ async fn test_maybe_add_additional_relays_failure() -> Result<()> { async fn enable_config(context: &Context) { context - .set_config_bool(Config::AutomaticRelayManagement, true) + .set_config_bool(Config::Autorelay, true) .await .unwrap(); } diff --git a/src/config.rs b/src/config.rs index 8cf59b025a..98a4621e8c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -358,13 +358,13 @@ pub enum Config { LastCantDecryptOutgoingMsgs, /// Timestamp of the last time automatic relay management was run - LastAutomaticRelayManagement, + LastAutorelay, /// Whether to automatically add/remove transports - AutomaticRelayManagement, + Autorelay, /// Whether automatic relay management successfully added the desired number of relays - AutomaticRelayManagementFinished, + AutorelayFinished, /// Whether to avoid using IMAP IDLE even if the server supports it. /// diff --git a/src/context.rs b/src/context.rs index fc50fa2c06..9670f8ff7c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1050,20 +1050,18 @@ impl Context { .to_string(), ); res.insert( - "last_automatic_relay_management", - self.get_config_i64(Config::LastAutomaticRelayManagement) + "last_autorelay", + self.get_config_i64(Config::LastAutorelay) .await? .to_string(), ); res.insert( - "automatic_relay_management", - self.get_config_bool(Config::AutomaticRelayManagement) - .await? - .to_string(), + "autorelay", + self.get_config_bool(Config::Autorelay).await?.to_string(), ); res.insert( - "automatic_relay_management_finished", - self.get_config_bool(Config::AutomaticRelayManagementFinished) + "autorelay_finished", + self.get_config_bool(Config::AutorelayFinished) .await? .to_string(), ); diff --git a/src/imap/idle.rs b/src/imap/idle.rs index 4bf9b3f665..1744f2a03b 100644 --- a/src/imap/idle.rs +++ b/src/imap/idle.rs @@ -53,9 +53,9 @@ impl Session { // we try to add additional relays right before going into IDLE mode, // because we are connected and don't have anything important to do. - tokio::task::spawn( - crate::automatic_relay_management::maybe_add_additional_relays(context.clone()), - ); + tokio::task::spawn(crate::autorelay::maybe_add_additional_relays( + context.clone(), + )); let mut handle = self.inner.idle(); handle diff --git a/src/lib.rs b/src/lib.rs index 94e9e56d8f..1c576ba22b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ pub use events::*; mod aheader; pub mod appversions; -mod automatic_relay_management; +mod autorelay; pub mod blob; pub mod calls; pub mod chat; diff --git a/src/qr.rs b/src/qr.rs index 7ebe21bc7e..165a1371dc 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -11,7 +11,7 @@ use deltachat_contact_tools::{ContactAddress, addr_normalize, may_be_valid_addr} use percent_encoding::{NON_ALPHANUMERIC, percent_decode_str, percent_encode}; use serde::Deserialize; -use crate::automatic_relay_management::login_param_from_host; +use crate::autorelay::login_param_from_host; use crate::config::Config; use crate::contact::{Contact, ContactId, Origin}; use crate::context::Context;