From 0bf3d20e07b44c8ff207ee999208e82179c6dbe8 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 15 Sep 2019 19:31:07 +0200 Subject: [PATCH] fix and implement ffi tranlation --- deltachat-ffi/src/lib.rs | 81 ++++++++++++++++++++++++++++++++-------- examples/repl/main.rs | 7 +--- examples/simple.rs | 5 +-- src/dc_receive_imf.rs | 6 +-- src/events.rs | 5 +-- src/imap.rs | 13 +++---- src/param.rs | 2 +- src/smtp.rs | 2 +- 8 files changed, 80 insertions(+), 41 deletions(-) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index a3459e400..593599b26 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -22,7 +22,6 @@ use std::sync::RwLock; use libc::uintptr_t; use num_traits::{FromPrimitive, ToPrimitive}; -use deltachat::constants::Event; use deltachat::contact::Contact; use deltachat::context::Context; use deltachat::dc_tools::{as_path, as_str, dc_strdup, to_string, OsStrExt, StrExt}; @@ -66,7 +65,7 @@ unsafe impl Sync for ContextWrapper {} /// @param data2 depends on the event parameter /// @return return 0 unless stated otherwise in the event parameter documentation pub type dc_callback_t = - unsafe extern "C" fn(_: &dc_context_t, _: Event, _: uintptr_t, _: uintptr_t) -> uintptr_t; + unsafe extern "C" fn(_: &dc_context_t, _: i32, _: uintptr_t, _: uintptr_t) -> uintptr_t; /// Struct representing the deltachat context. /// @@ -81,12 +80,8 @@ impl ContextWrapper { /// called and an actual [Context] exists. /// /// This function makes it easy to log an error. - fn error(&self, msg: &str) { - if let Some(cb) = self.cb { - let msg_c = - CString::new(msg).unwrap_or(CString::new("[invalid error message]").unwrap()); - unsafe { cb(self, Event::ERROR, 0, msg_c.as_ptr() as libc::uintptr_t) }; - } + unsafe fn error(&self, msg: &str) { + self.translate_cb(Event::Error(msg.to_string())); } /// Unlock the context and execute a closure with it. @@ -112,11 +107,72 @@ impl ContextWrapper { match guard.as_ref() { Some(ref ctx) => Ok(ctxfn(ctx)), None => { - self.error("context not open"); + unsafe { self.error("context not open") }; Err(()) } } } + + /// Translates the callback from the rust style to the C-style version. + unsafe fn translate_cb(&self, event: Event) -> uintptr_t { + match self.cb { + Some(ffi_cb) => { + let event_id = event.as_id(); + match event { + Event::Info(msg) + | Event::SmtpConnected(msg) + | Event::ImapConnected(msg) + | Event::SmtpMessageSent(msg) + | Event::Warning(msg) + | Event::Error(msg) + | Event::ErrorNetwork(msg) + | Event::ErrorSelfNotInGroup(msg) => { + let data2 = CString::new(msg).unwrap(); + ffi_cb(self, event_id, 0, data2.as_ptr() as uintptr_t) + } + Event::MsgsChanged { chat_id, msg_id } + | Event::IncomingMsg { chat_id, msg_id } + | Event::MsgDelivered { chat_id, msg_id } + | Event::MsgFailed { chat_id, msg_id } + | Event::MsgRead { chat_id, msg_id } => { + ffi_cb(self, event_id, chat_id as uintptr_t, msg_id as uintptr_t) + } + Event::ChatModified(chat_id) => ffi_cb(self, event_id, chat_id as uintptr_t, 0), + Event::ContactsChanged(id) | Event::LocationChanged(id) => { + let id = id.unwrap_or_default(); + ffi_cb(self, event_id, id as uintptr_t, 0) + } + Event::ConfigureProgress(progress) | Event::ImexProgress(progress) => { + ffi_cb(self, event_id, progress as uintptr_t, 0) + } + Event::ImexFileWritten(file) => { + let data1 = file.to_c_string().unwrap(); + ffi_cb(self, event_id, data1.as_ptr() as uintptr_t, 0) + } + Event::SecurejoinInviterProgress { + contact_id, + progress, + } + | Event::SecurejoinJoinerProgress { + contact_id, + progress, + } => ffi_cb( + self, + event_id, + contact_id as uintptr_t, + progress as uintptr_t, + ), + Event::GetString { id, count } => ffi_cb( + self, + event_id, + id.to_u32().unwrap_or_default() as uintptr_t, + count as uintptr_t, + ), + } + } + None => 0, + } + } } #[no_mangle] @@ -175,13 +231,8 @@ pub unsafe extern "C" fn dc_open( return 0; } let ffi_context = &*context; + let rust_cb = move |_ctx: &Context, evt: Event| ffi_context.translate_cb(evt); - let rust_cb = - move |_ctx: &Context, evt: Event, d0: uintptr_t, d1: uintptr_t| match ffi_context.cb { - Some(ffi_cb) => ffi_cb(ffi_context, evt, d0, d1), - None => 0, - }; - let ffi_context = &mut *context; let ctx = if blobdir.is_null() { Context::new( Box::new(rust_cb), diff --git a/examples/repl/main.rs b/examples/repl/main.rs index 3bc7f8014..6adbe567e 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -65,11 +65,8 @@ fn receive_event(_context: &Context, event: Event) -> libc::uintptr_t { Event::Error(msg) => { println!("\x1b[31m[DC_EVENT_ERROR] {}\x1b[0m", msg); } - Event::ErrorNetwork(c, msg) => { - println!( - "\x1b[31m[DC_EVENT_ERROR_NETWORK] first={}, msg={}\x1b[0m", - c, msg - ); + Event::ErrorNetwork(msg) => { + println!("\x1b[31m[DC_EVENT_ERROR_NETWORK] msg={}\x1b[0m", msg); } Event::ErrorSelfNotInGroup(msg) => { println!("\x1b[31m[DC_EVENT_ERROR_SELF_NOT_IN_GROUP] {}\x1b[0m", msg); diff --git a/examples/simple.rs b/examples/simple.rs index 3236c7618..b715dbb3e 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -23,10 +23,7 @@ fn cb(_ctx: &Context, event: Event) -> usize { print!(" progress: {}\n", progress); 0 } - Event::Info(msg) - | Event::Warning(msg) - | Event::Error(msg) - | Event::ErrorNetwork(_, msg) => { + Event::Info(msg) | Event::Warning(msg) | Event::Error(msg) | Event::ErrorNetwork(msg) => { print!(" {}\n", msg); 0 } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index deb861de5..f24fa7d00 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -102,15 +102,15 @@ pub unsafe fn dc_receive_imf( free(rfc724_mid.cast()); if let Some(create_event_to_send) = create_event_to_send { - for (msg_id, insert_id) in created_db_entries { + for (chat_id, msg_id) in created_db_entries { let event = match create_event_to_send { CreateEvent::MsgsChanged => Event::MsgsChanged { msg_id: *msg_id as u32, - chat_id: *insert_id as u32, + chat_id: *chat_id as u32, }, CreateEvent::IncomingMsg => Event::IncomingMsg { msg_id: *msg_id as u32, - chat_id: *insert_id as u32, + chat_id: *chat_id as u32, }, }; context.call_cb(event); diff --git a/src/events.rs b/src/events.rs index ab7920dd2..570dedf31 100644 --- a/src/events.rs +++ b/src/events.rs @@ -81,12 +81,9 @@ pub enum Event { /// it is probably more useful to report this to the user /// instead of the string from data2. /// - /// @param data1 (usize) 1=first/new network error, should be reported the user; - /// 0=subsequent network error, should be logged only - /// @param data2 (String) string /// @return 0 #[strum(props(id = "401"))] - ErrorNetwork(usize, String), + ErrorNetwork(String), /// An action cannot be performed because the user is not in the group. /// Reported eg. after a call to diff --git a/src/imap.rs b/src/imap.rs index 86b411766..35355001e 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -440,13 +440,10 @@ impl Imap { emit_event!( context, - Event::ErrorNetwork( - 0, - format!( - "Could not connect to IMAP-server {}:{}. ({})", - imap_server, imap_port, err - ) - ) + Event::ErrorNetwork(format!( + "Could not connect to IMAP-server {}:{}. ({})", + imap_server, imap_port, err + )) ); return false; @@ -464,7 +461,7 @@ impl Imap { Err((err, _)) => { emit_event!( context, - Event::ErrorNetwork(0, format!("Cannot login ({})", err)) + Event::ErrorNetwork(format!("Cannot login ({})", err)) ); self.unsetup_handle(context); diff --git a/src/param.rs b/src/param.rs index f18f3d04b..101aa3549 100644 --- a/src/param.rs +++ b/src/param.rs @@ -94,7 +94,7 @@ impl fmt::Display for Params { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (i, (key, value)) in self.inner.iter().enumerate() { if i > 0 { - write!(f, "\n")?; + writeln!(f)?; } write!(f, "{}={}", *key as u8 as char, value)?; } diff --git a/src/smtp.rs b/src/smtp.rs index ae0007be8..89f95444d 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -52,7 +52,7 @@ impl Smtp { } if lp.send_server.is_empty() || lp.send_port == 0 { - context.call_cb(Event::ErrorNetwork(0, "SMTP bad parameters.".into())); + context.call_cb(Event::ErrorNetwork("SMTP bad parameters.".into())); } self.from = if let Ok(addr) = EmailAddress::new(lp.addr.clone()) {