mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
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:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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, ¶m)
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
86
src/imex.rs
86
src/imex.rs
@@ -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, ¶m);
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user