move all alloc/free/stop/has/shall_stop*ongoing* methods to context

introduce stop_ongoing to bindings and test for cancelation of configure
This commit is contained in:
holger krekel
2019-10-06 23:50:16 +02:00
parent 32ef0d4dc3
commit 51534b2fae
7 changed files with 102 additions and 144 deletions

View File

@@ -1621,7 +1621,7 @@ pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) {
}
let ffi_context = &*context;
ffi_context
.with_inner(|ctx| configure::dc_stop_ongoing_process(ctx))
.with_inner(|ctx| ctx.stop_ongoing())
.ok();
}

View File

@@ -411,6 +411,9 @@ class Account(object):
raise ValueError("could not join group")
return Chat(self, chat_id)
def stop_ongoing(self):
lib.dc_stop_ongoing_process(self._dc_context)
#
# meta API for start/stop and event based processing
#
@@ -432,7 +435,7 @@ class Account(object):
def stop_threads(self, wait=True):
""" stop IMAP/SMTP threads. """
lib.dc_stop_ongoing_process(self._dc_context)
self.stop_ongoing()
self._threads.stop(wait=wait)
def shutdown(self, wait=True):

View File

@@ -350,6 +350,12 @@ class TestOnlineAccount:
assert chat.id > const.DC_CHAT_ID_LAST_SPECIAL
return chat
def test_configure_canceled(self, acfactory):
ac1 = acfactory.get_online_configuring_account()
wait_configuration_progress(ac1, 200)
ac1.stop_ongoing()
wait_configuration_progress(ac1, 0, 0)
def test_export_import_self_keys(self, acfactory, tmpdir):
ac1, ac2 = acfactory.get_two_online_accounts()
dir = tmpdir.mkdir("exportdir")

View File

@@ -28,7 +28,7 @@ macro_rules! progress {
// connect
pub unsafe fn configure(context: &Context) {
if dc_has_ongoing(context) {
if context.has_ongoing() {
warn!(context, "There is already another ongoing process running.",);
return;
}
@@ -53,7 +53,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
let mut ongoing_allocated_here = false;
let mut param_autoconfig: Option<LoginParam> = None;
if dc_alloc_ongoing(context) {
if context.alloc_ongoing() {
ongoing_allocated_here = true;
if !context.sql.is_open() {
error!(context, "Cannot configure, database not opened.",);
@@ -74,9 +74,6 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
context.smtp.clone().lock().unwrap().disconnect();
info!(context, "Configure ...",);
let s_a = context.running_state.clone();
let s = s_a.read().unwrap();
// Variables that are shared between steps:
let mut param = LoginParam::from_database(context, "");
// need all vars here to be mutable because rust thinks the same step could be called multiple times
@@ -88,7 +85,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
const STEP_3_INDEX: u8 = 13;
let mut step_counter: u8 = 0;
while !s.shall_stop_ongoing {
while !context.shall_stop_ongoing() {
step_counter = step_counter + 1;
let success = match step_counter {
@@ -358,7 +355,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
break;
}
// probe STARTTLS/993
if s.shall_stop_ongoing {
if context.shall_stop_ongoing() {
ok_to_continue8 = false;
break;
}
@@ -372,7 +369,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
break;
}
// probe STARTTLS/143
if s.shall_stop_ongoing {
if context.shall_stop_ongoing() {
ok_to_continue8 = false;
break;
}
@@ -389,7 +386,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
break;
}
// next probe round with only the localpart of the email-address as the loginname
if s.shall_stop_ongoing {
if context.shall_stop_ongoing() {
ok_to_continue8 = false;
break;
}
@@ -426,7 +423,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
{
if param_autoconfig.is_some() {
success = false;
} else if s.shall_stop_ongoing {
} else if context.shall_stop_ongoing() {
success = false;
} else {
progress!(context, 850);
@@ -442,7 +439,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
.unwrap()
.connect(context, &param)
{
if s.shall_stop_ongoing {
if context.shall_stop_ongoing() {
success = false;
} else {
progress!(context, 860);
@@ -553,47 +550,12 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) {
}
*/
if ongoing_allocated_here {
dc_free_ongoing(context);
context.free_ongoing();
}
progress!(context, if success { 1000 } else { 0 });
}
/*******************************************************************************
* Ongoing process allocation/free/check
******************************************************************************/
pub fn dc_alloc_ongoing(context: &Context) -> bool {
if dc_has_ongoing(context) {
warn!(context, "There is already another ongoing process running.",);
false
} else {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = true;
s.shall_stop_ongoing = false;
true
}
}
pub fn dc_free_ongoing(context: &Context) {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = false;
s.shall_stop_ongoing = true;
}
fn dc_has_ongoing(context: &Context) -> bool {
let s_a = context.running_state.clone();
let s = s_a.read().unwrap();
s.ongoing_running || !s.shall_stop_ongoing
}
/*******************************************************************************
* Connect to configured account
******************************************************************************/
@@ -620,19 +582,6 @@ pub fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> libc::c_
* Configure a Context
******************************************************************************/
/// Signal an ongoing process to stop.
pub fn dc_stop_ongoing_process(context: &Context) {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
if s.ongoing_running && !s.shall_stop_ongoing {
info!(context, "Signaling the ongoing process to stop ASAP.",);
s.shall_stop_ongoing = true;
} else {
info!(context, "No ongoing process to stop.",);
};
}
pub fn read_autoconf_file(context: &Context, url: &str) -> Option<String> {
info!(context, "Testing {} ...", url);

View File

@@ -68,7 +68,7 @@ pub struct Context {
#[derive(Debug, PartialEq, Eq)]
pub struct RunningState {
pub ongoing_running: bool,
pub shall_stop_ongoing: bool,
shall_stop_ongoing: bool,
}
/// Return some info about deltachat-core
@@ -220,6 +220,62 @@ impl Context {
(*self.cb)(self, event)
}
/*******************************************************************************
* Ongoing process allocation/free/check
******************************************************************************/
pub fn alloc_ongoing(&self) -> bool {
if self.has_ongoing() {
warn!(self, "There is already another ongoing process running.",);
false
} else {
let s_a = self.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = true;
s.shall_stop_ongoing = false;
true
}
}
pub fn free_ongoing(&self) {
let s_a = self.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = false;
s.shall_stop_ongoing = true;
}
pub fn has_ongoing(&self) -> bool {
let s_a = self.running_state.clone();
let s = s_a.read().unwrap();
s.ongoing_running || !s.shall_stop_ongoing
}
/// Signal an ongoing process to stop.
pub fn stop_ongoing(&self) {
let s_a = self.running_state.clone();
let mut s = s_a.write().unwrap();
if s.ongoing_running && !s.shall_stop_ongoing {
info!(self, "Signaling the ongoing process to stop ASAP.",);
s.shall_stop_ongoing = true;
} else {
info!(self, "No ongoing process to stop.",);
};
}
pub fn shall_stop_ongoing(&self) -> bool {
self.running_state.clone().read().unwrap().shall_stop_ongoing
}
/*******************************************************************************
* UI chat/message related API
******************************************************************************/
pub fn get_info(&self) -> HashMap<&'static str, String> {
let unset = "0";
let l = LoginParam::from_database(self, "");

View File

@@ -110,32 +110,26 @@ pub fn has_backup(context: &Context, dir_name: impl AsRef<Path>) -> Result<Strin
}
pub fn initiate_key_transfer(context: &Context) -> Result<String> {
ensure!(context.alloc_ongoing(), "could not allocate ongoing");
let res = do_initiate_key_transfer(context);
context.free_ongoing();
res
}
fn do_initiate_key_transfer(context: &Context) -> Result<String> {
let mut msg: Message;
ensure!(dc_alloc_ongoing(context), "could not allocate ongoing");
let setup_code = create_setup_code(context);
/* this may require a keypair to be created. this may take a second ... */
if !context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
if let Ok(ref setup_file_content) = render_setup_file(context, &setup_code) {
ensure!(!context.shall_stop_ongoing(), "canceled");
let setup_file_content = render_setup_file(context, &setup_code)?;
/* encrypting may also take a while ... */
if !context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
ensure!(!context.shall_stop_ongoing(), "canceled");
let setup_file_name = context.new_blob_file(
"autocrypt-setup-message.html",
setup_file_content.as_bytes(),
)?;
{
if let Ok(chat_id) = chat::create_by_contact_id(context, 1) {
let chat_id = chat::create_by_contact_id(context, 1)?;
msg = Message::default();
msg.type_0 = Viewtype::File;
msg.param.set(Param::File, setup_file_name);
@@ -146,25 +140,10 @@ pub fn initiate_key_transfer(context: &Context) -> Result<String> {
msg.param
.set_int(Param::ForcePlaintext, DC_FP_NO_AUTOCRYPT_HEADER);
if !context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
if let Ok(msg_id) = chat::send_msg(context, chat_id, &mut msg) {
ensure!(!context.shall_stop_ongoing(), "canceled");
let msg_id = chat::send_msg(context, chat_id, &mut msg)?;
info!(context, "Wait for setup message being sent ...",);
loop {
if context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
break;
}
while !context.shall_stop_ongoing() {
std::thread::sleep(std::time::Duration::from_secs(1));
if let Ok(msg) = Message::load_from_db(context, msg_id) {
if msg.is_sent() {
@@ -173,15 +152,6 @@ pub fn initiate_key_transfer(context: &Context) -> Result<String> {
}
}
}
}
}
}
}
}
}
}
dc_free_ongoing(context);
Ok(setup_code)
}
@@ -420,7 +390,7 @@ pub fn normalize_setup_code(s: &str) -> String {
#[allow(non_snake_case)]
pub fn job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> {
ensure!(dc_alloc_ongoing(context), "could not allocate ongoing");
ensure!(context.alloc_ongoing(), "could not allocate ongoing");
let what: Option<ImexMode> = job.param.get_int(Param::Cmd).and_then(ImexMode::from_i32);
let param = job.param.get(Param::Arg).unwrap_or_default();
@@ -432,7 +402,7 @@ pub fn job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> {
if what == Some(ImexMode::ExportBackup) || what == Some(ImexMode::ExportSelfKeys) {
// before we export anything, make sure the private key exists
if e2ee::ensure_secret_key_exists(context).is_err() {
dc_free_ongoing(context);
context.free_ongoing();
bail!("Cannot create private key or private key not available.");
} else {
dc_create_folder(context, &param);
@@ -448,7 +418,7 @@ pub fn job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> {
bail!("unknown IMEX type");
}
};
dc_free_ongoing(context);
context.free_ongoing();
match success {
Ok(()) => {
info!(context, "IMEX successfully completed");
@@ -514,15 +484,7 @@ fn import_backup(context: &Context, backup_to_import: impl AsRef<Path>) -> Resul
|files| {
for (processed_files_cnt, file) in files.enumerate() {
let (file_name, file_blob) = file?;
if context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
bail!("received stop signal");
}
ensure!(!context.shall_stop_ongoing(), "received stop signal");
let mut permille = processed_files_cnt * 1000 / total_files_cnt;
if permille < 10 {
permille = 10
@@ -636,15 +598,7 @@ fn add_files_to_export(context: &Context, dest_path_filename: &PathBuf) -> Resul
let mut processed_files_cnt = 0;
for entry in dir_handle {
let entry = entry?;
if context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
{
bail!("canceled during export-files");
}
ensure!(!context.shall_stop_ongoing(), "canceled during export-files");
processed_files_cnt += 1;
let permille = max(min(processed_files_cnt * 1000 / total_files_cnt, 990), 10);
context.call_cb(Event::ImexProgress(permille));

View File

@@ -3,7 +3,6 @@ use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
use crate::aheader::EncryptPreference;
use crate::chat::{self, Chat};
use crate::config::*;
use crate::configure::*;
use crate::constants::*;
use crate::contact::*;
use crate::context::Context;
@@ -157,7 +156,7 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> u32 {
bob.qr_scan = None;
if ongoing_allocated {
dc_free_ongoing(context);
context.free_ongoing();
}
ret_chat_id as u32
};
@@ -170,7 +169,7 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> u32 {
info!(context, "Requesting secure-join ...",);
ensure_secret_key_exists(context).ok();
if !dc_alloc_ongoing(context) {
if !context.alloc_ongoing() {
return cleanup(&context, contact_chat_id, false, join_vg);
}
let qr_scan = check_qr(context, &qr);
@@ -184,7 +183,7 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> u32 {
error!(context, "Unknown contact.",);
return cleanup(&context, contact_chat_id, true, join_vg);
}
if check_exit(context) {
if context.shall_stop_ongoing() {
return cleanup(&context, contact_chat_id, true, join_vg);
}
join_vg = qr_scan.get_state() == LotState::QrAskVerifyGroup;
@@ -240,21 +239,12 @@ pub fn dc_join_securejoin(context: &Context, qr: &str) -> u32 {
}
// Bob -> Alice
while !check_exit(&context) {
while !context.shall_stop_ongoing() {
std::thread::sleep(std::time::Duration::new(0, 3_000_000));
}
cleanup(&context, contact_chat_id, true, join_vg)
}
fn check_exit(context: &Context) -> bool {
context
.running_state
.clone()
.read()
.unwrap()
.shall_stop_ongoing
}
fn send_handshake_msg(
context: &Context,
contact_chat_id: u32,
@@ -636,7 +626,7 @@ pub fn handle_securejoin_handshake(
fn end_bobs_joining(context: &Context, status: libc::c_int) {
context.bob.write().unwrap().status = status;
dc_stop_ongoing_process(context);
context.stop_ongoing();
}
fn secure_connection_established(context: &Context, contact_chat_id: u32) {