#![allow(unsafe_code)]
pub mod access_container;
pub mod cipher_opt;
pub mod crypto;
pub mod immutable_data;
pub mod ipc;
pub mod logging;
pub mod mdata_info;
pub mod mutable_data;
pub mod nfs;
pub mod object_cache;
#[cfg(any(test, feature = "testing"))]
pub mod test_utils;
mod helper;
#[cfg(test)]
mod tests;
use super::errors::AppError;
use super::App;
use config_file_handler;
use ffi_utils::{catch_unwind_cb, from_c_str, FfiResult, OpaqueCtx, ReprC, FFI_RESULT_OK};
use futures::Future;
use maidsafe_utilities::serialisation::deserialise;
use safe_core::ffi::ipc::resp::AuthGranted;
use safe_core::ffi::AccountInfo;
use safe_core::ipc::{AuthGranted as NativeAuthGranted, BootstrapConfig};
use safe_core::{self, Client, FutureExt};
use std::ffi::{CStr, CString, OsStr};
use std::os::raw::{c_char, c_void};
use std::slice;
#[no_mangle]
pub unsafe extern "C" fn app_unregistered(
bootstrap_config: *const u8,
bootstrap_config_len: usize,
user_data: *mut c_void,
o_disconnect_notifier_cb: extern "C" fn(user_data: *mut c_void),
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult, app: *mut App),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let user_data = OpaqueCtx(user_data);
let config = if bootstrap_config_len == 0 || bootstrap_config.is_null() {
None
} else {
let config_serialised = slice::from_raw_parts(bootstrap_config, bootstrap_config_len);
Some(deserialise::<BootstrapConfig>(config_serialised)?)
};
let app = App::unregistered(move || o_disconnect_notifier_cb(user_data.0), config)?;
o_cb(user_data.0, FFI_RESULT_OK, Box::into_raw(Box::new(app)));
Ok(())
})
}
#[no_mangle]
pub unsafe extern "C" fn app_registered(
app_id: *const c_char,
auth_granted: *const AuthGranted,
user_data: *mut c_void,
o_disconnect_notifier_cb: extern "C" fn(user_data: *mut c_void),
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult, app: *mut App),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let user_data = OpaqueCtx(user_data);
let app_id = from_c_str(app_id)?;
let auth_granted = NativeAuthGranted::clone_from_repr_c(auth_granted)?;
let app = App::registered(app_id, auth_granted, move || {
o_disconnect_notifier_cb(user_data.0)
})?;
o_cb(user_data.0, FFI_RESULT_OK, Box::into_raw(Box::new(app)));
Ok(())
})
}
#[no_mangle]
pub unsafe extern "C" fn app_reconnect(
app: *mut App,
user_data: *mut c_void,
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let user_data = OpaqueCtx(user_data);
(*app).send(move |client, _| {
try_cb!(
client.restart_routing().map_err(AppError::from),
user_data.0,
o_cb
);
o_cb(user_data.0, FFI_RESULT_OK);
None
})
})
}
#[no_mangle]
pub unsafe extern "C" fn app_account_info(
app: *mut App,
user_data: *mut c_void,
o_cb: extern "C" fn(
user_data: *mut c_void,
result: *const FfiResult,
account_info: *const AccountInfo,
),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let user_data = OpaqueCtx(user_data);
(*app).send(move |client, _| {
client
.get_account_info()
.map(move |acc_info| {
let ffi_acc = AccountInfo {
mutations_done: acc_info.mutations_done,
mutations_available: acc_info.mutations_available,
};
o_cb(user_data.0, FFI_RESULT_OK, &ffi_acc);
})
.map_err(move |e| {
call_result_cb!(Err::<(), _>(AppError::from(e)), user_data, o_cb);
})
.into_box()
.into()
})
})
}
#[no_mangle]
pub unsafe extern "C" fn app_exe_file_stem(
user_data: *mut c_void,
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult, filename: *const c_char),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
if let Ok(path) = config_file_handler::exe_file_stem()?.into_string() {
let path_c_str = CString::new(path)?;
o_cb(user_data, FFI_RESULT_OK, path_c_str.as_ptr());
} else {
call_result_cb!(
Err::<(), _>(AppError::from(
"config_file_handler returned invalid string",
)),
user_data,
o_cb
);
}
Ok(())
});
}
#[no_mangle]
pub unsafe extern "C" fn app_set_additional_search_path(
new_path: *const c_char,
user_data: *mut c_void,
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let new_path = CStr::from_ptr(new_path).to_str()?;
config_file_handler::set_additional_search_path(OsStr::new(new_path));
o_cb(user_data, FFI_RESULT_OK);
Ok(())
});
}
#[no_mangle]
pub unsafe extern "C" fn app_free(app: *mut App) {
let _ = Box::from_raw(app);
}
#[no_mangle]
pub unsafe extern "C" fn app_reset_object_cache(
app: *mut App,
user_data: *mut c_void,
o_cb: extern "C" fn(user_data: *mut c_void, result: *const FfiResult),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let user_data = OpaqueCtx(user_data);
(*app).send(move |_, context| {
context.object_cache().reset();
o_cb(user_data.0, FFI_RESULT_OK);
None
})
})
}
#[no_mangle]
pub unsafe extern "C" fn app_container_name(
app_id: *const c_char,
user_data: *mut c_void,
o_cb: extern "C" fn(
user_data: *mut c_void,
result: *const FfiResult,
container_name: *const c_char,
),
) {
catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
let name = CString::new(safe_core::app_container_name(
CStr::from_ptr(app_id).to_str()?,
))?;
o_cb(user_data, FFI_RESULT_OK, name.as_ptr());
Ok(())
})
}