update to lcg1.7 including new APIs, new structs (ACL) and testing using bindings as helper functions with wrappers to rust-ify results and api
This commit is contained in:
parent
661f1f3f4c
commit
708e6ff034
6
build.rs
6
build.rs
|
@ -15,9 +15,9 @@ fn main() {
|
|||
println!("cargo:rerun-if-changed=libCwtch.h");
|
||||
|
||||
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
|
||||
// https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.5.4
|
||||
// https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.7.0
|
||||
Command::new("wget")
|
||||
.arg("https://git.openprivacy.ca/attachments/dd3c6b41-98e4-4e7b-81af-d21893bfe389")
|
||||
.arg("https://git.openprivacy.ca/attachments/390d383b-ab02-489b-b5c9-e62267d8b3fd")
|
||||
.arg("-O")
|
||||
.arg(lib_cwtch_path)
|
||||
.output()
|
||||
|
@ -29,5 +29,5 @@ fn main() {
|
|||
io::copy(&mut file, &mut hasher).expect("failed to copy file into hasher");
|
||||
let hash_bytes = hasher.finalize();
|
||||
|
||||
assert_eq!(hash_bytes[..], hex!("776a26076dfad3370d1b2edec9ad954187584f54483ec201163be0dc356c10b0fe74168e8e95f2116f458e5676e1fb07fbd0357cab1e4389ac762fe03bd5ef67")[..]);
|
||||
assert_eq!(hash_bytes[..], hex!("271c281bad59696fc4ea5e559b5d3fe5c1949384c26dd891dde91b0af0a012e30bdbc3b16781ec5de795d2945e2f42415a8985451b49394b3c85c412ab4769d3")[..]);
|
||||
}
|
||||
|
|
14
libCwtch.h
14
libCwtch.h
|
@ -61,6 +61,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen);
|
||||
extern int c_Started();
|
||||
extern void c_ReconnectCwtchForeground();
|
||||
|
||||
// A generic method for Rebroadcasting App Events from a UI
|
||||
|
@ -86,11 +87,14 @@ extern char* c_GetMessageByID(char* profile_ptr, int profile_len, int conversati
|
|||
// the pointer returned from this function **must** be freed by calling c_Free
|
||||
extern char* c_GetMessagesByContentHash(char* profile_ptr, int profile_len, int conversation_id, char* contenthash_ptr, int contenthash_len);
|
||||
|
||||
// the pointer returned from this function **must** be Freed by c_Free
|
||||
extern char* c_GetMessages(char* profile_ptr, int profile_len, int conversation_id, int message_index, int count);
|
||||
|
||||
// Dangerous function. Should only be used as documented in `MEMORY.md`
|
||||
extern void c_FreePointer(char* ptr);
|
||||
extern void c_SendMessage(char* profile_ptr, int profile_len, int conversation_id, char* msg_ptr, int msg_len);
|
||||
extern void c_SendInvitation(char* profile_ptr, int profile_len, int conversation_id, int target_id);
|
||||
extern void c_ShareFile(char* profile_ptr, int profile_len, int conversation_id, char* filepath_ptr, int filepath_len);
|
||||
extern char* c_SendMessage(char* profile_ptr, int profile_len, int conversation_id, char* msg_ptr, int msg_len);
|
||||
extern char* c_SendInvitation(char* profile_ptr, int profile_len, int conversation_id, int target_id);
|
||||
extern char* c_ShareFile(char* profile_ptr, int profile_len, int conversation_id, char* filepath_ptr, int filepath_len);
|
||||
extern void c_DownloadFile(char* profile_ptr, int profile_len, int conversation_id, char* filepath_ptr, int filepath_len, char* manifestpath_ptr, int manifestpath_len, char* filekey_ptr, int filekey_len);
|
||||
extern void c_CheckDownloadStatus(char* profilePtr, int profileLen, char* fileKeyPtr, int fileKeyLen);
|
||||
extern void c_VerifyOrResumeDownload(char* profile_ptr, int profile_len, int conversation_id, char* filekey_ptr, int filekey_len);
|
||||
|
@ -101,9 +105,13 @@ extern void c_ArchiveConversation(char* profile_ptr, int profile_len, int conver
|
|||
extern void c_DeleteContact(char* profile_ptr, int profile_len, int conversation_id);
|
||||
extern void c_ImportBundle(char* profile_ptr, int profile_len, char* bundle_ptr, int bundle_len);
|
||||
extern void c_SetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern char* c_GetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len);
|
||||
extern void c_SetConversationAttribute(char* profile_ptr, int profile_len, int conversation_id, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern char* c_GetConversationAttribute(char* profile_ptr, int profile_len, int conversation_id, char* key_ptr, int key_len);
|
||||
extern void c_SetMessageAttribute(char* profile_ptr, int profile_len, int conversation_id, int channel_id, int message_id, char* key_ptr, int key_len, char* val_ptr, int val_len);
|
||||
extern void c_ChangePassword(char* profile_ptr, int profile_len, char* oldpassword_ptr, int oldpassword_len, char* newpassword_ptr, int newpassword_len, char* newpassword_again_ptr, int newpassword_again_len);
|
||||
extern void c_ExportProfile(char* profile_ptr, int profile_len, char* file_ptr, int file_len);
|
||||
extern char* c_ImportProfile(char* file_ptr, int file_len, char* passwordPtr, int passwordLen);
|
||||
extern void c_ShutdownCwtch();
|
||||
extern void c_LoadServers(char* passwordPtr, int passwordLen);
|
||||
extern void c_CreateServer(char* passwordPtr, int passwordLen, char* descPtr, int descLen, char autostart);
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::ffi::CString;
|
|||
|
||||
use super::CwtchLib;
|
||||
use crate::cwtchlib_go::bindings;
|
||||
use crate::{CwtchError, structs::*};
|
||||
|
||||
struct c_str_wrap {
|
||||
raw: *mut i8,
|
||||
|
@ -80,8 +81,16 @@ macro_rules! c_bind {
|
|||
|
||||
pub struct CwtchLibGo {}
|
||||
|
||||
// Some bindings are going to be wrapped so we can handle their returns and give most rust idiomatic returns (esp for json returning apis)
|
||||
// so we pre define the real binding here as a _helper function and in the impl for CwtchLib define the wrapper
|
||||
impl CwtchLibGo {
|
||||
c_bind!(_get_profile_attribute(profile: &str, key: &str;;) c_GetProfileAttribute -> String);
|
||||
c_bind!(_get_conversation_attribute(profile: &str; conversation_id: i32; key: &str) c_GetConversationAttribute -> String);
|
||||
}
|
||||
|
||||
impl CwtchLib for CwtchLibGo {
|
||||
c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> i32);
|
||||
c_bind!(started(;;) c_Started -> i32);
|
||||
c_bind!(send_app_event(event_json: &str;;) c_SendAppEvent);
|
||||
c_bind!(send_profile_event(profile: &str, event_jason: &str;;) c_SendProfileEvent);
|
||||
c_bind!(get_appbus_event(;;) c_GetAppBusEvent -> String);
|
||||
|
@ -93,9 +102,10 @@ impl CwtchLib for CwtchLibGo {
|
|||
c_bind!(get_message(profile: &str; conversation_id: i32, message_index: i32 ;) c_GetMessage -> String);
|
||||
c_bind!(get_message_by_id(profile: &str ; conversation_id: i32, message_id: i32 ;) c_GetMessageByID -> String);
|
||||
c_bind!(get_message_by_content_hash(profile: &str ; conversation_id: i32 ; hash: &str) c_GetMessagesByContentHash -> String);
|
||||
c_bind!(send_message(profile: &str; conversation_id: i32; msg: &str) c_SendMessage);
|
||||
c_bind!(send_invitation(profile: &str; conversation_id: i32, target_id: i32;) c_SendInvitation);
|
||||
c_bind!(share_file(profile: &str; conversation_id: i32; file_path: &str) c_ShareFile);
|
||||
c_bind!(get_messages(profile: &str; conversation_id: i32, message_index: i32, count: i32 ;) c_GetMessages -> String);
|
||||
c_bind!(send_message(profile: &str; conversation_id: i32; msg: &str) c_SendMessage -> String);
|
||||
c_bind!(send_invitation(profile: &str; conversation_id: i32, target_id: i32;) c_SendInvitation -> String);
|
||||
c_bind!(share_file(profile: &str; conversation_id: i32; file_path: &str) c_ShareFile -> String);
|
||||
c_bind!(download_file(profile: &str; conversation_id: i32; file_path: &str, manifest_path: &str, file_key: &str) c_DownloadFile);
|
||||
c_bind!(check_download_status(profile: &str, file_key: &str;;) c_CheckDownloadStatus);
|
||||
c_bind!(verify_or_resume_download(profile: &str; conversation_id: i32; file_key: &str) c_VerifyOrResumeDownload);
|
||||
|
@ -110,9 +120,33 @@ impl CwtchLib for CwtchLibGo {
|
|||
c_bind!(delete_contact(profile: &str; conversation_id: i32;) c_DeleteContact);
|
||||
c_bind!(import_bundle(profile: &str, bundle: &str;;) c_ImportBundle);
|
||||
c_bind!(set_profile_attribute(profile: &str, key: &str, val: &str;;) c_SetProfileAttribute);
|
||||
fn get_profile_attribute(&self, profile: &str, key: &str) -> Result<Option<String>, CwtchError> {
|
||||
let resp = self._get_profile_attribute(profile, key);
|
||||
let attr: Attribute = match serde_json::from_str(&resp) {
|
||||
Ok(attr) => attr,
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
match attr.exists {
|
||||
true => Ok(Some(attr.value)),
|
||||
false => Ok(None),
|
||||
}
|
||||
}
|
||||
c_bind!(set_conversation_attribute(profile: &str; conversation_id: i32; key: &str, val: &str) c_SetConversationAttribute);
|
||||
fn get_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str) -> Result<Option<String>, CwtchError> {
|
||||
let resp = self._get_conversation_attribute(profile, conversation_id, key);
|
||||
let attr: Attribute = match serde_json::from_str(&resp) {
|
||||
Ok(attr) => attr,
|
||||
Err(e) => return Err(e.to_string()),
|
||||
};
|
||||
match attr.exists {
|
||||
true => Ok(Some(attr.value)),
|
||||
false => Ok(None),
|
||||
}
|
||||
}
|
||||
c_bind!(set_message_attribute(profile: &str; conversation_id: i32, channel_id: i32, message_id: i32; key: &str, val: &str) c_SetMessageAttribute);
|
||||
c_bind!(change_password(profile: &str, old_pass: &str, new_pass: &str, new_pass_again: &str;;) c_ChangePassword);
|
||||
c_bind!(export_profile(profile: &str, filename: &str;;) c_ExportProfile);
|
||||
c_bind!(import_profile(filename: &str, password: &str;;) c_ImportProfile -> String);
|
||||
|
||||
fn shutdown_cwtch(&self) {
|
||||
unsafe {
|
||||
|
|
|
@ -208,6 +208,9 @@ extern "C" {
|
|||
torLen: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_Started() -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ReconnectCwtchForeground();
|
||||
}
|
||||
|
@ -285,6 +288,15 @@ extern "C" {
|
|||
contenthash_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetMessages(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
conversation_id: ::std::os::raw::c_int,
|
||||
message_index: ::std::os::raw::c_int,
|
||||
count: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char);
|
||||
}
|
||||
|
@ -295,7 +307,7 @@ extern "C" {
|
|||
conversation_id: ::std::os::raw::c_int,
|
||||
msg_ptr: *mut ::std::os::raw::c_char,
|
||||
msg_len: ::std::os::raw::c_int,
|
||||
);
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SendInvitation(
|
||||
|
@ -303,7 +315,7 @@ extern "C" {
|
|||
profile_len: ::std::os::raw::c_int,
|
||||
conversation_id: ::std::os::raw::c_int,
|
||||
target_id: ::std::os::raw::c_int,
|
||||
);
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ShareFile(
|
||||
|
@ -312,7 +324,7 @@ extern "C" {
|
|||
conversation_id: ::std::os::raw::c_int,
|
||||
filepath_ptr: *mut ::std::os::raw::c_char,
|
||||
filepath_len: ::std::os::raw::c_int,
|
||||
);
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_DownloadFile(
|
||||
|
@ -397,6 +409,14 @@ extern "C" {
|
|||
val_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetProfileAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
key_ptr: *mut ::std::os::raw::c_char,
|
||||
key_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SetConversationAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
|
@ -408,6 +428,15 @@ extern "C" {
|
|||
val_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_GetConversationAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
conversation_id: ::std::os::raw::c_int,
|
||||
key_ptr: *mut ::std::os::raw::c_char,
|
||||
key_len: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_SetMessageAttribute(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
|
@ -433,6 +462,22 @@ extern "C" {
|
|||
newpassword_again_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ExportProfile(
|
||||
profile_ptr: *mut ::std::os::raw::c_char,
|
||||
profile_len: ::std::os::raw::c_int,
|
||||
file_ptr: *mut ::std::os::raw::c_char,
|
||||
file_len: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ImportProfile(
|
||||
file_ptr: *mut ::std::os::raw::c_char,
|
||||
file_len: ::std::os::raw::c_int,
|
||||
passwordPtr: *mut ::std::os::raw::c_char,
|
||||
passwordLen: ::std::os::raw::c_int,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn c_ShutdownCwtch();
|
||||
}
|
||||
|
|
33
src/lib.rs
33
src/lib.rs
|
@ -9,11 +9,17 @@ mod cwtchlib_go;
|
|||
/// Basic structs using data from Cwtch and for deserializing JSON and serializing to JSON to communicate with Cwtch
|
||||
pub mod structs;
|
||||
|
||||
/// Error type for Cwtch lib related errors, intended for use with Result
|
||||
pub type CwtchError = String;
|
||||
|
||||
/// Interface to a Cwtch app with API matching libcwtch
|
||||
pub trait CwtchLib {
|
||||
/// Start a cwtch application using app_dir to store all user profile data and looking to tor_path to find tor to run
|
||||
fn start_cwtch(&self, app_dir: &str, tor_path: &str) -> i32;
|
||||
|
||||
/// Return 1 if cwtch has been started and 0 if not
|
||||
fn started(&self) -> i32;
|
||||
|
||||
/// Send json of a structs::CwtchEvent to the cwtch app bus
|
||||
fn send_app_event(&self, event_json: &str);
|
||||
|
||||
|
@ -52,14 +58,17 @@ pub trait CwtchLib {
|
|||
hash: &str,
|
||||
) -> String;
|
||||
|
||||
/// Send json of a structs::Message from profile to contact
|
||||
fn send_message(&self, profile: &str, conversation_id: i32, msg: &str);
|
||||
/// Bulk get messages starting at message index and of count amoung
|
||||
fn get_messages(&self, profile: &str, conversation_id: i32, message_index: i32, count: i32) -> String;
|
||||
|
||||
/// Send profile's contact an invite for/to target
|
||||
fn send_invitation(&self, profile: &str, conversation_id: i32, target_id: i32);
|
||||
/// Send json of a structs::Message from profile to contact. Returns computed sent message (including index and hash values)
|
||||
fn send_message(&self, profile: &str, conversation_id: i32, msg: &str) -> String;
|
||||
|
||||
/// share a file file_path with a conersation
|
||||
fn share_file(&self, profile: &str, conversation_id: i32, file_path: &str);
|
||||
/// Send profile's contact an invite for/to target. Returns computed sent message (including index and hash values)
|
||||
fn send_invitation(&self, profile: &str, conversation_id: i32, target_id: i32) -> String;
|
||||
|
||||
/// share a file file_path with a conersation. Returns computed sent message (including index and hash values)
|
||||
fn share_file(&self, profile: &str, conversation_id: i32, file_path: &str) -> String;
|
||||
|
||||
/// download a file from a conversation to the file_path
|
||||
fn download_file(
|
||||
|
@ -98,6 +107,9 @@ pub trait CwtchLib {
|
|||
/// Set a profile attribute key to val
|
||||
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str);
|
||||
|
||||
/// Get a profile attribute
|
||||
fn get_profile_attribute(&self, profile: &str, key: &str) -> Result<Option<String>, CwtchError>;
|
||||
|
||||
/// Set a profile's contact's attribute of key to val
|
||||
fn set_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str, val: &str);
|
||||
|
||||
|
@ -112,9 +124,18 @@ pub trait CwtchLib {
|
|||
attribute_value: &str,
|
||||
);
|
||||
|
||||
/// Get an attribute for a conversation
|
||||
fn get_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str) -> Result<Option<String>, CwtchError>;
|
||||
|
||||
/// Change a profile's password to new_pass if old_pass is correct
|
||||
fn change_password(&self, profile: &str, old_pass: &str, new_pass: &str, new_pass_again: &str);
|
||||
|
||||
/// Export a profile to filename
|
||||
fn export_profile(&self, profile: &str, filename: &str);
|
||||
|
||||
/// Import a profile from a file with supplied password. Json of a profile struct returned on success
|
||||
fn import_profile(&self, filename: &str, password: &str) -> String;
|
||||
|
||||
/// Shutdown the cwtch app and associated ACN
|
||||
fn shutdown_cwtch(&self);
|
||||
|
||||
|
|
|
@ -57,6 +57,17 @@ pub enum ContactAuthorization {
|
|||
Blocked,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
#[allow(non_snake_case)]
|
||||
/// Struct to deserialize the results of Get*Attribute requests into
|
||||
pub struct Attribute {
|
||||
/// Was the attribute value found in storage
|
||||
pub exists: bool,
|
||||
/// The value of the requested attribute
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -70,6 +81,22 @@ pub struct CwtchEvent {
|
|||
pub data: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
#[allow(non_snake_case)]
|
||||
/// AccessControl is a type determining client assigned authorization to a peer
|
||||
pub struct AccessControl {
|
||||
/// Any attempts from this handle to connect are blocked
|
||||
pub blocked: bool,
|
||||
/// Allows a handle to access the conversation
|
||||
pub read: bool,
|
||||
/// Allows a handle to append new messages to the conversation
|
||||
pub append: bool,
|
||||
}
|
||||
|
||||
/// represents an access control list for a conversation. Mapping handles to conversation functions
|
||||
pub type ACL = HashMap<String, AccessControl>;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -88,6 +115,8 @@ pub struct Conversation {
|
|||
pub status: ConnectionState,
|
||||
/// has the conversation been manually accpted
|
||||
pub accepted: bool,
|
||||
///represents an access control list for a conversation. Mapping handles to conversation functions
|
||||
pub access_control_list: ACL,
|
||||
/// has the conversation been manually blocked
|
||||
pub blocked: bool,
|
||||
/// is this conversation a group? if so "onion" will be a group ID
|
||||
|
@ -105,11 +134,13 @@ pub struct Server {
|
|||
pub status: ConnectionState,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[serde_as]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
/// Struct to serialize/deserialize profiles coming from libcwtch-go
|
||||
pub struct Profile {
|
||||
/// onion address / ID of the profile
|
||||
pub onion: String,
|
||||
#[serde(alias = "onion")]
|
||||
pub handle: String,
|
||||
/// nick name of the onion as supplied by libcwtch-go based on "name" attribute
|
||||
pub nick: String,
|
||||
/// path to a profile image, controled by "picture" attribute
|
||||
|
@ -249,7 +280,7 @@ impl Profile {
|
|||
Err(e) => return Err(e),
|
||||
};
|
||||
Ok(Profile {
|
||||
onion: identity.to_string(),
|
||||
handle: identity.to_string(),
|
||||
nick: name.to_string(),
|
||||
image_path: picture.to_string(),
|
||||
attr: Default::default(),
|
||||
|
|
Loading…
Reference in New Issue