Merge pull request 'migrate to libcwtch-go 1.5' (#9) from lcg1.5 into main

Reviewed-on: #9
This commit is contained in:
Sarah Jamie Lewis 2022-01-17 23:57:13 +00:00 committed by Dan Ballard
commit 5bed265440
12 changed files with 368 additions and 327 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target
.idea
example_cwtch_dir
Cargo.lock

179
Cargo.lock generated
View File

@ -1,179 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "darling"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "libc"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "libcwtch"
version = "0.1.0"
dependencies = [
"libc",
"serde",
"serde_json",
"serde_with",
]
[[package]]
name = "proc-macro2"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_with"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "062b87e45d8f26714eacfaef0ed9a583e2bfd50ebd96bdd3c200733bd5758e2c"
dependencies = [
"rustversion",
"serde",
"serde_with_macros",
]
[[package]]
name = "serde_with_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98c1fcca18d55d1763e1c16873c4bde0ac3ef75179a28c7b372917e0494625be"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"

View File

@ -1,13 +1,17 @@
[package]
name = "libcwtch"
version = "0.1.0"
version = "0.2.0"
authors = ["Dan Ballard <dan@mindstab.net>"]
edition = "2018"
license = "MIT"
description = "libcwtch is an interface to a Cwtch app that allows creating of profiles to communicate with contacts over the Cwtch protocol"
repository = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs"
readme = "README.md"
documentation = "https://docs.rs/libcwtch/0.1.0/libcwtch/"
documentation = "https://docs.rs/libcwtch/0.2.0/libcwtch/"
[build-dependencies]
hex-literal = "0.3.4"
sha2 = "0.10.1"
[dependencies]
libc = "0.2"

View File

@ -8,7 +8,7 @@ Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes
### Updating libCwtch and bingings.rs with Bindgen
```
```sh
cargo install bindgen
```
@ -16,7 +16,7 @@ libCwtch.so version is specified in build.rs. If updating, also download the cor
the 'preamble from import "C"' section as it imports headers required for the C lib to compile
but that we don't want to create rust bindings for (like importing stdlib.h). Then:
```
```sh
bindgen libCwtch.h -o src/cwtchlib_go/bindings.rs
```

View File

@ -1,6 +1,10 @@
use std::process::Command;
use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;
use std::{env, io};
use hex_literal::hex;
use sha2::{Digest, Sha512};
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
@ -11,6 +15,19 @@ 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.2.0
Command::new("wget").arg("https://git.openprivacy.ca/attachments/e77c69f0-9487-4808-bc23-092d943bc4a6").arg("-O").arg(lib_cwtch_path).output().expect("failed to download libCwtch.so");
}
// https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.5.4
Command::new("wget")
.arg("https://git.openprivacy.ca/attachments/dd3c6b41-98e4-4e7b-81af-d21893bfe389")
.arg("-O")
.arg(lib_cwtch_path)
.output()
.expect("failed to download libCwtch.so");
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
let mut hasher = Sha512::new();
let mut file = fs::File::open(&lib_cwtch_path).expect("could not open lib to hash");
io::copy(&mut file, &mut hasher).expect("failed to copy file into hasher");
let hash_bytes = hasher.finalize();
assert_eq!(hash_bytes[..], hex!("776a26076dfad3370d1b2edec9ad954187584f54483ec201163be0dc356c10b0fe74168e8e95f2116f458e5676e1fb07fbd0357cab1e4389ac762fe03bd5ef67")[..]);
}

View File

@ -6,7 +6,10 @@ use libcwtch::CwtchLib;
fn main() {
let bot_home = "example_cwtch_dir";
std::fs::remove_dir_all(&bot_home).expect("Error removing previous bot_home directory");
match std::fs::remove_dir_all(&bot_home) {
// this will always error on first run as we haven't created the directory, it's just a function to clear it on successive runs, so this error is to be ignored
_ => (),
}
std::fs::create_dir_all(&bot_home).expect("Error creating bot_home directory");
let cwtch = libcwtch::new_cwtchlib_go();
@ -34,25 +37,28 @@ fn main() {
);
// process json for profile, contacts and servers...else {
let profile = Profile::new(
let profile = match Profile::new(
&event.data["Identity"],
&event.data["name"],
&event.data["picture"],
&event.data["ContactsJson"],
&event.data["ServerList"],
);
) {
Ok(p) => p,
Err(e) => panic!("error parsing profile: {}", e),
};
print!("profile: {:?}", profile);
}
"NewMessageFromPeer" => {
let to = &event.data["ProfileOnion"];
let conversation = &event.data["RemotePeer"];
let conversation_id = event.data["ConversationID"].parse::<i32>().unwrap();
let message: Message =
serde_json::from_str(&event.data["Data"]).expect("Error parsing message");
let response = Message { o: 1, d: message.d };
let response_json =
serde_json::to_string(&response).expect("Error parsing json response");
cwtch.send_message(&to, &conversation, &response_json);
cwtch.send_message(&to, conversation_id, &response_json);
}
_ => eprintln!("unhandled event!"),
};

View File

@ -73,31 +73,47 @@ extern void c_SendProfileEvent(char* onion_ptr, int onion_len, char* json_ptr, i
extern char* c_GetAppBusEvent();
extern void c_CreateProfile(char* nick_ptr, int nick_len, char* pass_ptr, int pass_len);
extern void c_LoadProfiles(char* passwordPtr, int passwordLen);
extern void c_AcceptContact(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
extern void c_RejectInvite(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
extern void c_BlockContact(char* profilePtr, int profileLen, char* handlePtr, int handleLen);
extern void c_UpdateMessageFlags(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, int mIdx, long unsigned int message_flags);
extern void c_AcceptConversation(char* profilePtr, int profileLen, int conversation_id);
extern void c_BlockContact(char* profilePtr, int profileLen, int conversation_id);
extern void c_UnblockContact(char* profilePtr, int profileLen, int conversation_id);
// the pointer returned from this function **must** be Freed by c_Free
extern char* c_GetMessage(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, int message_index);
extern char* c_GetMessage(char* profile_ptr, int profile_len, int conversation_id, int message_index);
// the pointer returned from this function **must** be Freed by c_Free
extern char* c_GetMessageByID(char* profile_ptr, int profile_len, int conversation_id, int message_index);
// the pointer returned from this function **must** be freed by calling c_Free
extern char* c_GetMessagesByContentHash(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, char* contenthash_ptr, int contenthash_len);
extern char* c_GetMessagesByContentHash(char* profile_ptr, int profile_len, int conversation_id, char* contenthash_ptr, int contenthash_len);
// 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, char* handle_ptr, int handle_len, char* msg_ptr, int msg_len);
extern void c_SendInvitation(char* profile_ptr, int profile_len, char* handle_ptr, int handle_len, char* target_ptr, int target_len);
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 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);
extern void c_ResetTor();
extern void c_CreateGroup(char* profile_ptr, int profile_len, char* server_ptr, int server_len, char* name_ptr, int name_len);
extern void c_DeleteProfile(char* profile_ptr, int profile_len, char* password_ptr, int password_len);
extern void c_ArchiveConversation(char* profile_ptr, int profile_len, char* contact_ptr, int contact_len);
extern void c_DeleteContact(char* profile_ptr, int profile_len, char* hanlde_ptr, int handle_len);
extern void c_ArchiveConversation(char* profile_ptr, int profile_len, int conversation_id);
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 void c_SetContactAttribute(char* profile_ptr, int profile_len, char* contact_ptr, int contact_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
extern void c_SetGroupAttribute(char* profile_ptr, int profile_len, char* group_ptr, int group_len, char* key_ptr, int key_len, char* val_ptr, int val_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 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_ShutdownCwtch();
extern void c_LoadServers(char* passwordPtr, int passwordLen);
extern void c_CreateServer(char* passwordPtr, int passwordLen, char* descPtr, int descLen, char autostart);
extern void c_DeleteServer(char* onionPtr, int onionLen, char* currentPasswordPtr, int currentPasswordLen);
extern void c_LaunchServers();
extern void c_LaunchServer(char* onionPtr, int onionLen);
extern void c_StopServer(char* onionPtr, int onionLen);
extern void c_StopServers();
extern void c_DestroyServers();
extern void c_SetServerAttribute(char* onionPtr, int onionLen, char* keyPtr, int keyLen, char* valPtr, int valLen);
#ifdef __cplusplus
}

View File

@ -30,29 +30,31 @@ impl c_str_wrap {
impl Drop for c_str_wrap {
fn drop(&mut self) {
unsafe {
CString::from_raw(self.raw);
drop(CString::from_raw(self.raw));
}
}
}
// c_bind handles setting up c string arguments and freeing them
// c_bind!( $fn_name ( [ $string_args ]* ; [ $non_string_args : $type ]* ) $c_function -> $return_type? )
// c_bind!( $fn_name ( [ $string_args: &str],* [ $non_string_args : $type ],* ) $c_function -> $return_type? )
macro_rules! c_bind {
// macro for returnless fns
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),*) $bind_fn:ident) => {
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) {
$(let $str = c_str_wrap::new($str);)*
// No return
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident) => {
fn $func_name(&self, $($str1: &str, )* $($args: $t, )* $($str2: &str, )*) {
$(let $str1 = c_str_wrap::new($str1);)*
$(let $str2 = c_str_wrap::new($str2);)*
unsafe {
bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
}
}
};
// macro for str returning fns
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),* ) $bind_fn:ident -> String) => {
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) -> String {
$(let $str = c_str_wrap::new($str);)*
// String return
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident -> String) => {
fn $func_name(&self, $($str1: &str, )* $($args: $t, )* $($str2: &str, )*) -> String {
$(let $str1 = c_str_wrap::new($str1);)*
$(let $str2 = c_str_wrap::new($str2);)*
unsafe {
let result_ptr = bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
let result_ptr = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
let result = match CStr::from_ptr(result_ptr).to_str() {
Ok(s) => s.to_owned(),
Err(_) => "".to_string()
@ -63,12 +65,13 @@ macro_rules! c_bind {
}
}
};
// macro for value returning fns
($func_name:ident ($($str:ident),* ; $($arg:ident: $t:ty),* ) $bind_fn:ident -> $bind_fn_ty:ty) => {
fn $func_name(&self, $($str: &str, )* $($arg: $t, )*) -> $bind_fn_ty {
$(let $str = c_str_wrap::new($str);)*
// Non String return
($func_name:ident ($($str1:ident: &str),* ; $($args:ident: $t:ty),* ; $($str2:ident: &str),*) $bind_fn:ident -> $bind_fn_ty:ty) => {
fn $func_name(&self, $($str1: &str, )* $($args: t, )* $($str2: &str, )*) -> $bind_fn_ty {
$(let $str1 = c_str_wrap::new($str1);)*
$(let $str2 = c_str_wrap::new($str2);)*
unsafe {
let result = bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
let result = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
result
}
}
@ -77,41 +80,53 @@ macro_rules! c_bind {
pub struct CwtchLibGo {}
impl CwtchLibGo {
c_bind!(send_profile_event(profile, event_json;) c_SendProfileEvent);
}
impl CwtchLib for CwtchLibGo {
c_bind!(start_cwtch(app_dir, tor_path;) c_StartCwtch -> i32);
c_bind!(send_app_event(event_json;) c_SendAppEvent);
c_bind!(get_appbus_event(;) c_GetAppBusEvent -> String);
c_bind!(create_profile(nick, pass;) c_CreateProfile);
c_bind!(load_profiles(pass;) c_LoadProfiles);
c_bind!(accept_contact(profile, contact;) c_AcceptContact);
c_bind!(reject_invite(profile, contact;) c_RejectInvite);
c_bind!(block_contact(profile, contact;) c_BlockContact);
c_bind!(update_message_flags(profile, contact; message_id: i32, message_flags: u64) c_UpdateMessageFlags);
c_bind!(get_message(profile, contact; message_index: i32) c_GetMessage -> String);
c_bind!(get_message_by_content_hash(profile, contact, hash;) c_GetMessagesByContentHash -> String);
c_bind!(send_message(profile, contact, msg;) c_SendMessage);
c_bind!(send_invitation(profile, contact, target;) c_SendInvitation);
c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> 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);
c_bind!(create_profile(nick: &str, pass: &str;;) c_CreateProfile);
c_bind!(load_profiles(pass: &str;;) c_LoadProfiles);
c_bind!(accept_conversation(profile: &str ; conversation_id: i32 ;) c_AcceptConversation);
c_bind!(block_contact(profile: &str ; conversation_id: i32; ) c_BlockContact);
c_bind!(unblock_contact(profile: &str ; conversation_id: i32; ) c_UnblockContact);
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!(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);
fn reset_tor(&self) {
unsafe {
bindings::c_ResetTor();
}
}
c_bind!(create_group(profile, server, name;) c_CreateGroup);
c_bind!(delete_profile(profile, pass;) c_DeleteProfile);
c_bind!(archive_conversation(profile, contact;) c_ArchiveConversation);
c_bind!(delete_contact(profile, group;) c_DeleteContact);
c_bind!(import_bundle(profile, bundle;) c_ImportBundle);
c_bind!(set_profile_attribute(profile, key, val;) c_SetProfileAttribute);
c_bind!(set_contact_attribute(profile, contact, key, val;) c_SetContactAttribute);
c_bind!(set_group_attribute(profile, group, key, val;) c_SetGroupAttribute);
c_bind!(create_group(profile: &str, server: &str, name: &str;;) c_CreateGroup);
c_bind!(delete_profile(profile: &str, pass: &str;;) c_DeleteProfile);
c_bind!(archive_conversation(profile: &str; conversation_id: i32;) c_ArchiveConversation);
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);
c_bind!(set_conversation_attribute(profile: &str; conversation_id: i32; key: &str, val: &str) c_SetConversationAttribute);
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);
fn shutdown_cwtch(&self) {
unsafe {
bindings::c_ShutdownCwtch();
}
}
c_bind!(load_servers(password: &str;;) c_LoadServers);
c_bind!(create_server(password: &str, description: &str; autostart: i8;) c_CreateServer);
c_bind!(delete_server(onion: &str, current_password: &str;;) c_DeleteServer);
c_bind!(launch_servers(;;) c_LaunchServers);
c_bind!(launch_server(onion: &str;;) c_LaunchServer);
c_bind!(stop_server(onion: &str;;) c_StopServer);
c_bind!(stop_servers(;;) c_StopServers);
c_bind!(destroy_servers(;;) c_DestroyServers);
c_bind!(set_server_attribute(onion: &str, key: &str, val: &str;;) c_SetServerAttribute);
}

View File

@ -1,4 +1,4 @@
/* automatically generated by rust-bindgen 0.58.1 */
/* automatically generated by rust-bindgen 0.59.2 */
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)]
@ -240,45 +240,39 @@ extern "C" {
);
}
extern "C" {
pub fn c_AcceptContact(
pub fn c_AcceptConversation(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
handlePtr: *mut ::std::os::raw::c_char,
handleLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_RejectInvite(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
handlePtr: *mut ::std::os::raw::c_char,
handleLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_BlockContact(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
handlePtr: *mut ::std::os::raw::c_char,
handleLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_UpdateMessageFlags(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
mIdx: ::std::os::raw::c_int,
message_flags: ::std::os::raw::c_ulong,
pub fn c_UnblockContact(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_GetMessage(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
message_index: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_GetMessageByID(
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,
) -> *mut ::std::os::raw::c_char;
}
@ -286,8 +280,7 @@ extern "C" {
pub fn c_GetMessagesByContentHash(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
contenthash_ptr: *mut ::std::os::raw::c_char,
contenthash_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
@ -299,8 +292,7 @@ extern "C" {
pub fn c_SendMessage(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
msg_ptr: *mut ::std::os::raw::c_char,
msg_len: ::std::os::raw::c_int,
);
@ -309,10 +301,47 @@ extern "C" {
pub fn c_SendInvitation(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
target_ptr: *mut ::std::os::raw::c_char,
target_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
target_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ShareFile(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filepath_ptr: *mut ::std::os::raw::c_char,
filepath_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DownloadFile(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filepath_ptr: *mut ::std::os::raw::c_char,
filepath_len: ::std::os::raw::c_int,
manifestpath_ptr: *mut ::std::os::raw::c_char,
manifestpath_len: ::std::os::raw::c_int,
filekey_ptr: *mut ::std::os::raw::c_char,
filekey_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_CheckDownloadStatus(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
fileKeyPtr: *mut ::std::os::raw::c_char,
fileKeyLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_VerifyOrResumeDownload(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filekey_ptr: *mut ::std::os::raw::c_char,
filekey_len: ::std::os::raw::c_int,
);
}
extern "C" {
@ -340,16 +369,14 @@ extern "C" {
pub fn c_ArchiveConversation(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
contact_ptr: *mut ::std::os::raw::c_char,
contact_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DeleteContact(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
hanlde_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
@ -371,11 +398,10 @@ extern "C" {
);
}
extern "C" {
pub fn c_SetContactAttribute(
pub fn c_SetConversationAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
contact_ptr: *mut ::std::os::raw::c_char,
contact_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,
val_ptr: *mut ::std::os::raw::c_char,
@ -383,17 +409,78 @@ extern "C" {
);
}
extern "C" {
pub fn c_SetGroupAttribute(
pub fn c_SetMessageAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
group_ptr: *mut ::std::os::raw::c_char,
group_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
channel_id: ::std::os::raw::c_int,
message_id: ::std::os::raw::c_int,
key_ptr: *mut ::std::os::raw::c_char,
key_len: ::std::os::raw::c_int,
val_ptr: *mut ::std::os::raw::c_char,
val_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ChangePassword(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
oldpassword_ptr: *mut ::std::os::raw::c_char,
oldpassword_len: ::std::os::raw::c_int,
newpassword_ptr: *mut ::std::os::raw::c_char,
newpassword_len: ::std::os::raw::c_int,
newpassword_again_ptr: *mut ::std::os::raw::c_char,
newpassword_again_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ShutdownCwtch();
}
extern "C" {
pub fn c_LoadServers(
passwordPtr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_CreateServer(
passwordPtr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int,
descPtr: *mut ::std::os::raw::c_char,
descLen: ::std::os::raw::c_int,
autostart: ::std::os::raw::c_char,
);
}
extern "C" {
pub fn c_DeleteServer(
onionPtr: *mut ::std::os::raw::c_char,
onionLen: ::std::os::raw::c_int,
currentPasswordPtr: *mut ::std::os::raw::c_char,
currentPasswordLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_LaunchServers();
}
extern "C" {
pub fn c_LaunchServer(onionPtr: *mut ::std::os::raw::c_char, onionLen: ::std::os::raw::c_int);
}
extern "C" {
pub fn c_StopServer(onionPtr: *mut ::std::os::raw::c_char, onionLen: ::std::os::raw::c_int);
}
extern "C" {
pub fn c_StopServers();
}
extern "C" {
pub fn c_DestroyServers();
}
extern "C" {
pub fn c_SetServerAttribute(
onionPtr: *mut ::std::os::raw::c_char,
onionLen: ::std::os::raw::c_int,
keyPtr: *mut ::std::os::raw::c_char,
keyLen: ::std::os::raw::c_int,
valPtr: *mut ::std::os::raw::c_char,
valLen: ::std::os::raw::c_int,
);
}

View File

@ -2,5 +2,6 @@
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(deref_nullptr)]
pub mod bindings;
pub mod bindings;

View File

@ -17,6 +17,9 @@ pub trait CwtchLib {
/// Send json of a structs::CwtchEvent to the cwtch app bus
fn send_app_event(&self, event_json: &str);
/// Send json of a structs::CwtchEvent to a cwtch profile
fn send_profile_event(&self, profile: &str, event_json: &str);
/// Pull json of a structs::CwtchEvent off the appbus for responding to
fn get_appbus_event(&self) -> String;
@ -26,35 +29,53 @@ pub trait CwtchLib {
/// Load any profiles encrypted by pass
fn load_profiles(&self, pass: &str);
/// Cause profile to accept contact
fn accept_contact(&self, profile: &str, contact: &str);
/// Cause profile to accept conversation
fn accept_conversation(&self, profile: &str, conversation_id: i32);
/// Cause profile to reject contact
fn reject_invite(&self, profile: &str, contact: &str);
/// Cause profile to block conversation
fn block_contact(&self, profile: &str, conversation_id: i32);
/// Cause profile to block contact
fn block_contact(&self, profile: &str, contact: &str);
/// Cause profile to unblock contact
fn unblock_contact(&self, profile: &str, conversation_id: i32);
/// Cause profile to update contact's message to have it's flags updated
fn update_message_flags(
/// Get a specific message for conversation of profile by index
fn get_message(&self, profile: &str, conversation_id: i32, message_index: i32) -> String;
/// Get a specific message for a conversation by its id
fn get_message_by_id(&self, profile: &str, conversation_id: i32, message_id: i32) -> String;
/// Get a specific message for conversation of profile by hash
fn get_message_by_content_hash(
&self,
profile: &str,
contact: &str,
message_id: i32,
message_flags: u64,
);
/// Get a specific message for contact of profile by index
fn get_message(&self, profile: &str, contact: &str, message_index: i32) -> String;
/// Get a specific message for contact of profile by hash
fn get_message_by_content_hash(&self, profile: &str, contact: &str, hash: &str) -> String;
conversation_id: i32,
hash: &str,
) -> String;
/// Send json of a structs::Message from profile to contact
fn send_message(&self, profile: &str, contact: &str, msg: &str);
fn send_message(&self, profile: &str, conversation_id: i32, msg: &str);
/// Send profile's contact an invite for/to target
fn send_invitation(&self, profile: &str, contact: &str, target: &str);
fn send_invitation(&self, profile: &str, conversation_id: i32, target_id: i32);
/// share a file file_path with a conersation
fn share_file(&self, profile: &str, conversation_id: i32, file_path: &str);
/// download a file from a conversation to the file_path
fn download_file(
&self,
profile: &str,
conversation_id: i32,
file_path: &str,
manifest_path: &str,
file_key: &str,
);
/// Query the status of a download
fn check_download_status(&self, profile: &str, file_key: &str);
/// Verufy a download is done, and if not, resume it
fn verify_or_resume_download(&self, profile: &str, conversation_id: i32, file_key: &str);
/// Ask the ACN inside the Cwtch app to restart the tor connection
fn reset_tor(&self);
@ -66,10 +87,10 @@ pub trait CwtchLib {
fn delete_profile(&self, profile: &str, pass: &str);
/// Cause profile to archive conversation with contact
fn archive_conversation(&self, profile: &str, contact: &str);
fn archive_conversation(&self, profile: &str, conversation_id: i32);
/// Cause profile to delete contact/group identified by handle
fn delete_contact(&self, profile: &str, handle: &str);
fn delete_contact(&self, profile: &str, conversation_id: i32);
/// Cuase profile to attempt to import a contact/group/keybundle identified by bundle
fn import_bundle(&self, profile: &str, bundle: &str);
@ -78,13 +99,53 @@ pub trait CwtchLib {
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str);
/// Set a profile's contact's attribute of key to val
fn set_contact_attribute(&self, profile: &str, contact: &str, key: &str, val: &str);
fn set_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str, val: &str);
/// Set a profile's group's attribute of key to val
fn set_group_attribute(&self, profile: &str, group: &str, key: &str, val: &str);
/// Set an attribute on a message in a conversation
fn set_message_attribute(
&self,
profile: &str,
conversation_id: i32,
channel_id: i32,
message_id: i32,
attribute_key: &str,
attribute_value: &str,
);
/// 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);
/// Shutdown the cwtch app and associated ACN
fn shutdown_cwtch(&self);
/// Server functions require server experiment to be enabled
/// Load all servers encrypted by password
fn load_servers(&self, password: &str);
/// Create a new server, encrypted with password, autostart i8 used as bool
fn create_server(&self, password: &str, description: &str, autostart: i8);
/// Delete the specified server (if password is correct)
fn delete_server(&self, onion: &str, current_password: &str);
/// Launch all loaded servers
fn launch_servers(&self);
/// Launch the specified server
fn launch_server(&self, onion: &str);
/// Stop the specified server
fn stop_server(&self, onion: &str);
/// Stop all running servers
fn stop_servers(&self);
/// Destroy all servers leaving htem un-re-runnable. call only on shutdown
fn destroy_servers(&self);
/// Set the specified server's attribute of key to val
fn set_server_attribute(&self, onion: &str, key: &str, val: &str);
}
/// Create a new CwtchLib that is backed by bindings to libcwtch-go

View File

@ -119,41 +119,53 @@ impl Profile {
picture: &str,
contacts_json: &str,
server_list: &str,
) -> Profile {
let contacts = Profile::process_contacts(contacts_json);
let servers = Profile::process_servers(server_list);
Profile {
) -> Result<Profile, String> {
let contacts = match Profile::process_contacts(contacts_json) {
Ok(c) => c,
Err(e) => return Err(e),
};
let servers = match Profile::process_servers(server_list) {
Ok(s) => s,
Err(e) => return Err(e),
};
Ok(Profile {
onion: identity.to_string(),
nick: name.to_string(),
image_path: picture.to_string(),
attr: Default::default(),
contacts: contacts,
servers: servers,
}
})
}
fn process_contacts(constacts_json: &str) -> HashMap<String, Contact> {
fn process_contacts(constacts_json: &str) -> Result<HashMap<String, Contact>, String> {
let mut contacts: HashMap<String, Contact> = HashMap::new();
if constacts_json == "null" {
return contacts;
return Ok(contacts);
}
println!("contacts_json: '{}'", constacts_json);
let contacts_map: Vec<Contact> = serde_json::from_str(constacts_json).unwrap();
let contacts_map: Vec<Contact> = match serde_json::from_str(constacts_json) {
Ok(cm) => cm,
Err(e) => return Err(format!("invalid json: {:?}", e)),
};
for contact in contacts_map {
contacts.insert(contact.onion.clone(), contact);
}
contacts
Ok(contacts)
}
fn process_servers(servers_json: &str) -> HashMap<String, Server> {
fn process_servers(servers_json: &str) -> Result<HashMap<String, Server>, String> {
let mut servers: HashMap<String, Server> = HashMap::new();
if servers_json == "null" {
return servers;
return Ok(servers);
}
let servers_map: Vec<Server> = serde_json::from_str(servers_json).unwrap();
let servers_map: Vec<Server> = match serde_json::from_str(servers_json) {
Ok(sm) => sm,
Err(e) => return Err(format!("invalid json: {:?}", e)),
};
for server in servers_map {
servers.insert(server.onion.clone(), server);
}
servers
Ok(servers)
}
}