diff --git a/build.rs b/build.rs index 75dfb48..b19c044 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,7 @@ fn main() { if std::env::var("LCG_DIR").is_err() { // https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.7.1 Command::new("wget") - .arg("https://git.openprivacy.ca/attachments/98184e9c-1dc7-431a-9601-91a9e763e8fc") + .arg("https://git.openprivacy.ca/attachments/5fa8e7f5-13c2-4634-b531-0398cd7c6353") .arg("-O") .arg(lib_cwtch_path.clone()) .output() @@ -33,7 +33,7 @@ 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!("cb4368d72a46f8046261c50e6e9ecf170d8e606871d5de2c1e9e34303533c344f92f5d946d7e12614581dfa3ae8e638512af7f4623ed91b1ceb1570de14bf192")[..]); + assert_eq!(hash_bytes[..], hex!("dc53eb4948357128a72f740cf48402e966e886c60bc150bd26d10d3c98dda64c3658322c15f3b93781365d40dd4315b1056fb9aa6ee3a56f8968d4bff1bc8f0d")[..]); } else { let local_lcg = Path::new(std::env::var("LCG_DIR").unwrap().as_str()).join("libCwtch.so"); fs::copy(local_lcg, lib_cwtch_path).expect("could not find local lcg"); diff --git a/examples/echobot.rs b/examples/echobot.rs index 185816b..f358477 100644 --- a/examples/echobot.rs +++ b/examples/echobot.rs @@ -27,7 +27,7 @@ fn main() { Event::CwtchStarted => { println!("event CwtchStarted!"); println!("Creating bot"); - cwtch.create_profile("Echobot", "be gay do crime"); + cwtch.create_profile("Echobot", "be gay do crime", true); } Event::NewPeer { profile_id, tag, created, name, default_picture, picture, online, profile_data } => { println!( @@ -40,7 +40,7 @@ fn main() { print!("profile: {:?}", profile); } Event::NewMessageFromPeer { profile_id, conversation_id, contact_id: contact, nick, timestamp_received, message, notification, picture } => { - let response = Message { o: message.o.into(), d: message.d }; + let response = MessageWrapper { o: message.o.into(), d: message.d }; cwtch.send_message( &profile_id, conversation_id, &response); } _ => eprintln!("unhandled event!"), diff --git a/libCwtch.h b/libCwtch.h index f30c8cf..473744f 100644 --- a/libCwtch.h +++ b/libCwtch.h @@ -1,11 +1,11 @@ /* Code generated by cmd/cgo; DO NOT EDIT. */ -/* package git.openprivacy.ca/cwtch.im/libcwtch-go */ +/* package git.openprivacy.ca/cwtch.im/cwtch-autobindings */ #line 1 "cgo-builtin-export-prolog" -#include /* for ptrdiff_t below */ +#include #ifndef GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H @@ -16,6 +16,7 @@ typedef struct { const char *p; ptrdiff_t n; } _GoString_; #endif + /* Start of boilerplate cgo prologue. */ #line 1 "cgo-gcc-export-header-prolog" @@ -32,11 +33,17 @@ typedef long long GoInt64; typedef unsigned long long GoUint64; typedef GoInt64 GoInt; typedef GoUint64 GoUint; -typedef __SIZE_TYPE__ GoUintptr; +typedef size_t GoUintptr; typedef float GoFloat32; typedef double GoFloat64; +#ifdef _MSC_VER +#include +typedef _Fcomplex GoComplex64; +typedef _Dcomplex GoComplex128; +#else typedef float _Complex GoComplex64; typedef double _Complex GoComplex128; +#endif /* static assertion to make sure the file is being used on architecture @@ -60,69 +67,61 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 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 -extern void c_SendAppEvent(char* json_ptr, int json_len); - -// A generic method for Rebroadcasting Profile Events from a UI -extern void c_SendProfileEvent(char* onion_ptr, int onion_len, char* json_ptr, int json_len); - -// the pointer returned from this function **must** be freed using c_Free -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_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, 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, 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 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); -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, 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 int c_Started(); +extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen); + +// the pointer returned from this function **must** be freed using c_Free +// +extern char* c_GetAppBusEvent(); +extern void c_ReconnectCwtchForeground(); +extern void c_ShutdownCwtch(); 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); -extern void c_DeleteServer(char* onionPtr, int onionLen, char* currentPasswordPtr, int currentPasswordLen); +extern void c_ResetTor(); +extern void c_UpdateSettings(char* json_ptr, int json_len); +extern void c_ActivatePeerEngine(char* onion_ptr, int onion_len); +extern void c_DeactivatePeerEngine(char* onion_ptr, int onion_len); +extern void c_CreateProfile(char* name_ptr, int name_len, char* password_ptr, int password_len, char autostart1); +extern void c_LoadProfiles(char* password_ptr, int password_len); +extern void c_DeleteProfile(char* onion_ptr, int onion_len, char* password_ptr, int password_len); +extern char* c_ImportProfile(char* file2_ptr, int file2_len, char* password_ptr, int password_len); +extern void c_ChangePassword(char* onion_ptr, int onion_len, char* current3_ptr, int current3_len, char* newPassword4_ptr, int newPassword4_len, char* newPasswordAgain5_ptr, int newPasswordAgain5_len); +extern void c_ExportProfile(char* onion_ptr, int onion_len, char* file6_ptr, int file6_len); +extern char* c_ImportBundle(char* onion_ptr, int onion_len, char* bundle7_ptr, int bundle7_len); +extern void c_ArchiveConversation(char* onion_ptr, int onion_len, int conversation); +extern void c_AcceptConversation(char* onion_ptr, int onion_len, int conversation); +extern void c_BlockConversation(char* onion_ptr, int onion_len, int conversation); +extern void c_UnblockConversation(char* onion_ptr, int onion_len, int conversation); +extern void c_DeleteConversation(char* onion_ptr, int onion_len, int conversation); +extern char* c_SendMessage(char* onion_ptr, int onion_len, int conversation, char* msg8_ptr, int msg8_len); +extern char* c_GetMessageById(char* onion_ptr, int onion_len, int conversation, int message_id); +extern char* c_GetMessageByContentHash(char* onion_ptr, int onion_len, int conversation, char* contentHash9_ptr, int contentHash9_len); +extern char* c_GetMessages(char* onion_ptr, int onion_len, int conversation, int index, int count); +extern char* c_SendInviteMessage(char* onion_ptr, int onion_len, int conversation, int target); +extern void c_UpdateMessageAttribute(char* onion_ptr, int onion_len, int conversation, int channel_id, int message_id, char* attributeKey10_ptr, int attributeKey10_len, char* attributeValue11_ptr, int attributeValue11_len); +extern void c_StartGroup(char* onion_ptr, int onion_len, char* name12_ptr, int name12_len, char* server13_ptr, int server13_len); +extern void c_DownloadFileDefaultLimit(char* onion_ptr, int onion_len, int conversation, char* filepath14_ptr, int filepath14_len, char* manifest15_ptr, int manifest15_len, char* filekey16_ptr, int filekey16_len); +extern void c_RestartFileShare(char* onion_ptr, int onion_len, char* filekey17_ptr, int filekey17_len); +extern void c_StopFileShare(char* onion_ptr, int onion_len, char* filekey18_ptr, int filekey18_len); +extern void c_CheckDownloadStatus(char* onion_ptr, int onion_len, char* filekey19_ptr, int filekey19_len); +extern void c_VerifyOrResumeDownload(char* onion_ptr, int onion_len, int conversation, char* filekey20_ptr, int filekey20_len); +extern char* c_ShareFile(char* onion_ptr, int onion_len, int conversation, char* filepath21_ptr, int filepath21_len); +extern char* c_GetSharedFiles(char* onion_ptr, int onion_len, int conversation); +extern void c_CreateServer(char* password_ptr, int password_len, char* description22_ptr, int description22_len, char autostart23); +extern void c_SetServerAttribute(char* handle24_ptr, int handle24_len, char* key25_ptr, int key25_len, char* val26_ptr, int val26_len); +extern void c_LoadServers(char* password_ptr, int password_len); extern void c_LaunchServers(); -extern void c_LaunchServer(char* onionPtr, int onionLen); -extern void c_StopServer(char* onionPtr, int onionLen); +extern void c_LaunchServer(char* handle27_ptr, int handle27_len); +extern void c_StopServer(char* handle28_ptr, int handle28_len); extern void c_StopServers(); extern void c_DestroyServers(); -extern void c_SetServerAttribute(char* onionPtr, int onionLen, char* keyPtr, int keyLen, char* valPtr, int valLen); -extern char* c_GetDebugInfo(); +extern void c_DeleteServer(char* handle29_ptr, int handle29_len, char* password_ptr, int password_len); #ifdef __cplusplus } diff --git a/src/bindings_go.rs b/src/bindings_go.rs index 3efba74..862d802 100644 --- a/src/bindings_go.rs +++ b/src/bindings_go.rs @@ -85,31 +85,36 @@ 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!(_update_settings(settings_json: &str;;) c_UpdateSettings); 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); c_bind!(_get_appbus_event(;;) c_GetAppBusEvent -> String); - c_bind!(_send_profile_event(profile: &str, event_jason: &str;;) c_SendProfileEvent); - 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!(_create_profile(nick: &str, pass: &str; autostart: i8;) c_CreateProfile); + c_bind!(_activate_peer_engine(profile: &str;;) c_ActivatePeerEngine); + c_bind!(_deactivate_peer_engine(profile: &str;;) c_DeactivatePeerEngine); + c_bind!(_accept_conversation(profile: &str ; conversation_id: i32; ) c_AcceptConversation); + c_bind!(_block_conversation(profile: &str ; conversation_id: i32; ) c_BlockConversation); + c_bind!(_unblock_conversation(profile: &str ; conversation_id: i32; ) c_UnblockConversation); + 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_GetMessageByContentHash -> String); 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!(_send_invite_message(profile: &str; conversation_id: i32, target_id: i32;) c_SendInviteMessage -> 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!(_get_shared_files(profile: &str; conversaion_id: i32;) c_GetSharedFiles -> String); + c_bind!(_restart_fileshare(profile: &str, file_key: &str;;) c_RestartFileShare); + c_bind!(_stop_fileshare(profile: &str, file_key: &str;;) c_StopFileShare); + c_bind!(_download_file_default_limit(profile: &str; conversation_id: i32; file_path: &str, manifest_path: &str, file_key: &str) c_DownloadFileDefaultLimit); 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); - c_bind!(_create_group(profile: &str, server: &str, name: &str;;) c_CreateGroup); + c_bind!(_start_group(profile: &str, name: &str, server: &str;;) c_StartGroup); 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!(_delete_conversation(profile: &str; conversation_id: i32;) c_DeleteConversation); 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!(_update_message_attribute(profile: &str; conversation_id: i32, channel_id: i32, message_id: i32; key: &str, val: &str) c_UpdateMessageAttribute); 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!(_delete_server(server: &str, current_password: &str;;) c_DeleteServer); @@ -121,24 +126,33 @@ impl CwtchLibGo { 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); - fn send_profile_event(&self, profile: &ProfileIdentity, event_jason: &str) { - self._send_profile_event(profile.as_str(), event_jason) - + fn update_settings(&self, settings: &Settings) { + let settings_json = match serde_json::to_string(settings) { + Ok(s) => s, + Err(_) => return, + }; + self._update_settings(&settings_json) } - c_bind!(create_profile(nick: &str, pass: &str;;) c_CreateProfile); + c_bind!(reconnect_cwtch_foreground(;;) c_ReconnectCwtchForeground); + fn create_profile(&self, nick: &str, pass: &str, autostart: bool) { + self._create_profile(nick, pass, if autostart { 1 } else { 0 }) + } + fn activate_peer_engine(&self, profile: &ProfileIdentity) { + self._activate_peer_engine(profile.as_str()) + } + fn deactivate_peer_engine(&self, profile: &ProfileIdentity) { + self._deactivate_peer_engine(profile.as_str()) + } + c_bind!(load_profiles(pass: &str;;) c_LoadProfiles); fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { self._accept_conversation(profile.as_str(), conversation_id.into()) } - fn block_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { - self._block_contact(String::from(profile).as_str(), conversation_id.into()) + fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { + self._block_conversation(String::from(profile).as_str(), conversation_id.into()) } - fn unblock_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { - self._unblock_contact(String::from(profile).as_str(), conversation_id.into()) - } - fn get_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32) -> String { - self._get_message(String::from(profile).as_str(), conversation_id.into(), message_index) + fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { + self._unblock_conversation(String::from(profile).as_str(), conversation_id.into()) } fn get_message_by_id(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_id: i32) -> String { self._get_message_by_id(String::from(profile).as_str(), conversation_id.into(), message_id) @@ -152,25 +166,39 @@ impl CwtchLib for CwtchLibGo { fn send_message_raw(&self, profile: &ProfileIdentity, conversation_id: ConversationID, msg: &str) -> String { self._send_message(String::from(profile).as_str(), conversation_id.into(), msg) } - fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &Message) -> Result { + fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &MessageWrapper) -> Result { match serde_json::to_string(&message) { Ok(message_json) => Ok(self._send_message(&String::from(profile), conversation_id.into(), &message_json)), Err(e) => Err(format!("Error parsing json response: {}", e.to_string())) } } - fn send_invitation(&self, profile: &ProfileIdentity, conversation_id: ConversationID, target_id: i32) -> String { - self._send_invitation(String::from(profile).as_str(), conversation_id.into(), target_id) + fn send_invite_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, target_id: i32) -> String { + self._send_invite_message(String::from(profile).as_str(), conversation_id.into(), target_id) } fn share_file(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str) -> String { self._share_file(String::from(profile).as_str(), conversation_id.into(), file_path) } - fn download_file(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str, manifest_path: &str, file_key: FileKey) { - self._download_file(String::from(profile).as_str(), conversation_id.into(), file_path, manifest_path, String::from(file_key).as_str()) + fn get_shared_files(&self, profile: &ProfileIdentity, conversaion_id: ConversationID) -> Vec { + let json = self._get_shared_files(profile.as_str(), conversaion_id.into()); + + match serde_json::from_str(&json) { + Ok(l) => l, + Err(_) => vec!(), + } } - fn check_download_status(&self, profile: &ProfileIdentity, file_key: FileKey) { + fn download_file_default_limit(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str, manifest_path: &str, file_key: &FileKey) { + self._download_file_default_limit(String::from(profile).as_str(), conversation_id.into(), file_path, manifest_path, String::from(file_key).as_str()) + } + fn restart_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey) { + self._restart_fileshare(profile.as_str(), file_key.as_str()) + } + fn stop_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey) { + self._stop_fileshare(profile.as_str(), file_key.as_str()) + } + fn check_download_status(&self, profile: &ProfileIdentity, file_key: &FileKey) { self._check_download_status(String::from(profile).as_str(), String::from(file_key).as_str()) } - fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: FileKey) { + fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey) { self._verify_or_resume_download(String::from(profile).as_str(), conversation_id.into(), String::from(file_key).as_str()) } @@ -179,8 +207,8 @@ impl CwtchLib for CwtchLibGo { bindings::c_ResetTor(); } } - fn create_group(&self, profile: &ProfileIdentity, server: &str, name: &str) { - self._create_group(String::from(profile).as_str(), server, name) + fn start_group(&self, profile: &ProfileIdentity, server: &str, name: &str) { + self._start_group(String::from(profile).as_str(), server, name) } fn delete_profile(&self, profile: &ProfileIdentity, pass: &str) { self._delete_profile(String::from(profile).as_str(), pass) @@ -188,8 +216,8 @@ impl CwtchLib for CwtchLibGo { fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { self._archive_conversation(String::from(profile).as_str(), conversation_id.into()) } - fn delete_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { - self._delete_contact(profile.as_str(), conversation_id.into()) + fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) { + self._delete_conversation(profile.as_str(), conversation_id.into()) } fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str) { self._import_bundle(String::from(profile).as_str(), bundle) @@ -223,8 +251,8 @@ impl CwtchLib for CwtchLibGo { false => Ok(None), } } - fn set_message_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, channel_id: i32, message_id: i32, key: &str, val: &str) { - self._set_message_attribute(String::from(profile).as_str(), conversation_id.into(), channel_id, message_id, key, val) + fn update_message_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, channel_id: i32, message_id: i32, key: &str, val: &str) { + self._update_message_attribute(String::from(profile).as_str(), conversation_id.into(), channel_id, message_id, key, val) } fn change_password(&self, profile: &ProfileIdentity, old_pass: &str, new_pass: &str, new_pass_again: &str) { self._change_password(String::from(profile).as_str(), old_pass, new_pass, new_pass_again) @@ -259,7 +287,8 @@ impl CwtchLib for CwtchLibGo { fn set_server_attribute(&self, server: ServerIdentity, key: &str, val: &str) { self._set_server_attribute(String::from(server).as_str(), key, val) } - c_bind!(get_debug_info(;;) c_GetDebugInfo -> String); + // todo: reenabled in 1.12 + //c_bind!(get_debug_info(;;) c_GetDebugInfo -> String); fn get_appbus_event(&self) -> Event { let event_json = self._get_appbus_event(); diff --git a/src/cwtchlib_go/bindings.rs b/src/cwtchlib_go/bindings.rs index 29d11ac..bb3e28c 100644 --- a/src/cwtchlib_go/bindings.rs +++ b/src/cwtchlib_go/bindings.rs @@ -102,7 +102,7 @@ pub type GoInt64 = ::std::os::raw::c_longlong; pub type GoUint64 = ::std::os::raw::c_ulonglong; pub type GoInt = GoInt64; pub type GoUint = GoUint64; -pub type GoUintptr = ::std::os::raw::c_ulong; +pub type GoUintptr = size_t; pub type GoFloat32 = f32; pub type GoFloat64 = f64; pub type GoComplex64 = __BindgenComplex; @@ -200,6 +200,12 @@ fn bindgen_test_layout_GoSlice() { ) ); } +extern "C" { + pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char); +} +extern "C" { + pub fn c_Started() -> ::std::os::raw::c_int; +} extern "C" { pub fn c_StartCwtch( dir_c: *mut ::std::os::raw::c_char, @@ -209,195 +215,13 @@ extern "C" { ) -> ::std::os::raw::c_int; } extern "C" { - pub fn c_Started() -> ::std::os::raw::c_int; + pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char; } extern "C" { pub fn c_ReconnectCwtchForeground(); } extern "C" { - pub fn c_SendAppEvent(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int); -} -extern "C" { - pub fn c_SendProfileEvent( - onion_ptr: *mut ::std::os::raw::c_char, - onion_len: ::std::os::raw::c_int, - json_ptr: *mut ::std::os::raw::c_char, - json_len: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn c_CreateProfile( - nick_ptr: *mut ::std::os::raw::c_char, - nick_len: ::std::os::raw::c_int, - pass_ptr: *mut ::std::os::raw::c_char, - pass_len: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_LoadProfiles( - passwordPtr: *mut ::std::os::raw::c_char, - passwordLen: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_AcceptConversation( - 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_BlockContact( - 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_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, - 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; -} -extern "C" { - pub fn c_GetMessagesByContentHash( - profile_ptr: *mut ::std::os::raw::c_char, - profile_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; -} -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); -} -extern "C" { - pub fn c_SendMessage( - profile_ptr: *mut ::std::os::raw::c_char, - profile_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, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn c_SendInvitation( - profile_ptr: *mut ::std::os::raw::c_char, - 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( - 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, - ) -> *mut ::std::os::raw::c_char; -} -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" { - pub fn c_ResetTor(); -} -extern "C" { - pub fn c_CreateGroup( - profile_ptr: *mut ::std::os::raw::c_char, - profile_len: ::std::os::raw::c_int, - server_ptr: *mut ::std::os::raw::c_char, - server_len: ::std::os::raw::c_int, - name_ptr: *mut ::std::os::raw::c_char, - name_len: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_DeleteProfile( - profile_ptr: *mut ::std::os::raw::c_char, - profile_len: ::std::os::raw::c_int, - password_ptr: *mut ::std::os::raw::c_char, - password_len: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_ArchiveConversation( - profile_ptr: *mut ::std::os::raw::c_char, - profile_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, - conversation_id: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn c_ImportBundle( - profile_ptr: *mut ::std::os::raw::c_char, - profile_len: ::std::os::raw::c_int, - bundle_ptr: *mut ::std::os::raw::c_char, - bundle_len: ::std::os::raw::c_int, - ); + pub fn c_ShutdownCwtch(); } extern "C" { pub fn c_SetProfileAttribute( @@ -438,80 +262,284 @@ extern "C" { ) -> *mut ::std::os::raw::c_char; } extern "C" { - pub fn c_SetMessageAttribute( - profile_ptr: *mut ::std::os::raw::c_char, - profile_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, + pub fn c_ResetTor(); +} +extern "C" { + pub fn c_UpdateSettings(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int); +} +extern "C" { + pub fn c_ActivatePeerEngine( + onion_ptr: *mut ::std::os::raw::c_char, + onion_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, + pub fn c_DeactivatePeerEngine( + onion_ptr: *mut ::std::os::raw::c_char, + onion_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, + pub fn c_CreateProfile( + name_ptr: *mut ::std::os::raw::c_char, + name_len: ::std::os::raw::c_int, + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::std::os::raw::c_int, + autostart1: ::std::os::raw::c_char, + ); +} +extern "C" { + pub fn c_LoadProfiles( + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_DeleteProfile( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + password_ptr: *mut ::std::os::raw::c_char, + password_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, + file2_ptr: *mut ::std::os::raw::c_char, + file2_len: ::std::os::raw::c_int, + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_char; } extern "C" { - pub fn c_ShutdownCwtch(); + pub fn c_ChangePassword( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + current3_ptr: *mut ::std::os::raw::c_char, + current3_len: ::std::os::raw::c_int, + newPassword4_ptr: *mut ::std::os::raw::c_char, + newPassword4_len: ::std::os::raw::c_int, + newPasswordAgain5_ptr: *mut ::std::os::raw::c_char, + newPasswordAgain5_len: ::std::os::raw::c_int, + ); } extern "C" { - pub fn c_LoadServers( - passwordPtr: *mut ::std::os::raw::c_char, - passwordLen: ::std::os::raw::c_int, + pub fn c_ExportProfile( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + file6_ptr: *mut ::std::os::raw::c_char, + file6_len: ::std::os::raw::c_int, ); } +extern "C" { + pub fn c_ImportBundle( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + bundle7_ptr: *mut ::std::os::raw::c_char, + bundle7_len: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_ArchiveConversation( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_AcceptConversation( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_BlockConversation( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_UnblockConversation( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_DeleteConversation( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_SendMessage( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + msg8_ptr: *mut ::std::os::raw::c_char, + msg8_len: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_GetMessageById( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + message_id: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_GetMessageByContentHash( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + contentHash9_ptr: *mut ::std::os::raw::c_char, + contentHash9_len: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_GetMessages( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + index: ::std::os::raw::c_int, + count: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_SendInviteMessage( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + target: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_UpdateMessageAttribute( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + channel_id: ::std::os::raw::c_int, + message_id: ::std::os::raw::c_int, + attributeKey10_ptr: *mut ::std::os::raw::c_char, + attributeKey10_len: ::std::os::raw::c_int, + attributeValue11_ptr: *mut ::std::os::raw::c_char, + attributeValue11_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_StartGroup( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + name12_ptr: *mut ::std::os::raw::c_char, + name12_len: ::std::os::raw::c_int, + server13_ptr: *mut ::std::os::raw::c_char, + server13_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_DownloadFileDefaultLimit( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + filepath14_ptr: *mut ::std::os::raw::c_char, + filepath14_len: ::std::os::raw::c_int, + manifest15_ptr: *mut ::std::os::raw::c_char, + manifest15_len: ::std::os::raw::c_int, + filekey16_ptr: *mut ::std::os::raw::c_char, + filekey16_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_RestartFileShare( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + filekey17_ptr: *mut ::std::os::raw::c_char, + filekey17_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_StopFileShare( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + filekey18_ptr: *mut ::std::os::raw::c_char, + filekey18_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_CheckDownloadStatus( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + filekey19_ptr: *mut ::std::os::raw::c_char, + filekey19_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_VerifyOrResumeDownload( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + filekey20_ptr: *mut ::std::os::raw::c_char, + filekey20_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_ShareFile( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + filepath21_ptr: *mut ::std::os::raw::c_char, + filepath21_len: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} +extern "C" { + pub fn c_GetSharedFiles( + onion_ptr: *mut ::std::os::raw::c_char, + onion_len: ::std::os::raw::c_int, + conversation: ::std::os::raw::c_int, + ) -> *mut ::std::os::raw::c_char; +} 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, + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::std::os::raw::c_int, + description22_ptr: *mut ::std::os::raw::c_char, + description22_len: ::std::os::raw::c_int, + autostart23: ::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, + pub fn c_SetServerAttribute( + handle24_ptr: *mut ::std::os::raw::c_char, + handle24_len: ::std::os::raw::c_int, + key25_ptr: *mut ::std::os::raw::c_char, + key25_len: ::std::os::raw::c_int, + val26_ptr: *mut ::std::os::raw::c_char, + val26_len: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn c_LoadServers( + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::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); + pub fn c_LaunchServer( + handle27_ptr: *mut ::std::os::raw::c_char, + handle27_len: ::std::os::raw::c_int, + ); } extern "C" { - pub fn c_StopServer(onionPtr: *mut ::std::os::raw::c_char, onionLen: ::std::os::raw::c_int); + pub fn c_StopServer( + handle28_ptr: *mut ::std::os::raw::c_char, + handle28_len: ::std::os::raw::c_int, + ); } extern "C" { pub fn c_StopServers(); @@ -520,15 +548,10 @@ 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, + pub fn c_DeleteServer( + handle29_ptr: *mut ::std::os::raw::c_char, + handle29_len: ::std::os::raw::c_int, + password_ptr: *mut ::std::os::raw::c_char, + password_len: ::std::os::raw::c_int, ); } -extern "C" { - pub fn c_GetDebugInfo() -> *mut ::std::os::raw::c_char; -} diff --git a/src/event.rs b/src/event.rs index 6987b09..46fefd3 100644 --- a/src/event.rs +++ b/src/event.rs @@ -5,7 +5,7 @@ use chrono::{DateTime, FixedOffset}; use chrono::prelude::*; use std::convert::From; -use crate::structs::{ACL, ConnectionState, CwtchEvent, Message, Profile, Settings}; +use crate::structs::{ACL, ConnectionState, CwtchEvent, MessageWrapper, Profile, Settings}; #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)] @@ -127,6 +127,19 @@ impl From for String { } } +impl From<&FileKey> for String { + fn from(x: &FileKey) -> Self { + x.into() + } +} + +impl FileKey { + /// Get &str of FileKey String + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + #[derive(Debug, Clone)] /// Enum for type of notification a UI/client should emit for a new message pub enum MessageNotification { @@ -333,7 +346,7 @@ pub enum Event { /// time message was received timestamp_received: DateTime, /// the message - message: Message, + message: MessageWrapper, /// notification instructions (based on settings) notification: MessageNotification, /// path to picture for the contact @@ -456,7 +469,7 @@ pub enum Event { /// message index index: i32, /// the message - message: Message, + message: MessageWrapper, /// hash of the message content_hash: String, /// path to picture for sender @@ -636,7 +649,7 @@ impl From<&CwtchEvent> for Event { contact_id: cwtch_event.data["RemotePeer"].clone().into(), nick: cwtch_event.data["Nick"].clone(), timestamp_received: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampReceived"].as_str()).unwrap_or( DateTime::from(Utc::now())), - message: Message::from_json(&cwtch_event.data["Data"]), + message: MessageWrapper::from_json(&cwtch_event.data["Data"]), notification: MessageNotification::from(cwtch_event.data["notification"].clone()), picture: cwtch_event.data["picture"].clone(), }, @@ -772,7 +785,7 @@ impl From<&CwtchEvent> for Event { conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(), contact_id: cwtch_event.data["RemotePeer"].clone().into(), nick: cwtch_event.data["Nick"].clone(), - message: Message::from_json(&cwtch_event.data["Data"]), + message: MessageWrapper::from_json(&cwtch_event.data["Data"]), notification: MessageNotification::from(cwtch_event.data["notification"].clone()), picture: cwtch_event.data["picture"].clone(), }, diff --git a/src/lib.rs b/src/lib.rs index 458804c..750cdb2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ #![deny(missing_docs)] use crate::event::{ConversationID, Event, FileKey, ProfileIdentity, ServerIdentity}; -use crate::structs::Message; +use crate::structs::{MessageWrapper, Settings, SharedFile}; mod bindings_go; mod cwtchlib_go; @@ -25,17 +25,24 @@ pub trait CwtchLib { /// 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); + /// Like StartCwtch, but StartCwtch has already been called so we don't need to restart Tor etc (probably) + /// Do need to re-send initial state tho, eg profiles that are already loaded (used by android when ui state is lost) + fn reconnect_cwtch_foreground(&self); - /// Send json of a structs::CwtchEvent to a cwtch profile - fn send_profile_event(&self, profile: &ProfileIdentity, event_json: &str); + /// Save and update the settings based on this settings + fn update_settings(&self, settings: &Settings); + + /// Activate the networking engine of a profile so it can send and listen to/for messages + fn activate_peer_engine(&self, profile: &ProfileIdentity); + + /// Deactivate the networking engine of a profile so it cannot send and listen to/for messages + fn deactivate_peer_engine(&self, profile: &ProfileIdentity); /// Pull json of a structs::CwtchEvent off the appbus for responding to fn get_appbus_event(&self) -> Event; /// Create a new profile encrypted with pass - fn create_profile(&self, nick: &str, pass: &str); + fn create_profile(&self, nick: &str, pass: &str, autostart: bool); /// Load any profiles encrypted by pass fn load_profiles(&self, pass: &str); @@ -44,13 +51,10 @@ pub trait CwtchLib { fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID); /// Cause profile to block conversation - fn block_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID); + fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID); - /// Cause profile to unblock contact - fn unblock_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID); - - /// Get a specific message for conversation of profile by index - fn get_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32) -> String; + /// Cause profile to unblock conversation + fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID); /// Get a specific message for a conversation by its id fn get_message_by_id(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_id: i32) -> String; @@ -70,35 +74,44 @@ pub trait CwtchLib { fn send_message_raw(&self, profile: &ProfileIdentity, conversation_id: ConversationID, msg: &str) -> String; /// Send structs::Message from profile to contact. Returns computed sent message (including index and hash values) or Error - fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &Message) -> Result; + fn send_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message: &MessageWrapper) -> Result; - /// Send profile's contact an invite for/to target. Returns computed sent message (including index and hash values) - fn send_invitation(&self, profile: &ProfileIdentity, conversation_id: ConversationID, target_id: i32) -> String; + /// Send profile's contact an invite for/to target. Returns computed sent message (including index and hash values) + fn send_invite_message(&self, profile: &ProfileIdentity, conversation_id: ConversationID, 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: &ProfileIdentity, conversation_id: ConversationID, file_path: &str) -> String; + /// get list of SharedFile for a conversation + fn get_shared_files(&self, profile: &ProfileIdentity, conversaion_id: ConversationID) -> Vec; + /// download a file from a conversation to the file_path - fn download_file( + fn download_file_default_limit( &self, profile: &ProfileIdentity, conversation_id: ConversationID, file_path: &str, manifest_path: &str, - file_key: FileKey, + file_key: &FileKey, ); + /// Restart a fileshare (used when restarting app to reoffer a previously created fileshare) + fn restart_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey); + + /// Stop offering a fileshare + fn stop_fileshare(&self, profile: &ProfileIdentity, file_key: &FileKey); + /// Query the status of a download - fn check_download_status(&self, profile: &ProfileIdentity, file_key: FileKey); + fn check_download_status(&self, profile: &ProfileIdentity, file_key: &FileKey); /// Verufy a download is done, and if not, resume it - fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: FileKey); + fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey); /// Ask the ACN inside the Cwtch app to restart the tor connection fn reset_tor(&self); /// Cause profile to create a group on server with name - fn create_group(&self, profile: &ProfileIdentity, server: &str, name: &str); + fn start_group(&self, profile: &ProfileIdentity, name: &str, server: &str); /// Delete profile with encryption/password check of pass fn delete_profile(&self, profile: &ProfileIdentity, pass: &str); @@ -107,7 +120,7 @@ pub trait CwtchLib { fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID); /// Cause profile to delete contact/group identified by handle - fn delete_contact(&self, profile: &ProfileIdentity, conversation_id: ConversationID); + fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID); /// Cuase profile to attempt to import a contact/group/keybundle identified by bundle fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str); @@ -121,8 +134,8 @@ pub trait CwtchLib { /// Set a profile's contact's attribute of key to val fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str); - /// Set an attribute on a message in a conversation - fn set_message_attribute( + /// Update an attribute on a message in a conversation + fn update_message_attribute( &self, profile: &ProfileIdentity, conversation_id: ConversationID, @@ -176,8 +189,9 @@ pub trait CwtchLib { /// Set the specified server's attribute of key to val fn set_server_attribute(&self, server: ServerIdentity, key: &str, val: &str); - /// Get debug info (mem, goroutine stats) from lcg in json - fn get_debug_info(&self) -> String; + // Get debug info (mem, goroutine stats) from lcg in json + // todo: reenable in 1.12 + //fn get_debug_info(&self) -> String; } /// Create a new CwtchLib that is backed by bindings to libcwtch-go diff --git a/src/structs.rs b/src/structs.rs index 706c07f..984d173 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DefaultOnError}; use serde_repr::*; use std::collections::HashMap; -use crate::event::ContactIdentity; +use crate::event::{ContactIdentity, FileKey}; #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)] /// Defines the states a Cwtch connection can be in @@ -186,27 +186,119 @@ impl From for MessageType { } } - #[derive(Debug, Serialize, Deserialize, Clone)] /// Struct to serialize/deserialize messages sent over Cwtch between profiles / conversation -pub struct Message { +/// Overlay => data +/// 1 TextMessage: d = plain text message +/// 10 QuotedMessage: d = json of QuotedMessageStructure, body = plain text of message +pub struct MessageWrapper { /// overlay id that the message is targeting as defined in cwtch/model/overlay.go /// [ OverlayChat = 1, OverlayInviteContact = 100, OverlayInviteGroup = 101, OverlayFileSharing = 200 ] pub o: MessageType, - /// data of the message + /// data of the message, for OverlayChat, a pub d: String, } -impl Message { +impl MessageWrapper { /// parse json into a Message pub fn from_json(json: &str) -> Self { match serde_json::from_str(json) { Ok(m) => m, - Err(e) => Message{o: MessageType::MalformedMessage, d: e.to_string()} + Err(e) => MessageWrapper {o: MessageType::MalformedMessage, d: e.to_string()} } } } +#[derive(Debug, Serialize, Deserialize, Clone)] +/// defined: cwtch-ui/lib/model/messages/quotedmessage.dart ~ln 15 +#[allow(non_snake_case)] +pub struct QuotedMessageStructure { + /// hash message id of message being quoted + pub quotedHash: String, + /// plain text of the reply message + pub body: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +/// LocallyIndexedMessage is a type wrapper around a Message and a TimeLine Index that is local to this +/// instance of the timeline. +/// defined in: cwtch/model/message.go ~ln 31 +#[allow(non_snake_case)] +pub struct LocallyIndexedMessage { + /// The message + pub Message: LocalMessage, + /// the local index in this timeline instance + pub LocalIndex: i32, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +/// Message is a local representation of a given message sent over a group chat channel. +/// defined in: cwtch/model/message.go ~ln 38 +#[allow(non_snake_case)] +pub struct LocalMessage { + /// Timestamp of the message from sender + pub Timestamp: String, //time.Time + /// Timestamp message was received at + pub Received: String, //time.Time + /// ContactId of the sender + pub PeerID: String, + /// Message contents + pub Message: MessageWrapper, + /// author's signature verifying the message + pub Signature: String, + /// the signature of hte previous message in the sender's timeline + pub PreviousMessageSig: String, + /// was message confirmed by server + pub ReceivedByServer: bool, + /// was the message ack'ed by the recipient peer + pub Acknowledged: bool, // peer to peer + /// message if there was an error, empty if fine + pub Error: String, + /// Application specific flags, useful for storing small amounts of metadata + pub Flags: u64 +} + +// Only for internal use? +/* +#[derive(Debug, Serialize, Deserialize, Clone)] +/// FilesharingOverlayMessage presents the canonical format of the File Sharing functionality Overlay Message +/// This is the format that the UI will parse to display the message +/// defined: cwtch/functionality/filesharing/filesharing_functionality.go ~ln 156 +pub struct FilesharingOverlayMessage { + #[serde(alias = "f")] + pub name: String, + #[serde(alias = "h")] + pub hash: String, + #[serde(alias = "n")] + pub nonce: String, + #[serde(alias = "s")] + pub size: u64, +} +*/ + +#[derive(Debug, Serialize, Deserialize, Clone)] +/// SharedFile struct from cwtch defined in cwtch/functionality/filesharing/filesharing_functionality.go ~ln 464 +#[allow(non_snake_case)] +pub struct SharedFile { + /// The roothash.nonce identifier derived for this file share + pub FileKey: FileKey, + + /// Path is the OS specific location of the file + pub Path: String, + + /// DateShared is the original datetime the file was shared + /// go time.Time, => DateTime + /// DateTime::parse_from_rfc3339(cwtch_event.data["TimestampSent"].as_str()).unwrap_or( DateTime::from(Utc::now())), + pub DateShared: String, + + /// Active is true if the file is currently being shared, false otherwise + pub Active: bool, + + /// Expired is true if the file is not eligible to be shared (because e.g. it has been too long since the file was originally shared, + /// or the file no longer exists). + pub Expired: bool +} + #[derive(Debug, Serialize, Deserialize, Clone)] /// Settings as defined in libcwtch-go/utils/settings.go and should be populated by handeling the UpdateGlobalSettings event emited during cwtch.start() #[allow(non_snake_case)] @@ -286,20 +378,7 @@ impl Experiments { impl Settings { /// Given a CwtchLib, handles sending an event to it with updated settings represented by this struct for saving pub fn save(&self, cwtch: &dyn CwtchLib) -> Result<(), String> { - let settings_json = match serde_json::to_string(&self) { - Ok(s) => s, - Err(e) => return Err(e.to_string()), - }; - let save_settings_event: CwtchEvent = CwtchEvent { - event_type: "UpdateGlobalSettings".to_string(), - event_ID: "0".to_string(), - data: HashMap::from([("Data".to_string(), settings_json)]), - }; - let event_json = match serde_json::to_string(&save_settings_event) { - Ok(s) => s, - Err(e) => return Err(e.to_string()), - }; - cwtch.send_app_event(&event_json); + cwtch.update_settings(&self); return Ok(()); } }