diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index aabe0eaf3..3687ea9be 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2650,6 +2650,21 @@ void dc_accounts_stop_io (dc_accounts_t* accounts); void dc_accounts_maybe_network (dc_accounts_t* accounts); +/** + * This function can be called when there is a hint that the network is lost. + * This is similar to dc_accounts_maybe_network(), however, + * it does not retry job processing. + * + * dc_accounts_maybe_network_lost() is needed only on systems + * where the core cannot find out the connectivity loss on its own, eg. iOS. + * The function is not needed on Android, MacOS, Windows or Linux. + * + * @memberof dc_accounts_t + * @param accounts Account manager as created by dc_accounts_new(). + */ +void dc_accounts_maybe_network_lost (dc_accounts_t* accounts); + + /** * Create the event emitter that is used to receive events. * diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 85cd9c210..8d8b14a05 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -3867,7 +3867,7 @@ pub unsafe extern "C" fn dc_accounts_stop_io(accounts: *mut dc_accounts_t) { #[no_mangle] pub unsafe extern "C" fn dc_accounts_maybe_network(accounts: *mut dc_accounts_t) { if accounts.is_null() { - eprintln!("ignoring careless call to dc_accounts_mabye_network()"); + eprintln!("ignoring careless call to dc_accounts_maybe_network()"); return; } @@ -3875,6 +3875,17 @@ pub unsafe extern "C" fn dc_accounts_maybe_network(accounts: *mut dc_accounts_t) block_on(accounts.maybe_network()); } +#[no_mangle] +pub unsafe extern "C" fn dc_accounts_maybe_network_lost(accounts: *mut dc_accounts_t) { + if accounts.is_null() { + eprintln!("ignoring careless call to dc_accounts_maybe_network_lost()"); + return; + } + + let accounts = &*accounts; + block_on(accounts.maybe_network_lost()); +} + pub type dc_accounts_event_emitter_t = deltachat::accounts::EventEmitter; #[no_mangle] diff --git a/src/accounts.rs b/src/accounts.rs index 27421ed8f..7eb0e3bff 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -219,6 +219,13 @@ impl Accounts { } } + pub async fn maybe_network_lost(&self) { + let accounts = &*self.accounts.read().await; + for account in accounts.values() { + account.maybe_network_lost().await; + } + } + /// Unified event emitter. pub async fn get_event_emitter(&self) -> EventEmitter { let emitters: Vec<_> = self diff --git a/src/scheduler.rs b/src/scheduler.rs index 7e15bb865..c67a33a8e 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -44,6 +44,13 @@ impl Context { connectivity::idle_interrupted(lock).await; } + /// Indicate that the network likely is lost. + pub async fn maybe_network_lost(&self) { + let lock = self.scheduler.read().await; + lock.maybe_network_lost().await; + connectivity::idle_interrupted(lock).await; + } + pub(crate) async fn interrupt_inbox(&self, info: InterruptInfo) { self.scheduler.read().await.interrupt_inbox(info).await; } @@ -425,6 +432,18 @@ impl Scheduler { .await; } + async fn maybe_network_lost(&self) { + if !self.is_running() { + return; + } + + self.interrupt_inbox(InterruptInfo::new(false, None)) + .join(self.interrupt_mvbox(InterruptInfo::new(false, None))) + .join(self.interrupt_sentbox(InterruptInfo::new(false, None))) + .join(self.interrupt_smtp(InterruptInfo::new(false, None))) + .await; + } + async fn interrupt_inbox(&self, info: InterruptInfo) { if let Scheduler::Running { ref inbox, .. } = self { inbox.interrupt(info).await;