diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index c07fa624d..980702a3e 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -2706,13 +2706,21 @@ char * dc_backup_provider_qr_svg (dc_context_t* context, const dc_backup_provide /** * Waits for the sending to finish and frees the backup provider object. * - * @memberof dc_backup_sender_t + * This should only be called once. + * + * @memberof dc_backup_provider_t * @param context The context. * @param backup_provider The backup provider object as created by * dc_backup_provider_new(). If NULL is given nothing is done. */ void dc_backup_provider_wait (dc_context_t* context, dc_backup_provider_t* backup_provider); +/** + * Frees a dc_backup_provider_t object. + * + * @memberof dc_backup_provider_t + */ +void dc_backup_prvider_unref (dc_backup_provider_t* backup_provider); /** * Gets a backup offered by a dc_backup_provider_t object on another device. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index f7534d679..17104d238 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -4185,12 +4185,17 @@ pub unsafe extern "C" fn dc_backup_provider_wait( return; } let ctx = &*context; - let provider = Box::from_raw(provider); - block_on(provider.join()) + let provider = &mut *provider; + block_on(provider) .log_err(ctx, "Failed to join provider") .ok(); } +#[no_mangle] +pub unsafe extern "C" fn dc_backup_provider_unref(provider: *mut dc_backup_provider_t) { + drop(Box::from_raw(provider)); +} + #[no_mangle] pub unsafe extern "C" fn dc_receive_backup( context: *mut dc_context_t, diff --git a/deltachat-jsonrpc/src/api/mod.rs b/deltachat-jsonrpc/src/api/mod.rs index 047c285cc..6ff1a371d 100644 --- a/deltachat-jsonrpc/src/api/mod.rs +++ b/deltachat-jsonrpc/src/api/mod.rs @@ -1371,7 +1371,7 @@ impl CommandApi { return Err(err); } }; - let res = provider.join().await; + let res = provider.await; ctx.start_io().await; res } diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index 0a41da87c..a90577009 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -492,7 +492,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu let provider = BackupProvider::prepare(&context).await?; let qr = provider.qr(); println!("QR code: {}", format_backup(&qr)?); - provider.join().await?; + provider.await?; } "receive-backup" => { ensure!(!arg1.is_empty(), "Argument is missing."); diff --git a/src/imex/transfer.rs b/src/imex/transfer.rs index aa32ba3c4..51c2b891c 100644 --- a/src/imex/transfer.rs +++ b/src/imex/transfer.rs @@ -22,7 +22,10 @@ //! getter can not connect to an impersonated provider and the provider does not offer the //! download to an impersonated getter. +use std::future::Future; use std::path::{Path, PathBuf}; +use std::pin::Pin; +use std::task::Poll; use anyhow::{anyhow, bail, ensure, format_err, Context as _, Result}; use async_channel::Receiver; @@ -57,6 +60,9 @@ use super::{export_database, DeleteOnDrop, DBFILE_BACKUP_NAME}; /// /// This starts a task which acquires the global "ongoing" mutex. If you need to stop the /// task use the [`Context::stop_ongoing`] mechanism. +/// +/// The task implements [`Future`] and awaiting it will complete once a transfer has been +/// either completed or aborted. #[derive(Debug)] pub struct BackupProvider { /// The supervisor task, run by [`BackupProvider::watch_provider`]. @@ -244,15 +250,13 @@ impl BackupProvider { ticket: self.ticket.clone(), } } +} - /// Awaits the [`BackupProvider`] until it is finished. - /// - /// This waits until someone connected to the sender and finished transferring a backup. - /// A failed transfer also counts as a finished transfer. If the [`BackupProvider`] - /// task results in an error it will be returned here. - pub async fn join(self) -> Result<()> { - self.handle.await??; - Ok(()) +impl Future for BackupProvider { + type Output = Result<()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { + Pin::new(&mut self.handle).poll(cx)? } } @@ -507,7 +511,7 @@ mod tests { get_backup(&ctx1, provider.qr()).await.unwrap(); // Make sure the provider finishes without an error. - tokio::time::timeout(Duration::from_secs(30), provider.join()) + tokio::time::timeout(Duration::from_secs(30), provider) .await .expect("timed out") .expect("error in provider");