mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 13:56: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
|
* The object must be passed to the other context functions
|
||||||
* and must be freed using dc_context_unref() after usage.
|
* 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
|
* TODO: Document
|
||||||
*/
|
*/
|
||||||
void dc_run (dc_context_t* context);
|
void dc_context_run (dc_context_t* context, dc_callback_t cb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Document
|
* 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
|
* 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
|
/// and protected by an [RwLock]. Other than that it needs to store
|
||||||
/// the data which is passed into [dc_context_new].
|
/// the data which is passed into [dc_context_new].
|
||||||
pub struct ContextWrapper {
|
pub struct ContextWrapper {
|
||||||
cb: Option<dc_callback_t>,
|
|
||||||
userdata: *mut libc::c_void,
|
userdata: *mut libc::c_void,
|
||||||
os_name: String,
|
os_name: String,
|
||||||
inner: RwLock<Option<context::Context>>,
|
inner: RwLock<Option<context::Context>>,
|
||||||
@@ -91,7 +90,10 @@ impl ContextWrapper {
|
|||||||
///
|
///
|
||||||
/// This function makes it easy to log an error.
|
/// This function makes it easy to log an error.
|
||||||
unsafe fn error(&self, msg: &str) {
|
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.
|
/// 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]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn dc_context_new(
|
pub unsafe extern "C" fn dc_context_new(
|
||||||
cb: Option<dc_callback_t>,
|
|
||||||
userdata: *mut libc::c_void,
|
userdata: *mut libc::c_void,
|
||||||
os_name: *const libc::c_char,
|
os_name: *const libc::c_char,
|
||||||
) -> *mut dc_context_t {
|
) -> *mut dc_context_t {
|
||||||
@@ -215,7 +139,6 @@ pub unsafe extern "C" fn dc_context_new(
|
|||||||
to_string_lossy(os_name)
|
to_string_lossy(os_name)
|
||||||
};
|
};
|
||||||
let ffi_ctx = ContextWrapper {
|
let ffi_ctx = ContextWrapper {
|
||||||
cb,
|
|
||||||
userdata,
|
userdata,
|
||||||
os_name,
|
os_name,
|
||||||
inner: RwLock::new(None),
|
inner: RwLock::new(None),
|
||||||
@@ -257,17 +180,11 @@ pub unsafe extern "C" fn dc_open(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let ffi_context = &*context;
|
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 {
|
let ctx = if blobdir.is_null() || *blobdir == 0 {
|
||||||
Context::new(
|
Context::new(ffi_context.os_name.clone(), as_path(dbfile).to_path_buf())
|
||||||
Box::new(rust_cb),
|
|
||||||
ffi_context.os_name.clone(),
|
|
||||||
as_path(dbfile).to_path_buf(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Context::with_blobdir(
|
Context::with_blobdir(
|
||||||
Box::new(rust_cb),
|
|
||||||
ffi_context.os_name.clone(),
|
ffi_context.os_name.clone(),
|
||||||
as_path(dbfile).to_path_buf(),
|
as_path(dbfile).to_path_buf(),
|
||||||
as_path(blobdir).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]
|
#[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() {
|
if context.is_null() {
|
||||||
eprintln!("ignoring careless call to dc_run()");
|
eprintln!("ignoring careless call to dc_run()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ffi_context = &*context;
|
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]
|
#[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() {
|
if context.is_null() {
|
||||||
eprintln!("ignoring careless call to dc_shutdown()");
|
eprintln!("ignoring careless call to dc_shutdown()");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class Account(object):
|
|||||||
:param debug: turn on debug logging for events.
|
:param debug: turn on debug logging for events.
|
||||||
"""
|
"""
|
||||||
self._dc_context = ffi.gc(
|
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,
|
_destroy_dc_context,
|
||||||
)
|
)
|
||||||
if eventlogging:
|
if eventlogging:
|
||||||
@@ -566,7 +566,7 @@ class IOThreads:
|
|||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
def stop(self, wait=False):
|
def stop(self, wait=False):
|
||||||
lib.dc_shutdown(self._dc_context)
|
lib.dc_context_shutdown(self._dc_context)
|
||||||
|
|
||||||
if wait:
|
if wait:
|
||||||
for name, thread in self._name2thread.items():
|
for name, thread in self._name2thread.items():
|
||||||
@@ -575,7 +575,7 @@ class IOThreads:
|
|||||||
def dc_thread_run(self):
|
def dc_thread_run(self):
|
||||||
self._log_event("py-bindings-info", 0, "DC THREAD START")
|
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")
|
self._log_event("py-bindings-info", 0, "INBOX THREAD FINISHED")
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::sync::{
|
|||||||
Arc, Condvar, Mutex, RwLock,
|
Arc, Condvar, Mutex, RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crossbeam::channel::select;
|
||||||
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
||||||
|
|
||||||
use crate::chat::*;
|
use crate::chat::*;
|
||||||
@@ -188,10 +189,9 @@ impl Context {
|
|||||||
where
|
where
|
||||||
F: Fn(&Context, Event) -> () + Send + Sync,
|
F: Fn(&Context, Event) -> () + Send + Sync,
|
||||||
{
|
{
|
||||||
// TODO: ensure this can be only called once.
|
if self.is_running.swap(true, Ordering::Relaxed) {
|
||||||
|
panic!("Run can only be called once");
|
||||||
use crossbeam::channel::select;
|
}
|
||||||
self.is_running.store(true, Ordering::Relaxed);
|
|
||||||
|
|
||||||
crossbeam::scope(|s| {
|
crossbeam::scope(|s| {
|
||||||
let imap_handle = s.spawn(|_| loop {
|
let imap_handle = s.spawn(|_| loop {
|
||||||
@@ -249,7 +249,10 @@ impl Context {
|
|||||||
|
|
||||||
/// Stop the run loop. Blocks until all threads have shutdown.
|
/// Stop the run loop. Blocks until all threads have shutdown.
|
||||||
pub fn shutdown(&self) {
|
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();
|
self.shutdown_sender.send(()).unwrap();
|
||||||
|
|
||||||
job::interrupt_inbox_idle(self);
|
job::interrupt_inbox_idle(self);
|
||||||
@@ -258,7 +261,6 @@ impl Context {
|
|||||||
job::interrupt_smtp_idle(self);
|
job::interrupt_smtp_idle(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect
|
|
||||||
pub fn configure(&self) {
|
pub fn configure(&self) {
|
||||||
if self.has_ongoing() {
|
if self.has_ongoing() {
|
||||||
warn!(self, "There is already another ongoing process running.");
|
warn!(self, "There is already another ongoing process running.");
|
||||||
|
|||||||
Reference in New Issue
Block a user