mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 01:46:30 +03:00
add json api to cffi and expose it in dc node
This commit is contained in:
@@ -16,6 +16,7 @@ crate-type = ["cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
deltachat = { path = "../", default-features = false }
|
||||
deltachat-jsonrpc = { path = "../deltachat-jsonrpc" }
|
||||
libc = "0.2"
|
||||
human-panic = "1"
|
||||
num-traits = "0.2"
|
||||
|
||||
@@ -23,7 +23,7 @@ typedef struct _dc_provider dc_provider_t;
|
||||
typedef struct _dc_event dc_event_t;
|
||||
typedef struct _dc_event_emitter dc_event_emitter_t;
|
||||
typedef struct _dc_accounts_event_emitter dc_accounts_event_emitter_t;
|
||||
|
||||
typedef struct _dc_json_api_instance dc_json_api_instance_t;
|
||||
|
||||
/**
|
||||
* @mainpage Getting started
|
||||
@@ -5178,6 +5178,55 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class dc_json_api_instance_t
|
||||
*
|
||||
* Opaque object for using the json rpc api from the cffi bindings.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create the jsonrpc instance that is used to call the jsonrpc.
|
||||
*
|
||||
* @memberof dc_accounts_t
|
||||
* @param account_manager The accounts object as created by dc_accounts_new().
|
||||
* @return Returns the jsonrpc instance, NULL on errors.
|
||||
* Must be freed using dc_json_api_unref() after usage.
|
||||
*
|
||||
*/
|
||||
dc_json_api_instance_t* dc_get_json_api(dc_accounts_t* account_manager);
|
||||
|
||||
/**
|
||||
* Free a jsonrpc instance.
|
||||
*
|
||||
* @memberof dc_json_api_instance_t
|
||||
* @param json_api_instance jsonrpc instance as returned from dc_get_json_api().
|
||||
* If NULL is given, nothing is done and an error is logged.
|
||||
*/
|
||||
void dc_json_api_unref(dc_json_api_instance_t* json_api_instance);
|
||||
|
||||
/**
|
||||
* Makes an asynchronous jsonrpc request,
|
||||
* returns immediately and once the result is ready it can be retrieved via dc_get_next_json_response()
|
||||
* the jsonrpc specification defines an invocation id that can then be used to match request and response.
|
||||
*
|
||||
* @memberof dc_json_api_instance_t
|
||||
* @param json_api_instance jsonrpc instance as returned from dc_get_json_api().
|
||||
* @param request JSON-RPC request as string
|
||||
*/
|
||||
void dc_json_request(dc_json_api_instance_t* json_api_instance, char* request);
|
||||
|
||||
/**
|
||||
* Get the next json_rpc response, blocks until there is a new event, so call this in a loop from a thread.
|
||||
*
|
||||
* @memberof dc_json_api_instance_t
|
||||
* @param json_api_instance jsonrpc instance as returned from dc_get_json_api().
|
||||
* @return JSON-RPC response as string
|
||||
* If NULL is returned, the accounts_t belonging to the jsonrpc instance is unref'd and no more events will come;
|
||||
* in this case, free the jsonrpc instance using dc_json_api_unref().
|
||||
*/
|
||||
char* dc_get_next_json_response(dc_json_api_instance_t* json_api_instance);
|
||||
|
||||
/**
|
||||
* @class dc_event_emitter_t
|
||||
*
|
||||
|
||||
@@ -18,6 +18,7 @@ use std::fmt::Write;
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use anyhow::Context as _;
|
||||
@@ -4093,11 +4094,11 @@ pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) {
|
||||
/// Reader-writer lock wrapper for accounts manager to guarantee thread safety when using
|
||||
/// `dc_accounts_t` in multiple threads at once.
|
||||
pub struct AccountsWrapper {
|
||||
inner: RwLock<Accounts>,
|
||||
inner: Arc<RwLock<Accounts>>,
|
||||
}
|
||||
|
||||
impl Deref for AccountsWrapper {
|
||||
type Target = RwLock<Accounts>;
|
||||
type Target = Arc<RwLock<Accounts>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
@@ -4106,7 +4107,7 @@ impl Deref for AccountsWrapper {
|
||||
|
||||
impl AccountsWrapper {
|
||||
fn new(accounts: Accounts) -> Self {
|
||||
let inner = RwLock::new(accounts);
|
||||
let inner = Arc::new(RwLock::new(accounts));
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
@@ -4424,3 +4425,73 @@ pub unsafe extern "C" fn dc_accounts_get_next_event(
|
||||
.map(|ev| Box::into_raw(Box::new(ev)))
|
||||
.unwrap_or_else(ptr::null_mut)
|
||||
}
|
||||
|
||||
use deltachat_jsonrpc::api::CommandApi;
|
||||
use deltachat_jsonrpc::yerpc::{MessageHandle, RpcHandle};
|
||||
|
||||
pub struct dc_json_api_instance_t {
|
||||
receiver: async_std::channel::Receiver<deltachat_jsonrpc::yerpc::Message>,
|
||||
handle: MessageHandle<CommandApi>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_get_json_api(
|
||||
account_manager: *mut dc_accounts_t,
|
||||
) -> *mut dc_json_api_instance_t {
|
||||
if account_manager.is_null() {
|
||||
eprintln!("ignoring careless call to dc_get_json_api()");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let cmd_api =
|
||||
deltachat_jsonrpc::api::CommandApi::new_from_cffi((*account_manager).inner.clone());
|
||||
|
||||
let (request_handle, receiver) = RpcHandle::new();
|
||||
let handle = MessageHandle::new(request_handle, cmd_api);
|
||||
|
||||
let instance = dc_json_api_instance_t { receiver, handle };
|
||||
|
||||
Box::into_raw(Box::new(instance))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_json_api_unref(json_api_instance: *mut dc_json_api_instance_t) {
|
||||
if json_api_instance.is_null() {
|
||||
eprintln!("ignoring careless call to dc_json_api_unref()");
|
||||
return;
|
||||
}
|
||||
|
||||
Box::from_raw(json_api_instance);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_json_request(
|
||||
json_api_instance: *mut dc_json_api_instance_t,
|
||||
request: *const libc::c_char,
|
||||
) {
|
||||
if json_api_instance.is_null() || request.is_null() {
|
||||
eprintln!("ignoring careless call to dc_json_request()");
|
||||
return;
|
||||
}
|
||||
|
||||
let api = &*json_api_instance;
|
||||
let handle = &api.handle;
|
||||
let request = to_string_lossy(request);
|
||||
async_std::task::spawn(async move {
|
||||
handle.handle_message(&request).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_get_next_json_response(
|
||||
json_api_instance: *mut dc_json_api_instance_t,
|
||||
) -> *mut libc::c_char {
|
||||
if json_api_instance.is_null() {
|
||||
eprintln!("ignoring careless call to dc_get_next_json_response()");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let api = &*json_api_instance;
|
||||
async_std::task::block_on(api.receiver.recv())
|
||||
.map(|result| serde_json::to_string(&result).unwrap_or_default().strdup())
|
||||
.unwrap_or(ptr::null_mut())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user