libcwtch-rs: Rust bindings for libcwtch-go

This commit is contained in:
Dan Ballard 2021-09-03 20:36:35 -07:00
commit 1ead7e597c
10 changed files with 884 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
.idea

96
Cargo.lock generated Normal file
View File

@ -0,0 +1,96 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[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",
]
[[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 = "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 = "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"

13
Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "libcwtch"
version = "0.1.0"
authors = ["Dan Ballard <dan@mindstab.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2"
serde_json = "1.0"
serde = { version = "1.0.127", features = ["derive"] }

21
README.md Normal file
View File

@ -0,0 +1,21 @@
# libCwtch-rs
Rust bindings for libCwtch
## Building
### Updating libCwtch and bingings.rs with Bindgen
```
cargo install bindgen
```
libCwtch.so version is specified in build.rs. If updating, also download the corresponding libCwtch.h and delete
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:
```
bindgen libCwtch.h -o src/gobindings/mod.rs
```
### Todo

16
build.rs Normal file
View File

@ -0,0 +1,16 @@
use std::process::Command;
use std::env;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
println!("cargo:rustc-flags=-L {}", out_dir.to_str().unwrap());
println!("cargo:rustc-link-lib=Cwtch");
println!("cargo:rerun-if-changed=build.rs");
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");
}

104
libCwtch.h Normal file
View File

@ -0,0 +1,104 @@
/* Code generated by cmd/cgo; DO NOT EDIT. */
/* package git.openprivacy.ca/cwtch.im/libcwtch-go */
#line 1 "cgo-builtin-export-prolog"
#include <stddef.h> /* for ptrdiff_t below */
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif
#endif
/* Start of boilerplate cgo prologue. */
#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen);
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_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);
// 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);
// 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);
// 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_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_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_ShutdownCwtch();
#ifdef __cplusplus
}
#endif

118
src/bindings_go.rs Normal file
View File

@ -0,0 +1,118 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
use std::ffi::{CString};
use std::ffi::{CStr};
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use super::{CwtchLib};
use crate::gobindings;
struct c_str_wrap {
raw: *mut i8,
len: i32
}
impl c_str_wrap {
pub fn new(str: &str) -> c_str_wrap {
let cs = match CString::new(str) {
Ok(s) => s,
Err(_) => CString::new("").unwrap()
};
c_str_wrap { len: cs.as_bytes().len() as i32, raw: cs.into_raw() }
}
}
impl Drop for c_str_wrap {
fn drop(&mut self) {
unsafe { 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? )
#[macro_export]
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);)*
unsafe {
gobindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
}
}
};
// 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);)*
unsafe {
let result_ptr = gobindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
let result = match CStr::from_ptr(result_ptr).to_str() {
Ok(s) => s.to_owned(),
Err(_) => "".to_string()
};
// return ownership of string memory and call the library to free it
gobindings::c_FreePointer(result_ptr);
result
}
}
};
// 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);)*
unsafe {
let result = gobindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
result
}
}
};
}
#[derive(Serialize, Deserialize, Debug)]
struct Event {
EventType: String,
Data: HashMap<String, String>
}
pub struct GoCwtchLib {}
impl GoCwtchLib {
c_bind!(send_profile_event(profile, event_json;) c_SendProfileEvent);
}
impl CwtchLib for GoCwtchLib {
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);
fn reset_tor(&self) {
unsafe { gobindings::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);
fn shutdown_cwtch(&self) {
unsafe { gobindings::c_ShutdownCwtch(); }
}
}

399
src/gobindings/mod.rs Normal file
View File

@ -0,0 +1,399 @@
/* automatically generated by rust-bindgen 0.58.1 */
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)]
pub struct __BindgenComplex<T> {
pub re: T,
pub im: T,
}
pub type size_t = ::std::os::raw::c_ulong;
pub type wchar_t = ::std::os::raw::c_int;
#[repr(C)]
#[repr(align(16))]
#[derive(Debug, Copy, Clone)]
pub struct max_align_t {
pub __clang_max_align_nonce1: ::std::os::raw::c_longlong,
pub __bindgen_padding_0: u64,
pub __clang_max_align_nonce2: u128,
}
#[test]
fn bindgen_test_layout_max_align_t() {
assert_eq!(
::std::mem::size_of::<max_align_t>(),
32usize,
concat!("Size of: ", stringify!(max_align_t))
);
assert_eq!(
::std::mem::align_of::<max_align_t>(),
16usize,
concat!("Alignment of ", stringify!(max_align_t))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce1 as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(max_align_t),
"::",
stringify!(__clang_max_align_nonce1)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce2 as *const _ as usize
},
16usize,
concat!(
"Offset of field: ",
stringify!(max_align_t),
"::",
stringify!(__clang_max_align_nonce2)
)
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _GoString_ {
pub p: *const ::std::os::raw::c_char,
pub n: isize,
}
#[test]
fn bindgen_test_layout__GoString_() {
assert_eq!(
::std::mem::size_of::<_GoString_>(),
16usize,
concat!("Size of: ", stringify!(_GoString_))
);
assert_eq!(
::std::mem::align_of::<_GoString_>(),
8usize,
concat!("Alignment of ", stringify!(_GoString_))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<_GoString_>())).p as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(p)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<_GoString_>())).n as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(n)
)
);
}
pub type GoInt8 = ::std::os::raw::c_schar;
pub type GoUint8 = ::std::os::raw::c_uchar;
pub type GoInt16 = ::std::os::raw::c_short;
pub type GoUint16 = ::std::os::raw::c_ushort;
pub type GoInt32 = ::std::os::raw::c_int;
pub type GoUint32 = ::std::os::raw::c_uint;
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 GoFloat32 = f32;
pub type GoFloat64 = f64;
pub type GoComplex64 = __BindgenComplex<f32>;
pub type GoComplex128 = __BindgenComplex<f64>;
pub type _check_for_64_bit_pointer_matching_GoInt = [::std::os::raw::c_char; 1usize];
pub type GoString = _GoString_;
pub type GoMap = *mut ::std::os::raw::c_void;
pub type GoChan = *mut ::std::os::raw::c_void;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct GoInterface {
pub t: *mut ::std::os::raw::c_void,
pub v: *mut ::std::os::raw::c_void,
}
#[test]
fn bindgen_test_layout_GoInterface() {
assert_eq!(
::std::mem::size_of::<GoInterface>(),
16usize,
concat!("Size of: ", stringify!(GoInterface))
);
assert_eq!(
::std::mem::align_of::<GoInterface>(),
8usize,
concat!("Alignment of ", stringify!(GoInterface))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<GoInterface>())).t as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(t)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<GoInterface>())).v as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(v)
)
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct GoSlice {
pub data: *mut ::std::os::raw::c_void,
pub len: GoInt,
pub cap: GoInt,
}
#[test]
fn bindgen_test_layout_GoSlice() {
assert_eq!(
::std::mem::size_of::<GoSlice>(),
24usize,
concat!("Size of: ", stringify!(GoSlice))
);
assert_eq!(
::std::mem::align_of::<GoSlice>(),
8usize,
concat!("Alignment of ", stringify!(GoSlice))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).data as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(data)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).len as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(len)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).cap as *const _ as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(cap)
)
);
}
extern "C" {
pub fn c_StartCwtch(
dir_c: *mut ::std::os::raw::c_char,
len: ::std::os::raw::c_int,
tor_c: *mut ::std::os::raw::c_char,
torLen: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
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_AcceptContact(
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,
);
}
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,
);
}
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,
);
}
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,
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,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::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_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,
handle_ptr: *mut ::std::os::raw::c_char,
handle_len: ::std::os::raw::c_int,
msg_ptr: *mut ::std::os::raw::c_char,
msg_len: ::std::os::raw::c_int,
);
}
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,
);
}
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,
contact_ptr: *mut ::std::os::raw::c_char,
contact_len: ::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,
);
}
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,
);
}
extern "C" {
pub fn c_SetProfileAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
key_ptr: *mut ::std::os::raw::c_char,
key_len: ::std::os::raw::c_int,
val_ptr: *mut ::std::os::raw::c_char,
val_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_SetContactAttribute(
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,
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_SetGroupAttribute(
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,
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_ShutdownCwtch();
}

40
src/lib.rs Normal file
View File

@ -0,0 +1,40 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
mod gobindings;
mod bindings_go;
pub mod structs;
pub trait CwtchLib {
fn start_cwtch(&self, app_dir: &str, tor_path: &str) -> i32;
fn send_app_event(&self, event_json: &str);
fn get_appbus_event(&self, ) -> String;
fn create_profile(&self, nick: &str, pass: &str);
fn load_profiles(&self, pass: &str);
fn accept_contact(&self, profile: &str, contact: &str);
fn reject_invite(&self, profile: &str, contact: &str);
fn block_contact(&self, profile: &str, contact: &str);
fn update_message_flags(&self, profile: &str, contact: &str, message_id: i32, message_flags: u64);
fn get_message(&self, profile: &str, contact: &str, message_index: i32) -> String;
fn get_message_by_content_hash(&self, profile: &str, contact: &str, hash: &str) -> String;
fn send_message(&self, profile: &str, contact: &str, msg: &str);
fn send_invitation(&self, profile: &str, contact: &str, target: &str);
fn reset_tor(&self, );
fn create_group(&self, profile: &str, server: &str, name: &str);
fn delete_profile(&self, profile: &str, pass: &str);
fn archive_conversation(&self, profile: &str, contact: &str);
fn delete_contact(&self, profile: &str, group: &str);
fn import_bundle(&self, profile: &str, bundle: &str);
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str);
fn set_contact_attribute(&self, profile: &str, contact: &str, key: &str, val: &str);
fn set_group_attribute(&self, profile: &str, group: &str, key: &str, val: &str);
fn shutdown_cwtch(&self, );
}
pub fn new_cwtchlib_go() -> impl CwtchLib {
bindings_go::GoCwtchLib {}
}

75
src/structs.rs Normal file
View File

@ -0,0 +1,75 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct CwtchEvent {
pub event_type: String,
pub event_ID: String,
pub data: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Contact {
pub onion: String,
pub name: String,
pub status: String,
pub authorization: String,
pub isGroup: bool,
//attr: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Server {
pub onion: String,
pub status: String,
}
#[derive(Debug)]
pub struct Profile {
pub onion: String,
pub nick: String,
pub imagePath: String,
pub attr: HashMap<String,String>,
pub contacts: HashMap<String, Contact>,
pub servers: HashMap<String, Server>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Message {
pub o: i64,
pub d: String
}
impl Profile {
pub fn new(identity: &str, name: &str, picture: &str, contacts_json: &str, server_list: &str) -> Profile {
let contacts = Profile::process_contacts(contacts_json);
let servers = Profile::process_servers(server_list);
Profile{ onion: identity.to_string(), nick: name.to_string(), imagePath: picture.to_string(), attr: Default::default(), contacts: contacts, servers: servers }
}
pub fn process_contacts(constacts_json: &str) -> HashMap<String, Contact> {
let mut contacts: HashMap<String, Contact> = HashMap::new();
if constacts_json == "null" {
return contacts;
}
println!("contacts_json: '{}'", constacts_json);
let contacts_map: Vec<Contact> = serde_json::from_str(constacts_json).unwrap();
for contact in contacts_map {
contacts.insert(contact.onion.clone(), contact);
}
contacts
}
pub fn process_servers(servers_json: &str) -> HashMap<String, Server> {
let mut servers: HashMap<String, Server> = HashMap::new();
if servers_json == "null" {
return servers;
}
let servers_map: Vec<Server> = serde_json::from_str(servers_json).unwrap();
for server in servers_map {
servers.insert(server.onion.clone(), server);
}
servers
}
}