Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

12 changed files with 422 additions and 2689 deletions

436
Cargo.lock generated
View File

@ -2,113 +2,11 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bindgen"
version = "0.65.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.22",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
dependencies = [
"generic-array",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "cpufeatures"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "darling"
version = "0.13.1"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12"
dependencies = [
"darling_core",
"darling_macro",
@ -116,73 +14,35 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.13.1"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
checksum = "2c34d8efb62d0c2d7f60ece80f75e5c63c1588ba68032740494b0b9a996466e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.85",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.13.1"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc"
dependencies = [
"darling_core",
"quote",
"syn 1.0.85",
"syn",
]
[[package]]
name = "digest"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "generic-array"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hex-literal"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
[[package]]
name = "ident_case"
version = "1.0.1"
@ -191,220 +51,92 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "itoa"
version = "1.0.1"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "libc"
version = "0.2.147"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "libcwtch"
version = "0.8.0"
version = "0.1.0"
dependencies = [
"bindgen",
"chrono",
"hex-literal",
"libc",
"serde",
"serde_json",
"serde_repr",
"serde_with",
"sha2",
]
[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "log"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "prettyplease"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282"
dependencies = [
"proc-macro2",
"syn 2.0.22",
]
[[package]]
name = "proc-macro2"
version = "1.0.63"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [
"unicode-ident",
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.28"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustversion"
version = "1.0.6"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
[[package]]
name = "ryu"
version = "1.0.9"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.133"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.133"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.85",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.75"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.85",
]
[[package]]
name = "serde_with"
version = "1.11.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3"
checksum = "062b87e45d8f26714eacfaef0ed9a583e2bfd50ebd96bdd3c200733bd5758e2c"
dependencies = [
"rustversion",
"serde",
@ -413,33 +145,16 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "1.5.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
checksum = "98c1fcca18d55d1763e1c16873c4bde0ac3ef75179a28c7b372917e0494625be"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 1.0.85",
"syn",
]
[[package]]
name = "sha2"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "strsim"
version = "0.10.0"
@ -448,96 +163,17 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.85"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "syn"
version = "2.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicode-ident"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "which"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
dependencies = [
"either",
"libc",
"once_cell",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -1,23 +1,16 @@
[package]
name = "libcwtch"
version = "0.8.0"
version = "0.1.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/"
[build-dependencies]
hex-literal = "0.3.4"
sha2 = "0.10.1"
bindgen = "0.65.1"
documentation = "https://docs.rs/libcwtch/0.1.0/libcwtch/"
[dependencies]
libc = "0.2"
serde_json = "1.0"
serde = { version = "1.0.127", features = ["derive"] }
serde_with = { version = "1.10.0" }
serde_repr = "0.1"
chrono = "0.4.19"

View File

@ -1,6 +1,6 @@
# libCwtch-rs
Rust bindings for [libCwtch autobindings](https://git.openprivacy.ca/cwtch.im/autobindings/)
Rust bindings for [libCwtch](https://git.openprivacy.ca/cwtch.im/libcwtch-go/)
Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes tor is on $PATH)
@ -8,12 +8,16 @@ Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes
### 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). `cargo build` automatically calls
`bindgen` for us and will regenerate `src/cwtchlib_go/bindings.rs` if libCwtch.h has changed.
but that we don't want to create rust bindings for (like importing stdlib.h). Then:
While developing you can use the `LCG_DIR` environment variable to specify the directory containing a local `libCwtch.so`
library to override the default one.
```
bindgen libCwtch.h -o src/cwtchlib_go/bindings.rs
```
This is useful in cases where you are adding or updating APIs prior to a release.
### Todo

View File

@ -1,63 +1,16 @@
use std::{env, io};
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use hex_literal::hex;
use sha2::{Digest, Sha512};
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");
// Do not fetch lib on docs.rs as it cannot, build will fail, docs won't build
// https://docs.rs/about/builds
if std::env::var("DOCS_RS").is_err() {
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");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=libCwtch.h");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("libCwtch.h")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from("src/cwtchlib_go");
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
if std::env::var("LCG_DIR").is_err() {
Command::new("wget")
.arg("https://git.openprivacy.ca/cwtch.im/autobindings/releases/download/v0.0.12/libCwtch.x64.so")
.arg("-O")
.arg(lib_cwtch_path.clone())
.output()
.expect("failed to download libCwtch.x64.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!("a3742e0cdedc00eb3673063b100b7596b05bdc9bb68a0fba6fd2423c9a41f1653597c4d44ba3877be08cbb5bba2806435830061ab3517cdd4472a18c7557d9c7")[..]);
} 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");
}
}
}
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");
}

View File

@ -1,52 +1,54 @@
use std::thread;
use std::{thread};
use libcwtch;
use libcwtch::structs::*;
use libcwtch::CwtchLib;
use libcwtch::event::Event;
use libcwtch::structs::{*};
fn main() {
let bot_home = "example_cwtch_dir";
let bot_home: String = "example_cwtch_dir".to_string();
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
Err(_e) => (),
_ => (),
}
std::fs::create_dir_all(&bot_home).expect("Error creating bot_home directory");
std::fs::create_dir_all(&bot_home).unwrap();
let cwtch = libcwtch::new_cwtchlib_go();
println!("start_cwtch");
let ret = cwtch.start_cwtch(bot_home, "");
let ret = cwtch.start_cwtch(bot_home.as_str(), "");
println!("start_cwtch returned {}", ret);
let event_loop_handle = thread::spawn(move || {
loop {
let event = cwtch.get_appbus_event();
println!("event: {:?}", event);
let event_str = cwtch.get_appbus_event();
println!("event: {}", event_str);
match event {
Event::CwtchStarted => {
let event: CwtchEvent = serde_json::from_str(&event_str).unwrap();
match event.event_type.as_str() {
"CwtchStarted" => {
println!("event CwtchStarted!");
println!("Creating bot");
cwtch.create_profile("Echobot", "be gay do crime", true);
}
Event::NewPeer { profile_id, tag, created, name, default_picture, picture, online, profile_data } => {
println!(
"\n***** {} at {} *****\n",
name, profile_id.as_str()
);
cwtch.create_profile("Echobot", "be gay do crime");
},
"NewPeer" => {
println!("\n***** {} at {} *****\n", event.data["name"], event.data["Identity"]);
// process json for profile, contacts and servers...else {
let profile = profile_data;
let profile = Profile::new(&event.data["Identity"], &event.data["name"], &event.data["picture"], &event.data["ContactsJson"], &event.data["ServerList"]);
print!("profile: {:?}", profile);
}
Event::NewMessageFromPeer { profile_id, conversation_id, contact_id: contact, nick, timestamp_received, message, notification, picture } => {
let response = MessageWrapper { o: message.o.into(), d: message.d };
cwtch.send_message( &profile_id, conversation_id, &response);
"NewMessageFromPeer" => {
let to = event.data["ProfileOnion"].to_string();
let conversation = event.data["RemotePeer"].to_string();
let message: Message = serde_json::from_str(event.data["Data"].as_str()).unwrap();
let response = Message{o:1, d:message.d};
let response_json = serde_json::to_string(&response).unwrap();
cwtch.send_message(to.as_str(), conversation.as_str(), response_json.as_str());
}
_ => eprintln!("unhandled event!"),
_ => println!("unhandled event!"),
};
}
};
});
event_loop_handle.join().expect("Error running event loop");
event_loop_handle.join().unwrap();
}

View File

@ -1,11 +1,11 @@
/* Code generated by cmd/cgo; DO NOT EDIT. */
/* package git.openprivacy.ca/cwtch.im/cwtch-autobindings */
/* package git.openprivacy.ca/cwtch.im/libcwtch-go */
#line 1 "cgo-builtin-export-prolog"
#include <stddef.h>
#include <stddef.h> /* for ptrdiff_t below */
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
@ -32,17 +32,11 @@ typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef size_t GoUintptr;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
#ifdef _MSC_VER
#include <complex.h>
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
@ -66,73 +60,44 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
extern "C" {
#endif
// Dangerous function. Should only be used as documented in `MEMORY.md`
//
extern void c_FreePointer(char* ptr);
extern int c_Started();
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_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_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_UpdateSettings(char* json_ptr, int json_len);
extern char* c_GetDebugInfo();
extern void c_ActivatePeerEngine(char* onion_ptr, int onion_len);
extern void c_DeactivatePeerEngine(char* onion_ptr, int onion_len);
extern void c_ConfigureConnections(char* onion_ptr, int onion_len, char listen1, char peers2, char servers3);
extern void c_CreateProfile(char* name_ptr, int name_len, char* password_ptr, int password_len, char autostart4);
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* file5_ptr, int file5_len, char* password_ptr, int password_len);
extern void c_ChangePassword(char* onion_ptr, int onion_len, char* current6_ptr, int current6_len, char* newPassword7_ptr, int newPassword7_len, char* newPasswordAgain8_ptr, int newPasswordAgain8_len);
extern void c_ExportProfile(char* onion_ptr, int onion_len, char* file9_ptr, int file9_len);
extern char* c_ImportBundle(char* onion_ptr, int onion_len, char* bundle10_ptr, int bundle10_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 void c_PeerWithOnion(char* onion_ptr, int onion_len, char* handle11_ptr, int handle11_len);
extern void c_DisconnectFromPeer(char* onion_ptr, int onion_len, char* handle12_ptr, int handle12_len);
extern char* c_GetConversationAccessControlList(char* onion_ptr, int onion_len, int conversation);
extern void c_UpdateConversationAccessControlList(char* onion_ptr, int onion_len, int conversation, char* json13_ptr, int json13_len);
extern char* c_SearchConversations(char* onion_ptr, int onion_len, char* pattern14_ptr, int pattern14_len);
extern char* c_SendMessage(char* onion_ptr, int onion_len, int conversation, char* msg15_ptr, int msg15_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* contentHash16_ptr, int contentHash16_len);
extern char* c_GetMessages(char* onion_ptr, int onion_len, int conversation, int index, unsigned 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* attributeKey17_ptr, int attributeKey17_len, char* attributeValue18_ptr, int attributeValue18_len);
extern void c_StartGroup(char* onion_ptr, int onion_len, char* name19_ptr, int name19_len, char* server20_ptr, int server20_len);
extern void c_QueueJoinServer(char* onion_ptr, int onion_len, char* handle21_ptr, int handle21_len);
extern void c_DisconnectFromServer(char* onion_ptr, int onion_len, char* handle22_ptr, int handle22_len);
extern void c_PublishServerUpdate(char* onion_ptr, int onion_len);
extern void c_GetServerInfoList(char* onion_ptr, int onion_len);
extern void c_DeleteServerInfo(char* onion_ptr, int onion_len, char* serverOnion23_ptr, int serverOnion23_len);
extern void c_DownloadFileDefaultLimit(char* onion_ptr, int onion_len, int conversation, char* filepath24_ptr, int filepath24_len, char* manifest25_ptr, int manifest25_len, char* filekey26_ptr, int filekey26_len);
extern void c_RestartFileShare(char* onion_ptr, int onion_len, char* filekey27_ptr, int filekey27_len);
extern void c_StopFileShare(char* onion_ptr, int onion_len, char* filekey28_ptr, int filekey28_len);
extern void c_CheckDownloadStatus(char* onion_ptr, int onion_len, char* filekey29_ptr, int filekey29_len);
extern void c_VerifyOrResumeDownloadDefaultLimit(char* onion_ptr, int onion_len, int conversation, char* filekey30_ptr, int filekey30_len);
extern char* c_ShareFile(char* onion_ptr, int onion_len, int conversation, char* filepath31_ptr, int filepath31_len);
extern char* c_GetSharedFiles(char* onion_ptr, int onion_len, int conversation);
extern void c_CreateServer(char* password_ptr, int password_len, char* description32_ptr, int description32_len, char autostart33);
extern void c_SetServerAttribute(char* handle34_ptr, int handle34_len, char* key35_ptr, int key35_len, char* val36_ptr, int val36_len);
extern void c_LoadServers(char* password_ptr, int password_len);
extern void c_LaunchServers();
extern void c_LaunchServer(char* handle37_ptr, int handle37_len);
extern void c_StopServer(char* handle38_ptr, int handle38_len);
extern void c_StopServers();
extern void c_DestroyServers();
extern void c_DeleteServer(char* handle39_ptr, int handle39_len, char* password_ptr, int password_len);
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
}

View File

@ -3,70 +3,51 @@
#![allow(non_snake_case)]
#![allow(dead_code)]
use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::{CString};
use std::ffi::{CStr};
use super::CwtchLib;
use super::{CwtchLib};
use crate::cwtchlib_go::bindings;
use crate::{ConversationID, CwtchError, FileKey, ProfileIdentity, ServerIdentity, structs::*};
use crate::event::Event;
type c_bool = core::ffi::c_char;
fn from_c_bool(b: c_bool) -> bool {
b == 1
}
fn to_c_bool(b: bool) -> c_bool {
if b { 1 } else { 0 }
}
struct c_str_wrap {
raw: *mut core::ffi::c_char,
len: i32,
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(),
Err(_) => CString::new("").unwrap()
};
c_str_wrap {
len: cs.as_bytes().len() as i32,
raw: cs.into_raw(),
}
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 {
drop(CString::from_raw(self.raw));
}
unsafe { CString::from_raw(self.raw); }
}
}
// c_bind handles setting up c string arguments and freeing them
// c_bind!( $fn_name ( [ $string_args: &str],* [ $non_string_args : $type ],* ) $c_function -> $return_type? )
// c_bind!( $fn_name ( [ $string_args ]* ; [ $non_string_args : $type ]* ) $c_function -> $return_type? )
macro_rules! c_bind {
// 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);)*
// 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 {
bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
}
}
};
// 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);)*
// 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 = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
let result_ptr = bindings::$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()
@ -77,13 +58,12 @@ macro_rules! c_bind {
}
}
};
// 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);)*
// 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 = bindings::$bind_fn($( $str1.raw, $str1.len, )* $($args,)* $( $str2.raw, $str2.len, )*);
let result = bindings::$bind_fn($( $str.raw, $str.len, )* $($arg,)* );
result
}
}
@ -92,278 +72,37 @@ macro_rules! c_bind {
pub struct CwtchLibGo {}
// Some bindings are going to be wrapped so we can handle their returns and give most rust idiomatic returns (esp for json returning apis)
// so we pre define the real binding here as a _helper function and in the impl for CwtchLib define the wrapper
impl CwtchLibGo {
c_bind!(_peer_with(profile: &str, new_peer: &str;;) c_PeerWithOnion);
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!(_configure_connections(profile: &str; listen: c_bool, peers: c_bool, servers: c_bool;) c_ConfigureConnections);
c_bind!(_create_profile(nick: &str, pass: &str; autostart: c_bool;) 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!(_disconnect_from_peer(profile: &str, peer_address: &str;;) c_DisconnectFromPeer);
c_bind!(_search_conversations(profile: &str, pattern: &str;;) c_SearchConversations -> String);
c_bind!(_get_conversation_access_control_list(profile: &str; conversation_id: i32;) c_GetConversationAccessControlList -> String);
c_bind!(_update_conversation_access_control_list(profile: &str; conversation_id: i32; acl: &str) c_UpdateConversationAccessControlList);
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: u32 ;) c_GetMessages -> String);
c_bind!(_send_message(profile: &str; conversation_id: i32; msg: &str) c_SendMessage -> 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!(_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_VerifyOrResumeDownloadDefaultLimit);
c_bind!(_start_group(profile: &str, name: &str, server: &str;;) c_StartGroup);
c_bind!(_queue_join_server(profile: &str, server: &str;;) c_QueueJoinServer);
c_bind!(_disconnect_from_server(profile: &str, server: &str;;) c_DisconnectFromServer);
c_bind!(_publish_server_update(profile: &str;;) c_PublishServerUpdate);
c_bind!(_get_server_info_list(profile: &str;;) c_GetServerInfoList);
c_bind!(_delete_server_info(profile: &str, server: &str;;) c_DeleteServerInfo);
c_bind!(_delete_profile(profile: &str, pass: &str;;) c_DeleteProfile);
c_bind!(_archive_conversation(profile: &str; conversation_id: i32;) c_ArchiveConversation);
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!(_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!(_create_server(password: &str, description: &str; autostart: c_bool;) c_CreateServer);
c_bind!(_delete_server(server: &str, current_password: &str;;) c_DeleteServer);
c_bind!(_launch_server(server: &str;;) c_LaunchServer);
c_bind!(_stop_server(server: &str;;) c_StopServer);
c_bind!(_set_server_attribute(server: &str, key: &str, val: &str;;) c_SetServerAttribute);
c_bind!(send_profile_event(profile, event_json;) c_SendProfileEvent);
}
impl CwtchLib for CwtchLibGo {
c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> i32);
c_bind!(started(;;) c_Started -> i32);
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!(reconnect_cwtch_foreground(;;) c_ReconnectCwtchForeground);
fn create_profile(&self, nick: &str, pass: &str, autostart: bool) {
self._create_profile(nick, pass, to_c_bool(autostart))
}
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())
}
fn configure_connections(&self, profile: &ProfileIdentity, listen: bool, peers: bool, servers: bool) {
self._configure_connections(profile.as_str(), to_c_bool(listen), to_c_bool(peers), to_c_bool(servers))
}
fn search_conversations(&self, profile: &ProfileIdentity, pattern: &str) -> String {
self._search_conversations(profile.as_str(), pattern)
}
fn get_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID) -> Result<ACL, CwtchError> {
let json = self._get_conversation_access_control_list(profile.as_str(), conversation_id.into());
match serde_json::from_str(&json) {
Ok(acl) => Ok(acl),
Err(e) => Err(e.to_string()),
}
}
fn update_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID, acl: ACL) {
match serde_json::to_string(&acl) {
Ok(acl_json) => self._update_conversation_access_control_list(profile.as_str(), conversation_id.into(), &acl_json),
Err(_) => return,
};
}
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 peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str) {
self._peer_with(profile.as_str(), new_peer_address)
}
fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
self._block_conversation(String::from(profile).as_str(), conversation_id.into())
}
fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
self._unblock_conversation(String::from(profile).as_str(), conversation_id.into())
}
fn disconnect_from_peer(&self, profile: &ProfileIdentity, peer_id: &str) {
self._disconnect_from_peer(profile.as_str(), peer_id)
}
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)
}
fn get_message_by_content_hash(&self, profile: &ProfileIdentity, conversation_id: ConversationID, hash: &str) -> String {
self._get_message_by_content_hash(String::from(profile).as_str(), conversation_id.into(), hash)
}
fn get_messages(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32, count: u32) -> String {
self._get_messages(String::from(profile).as_str(), conversation_id.into(), message_index, count)
}
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: &MessageWrapper) -> Result<String, CwtchError> {
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_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 get_shared_files(&self, profile: &ProfileIdentity, conversaion_id: ConversationID) -> Vec<SharedFile> {
let json = self._get_shared_files(profile.as_str(), conversaion_id.into());
match serde_json::from_str(&json) {
Ok(l) => l,
Err(_) => vec!(),
}
}
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) {
self._verify_or_resume_download(String::from(profile).as_str(), conversation_id.into(), String::from(file_key).as_str())
}
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 {
bindings::c_ResetTor();
}
unsafe { bindings::c_ResetTor(); }
}
fn start_group(&self, profile: &ProfileIdentity, server: &str, name: &str) {
self._start_group(String::from(profile).as_str(), server, name)
}
fn queue_join_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
self._queue_join_server(profile.as_str(), server.as_str())
}
fn disconnect_from_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
self._disconnect_from_server(profile.as_str(), server.as_str())
}
fn publish_server_update(&self, profile: &ProfileIdentity) {
self._publish_server_update(profile.as_str())
}
fn get_server_info_list(&self, profile: &ProfileIdentity) {
self._get_server_info_list(profile.as_str())
}
fn delete_server_info(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
self._delete_server_info(profile.as_str(), server.as_str())
}
fn delete_profile(&self, profile: &ProfileIdentity, pass: &str) {
self._delete_profile(String::from(profile).as_str(), pass)
}
fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
self._archive_conversation(String::from(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)
}
fn set_profile_attribute(&self, profile: &ProfileIdentity, key: &str, val: &str) {
self._set_profile_attribute(String::from(profile).as_str(), key, val)
}
fn get_profile_attribute(&self, profile: &ProfileIdentity, key: &str) -> Result<Option<String>, CwtchError> {
let resp = self._get_profile_attribute(String::from(profile).as_str(), key);
let attr: Attribute = match serde_json::from_str(&resp) {
Ok(attr) => attr,
Err(e) => return Err(e.to_string()),
};
match attr.exists {
true => Ok(Some(attr.value)),
false => Ok(None),
}
}
fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str) {
self._set_conversation_attribute(String::from(profile).as_str(), conversation_id.into(), key, val)
}
fn get_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str) -> Result<Option<String>, CwtchError> {
let resp = self._get_conversation_attribute(String::from(profile).as_str(), conversation_id.into(), key);
let attr: Attribute = match serde_json::from_str(&resp) {
Ok(attr) => attr,
Err(e) => return Err(e.to_string()),
};
match attr.exists {
true => Ok(Some(attr.value)),
false => Ok(None),
}
}
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)
}
fn export_profile(&self, profile: &ProfileIdentity, filename: &str) {
self._export_profile(String::from(profile).as_str(), filename)
}
c_bind!(import_profile(filename: &str, password: &str;;) c_ImportProfile -> String);
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 {
bindings::c_ShutdownCwtch();
}
unsafe { bindings::c_ShutdownCwtch(); }
}
c_bind!(load_servers(password: &str;;) c_LoadServers);
fn create_server(&self, password: &str, description: &str , autostart: bool) {
self._create_server(password, description, to_c_bool(autostart))
}
fn delete_server(&self, server: ServerIdentity, current_password: &str) {
self._delete_server(String::from(server).as_str(), current_password)
}
c_bind!(launch_servers(;;) c_LaunchServers);
fn launch_server(&self, server: ServerIdentity) {
self._launch_server(String::from(server).as_str())
}
fn stop_server(&self, server: ServerIdentity) {
self._stop_server(String::from(server).as_str())
}
c_bind!(stop_servers(;;) c_StopServers);
c_bind!(destroy_servers(;;) c_DestroyServers);
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);
fn get_appbus_event(&self) -> Event {
let event_json = self._get_appbus_event();
let cwtch_event: CwtchEvent = serde_json::from_str(&event_json).expect("Error parsing Cwtch event");
Event::from(&cwtch_event)
}
}
}

View File

@ -1,4 +1,4 @@
/* automatically generated by rust-bindgen 0.65.1 */
/* automatically generated by rust-bindgen 0.58.1 */
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)]
@ -6,6 +6,7 @@ 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))]
@ -17,8 +18,6 @@ pub struct max_align_t {
}
#[test]
fn bindgen_test_layout_max_align_t() {
const UNINIT: ::std::mem::MaybeUninit<max_align_t> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<max_align_t>(),
32usize,
@ -30,7 +29,9 @@ fn bindgen_test_layout_max_align_t() {
concat!("Alignment of ", stringify!(max_align_t))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce1) as usize - ptr as usize },
unsafe {
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce1 as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
@ -40,7 +41,9 @@ fn bindgen_test_layout_max_align_t() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce2) as usize - ptr as usize },
unsafe {
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce2 as *const _ as usize
},
16usize,
concat!(
"Offset of field: ",
@ -58,8 +61,6 @@ pub struct _GoString_ {
}
#[test]
fn bindgen_test_layout__GoString_() {
const UNINIT: ::std::mem::MaybeUninit<_GoString_> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<_GoString_>(),
16usize,
@ -71,7 +72,7 @@ fn bindgen_test_layout__GoString_() {
concat!("Alignment of ", stringify!(_GoString_))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<_GoString_>())).p as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
@ -81,7 +82,7 @@ fn bindgen_test_layout__GoString_() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).n) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<_GoString_>())).n as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
@ -101,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 = usize;
pub type GoUintptr = ::std::os::raw::c_ulong;
pub type GoFloat32 = f32;
pub type GoFloat64 = f64;
pub type GoComplex64 = __BindgenComplex<f32>;
@ -118,8 +119,6 @@ pub struct GoInterface {
}
#[test]
fn bindgen_test_layout_GoInterface() {
const UNINIT: ::std::mem::MaybeUninit<GoInterface> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<GoInterface>(),
16usize,
@ -131,7 +130,7 @@ fn bindgen_test_layout_GoInterface() {
concat!("Alignment of ", stringify!(GoInterface))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).t) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<GoInterface>())).t as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
@ -141,7 +140,7 @@ fn bindgen_test_layout_GoInterface() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<GoInterface>())).v as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
@ -160,8 +159,6 @@ pub struct GoSlice {
}
#[test]
fn bindgen_test_layout_GoSlice() {
const UNINIT: ::std::mem::MaybeUninit<GoSlice> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::std::mem::size_of::<GoSlice>(),
24usize,
@ -173,7 +170,7 @@ fn bindgen_test_layout_GoSlice() {
concat!("Alignment of ", stringify!(GoSlice))
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<GoSlice>())).data as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
@ -183,7 +180,7 @@ fn bindgen_test_layout_GoSlice() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<GoSlice>())).len as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
@ -193,7 +190,7 @@ fn bindgen_test_layout_GoSlice() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).cap) as usize - ptr as usize },
unsafe { &(*(::std::ptr::null::<GoSlice>())).cap as *const _ as usize },
16usize,
concat!(
"Offset of field: ",
@ -203,12 +200,6 @@ 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,
@ -217,14 +208,157 @@ extern "C" {
torLen: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_ReconnectCwtchForeground();
}
extern "C" {
pub fn c_ShutdownCwtch();
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(
@ -237,18 +371,11 @@ extern "C" {
);
}
extern "C" {
pub fn c_GetProfileAttribute(
pub fn c_SetContactAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
key_ptr: *mut ::std::os::raw::c_char,
key_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_SetConversationAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::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,
@ -256,393 +383,17 @@ extern "C" {
);
}
extern "C" {
pub fn c_GetConversationAttribute(
pub fn c_SetGroupAttribute(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::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,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
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_GetDebugInfo() -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_ActivatePeerEngine(
onion_ptr: *mut ::std::os::raw::c_char,
onion_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_DeactivatePeerEngine(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ConfigureConnections(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
listen1: ::std::os::raw::c_char,
peers2: ::std::os::raw::c_char,
servers3: ::std::os::raw::c_char,
);
}
extern "C" {
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,
autostart4: ::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(
file5_ptr: *mut ::std::os::raw::c_char,
file5_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_ChangePassword(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
current6_ptr: *mut ::std::os::raw::c_char,
current6_len: ::std::os::raw::c_int,
newPassword7_ptr: *mut ::std::os::raw::c_char,
newPassword7_len: ::std::os::raw::c_int,
newPasswordAgain8_ptr: *mut ::std::os::raw::c_char,
newPasswordAgain8_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ExportProfile(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
file9_ptr: *mut ::std::os::raw::c_char,
file9_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,
bundle10_ptr: *mut ::std::os::raw::c_char,
bundle10_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_PeerWithOnion(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
handle11_ptr: *mut ::std::os::raw::c_char,
handle11_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DisconnectFromPeer(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
handle12_ptr: *mut ::std::os::raw::c_char,
handle12_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_GetConversationAccessControlList(
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_UpdateConversationAccessControlList(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
conversation: ::std::os::raw::c_int,
json13_ptr: *mut ::std::os::raw::c_char,
json13_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_SearchConversations(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
pattern14_ptr: *mut ::std::os::raw::c_char,
pattern14_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
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,
msg15_ptr: *mut ::std::os::raw::c_char,
msg15_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,
contentHash16_ptr: *mut ::std::os::raw::c_char,
contentHash16_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_uint,
) -> *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,
attributeKey17_ptr: *mut ::std::os::raw::c_char,
attributeKey17_len: ::std::os::raw::c_int,
attributeValue18_ptr: *mut ::std::os::raw::c_char,
attributeValue18_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,
name19_ptr: *mut ::std::os::raw::c_char,
name19_len: ::std::os::raw::c_int,
server20_ptr: *mut ::std::os::raw::c_char,
server20_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_QueueJoinServer(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
handle21_ptr: *mut ::std::os::raw::c_char,
handle21_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DisconnectFromServer(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
handle22_ptr: *mut ::std::os::raw::c_char,
handle22_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_PublishServerUpdate(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_GetServerInfoList(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DeleteServerInfo(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
serverOnion23_ptr: *mut ::std::os::raw::c_char,
serverOnion23_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,
filepath24_ptr: *mut ::std::os::raw::c_char,
filepath24_len: ::std::os::raw::c_int,
manifest25_ptr: *mut ::std::os::raw::c_char,
manifest25_len: ::std::os::raw::c_int,
filekey26_ptr: *mut ::std::os::raw::c_char,
filekey26_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,
filekey27_ptr: *mut ::std::os::raw::c_char,
filekey27_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,
filekey28_ptr: *mut ::std::os::raw::c_char,
filekey28_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,
filekey29_ptr: *mut ::std::os::raw::c_char,
filekey29_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_VerifyOrResumeDownloadDefaultLimit(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
conversation: ::std::os::raw::c_int,
filekey30_ptr: *mut ::std::os::raw::c_char,
filekey30_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,
filepath31_ptr: *mut ::std::os::raw::c_char,
filepath31_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(
password_ptr: *mut ::std::os::raw::c_char,
password_len: ::std::os::raw::c_int,
description32_ptr: *mut ::std::os::raw::c_char,
description32_len: ::std::os::raw::c_int,
autostart33: ::std::os::raw::c_char,
);
}
extern "C" {
pub fn c_SetServerAttribute(
handle34_ptr: *mut ::std::os::raw::c_char,
handle34_len: ::std::os::raw::c_int,
key35_ptr: *mut ::std::os::raw::c_char,
key35_len: ::std::os::raw::c_int,
val36_ptr: *mut ::std::os::raw::c_char,
val36_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(
handle37_ptr: *mut ::std::os::raw::c_char,
handle37_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_StopServer(
handle38_ptr: *mut ::std::os::raw::c_char,
handle38_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_StopServers();
}
extern "C" {
pub fn c_DestroyServers();
}
extern "C" {
pub fn c_DeleteServer(
handle39_ptr: *mut ::std::os::raw::c_char,
handle39_len: ::std::os::raw::c_int,
password_ptr: *mut ::std::os::raw::c_char,
password_len: ::std::os::raw::c_int,
);
pub fn c_ShutdownCwtch();
}

View File

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

View File

@ -1,845 +0,0 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, FixedOffset};
use chrono::prelude::*;
use std::convert::From;
use crate::structs::{ACL, ConnectionState, CwtchEvent, MessageWrapper, Profile, Settings};
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Profile ID used to refer to profiles in Cwtch
pub struct ProfileIdentity(String);
impl From<String> for ProfileIdentity {
fn from(x: String) -> Self {
ProfileIdentity(x)
}
}
impl From<ProfileIdentity> for String {
fn from(x: ProfileIdentity) -> Self {
x.into()
}
}
impl From<&str> for ProfileIdentity {
fn from(x: &str) -> Self {
ProfileIdentity(x.to_string())
}
}
impl From<&ProfileIdentity> for String {
fn from(x: &ProfileIdentity) -> Self {
x.0.clone()
}
}
impl ProfileIdentity {
/// Get &str of ProfileIdentity String
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Contact ID used to refer to contacts in Cwtch
pub struct ContactIdentity(String);
impl From<String> for ContactIdentity {
fn from(x: String) -> Self {
ContactIdentity(x)
}
}
impl ContactIdentity {
/// Get &str of ContactIdentity String
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Conversation ID user to refer to a conversation with a Contact or Group in Cwtch
pub struct ConversationID(pub i32) ;
impl From<i32> for ConversationID {
fn from(x: i32) -> Self {
ConversationID(x)
}
}
impl From<ConversationID> for i32 {
fn from(x: ConversationID) -> Self {
x.0
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Group ID used to refer to a Group in Cwtch
pub struct GroupID(String) ;
impl From<String> for GroupID {
fn from(x: String) -> Self {
GroupID(x)
}
}
impl GroupID {
/// Get &str of GroupID String
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Server ID user to refer to a server in Cwtch
pub struct ServerIdentity(String);
impl From<String> for ServerIdentity {
fn from(x: String) -> Self {
ServerIdentity(x)
}
}
impl From<&str> for ServerIdentity {
fn from(x: &str) -> Self {
ServerIdentity(x.to_string())
}
}
impl From<ServerIdentity> for String {
fn from(x: ServerIdentity) -> Self {
x.into()
}
}
impl ServerIdentity {
/// Get &str of ServerIdentity String
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// FileKey ID user to refer to a file share in Cwtch
pub struct FileKey(String);
impl From<String> for FileKey {
fn from(x: String) -> Self {
FileKey(x)
}
}
impl From<FileKey> for String {
fn from(x: FileKey) -> Self {
x.into()
}
}
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 {
/// means no notification
None,
/// means emit a notification that a message event happened only
SimpleEvent,
/// means emit a notification event with Conversation handle included
ContactInfo,
}
impl From<String> for MessageNotification {
fn from(str: String) -> MessageNotification {
match str.as_str() {
"None" => MessageNotification::None,
"SimpleEvent" => MessageNotification::SimpleEvent,
"ContactInfo" => MessageNotification::ContactInfo,
_ => MessageNotification::None,
}
}
}
#[derive(Debug, Clone)]
/// Enum for results from NetworkCheck plugin on profiles
pub enum NetworkCheckStatus {
/// There was an error, this profile cannot connect to itself
Error,
/// Success connecting to self, profile is "online"
Success
}
impl From<String> for NetworkCheckStatus {
fn from(str: String) -> NetworkCheckStatus {
match str.as_str() {
"Error" => NetworkCheckStatus::Error,
"Success" => NetworkCheckStatus::Success,
_ => NetworkCheckStatus::Error,
}
}
}
#[derive(Debug, Clone)]
/// Enum denoting server storage mode
pub enum ServerStorageType {
/// indicates some app supplied default password is being used on this server for storage encryption
DefaultPassword,
/// indicates a user supplied password is being used on this server for storage encryption
Password,
/// indicates no password and no encryption is being used on server storage
NoPassword
}
impl From<String> for ServerStorageType {
fn from(str: String) -> ServerStorageType {
match str.as_str() {
"storage-default-password" => ServerStorageType::DefaultPassword,
"storage-password" => ServerStorageType::Password,
"storage-no-password" => ServerStorageType::NoPassword,
_ => ServerStorageType::DefaultPassword,
}
}
}
#[derive(Debug, Clone)]
/// Enum used by servers to declare their intent to be running or stopped
pub enum ServerIntent {
/// a server intends to be running
Running,
/// a server intends to be stopped
Stopped
}
impl From<String> for ServerIntent {
fn from(str: String) -> ServerIntent {
match str.as_str() {
"running" => ServerIntent::Running,
"stopped" => ServerIntent::Stopped,
_ => ServerIntent::Stopped,
}
}
}
#[derive(Debug, Clone)]
/// Enum for events from Cwtch appbus
pub enum Event {
// App events
/// Emited by libcwtch once Cwtch.Start() has been completed successfully, you can start making API calls, lcg is initialized
CwtchStarted,
/// A new peer has been loaded, details of peer. Identity should be stored so further API calls can be made
NewPeer {
/// identity field
profile_id: ProfileIdentity,
/// optional client specified tag
tag: String,
/// is this a newly created profile event, or a load
created: bool,
/// user supplied name of the profile
name: String,
/// default picture path
default_picture: String,
/// user supplied picture path
picture: String,
/// is the profile online
online: String,
/// The deserialized profile with contacts and server info
profile_data: Result<Profile, String>,
},
/// Cwtch had an error at the app level (not profile level), usually in response to an API call
AppError {
/// details of the app error that occured
error: String,
/// possible data about the error
data: String
},
/// Global settings being emited from lcg, usually in response to them being sent to be saved by client
UpdateGlobalSettings {
/// map of setting names to values (https://git.openprivacy.ca/cwtch.im/libcwtch-go/src/branch/trunk/utils/settings.go)
settings: Settings,
},
/// A profile has an error, usually emited in response to an API call
PeerError {
/// details of the peer error that occured
error: String
},
/// A profile was successfully deleted, it is no longer usable
PeerDeleted {
/// identity of deleted peer
profile_id: ProfileIdentity
},
/// Cwtch is shutting down, stop making API calls
Shutdown,
/// indicates status of the ACN (tor), usually during boot.
ACNStatus {
/// the percent of ACN boot (-1 to 100)
progress: i8,
/// an associated status message from the ACN
status: String,
},
/// Version of the ACN (currently tor)
ACNVersion {
/// version string from ACN app
version: String,
},
/// Notice from libCwtch that before completing load of a profile a storage migration is occuring so Start will take longer
StartingStorageMiragtion,
/// Notice from libCwtch that the storage migration is complete, profile being loaded resuming
DoneStorageMigration,
// app server events
/// A new server has been loaded
NewServer {
/// identity of server
server: ServerIdentity,
/// sharable / importable server bundle
server_bundle: String,
/// user supplied description
description: String,
/// storage mode the server is using
storage_type: ServerStorageType,
/// does/should the server auto start on cwtch start
autostart: bool,
/// is the server running
running: bool,
},
/// Response to request for server intent change, indicating the server is indending the new state
ServerIntentUpdate {
/// identity of server
server: ServerIdentity,
/// intent of the server to be running or not
intent: ServerIntent,
},
/// Notice a server was deleted (in response to an API call) and is no longer usable
ServerDeleted {
/// identity of server
server: ServerIdentity,
/// was deletion a success
success: bool,
/// optional error string in case of failure to delete
error: Option<String>,
},
/// Stats info for a server, periodically emited
ServerStatsUpdate {
/// identity of server
server: ServerIdentity,
/// count of total messages on the server
total_messages: i32,
/// count of total current connections to the server
connections: i32,
},
// profile events
/// A new message was received
NewMessageFromPeer {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// contact id
contact_id: ContactIdentity,
/// name of contact
nick: String,
/// time message was received
timestamp_received: DateTime<FixedOffset>,
/// the message
message: MessageWrapper,
/// notification instructions (based on settings)
notification: MessageNotification,
/// path to picture for the contact
picture: String,
},
/// A new contact has been created (imported, added, or contacted by)
ContactCreated {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// contact id
contact_id: ContactIdentity,
/// name of group
nick: String,
/// connection status to group server
status: ConnectionState,
/// number of unread messages in group
unread: i32,
/// path to picture for group
picture: String,
/// path to default picture for group
default_picture: String,
/// total number of messages in group
num_messages: i32,
/// has the user accepted the group
accepted: bool,
/// ACL for the group
access_control_list: ACL,
/// is the group blocked
blocked: bool,
/// is the group syncing
loading: bool,
/// time of last message from the group
last_msg_time: DateTime<FixedOffset>,
},
/// A peer has changed state
PeerStateChange {
/// identity field
profile_id: ProfileIdentity,
/// contact id
contact_id: ContactIdentity,
/// connection status to contact
connection_state: ConnectionState,
},
/// Notice from the network check plugin, a profile self check test by attempting to connecting to itself
NetworkStatus {
/// profile the check was performed on
profile_id: ProfileIdentity,
// it's technically a profile self check
/// error if there was one (can be empty)
error: String,
/// status of profile self connection check
status: NetworkCheckStatus,
},
/// Information from the ACN about a peer
ACNInfo {
/// identity field
profile_id: ProfileIdentity,
/// contact id
contact_id: ContactIdentity,
/// key of info
key: String,
/// data of info
data: String,
},
/// a profile attribute has been updated with a new value
UpdatedProfileAttribute {
/// identity field
profile_id: ProfileIdentity,
/// attribute key
key: String,
/// attribute new value
value: String,
},
/// emited to confirm ack of a message succeeded
IndexedAcknowledgement {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: i32,
/// index of message acked
index: i32,
},
/// emited to signal failure to ack a message
IndexedFailure {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// index of failure of message to ack
index: i32,
/// contact id
contact_id: ContactIdentity,
/// error string
error: String,
},
/// a peer has acked a message
PeerAcknowledgement {
/// identity field
profile_id: ProfileIdentity,
/// message id this is an ack to
event_id: String,
/// contact id
contact_id: ContactIdentity,
/// conversation id
conversation_id: i32,
},
/// New message received on a group
NewMessageFromGroup {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// time of message
timestamp_sent: DateTime<FixedOffset>,
/// contact id
contact_id: ContactIdentity,
/// message index
index: i32,
/// the message
message: MessageWrapper,
/// hash of the message
content_hash: String,
/// path to picture for sender
picture: String,
/// notification policy (based on settings)
notification: MessageNotification,
},
/// notice a group has been created
GroupCreated {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// group id
group_id: GroupID,
/// server the group is on
group_server: String,
/// name of group
group_name: String,
/// path to picture for group
picture: String,
/// Access Control List for group
access_control_list: ACL,
},
/// notice a new group exists
NewGroup {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
conversation_id: ConversationID,
/// server the group is on
group_server: String,
/// invite string
group_invite: String,
/// group name
group_name: String,
},
/// a server connection state has changed
ServerStateChange {
/// identity field
profile_id: ProfileIdentity,
/// server the group is on
group_server: String,
/// state of connection to server
state: ConnectionState,
},
/// A getval call to a peer has returned a response
NewRetValMessageFromPeer {
/// identity field
profile_id: ProfileIdentity,
/// conversation id
contact_id: ContactIdentity,
/// scope of the val
scope: String,
/// path of the val (zone.key)
path: String,
/// does the queried for value exist
exists: bool,
/// value
data: String,
/// optional filepath if there was a downloaded component
file_path: Option<String>,
},
/// result of a call to share a file, the filekey and manifest to operate on it
ShareManifest {
/// identity field
profile_id: ProfileIdentity,
/// filekey
filekey: FileKey,
/// serialized manifest of the share
serialized_manifest: String,
},
/// Information on a peer fileshare has been received
ManifestSizeReceived {
/// identity field
profile_id: ProfileIdentity,
/// filekey
filekey: FileKey,
/// size of manifest received for a share
manifest_size: i32,
/// contact id
contact_id: ContactIdentity,
},
/// An error has occured while trying to parse a peer sharefile
ManifestError {
/// identity field
profile_id: ProfileIdentity,
/// contact id
contact_id: ContactIdentity,
/// filekey
filekey: FileKey,
},
/// A peer message about a shared file has been received
ManifestReceived {
/// identity field
profile_id: ProfileIdentity,
/// contact id
contact_id: ContactIdentity,
/// filekey
filekey: FileKey,
/// serialized manifest
serialized_manifest: String,
},
/// a received manfiest has been saved
ManifestSaved {
/// identity field
profile_id: ProfileIdentity,
/// contact id
contact_id: ContactIdentity,
/// filekey
filekey: FileKey,
/// serialized manifest
serialized_manifest: String,
/// temporary storage path for share download
temp_file: String,
/// contact suggested share file name
name_suggestion: String,
},
/// periodically emited status updates about an active download of a shared file
FileDownloadProgressUpdate {
/// identity field
profile_id: ProfileIdentity,
/// filekey
filekey: FileKey,
/// progress of download of share in chunks
progress: i32,
/// size of share in chunks
filesize_in_chunks: i32,
/// contact suggested name for file
name_suggestion: String,
},
// FileDownloaded, ??
/// Indicates an event was sent from libCwtch that we don't handle/didn't anticipate
/// still passing it on giving the user a chance to react, but should be reported so we can handle it properly
ErrUnhandled {
/// name of unhandled event
name: String,
/// map of key:val attributes of unhandled event
data: HashMap<String, String>,
},
}
impl From<&CwtchEvent> for Event {
fn from(cwtch_event: &CwtchEvent) -> Self {
println!("EVENT: {:?}", cwtch_event);
match cwtch_event.event_type.as_str() {
"CwtchStarted" => Event::CwtchStarted,
"NewPeer" => Event::NewPeer {
profile_id: cwtch_event.data["Identity"].clone().into(),
tag: cwtch_event.data["tag"].clone(),
created: cwtch_event.data["Created"] == "true",
name: cwtch_event.data["name"].clone(),
default_picture: cwtch_event.data["defaultPicture"].clone(),
picture: cwtch_event.data["picture"].clone(),
online: cwtch_event.data["Online"].clone(),
profile_data: Profile::new(
cwtch_event.data["Identity"].clone().into(),
&cwtch_event.data["name"],
&cwtch_event.data["picture"],
&cwtch_event.data["ContactsJson"],
&cwtch_event.data["ServerList"],
)
},
"NewMessageFromPeer" => Event::NewMessageFromPeer {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
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(),
timestamp_received: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampReceived"].as_str()).unwrap_or( DateTime::from(Utc::now())),
message: MessageWrapper::from_json(&cwtch_event.data["Data"]),
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
picture: cwtch_event.data["picture"].clone(),
},
"PeerError" => Event::PeerError { error: cwtch_event.data["Error"].clone() },
"AppError" => Event::AppError {
error: match cwtch_event.data.contains_key("Error") {
true => cwtch_event.data["Error"].clone(),
false => "".to_string()
},
data: match cwtch_event.data.contains_key("Data") {
true => cwtch_event.data["Data"].clone(),
false => "".to_string()
}
},
"ContactCreated" => Event::ContactCreated {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
conversation_id: cwtch_event.data["ConversationID"].clone().parse().unwrap_or(-2).into(),
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
unread: cwtch_event.data["unread"].clone().parse().unwrap_or(0),
picture: cwtch_event.data["picture"].clone(),
default_picture: cwtch_event.data["defaultPicture"].clone(),
num_messages: cwtch_event.data["numMessages"].clone().parse().unwrap_or(0),
nick: cwtch_event.data["nick"].clone(),
accepted: cwtch_event.data["accepted"].clone().parse().unwrap_or(false),
status: ConnectionState::from(cwtch_event.data["status"].as_str()),
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
blocked: cwtch_event.data["blocked"].clone().parse().unwrap_or(false),
loading: cwtch_event.data["loading"].clone().parse().unwrap_or(false),
last_msg_time: DateTime::parse_from_rfc3339(cwtch_event.data["lastMsgTime"].as_str()).unwrap_or(DateTime::from(Utc::now())),
},
"PeerStateChange" => Event::PeerStateChange {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
connection_state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
},
"UpdateGlobalSettings" => Event::UpdateGlobalSettings {
settings: serde_json::from_str(cwtch_event.data["Data"].as_str()).expect("could not parse settings from libCwtch-go"),
},
"PeerDeleted" => Event::PeerDeleted { profile_id: cwtch_event.data["Identity"].clone().into() },
"ACNStatus" => Event::ACNStatus {
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
status: cwtch_event.data["Status"].clone(),
},
"ACNVersion" => Event::ACNVersion { version: cwtch_event.data["Data"].clone()},
"NetworkError" => Event::NetworkStatus {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
error: cwtch_event.data["Error"].clone(),
status: NetworkCheckStatus::from(cwtch_event.data["Status"].clone())
},
"ACNInfo" => Event::ACNInfo {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["Handle"].clone().into(),
key: cwtch_event.data["Key"].clone(),
data: cwtch_event.data["Data"].clone(),
},
"UpdatedProfileAttribute" => Event::UpdatedProfileAttribute {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
key: cwtch_event.data["Key"].clone(),
value: cwtch_event.data["Data"].clone(),
},
"IndexedAcknowledgement" => Event::IndexedAcknowledgement {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-1).into(),
index: cwtch_event.data["Index"].parse().unwrap_or(-1),
},
"ShareManifest" => Event::ShareManifest {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
},
"NewServer" => Event::NewServer {
server: cwtch_event.data["Onion"].clone().into(),
server_bundle: cwtch_event.data["ServerBundle"].clone(),
description: cwtch_event.data["Description"].clone(),
storage_type: ServerStorageType::from(cwtch_event.data["StorageType"].clone()),
autostart: cwtch_event.data["Autostart"].parse().unwrap_or(false),
running: cwtch_event.data["Running"].parse().unwrap_or(false),
},
"ServerIntentUpdate" => Event::ServerIntentUpdate {
server: cwtch_event.data["Identity"].clone().into(),
intent: ServerIntent::from(cwtch_event.data["Intent"].clone())
},
"ServerDeleted" => Event::ServerDeleted {
server: cwtch_event.data["Identity"].clone().into(),
success: cwtch_event.data["Status"].clone() == "success",
error: match cwtch_event.data.get("Error") {
Some(e) => Some(e.clone()),
None => None,
}
},
"ServerStatsUpdate" => Event::ServerStatsUpdate {
server: cwtch_event.data["Identity"].clone().into(),
total_messages: cwtch_event.data["TotalMessages"].parse().unwrap_or(0),
connections: cwtch_event.data["Connections"].parse().unwrap_or(0),
},
"ManifestSizeReceived" => Event::ManifestSizeReceived {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
manifest_size: cwtch_event.data["ManifestSize"].parse().unwrap_or(0),
contact_id: cwtch_event.data["Handle"].clone().into(),
},
"ManifestError" => Event::ManifestError {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["Handle"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
},
"ManifestReceived" => Event::ManifestReceived {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["Handle"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
},
"ManifestSaved" => Event::ManifestSaved {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["Handle"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
serialized_manifest: cwtch_event.data["SerializedManifest"].clone(),
temp_file: cwtch_event.data["TempFile"].clone(),
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
},
"FileDownloadProgressUpdate" => Event::FileDownloadProgressUpdate {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
filekey: cwtch_event.data["FileKey"].clone().into(),
progress: cwtch_event.data["Progress"].parse().unwrap_or(0),
filesize_in_chunks: cwtch_event.data["FileSizeInChunks"].parse().unwrap_or(0),
name_suggestion: cwtch_event.data["NameSuggestion"].clone(),
},
"PeerAcknowledgement" => Event::PeerAcknowledgement {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
event_id: cwtch_event.data["EventID"].clone(),
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
conversation_id: cwtch_event.data.get("ConversationID").unwrap_or(&"0".to_string()).parse().unwrap_or(0)
},
"NewMessageFromGroup" => Event::NewMessageFromGroup {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
timestamp_sent: DateTime::parse_from_rfc3339(cwtch_event.data["TimestampSent"].as_str()).unwrap_or( DateTime::from(Utc::now())),
index: cwtch_event.data["RemotePeer"].parse().unwrap_or(-1),
content_hash: cwtch_event.data["ContentHash"].clone(),
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
message: MessageWrapper::from_json(&cwtch_event.data["Data"]),
notification: MessageNotification::from(cwtch_event.data["notification"].clone()),
picture: cwtch_event.data["picture"].clone(),
},
"GroupCreated" => Event::GroupCreated {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
group_id: cwtch_event.data["GroupID"].clone().into(),
group_server: cwtch_event.data["GroupServer"].clone(),
group_name: cwtch_event.data["GroupName"].clone(),
picture: cwtch_event.data["picture"].clone(),
access_control_list: serde_json::from_str(cwtch_event.data["accessControlList"].as_str()).unwrap_or(ACL::new()),
},
"NewGroup" => Event::NewGroup {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
conversation_id: cwtch_event.data["ConversationID"].parse().unwrap_or(-2).into(),
group_server: cwtch_event.data["GroupServer"].clone(),
group_name: cwtch_event.data["GroupName"].clone(),
group_invite: cwtch_event.data["GroupInvite"].clone(),
},
"ServerStateChange" => Event::ServerStateChange {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
group_server: cwtch_event.data["GroupServer"].clone(),
state: ConnectionState::from(cwtch_event.data["ConnectionState"].as_str()),
},
"NewRetValMessageFromPeer" => Event::NewRetValMessageFromPeer {
profile_id: cwtch_event.data["ProfileOnion"].clone().into(),
contact_id: cwtch_event.data["RemotePeer"].clone().into(),
scope: cwtch_event.data["Scope"].clone(),
path: cwtch_event.data["Path"].clone(),
exists: cwtch_event.data["Exists"].parse().unwrap_or(false),
data: cwtch_event.data["Data"].clone(),
file_path: match cwtch_event.data.get("FilePath") {
Some(fp) => Some(fp.to_string()),
None => None,
},
},
_ => Event::ErrUnhandled {
name: cwtch_event.event_type.to_string(),
data: cwtch_event.data.clone(),
},
}
}
}

View File

@ -3,230 +3,85 @@
#![doc(html_root_url = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs")]
#![deny(missing_docs)]
use crate::event::{ConversationID, Event, FileKey, ProfileIdentity, ServerIdentity};
use crate::structs::{ACL, MessageWrapper, Settings, SharedFile};
mod bindings_go;
mod cwtchlib_go;
mod bindings_go;
/// Basic structs using data from Cwtch and for deserializing JSON and serializing to JSON to communicate with Cwtch
pub mod structs;
/// Additional structs for advnaced event handling and converstion helpers
pub mod event;
/// Error type for Cwtch lib related errors, intended for use with Result
pub type CwtchError = String;
/// Interface to a Cwtch app with API matching libcwtch
pub trait CwtchLib {
/// Start a cwtch application using app_dir to store all user profile data and looking to tor_path to find tor to run
fn start_cwtch(&self, app_dir: &str, tor_path: &str) -> i32;
/// Return 1 if cwtch has been started and 0 if not
fn started(&self) -> i32;
/// 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);
/// 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);
/// Send json of a structs::CwtchEvent to the cwtch app bus
fn send_app_event(&self, event_json: &str);
/// Pull json of a structs::CwtchEvent off the appbus for responding to
fn get_appbus_event(&self) -> Event;
/// configure a peer's connection settings, listen for incoming connections, connect to peers and connect to servers.
fn configure_connections(&self, profile: &ProfileIdentity, listen: bool, peers: bool, servers: bool);
fn get_appbus_event(&self, ) -> String;
/// Create a new profile encrypted with pass
fn create_profile(&self, nick: &str, pass: &str, autostart: bool);
fn create_profile(&self, nick: &str, pass: &str);
/// Load any profiles encrypted by pass
fn load_profiles(&self, pass: &str);
/// Cause profile to accept conversation
fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to accept contact
fn accept_contact(&self, profile: &str, contact: &str);
/// Cause profile to block conversation
fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to reject contact
fn reject_invite(&self, profile: &str, contact: &str);
/// Cause profile to unblock conversation
fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to block contact
fn block_contact(&self, profile: &str, contact: &str);
/// Attempt to peer with a a new peer
fn peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str);
/// Cause profile to update contact's message to have it's flags updated
fn update_message_flags(&self, profile: &str, contact: &str, message_id: i32, message_flags: u64);
/// manually disconnect from a conversation
fn disconnect_from_peer(&self, profile: &ProfileIdentity, peer_id: &str);
/// Get a specific message for contact of profile by index
fn get_message(&self, profile: &str, contact: &str, message_index: i32) -> String;
/// starts a search process on a profile for pattern. returns a searchID that resulting SearchResult messages will have
fn search_conversations(&self, profile: &ProfileIdentity, pattern: &str) -> String;
/// Get an ACL for a conversation
fn get_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID) -> Result<ACL, CwtchError>;
/// Update a conversation's ACL
fn update_conversation_access_control_list(&self, profile: &ProfileIdentity, conversation_id: ConversationID, acl: ACL);
/// Get a specific message for contact of profile by hash
fn get_message_by_content_hash(&self, profile: &str, contact: &str, hash: &str) -> String;
/// 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;
/// Send json of a structs::Message from profile to contact
fn send_message(&self, profile: &str, contact: &str, msg: &str);
/// Get a specific message for conversation of profile by hash
fn get_message_by_content_hash(
&self,
profile: &ProfileIdentity,
conversation_id: ConversationID,
hash: &str,
) -> String;
/// Bulk get messages starting at message index and of count amoung
fn get_messages(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_index: i32, count: u32) -> String;
/// Send json of a structs::Message from profile to contact. Returns computed sent message (including index and hash values)
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: &MessageWrapper) -> Result<String, CwtchError>;
/// 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<SharedFile>;
/// download a file from a conversation to the file_path
fn download_file_default_limit(
&self,
profile: &ProfileIdentity,
conversation_id: ConversationID,
file_path: &str,
manifest_path: &str,
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);
/// Verufy a download is done, and if not, resume it
fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey);
/// Send profile's contact an invite for/to target
fn send_invitation(&self, profile: &str, contact: &str, target: &str);
/// Ask the ACN inside the Cwtch app to restart the tor connection
fn reset_tor(&self);
fn reset_tor(&self, );
/// Cause profile to create a group on server with name
fn start_group(&self, profile: &ProfileIdentity, name: &str, server: &str);
/// Queue joining a server in the out going connections queue
fn queue_join_server(&self, profile: &ProfileIdentity, server: &ServerIdentity);
/// Disconnect from a specific server
fn disconnect_from_server(&self, profile: &ProfileIdentity, server: &ServerIdentity);
/// Publish server status updates for a profile
fn publish_server_update(&self, profile: &ProfileIdentity);
/// Get list of known servers for a profile
fn get_server_info_list(&self, profile: &ProfileIdentity);
/// Delete server information from a profile, preventing future connections for all groups hosted on it
fn delete_server_info(&self, profile: &ProfileIdentity, server: &ServerIdentity);
fn create_group(&self, profile: &str, server: &str, name: &str);
/// Delete profile with encryption/password check of pass
fn delete_profile(&self, profile: &ProfileIdentity, pass: &str);
fn delete_profile(&self, profile: &str, pass: &str);
/// Cause profile to archive conversation with contact
fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
fn archive_conversation(&self, profile: &str, contact: &str);
/// Cause profile to delete contact/group identified by handle
fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
fn delete_contact(&self, profile: &str, handle: &str);
/// Cuase profile to attempt to import a contact/group/keybundle identified by bundle
fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str);
fn import_bundle(&self, profile: &str, bundle: &str);
/// Set a profile attribute key to val
fn set_profile_attribute(&self, profile: &ProfileIdentity, key: &str, val: &str);
/// Get a profile attribute
fn get_profile_attribute(&self, profile: &ProfileIdentity, key: &str) -> Result<Option<String>, CwtchError>;
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str);
/// 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);
fn set_contact_attribute(&self, profile: &str, contact: &str, key: &str, val: &str);
/// Update an attribute on a message in a conversation
fn update_message_attribute(
&self,
profile: &ProfileIdentity,
conversation_id: ConversationID,
channel_id: i32,
message_id: i32,
attribute_key: &str,
attribute_value: &str,
);
/// Get an attribute for a conversation
fn get_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str) -> Result<Option<String>, CwtchError>;
/// Change a profile's password to new_pass if old_pass is correct
fn change_password(&self, profile: &ProfileIdentity, old_pass: &str, new_pass: &str, new_pass_again: &str);
/// Export a profile to filename
fn export_profile(&self, profile: &ProfileIdentity, filename: &str);
/// Import a profile from a file with supplied password. Json of a profile struct returned on success
fn import_profile(&self, filename: &str, password: &str) -> String;
/// Set a profile's group's attribute of key to val
fn set_group_attribute(&self, profile: &str, group: &str, key: &str, val: &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
fn create_server(&self, password: &str, description: &str, autostart: bool);
/// Delete the specified server (if password is correct)
fn delete_server(&self, server: ServerIdentity, current_password: &str);
/// Launch all loaded servers
fn launch_servers(&self);
/// Launch the specified server
fn launch_server(&self, server: ServerIdentity);
/// Stop the specified server
fn stop_server(&self, server: ServerIdentity);
/// 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, server: ServerIdentity, key: &str, val: &str);
/// Get debug info (mem, goroutine stats) from lcg in json
fn get_debug_info(&self) -> String;
fn shutdown_cwtch(&self, );
}
/// Create a new CwtchLib that is backed by bindings to libcwtch-go
pub fn new_cwtchlib_go() -> impl CwtchLib {
bindings_go::CwtchLibGo {}
}
}

View File

@ -1,12 +1,9 @@
use crate::structs::ConnectionState::Disconnected;
use crate::{ConversationID, CwtchLib, ProfileIdentity};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DefaultOnError};
use serde_repr::*;
use std::collections::HashMap;
use crate::event::{ContactIdentity, FileKey};
use crate::structs::ConnectionState::Disconnected;
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
#[derive(Serialize, Deserialize, Debug)]
/// Defines the states a Cwtch connection can be in
pub enum ConnectionState {
/// The Cwtch connection is not conected at all
@ -22,7 +19,7 @@ pub enum ConnectionState {
/// The connection attempt failed
Failed,
/// The connection has been killed
Killed,
Killed
}
impl Default for ConnectionState {
@ -31,22 +28,6 @@ impl Default for ConnectionState {
}
}
impl From<&str> for ConnectionState {
/// Creates a ConnectionState from a string sent from libcwtch-go
fn from(name: &str) -> Self {
match name {
"Disconnected" => ConnectionState::Disconnected,
"Connecting" => ConnectionState::Connecting,
"Connected" => ConnectionState::Connected,
"Authenticated" => ConnectionState::Authenticated,
"Synced" => ConnectionState::Synced,
"Failed" => ConnectionState::Failed,
"Killed" => ConnectionState::Killed,
_ => ConnectionState::Disconnected,
}
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
/// Defines the various authorization modes a contact can be in
@ -56,18 +37,7 @@ pub enum ContactAuthorization {
/// The contact is approved by the user (manual action)
Approved,
/// The contact is blocked by the user, should be ignored
Blocked,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
#[allow(non_snake_case)]
/// Struct to deserialize the results of Get*Attribute requests into
pub struct Attribute {
/// Was the attribute value found in storage
pub exists: bool,
/// The value of the requested attribute
pub value: String,
Blocked
}
#[derive(Serialize, Deserialize, Debug)]
@ -83,63 +53,26 @@ pub struct CwtchEvent {
pub data: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
#[allow(non_snake_case)]
/// AccessControl is a type determining client assigned authorization to a peer
pub struct AccessControl {
/// Any attempts from this handle to connect are blocked
pub blocked: bool,
/// Allows a handle to access the conversation
pub read: bool,
/// Allows a handle to append new messages to the conversation
pub append: bool,
/// Profile should automatically try to connect with peer
pub auto_connect: bool,
/// Profile should automatically exchange attributes like Name, Profile Image, etc.
pub exchange_attributes: bool,
/// Allows a handle to share files to a conversation
pub share_files: bool,
/// Indicates that certain filetypes should be autodownloaded and rendered when shared by this contact
pub render_images: bool
}
/// represents an access control list for a conversation. Mapping handles to conversation functions
pub type ACL = HashMap<String, AccessControl>;
#[serde_as]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
/// Struct to serialize/deserialize conversations coming from libcwtch-go
pub struct Conversation {
/// onion address / id of the conversation
#[serde(alias = "onion")]
pub contact_id: ContactIdentity,
/// unique identifier of the contact/conversation to be used in API access
pub identifier: ConversationID, // TODO TEST does this work here for serde deserializtion
/// display name of the conversation, as determined in libcwtch-go from name specified by contact
/// Struct to serialize/deserialize contacts coming from libcwtch-go
pub struct Contact {
/// onion address / id of the contact
pub onion: String,
/// display name of the contact, as determined in libcwtch-go from name specified by contact
pub name: String,
#[serde_as(deserialize_as = "DefaultOnError")]
// cwtch loads profile/conversation from storage and leaves status blank, it's filled in "soon" by events...
#[serde_as(deserialize_as = "DefaultOnError")] // cwtch loads profile/contacts from storage and leaves status blank, it's filled in "soon" by events...
/// contact connection status
pub status: ConnectionState,
/// has the conversation been manually accpted
pub accepted: bool,
///represents an access control list for a conversation. Mapping handles to conversation functions
pub access_control_list: ACL,
/// has the conversation been manually blocked
pub blocked: bool,
/// is this conversation a group? if so "onion" will be a group ID
/// FIXME: deprecate
/// contact authorization state as set by profile
pub authorization: ContactAuthorization,
/// is this contact a group? if so "onion" will be a group ID
pub is_group: bool,
//attr: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug)]
/// Struct to serialize/deserialize servers coming from libcwtch-go
pub struct Server {
/// onion address of the server
@ -148,317 +81,65 @@ pub struct Server {
pub status: ConnectionState,
}
#[derive(Debug, Clone)]
#[derive(Debug)]
/// Struct to serialize/deserialize profiles coming from libcwtch-go
pub struct Profile {
/// onion address / ID of the profile
pub profile_id: ProfileIdentity,
pub onion: String,
/// nick name of the onion as supplied by libcwtch-go based on "name" attribute
pub nick: String,
/// path to a profile image, controled by "picture" attribute
pub image_path: String,
/// all profile attributes
pub attr: HashMap<String, String>,
/// map of conversation [ onion => conversation ]
pub conversations: HashMap<ConversationID, Conversation>,
pub attr: HashMap<String,String>,
/// map of contacts [ onion => contact ]
pub contacts: HashMap<String, Contact>,
/// map of servers [ onion => server ]
pub servers: HashMap<String, Server>,
}
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Clone)]
#[repr(i32)]
/// Enum matching message types and their overlays as defined in Cwtch
/// - https://git.openprivacy.ca/cwtch.im/cwtch/src/commit/907a7ca638fbcbaac5d652608d455d4217597fa9/model/overlay.go
/// - https://git.openprivacy.ca/cwtch.im/cwtch-ui/src/commit/3a752b73972cbfc53b6da26116fe018ee2ac2343/lib/models/message.dart
pub enum MessageType {
/// A standard Cwtch message of text
TextMessage = 1,
/// This message is a text message but it also contains a reference to the message it is quoting
QuotedMessage = 10,
/// A shared contact message
SuggestContact = 100,
/// A group invite message
InviteGroup = 101,
/// a share file message
FileShare = 200,
/// This message is of an unsupported type so malformed
MalformedMessage,
}
impl From<i32> for MessageType {
fn from(x: i32) -> Self {
match x {
1 => MessageType::TextMessage,
10 => MessageType::QuotedMessage,
100 => MessageType::SuggestContact,
101 => MessageType::InviteGroup,
200 => MessageType::FileShare,
_ => MessageType::MalformedMessage,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
/// Struct to serialize/deserialize messages sent over Cwtch between profiles / conversation
/// Overlay => data
/// 1 TextMessage: d = plain text message
/// 10 QuotedMessage: d = json of QuotedMessageStructure, body = plain text of message
pub struct MessageWrapper {
#[derive(Debug, Serialize, Deserialize)]
/// Struct to serialize/deserialize messages sent over Cwtch between profiles / contacts
pub struct Message {
/// 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, for OverlayChat, a
pub d: String,
}
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) => 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<FixedOffset>
/// 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)]
pub struct Settings {
/// locale for the UI to use
pub Locale: String,
/// theme of the UI
pub Theme: String,
/// Theme mode of the ui, light or dark
pub ThemeMode: String,
/// previous pid of the run, managed by libcwtch-go
pub PreviousPid: i64,
/// controls if subsequent experiments are enabled at all
pub ExperimentsEnabled: bool,
/// map of experiment names and their enabled status
pub Experiments: HashMap<String, bool>,
/// Should the app block unknown conversations
pub BlockUnknownConnections: bool,
// Notification policy of a UI app
//pub NotificationPolicy: String, //Todo: NotificationPolicy struct
// Notification content to show for a UI app
//pub NotificationContent: String,
/// Should the UI hide conversation IDs
pub StreamerMode: bool,
/// Unused?
pub StateRootPane: i32,
/// is this the first run
pub FirstTime: bool,
/// UI column mode
pub UIColumnModePortrait: String,
/// UI column mode
pub UIColumnModeLandscape: String,
/// Path to download files to
pub DownloadPath: String,
// Turn on advanced tor config in the UI
//pub AllowAdvancedTorConfig: bool,
// Custom torrc value
//pub CustomTorrc: String,
// Use the value of CustomTorrc with tor
//pub UseCustomTorrc: bool,
// Unused? delete
//pub UseExternalTor: bool,
// Tor socks port, if not default
//pub CustomSocksPort: i32,
// Tor control port if not default
//pub CustomControlPort: i32,
// Use tor cache for faster start
//pub UseTorCache: bool,
// Tor config dir
//pub TorCacheDir: String,
}
/// Enum of experiment types that can be managed in Settings
pub enum Experiments {
/// experiment enabling in app management and running of Cwtch servers
ServersExperiment,
/// experiment enabling use of Cwtch groups
GroupExperiment,
/// experiment enabling filesharing
FileSharingExperiment,
/// experiment enabling auto downloading of image files to Settings::DownloadPath
ImagePreviewsExperiment,
}
impl Experiments {
/// returns the experiment settings key
pub fn to_key_string(self) -> String {
match self {
Experiments::ServersExperiment => "servers-experiment".to_string(),
Experiments::GroupExperiment => "tapir-groups-experiment".to_string(),
Experiments::FileSharingExperiment => "filesharing".to_string(),
Experiments::ImagePreviewsExperiment => "filesharing-images".to_string(),
}
}
}
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> {
cwtch.update_settings(&self);
return Ok(());
}
pub o: i64,
/// data of the message
pub d: String
}
impl Profile {
/// Create a new profile populated from supplied data
/// contacts_json as supplied by libcwtch-go, a map of conversations
/// contacts_json as supplied by libcwtch-go, a map of contacts
/// server_list as supplied by libcwtch-go, a map of servers
pub fn new(
identity: ProfileIdentity,
name: &str,
picture: &str,
conversations_json: &str,
server_list: &str,
) -> Result<Profile, String> {
let conversations = match Profile::process_conversations(conversations_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 {
profile_id: identity,
nick: name.to_string(),
image_path: picture.to_string(),
attr: Default::default(),
conversations,
servers: servers,
})
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(), image_path: picture.to_string(), attr: Default::default(), contacts: contacts, servers: servers }
}
fn process_conversations(conversations_json: &str) -> Result<HashMap<ConversationID, Conversation>, String> {
let mut conversations: HashMap<ConversationID, Conversation> = HashMap::new();
if conversations_json == "null" {
return Ok(conversations);
fn process_contacts(constacts_json: &str) -> HashMap<String, Contact> {
let mut contacts: HashMap<String, Contact> = HashMap::new();
if constacts_json == "null" {
return contacts;
}
let conversations_map: Vec<Conversation> = match serde_json::from_str(conversations_json) {
Ok(cm) => cm,
Err(e) => return Err(format!("invalid json: {:?}", e)),
};
for conversation in conversations_map {
conversations.insert(conversation.identifier, conversation);
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);
}
Ok(conversations)
contacts
}
fn process_servers(servers_json: &str) -> Result<HashMap<String, Server>, String> {
fn process_servers(servers_json: &str) -> HashMap<String, Server> {
let mut servers: HashMap<String, Server> = HashMap::new();
if servers_json == "null" {
return Ok(servers);
return servers;
}
let servers_map: Vec<Server> = match serde_json::from_str(servers_json) {
Ok(sm) => sm,
Err(e) => return Err(format!("invalid json: {:?}", e)),
};
let servers_map: Vec<Server> = serde_json::from_str(servers_json).unwrap();
for server in servers_map {
servers.insert(server.onion.clone(), server);
}
Ok(servers)
servers
}
/// Find a conversation_id associated with a remote handle (used for some events with no conversation id like PeerStateChange)
pub fn find_conversation_id_by_handle(&self, contact_id: ContactIdentity) -> Option<ConversationID> {
match self.conversations.values().filter(|c| c.contact_id == contact_id).next() {
Some(conversation) => Some(conversation.identifier),
None => None
}
}
}
}