mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 18:36:30 +03:00
update ffi
This commit is contained in:
@@ -243,7 +243,7 @@ typedef uintptr_t (*dc_callback_t) (dc_context_t* context, int event, uintptr_t
|
||||
* The object must be passed to the other context functions
|
||||
* and must be freed using dc_context_unref() after usage.
|
||||
*/
|
||||
dc_context_t* dc_context_new (dc_callback_t cb, void* userdata, const char* os_name);
|
||||
dc_context_t* dc_context_new (void* userdata, const char* os_name);
|
||||
|
||||
|
||||
/**
|
||||
@@ -540,12 +540,12 @@ int dc_is_configured (const dc_context_t* context);
|
||||
/**
|
||||
* TODO: Document
|
||||
*/
|
||||
void dc_run (dc_context_t* context);
|
||||
void dc_context_run (dc_context_t* context, dc_callback_t cb);
|
||||
|
||||
/**
|
||||
* TODO: Document
|
||||
*/
|
||||
void dc_shutdown (dc_context_t* context);
|
||||
void dc_context_shutdown (dc_context_t* context);
|
||||
|
||||
/**
|
||||
* This function can be called whenever there is a hint
|
||||
|
||||
@@ -57,7 +57,6 @@ use self::string::*;
|
||||
/// and protected by an [RwLock]. Other than that it needs to store
|
||||
/// the data which is passed into [dc_context_new].
|
||||
pub struct ContextWrapper {
|
||||
cb: Option<dc_callback_t>,
|
||||
userdata: *mut libc::c_void,
|
||||
os_name: String,
|
||||
inner: RwLock<Option<context::Context>>,
|
||||
@@ -91,7 +90,10 @@ impl ContextWrapper {
|
||||
///
|
||||
/// This function makes it easy to log an error.
|
||||
unsafe fn error(&self, msg: &str) {
|
||||
self.translate_cb(Event::Error(msg.to_string()));
|
||||
self.with_inner(|ctx| {
|
||||
ctx.call_cb(Event::Error(msg.to_string()));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Unlock the context and execute a closure with it.
|
||||
@@ -122,88 +124,10 @@ impl ContextWrapper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Translates the callback from the rust style to the C-style version.
|
||||
unsafe fn translate_cb(&self, event: Event) {
|
||||
if let Some(ffi_cb) = self.cb {
|
||||
let event_id = event.as_id();
|
||||
match event {
|
||||
Event::Info(msg)
|
||||
| Event::SmtpConnected(msg)
|
||||
| Event::ImapConnected(msg)
|
||||
| Event::SmtpMessageSent(msg)
|
||||
| Event::ImapMessageDeleted(msg)
|
||||
| Event::ImapMessageMoved(msg)
|
||||
| Event::ImapFolderEmptied(msg)
|
||||
| Event::NewBlobFile(msg)
|
||||
| Event::DeletedBlobFile(msg)
|
||||
| Event::Warning(msg)
|
||||
| Event::Error(msg)
|
||||
| Event::ErrorNetwork(msg)
|
||||
| Event::ErrorSelfNotInGroup(msg) => {
|
||||
let data2 = CString::new(msg).unwrap_or_default();
|
||||
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.to_u32() as uintptr_t,
|
||||
msg_id.to_u32() as uintptr_t,
|
||||
);
|
||||
}
|
||||
Event::ChatModified(chat_id) => {
|
||||
ffi_cb(self, event_id, chat_id.to_u32() 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_or_default();
|
||||
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::SecurejoinMemberAdded {
|
||||
chat_id,
|
||||
contact_id,
|
||||
} => {
|
||||
ffi_cb(
|
||||
self,
|
||||
event_id,
|
||||
chat_id.to_u32() as uintptr_t,
|
||||
contact_id as uintptr_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_context_new(
|
||||
cb: Option<dc_callback_t>,
|
||||
userdata: *mut libc::c_void,
|
||||
os_name: *const libc::c_char,
|
||||
) -> *mut dc_context_t {
|
||||
@@ -215,7 +139,6 @@ pub unsafe extern "C" fn dc_context_new(
|
||||
to_string_lossy(os_name)
|
||||
};
|
||||
let ffi_ctx = ContextWrapper {
|
||||
cb,
|
||||
userdata,
|
||||
os_name,
|
||||
inner: RwLock::new(None),
|
||||
@@ -257,17 +180,11 @@ 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 ctx = if blobdir.is_null() || *blobdir == 0 {
|
||||
Context::new(
|
||||
Box::new(rust_cb),
|
||||
ffi_context.os_name.clone(),
|
||||
as_path(dbfile).to_path_buf(),
|
||||
)
|
||||
Context::new(ffi_context.os_name.clone(), as_path(dbfile).to_path_buf())
|
||||
} else {
|
||||
Context::with_blobdir(
|
||||
Box::new(rust_cb),
|
||||
ffi_context.os_name.clone(),
|
||||
as_path(dbfile).to_path_buf(),
|
||||
as_path(blobdir).to_path_buf(),
|
||||
@@ -471,17 +388,100 @@ pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_run(context: *mut dc_context_t) {
|
||||
pub unsafe extern "C" fn dc_context_run(context: *mut dc_context_t, cb: Option<dc_callback_t>) {
|
||||
if context.is_null() {
|
||||
eprintln!("ignoring careless call to dc_run()");
|
||||
return;
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
ffi_context.with_inner(|ctx| ctx.run()).unwrap_or(())
|
||||
ffi_context
|
||||
.with_inner(|ctx| {
|
||||
ctx.run(|_ctx, event| {
|
||||
translate_cb(ffi_context, cb, event);
|
||||
})
|
||||
})
|
||||
.unwrap_or(())
|
||||
}
|
||||
|
||||
/// Translates the callback from the rust style to the C-style version.
|
||||
unsafe fn translate_cb(ctx: &ContextWrapper, ffi_cb: Option<dc_callback_t>, event: Event) {
|
||||
if let Some(ffi_cb) = ffi_cb {
|
||||
let event_id = event.as_id();
|
||||
match event {
|
||||
Event::Info(msg)
|
||||
| Event::SmtpConnected(msg)
|
||||
| Event::ImapConnected(msg)
|
||||
| Event::SmtpMessageSent(msg)
|
||||
| Event::ImapMessageDeleted(msg)
|
||||
| Event::ImapMessageMoved(msg)
|
||||
| Event::ImapFolderEmptied(msg)
|
||||
| Event::NewBlobFile(msg)
|
||||
| Event::DeletedBlobFile(msg)
|
||||
| Event::Warning(msg)
|
||||
| Event::Error(msg)
|
||||
| Event::ErrorNetwork(msg)
|
||||
| Event::ErrorSelfNotInGroup(msg) => {
|
||||
let data2 = CString::new(msg).unwrap_or_default();
|
||||
ffi_cb(ctx, 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(
|
||||
ctx,
|
||||
event_id,
|
||||
chat_id.to_u32() as uintptr_t,
|
||||
msg_id.to_u32() as uintptr_t,
|
||||
);
|
||||
}
|
||||
Event::ChatModified(chat_id) => {
|
||||
ffi_cb(ctx, event_id, chat_id.to_u32() as uintptr_t, 0);
|
||||
}
|
||||
Event::ContactsChanged(id) | Event::LocationChanged(id) => {
|
||||
let id = id.unwrap_or_default();
|
||||
ffi_cb(ctx, event_id, id as uintptr_t, 0);
|
||||
}
|
||||
Event::ConfigureProgress(progress) | Event::ImexProgress(progress) => {
|
||||
ffi_cb(ctx, event_id, progress as uintptr_t, 0);
|
||||
}
|
||||
Event::ImexFileWritten(file) => {
|
||||
let data1 = file.to_c_string().unwrap_or_default();
|
||||
ffi_cb(ctx, event_id, data1.as_ptr() as uintptr_t, 0);
|
||||
}
|
||||
Event::SecurejoinInviterProgress {
|
||||
contact_id,
|
||||
progress,
|
||||
}
|
||||
| Event::SecurejoinJoinerProgress {
|
||||
contact_id,
|
||||
progress,
|
||||
} => {
|
||||
ffi_cb(
|
||||
ctx,
|
||||
event_id,
|
||||
contact_id as uintptr_t,
|
||||
progress as uintptr_t,
|
||||
);
|
||||
}
|
||||
Event::SecurejoinMemberAdded {
|
||||
chat_id,
|
||||
contact_id,
|
||||
} => {
|
||||
ffi_cb(
|
||||
ctx,
|
||||
event_id,
|
||||
chat_id.to_u32() as uintptr_t,
|
||||
contact_id as uintptr_t,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_shutdown(context: *mut dc_context_t) {
|
||||
pub unsafe extern "C" fn dc_context_shutdown(context: *mut dc_context_t) {
|
||||
if context.is_null() {
|
||||
eprintln!("ignoring careless call to dc_shutdown()");
|
||||
return;
|
||||
|
||||
@@ -38,7 +38,7 @@ class Account(object):
|
||||
:param debug: turn on debug logging for events.
|
||||
"""
|
||||
self._dc_context = ffi.gc(
|
||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, as_dc_charpointer(os_name)),
|
||||
lib.dc_context_new(ffi.NULL, as_dc_charpointer(os_name)),
|
||||
_destroy_dc_context,
|
||||
)
|
||||
if eventlogging:
|
||||
@@ -566,7 +566,7 @@ class IOThreads:
|
||||
t.start()
|
||||
|
||||
def stop(self, wait=False):
|
||||
lib.dc_shutdown(self._dc_context)
|
||||
lib.dc_context_shutdown(self._dc_context)
|
||||
|
||||
if wait:
|
||||
for name, thread in self._name2thread.items():
|
||||
@@ -575,7 +575,7 @@ class IOThreads:
|
||||
def dc_thread_run(self):
|
||||
self._log_event("py-bindings-info", 0, "DC THREAD START")
|
||||
|
||||
lib.dc_run(self._dc_context)
|
||||
lib.dc_context_run(self._dc_context, lib.py_dc_callback)
|
||||
|
||||
self._log_event("py-bindings-info", 0, "INBOX THREAD FINISHED")
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::sync::{
|
||||
Arc, Condvar, Mutex, RwLock,
|
||||
};
|
||||
|
||||
use crossbeam::channel::select;
|
||||
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
||||
|
||||
use crate::chat::*;
|
||||
@@ -188,10 +189,9 @@ impl Context {
|
||||
where
|
||||
F: Fn(&Context, Event) -> () + Send + Sync,
|
||||
{
|
||||
// TODO: ensure this can be only called once.
|
||||
|
||||
use crossbeam::channel::select;
|
||||
self.is_running.store(true, Ordering::Relaxed);
|
||||
if self.is_running.swap(true, Ordering::Relaxed) {
|
||||
panic!("Run can only be called once");
|
||||
}
|
||||
|
||||
crossbeam::scope(|s| {
|
||||
let imap_handle = s.spawn(|_| loop {
|
||||
@@ -249,7 +249,10 @@ impl Context {
|
||||
|
||||
/// Stop the run loop. Blocks until all threads have shutdown.
|
||||
pub fn shutdown(&self) {
|
||||
self.is_running.store(false, Ordering::Relaxed);
|
||||
if !self.is_running.swap(false, Ordering::Relaxed) {
|
||||
// already shutdown
|
||||
return;
|
||||
}
|
||||
self.shutdown_sender.send(()).unwrap();
|
||||
|
||||
job::interrupt_inbox_idle(self);
|
||||
@@ -258,7 +261,6 @@ impl Context {
|
||||
job::interrupt_smtp_idle(self);
|
||||
}
|
||||
|
||||
// connect
|
||||
pub fn configure(&self) {
|
||||
if self.has_ongoing() {
|
||||
warn!(self, "There is already another ongoing process running.");
|
||||
|
||||
Reference in New Issue
Block a user