Compare commits

...

33 Commits
v0.3.0 ... main

Author SHA1 Message Date
Dan Ballard a148e1af47 upgrade to autobindings 0.0.12 2024-02-24 18:58:00 -08:00
Dan Ballard 98571f5559 fixes around group events 2023-10-21 10:00:17 -07:00
Dan Ballard 94a9a3448e upgrade to libcwtchgo autobindings v0.0.10 / parity with cwtch-ui 1.13 2023-09-27 17:34:42 -07:00
Dan Ballard 9114c88110 0.6.1: add AppError support for optional error and data 2023-09-22 23:31:25 -07:00
Dan Ballard c9f5ec2e42 remove use of u8/i8 and use bool in API and c_char in bindings 2023-07-23 14:43:40 -07:00
Dan Ballard 94504c1dbe update to autobindings 0.0.5 / ~ cwtchui 1.12 / cwtch 0.20.8 2023-06-26 00:03:04 -07:00
Dan Ballard 4f49da65cc 0.5.0 release 2023-05-08 15:41:41 -05:00
Dan Ballard e044e961f2 big version update to autobindings 0.0.3; api changes; added some structs, some used, some will be added to API but for now allow more straight forward deserialization 2023-05-07 13:21:14 -05:00
Dan Ballard b9eccdb751 v0.4.2 2023-04-25 11:42:43 -06:00
Dan Ballard 8e3ea76590 Merge pull request 'send_message takes Message, so deps dont need serde. add send_message_raw' (#19) from sendmsg into main
Reviewed-on: #19
Reviewed-by: Sarah Jamie Lewis <sarah@openprivacy.ca>
2023-04-25 17:36:03 +00:00
Dan Ballard 39299cea3b v 0.4.1 2023-04-25 11:21:11 -06:00
Dan Ballard 60d6074758 send_message takes Message, so deps dont need serde. add send_message_raw 2023-04-25 07:35:39 -06:00
Dan Ballard fff85a7a0e v0.4.0 2022-07-21 15:52:52 -07:00
Sarah Jamie Lewis ec4e6f4c22 Merge pull request 'add events wrapping enum' (#18) from events into main
Reviewed-on: #18
Reviewed-by: Sarah Jamie Lewis <sarah@openprivacy.ca>
2022-07-21 15:56:24 +00:00
Dan Ballard 52b799ef7c improvements for use with imp; migrate echobot to 2022-07-21 01:04:21 -07:00
Dan Ballard 752d2967e0 address PR comments 2022-07-15 14:39:32 -07:00
Dan Ballard 907af56eac make api use types part 2 2022-07-15 12:43:27 -07:00
Dan Ballard 3a685db27f adding typed types to api part 1 2022-07-15 12:23:13 -07:00
Dan Ballard 384c5880b2 typed IDs for most things, docs for all 2022-07-14 16:33:41 -07:00
Dan Ballard bd5d3f7e5f starting to type fields 2022-07-07 14:30:20 -07:00
Dan Ballard 577d8999cf add events wrapping enum 2022-07-06 23:52:30 -07:00
Dan Ballard 5eb98eccc7 digest bump 2022-05-15 10:24:31 -07:00
Sarah Jamie Lewis af2ea260d1 Merge pull request 'profile convo list by id, handle2id fn' (#17) from handle2convoid into main
Reviewed-on: #17
2022-05-02 20:04:52 +00:00
Sarah Jamie Lewis 62952f1ab9 Merge branch 'main' into handle2convoid 2022-05-02 20:04:40 +00:00
Dan Ballard 895a9e78d1 profile convo list by id, handle2id fn 2022-05-01 18:34:40 -07:00
Dan Ballard 0df0af57d8 Merge pull request 'Allow building from local' (#16) from local_override into main
Reviewed-on: #16
2022-04-27 20:29:27 +00:00
Sarah Jamie Lewis e3c47ba16b Allow building from local 2022-04-27 13:05:41 -07:00
Dan Ballard d223325646 version 0.3.1 now with hopefully building docs 2022-04-26 12:20:40 -07:00
Dan Ballard cc991cda70 bump yanked version of block-buffer 2022-04-26 12:19:59 -07:00
Sarah Jamie Lewis 58687001b6 Merge pull request 'prevent libcwtch.so fetch on build.rs so docs can build, be published' (#15) from docsrs into main
Reviewed-on: #15
2022-04-26 19:12:02 +00:00
Dan Ballard 99b813464a prevent libcwtch.so fetch on build.rs so docs can build, be published 2022-04-26 12:06:43 -07:00
Dan Ballard e2768b4779 Merge pull request '0.3.0' (#13) from lcg1.7.1 into main
Reviewed-on: #13
2022-04-22 00:41:28 +00:00
Dan Ballard 3a7c3e3000 0.3.0 2022-04-21 17:40:59 -07:00
12 changed files with 2418 additions and 496 deletions

1
.gitignore vendored
View File

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

543
Cargo.lock generated Normal file
View File

@ -0,0 +1,543 @@
# This file is automatically @generated by Cargo.
# 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.85",
]
[[package]]
name = "darling_macro"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
dependencies = [
"darling_core",
"quote",
"syn 1.0.85",
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "itoa"
version = "1.0.1"
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"
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libcwtch"
version = "0.8.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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "serde"
version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.85",
]
[[package]]
name = "serde_json"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3"
dependencies = [
"rustversion",
"serde",
"serde_with_macros",
]
[[package]]
name = "serde_with_macros"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 1.0.85",
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
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,20 +1,23 @@
[package] [package]
name = "libcwtch" name = "libcwtch"
version = "0.2.0" version = "0.8.0"
authors = ["Dan Ballard <dan@mindstab.net>"] authors = ["Dan Ballard <dan@mindstab.net>"]
edition = "2018" edition = "2018"
license = "MIT" license = "MIT"
description = "libcwtch is an interface to a Cwtch app that allows creating of profiles to communicate with contacts over the Cwtch protocol" 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" repository = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs"
readme = "README.md" readme = "README.md"
documentation = "https://docs.rs/libcwtch/0.2.0/libcwtch/" documentation = "https://docs.rs/libcwtch/"
[build-dependencies] [build-dependencies]
hex-literal = "0.3.4" hex-literal = "0.3.4"
sha2 = "0.10.1" sha2 = "0.10.1"
bindgen = "0.65.1"
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0.127", features = ["derive"] } serde = { version = "1.0.127", features = ["derive"] }
serde_with = { version = "1.10.0" } serde_with = { version = "1.10.0" }
serde_repr = "0.1"
chrono = "0.4.19"

View File

@ -1,6 +1,6 @@
# libCwtch-rs # libCwtch-rs
Rust bindings for [libCwtch](https://git.openprivacy.ca/cwtch.im/libcwtch-go/) Rust bindings for [libCwtch autobindings](https://git.openprivacy.ca/cwtch.im/autobindings/)
Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes tor is on $PATH) Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes tor is on $PATH)
@ -8,16 +8,12 @@ Example echobot in examples/echobot.rs (`cargo run --example echobot` -- assumes
### Updating libCwtch and bingings.rs with Bindgen ### Updating libCwtch and bingings.rs with Bindgen
```sh
cargo install bindgen
```
libCwtch.so version is specified in build.rs. If updating, also download the corresponding libCwtch.h and delete 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 the 'preamble from import "C"' section as it imports headers required for the C lib to compile
but that we don't want to create rust bindings for (like importing stdlib.h). Then: 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.
```sh While developing you can use the `LCG_DIR` environment variable to specify the directory containing a local `libCwtch.so`
bindgen libCwtch.h -o src/cwtchlib_go/bindings.rs library to override the default one.
```
### Todo This is useful in cases where you are adding or updating APIs prior to a release.

View File

@ -1,33 +1,63 @@
use std::fs;
use std::path::Path;
use std::process::Command;
use std::{env, io}; use std::{env, io};
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use hex_literal::hex; use hex_literal::hex;
use sha2::{Digest, Sha512}; use sha2::{Digest, Sha512};
fn main() { fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
println!("cargo:rustc-flags=-L {}", out_dir.to_str().unwrap());
println!("cargo:rustc-link-lib=Cwtch");
println!("cargo:rerun-if-changed=build.rs"); // Do not fetch lib on docs.rs as it cannot, build will fail, docs won't build
println!("cargo:rerun-if-changed=libCwtch.h"); // 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");
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so"); println!("cargo:rerun-if-changed=build.rs");
// https://git.openprivacy.ca/cwtch.im/libcwtch-go/releases v1.7.1 println!("cargo:rerun-if-changed=libCwtch.h");
Command::new("wget")
.arg("https://git.openprivacy.ca/attachments/98184e9c-1dc7-431a-9601-91a9e763e8fc")
.arg("-O")
.arg(lib_cwtch_path)
.output()
.expect("failed to download libCwtch.so");
let lib_cwtch_path = Path::new(&out_dir).join("libCwtch.so");
let mut hasher = Sha512::new();
let mut file = fs::File::open(&lib_cwtch_path).expect("could not open lib to hash");
io::copy(&mut file, &mut hasher).expect("failed to copy file into hasher");
let hash_bytes = hasher.finalize();
assert_eq!(hash_bytes[..], hex!("cb4368d72a46f8046261c50e6e9ecf170d8e606871d5de2c1e9e34303533c344f92f5d946d7e12614581dfa3ae8e638512af7f4623ed91b1ceb1570de14bf192")[..]); // 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");
}
}
} }

View File

@ -3,6 +3,7 @@ use std::thread;
use libcwtch; use libcwtch;
use libcwtch::structs::*; use libcwtch::structs::*;
use libcwtch::CwtchLib; use libcwtch::CwtchLib;
use libcwtch::event::Event;
fn main() { fn main() {
let bot_home = "example_cwtch_dir"; let bot_home = "example_cwtch_dir";
@ -19,46 +20,28 @@ fn main() {
let event_loop_handle = thread::spawn(move || { let event_loop_handle = thread::spawn(move || {
loop { loop {
let event_str = cwtch.get_appbus_event(); let event = cwtch.get_appbus_event();
println!("event: {}", event_str); println!("event: {:?}", event);
let event: CwtchEvent = match event {
serde_json::from_str(&event_str).expect("Error parsing Cwtch event"); Event::CwtchStarted => {
match event.event_type.as_str() {
"CwtchStarted" => {
println!("event CwtchStarted!"); println!("event CwtchStarted!");
println!("Creating bot"); println!("Creating bot");
cwtch.create_profile("Echobot", "be gay do crime"); cwtch.create_profile("Echobot", "be gay do crime", true);
} }
"NewPeer" => { Event::NewPeer { profile_id, tag, created, name, default_picture, picture, online, profile_data } => {
println!( println!(
"\n***** {} at {} *****\n", "\n***** {} at {} *****\n",
event.data["name"], event.data["Identity"] name, profile_id.as_str()
); );
// process json for profile, contacts and servers...else { // process json for profile, contacts and servers...else {
let profile = match Profile::new( let profile = profile_data;
&event.data["Identity"],
&event.data["name"],
&event.data["picture"],
&event.data["ContactsJson"],
&event.data["ServerList"],
) {
Ok(p) => p,
Err(e) => panic!("error parsing profile: {}", e),
};
print!("profile: {:?}", profile); print!("profile: {:?}", profile);
} }
"NewMessageFromPeer" => { Event::NewMessageFromPeer { profile_id, conversation_id, contact_id: contact, nick, timestamp_received, message, notification, picture } => {
let to = &event.data["ProfileOnion"]; let response = MessageWrapper { o: message.o.into(), d: message.d };
let conversation_id = event.data["ConversationID"].parse::<i32>().unwrap(); cwtch.send_message( &profile_id, conversation_id, &response);
let message: Message =
serde_json::from_str(&event.data["Data"]).expect("Error parsing message");
let response = Message { o: 1, d: message.d };
let response_json =
serde_json::to_string(&response).expect("Error parsing json response");
cwtch.send_message(&to, conversation_id, &response_json);
} }
_ => eprintln!("unhandled event!"), _ => eprintln!("unhandled event!"),
}; };

View File

@ -1,11 +1,11 @@
/* Code generated by cmd/cgo; DO NOT EDIT. */ /* Code generated by cmd/cgo; DO NOT EDIT. */
/* package git.openprivacy.ca/cwtch.im/libcwtch-go */ /* package git.openprivacy.ca/cwtch.im/cwtch-autobindings */
#line 1 "cgo-builtin-export-prolog" #line 1 "cgo-builtin-export-prolog"
#include <stddef.h> /* for ptrdiff_t below */ #include <stddef.h>
#ifndef GO_CGO_EXPORT_PROLOGUE_H #ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H
@ -32,11 +32,17 @@ typedef long long GoInt64;
typedef unsigned long long GoUint64; typedef unsigned long long GoUint64;
typedef GoInt64 GoInt; typedef GoInt64 GoInt;
typedef GoUint64 GoUint; typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr; typedef size_t GoUintptr;
typedef float GoFloat32; typedef float GoFloat32;
typedef double GoFloat64; typedef double GoFloat64;
#ifdef _MSC_VER
#include <complex.h>
typedef _Fcomplex GoComplex64;
typedef _Dcomplex GoComplex128;
#else
typedef float _Complex GoComplex64; typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128; typedef double _Complex GoComplex128;
#endif
/* /*
static assertion to make sure the file is being used on architecture static assertion to make sure the file is being used on architecture
@ -60,69 +66,73 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
extern "C" { extern "C" {
#endif #endif
extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen);
extern int c_Started();
extern void c_ReconnectCwtchForeground();
// A generic method for Rebroadcasting App Events from a UI
extern void c_SendAppEvent(char* json_ptr, int json_len);
// A generic method for Rebroadcasting Profile Events from a UI
extern void c_SendProfileEvent(char* onion_ptr, int onion_len, char* json_ptr, int json_len);
// the pointer returned from this function **must** be freed using c_Free
extern char* c_GetAppBusEvent();
extern void c_CreateProfile(char* nick_ptr, int nick_len, char* pass_ptr, int pass_len);
extern void c_LoadProfiles(char* passwordPtr, int passwordLen);
extern void c_AcceptConversation(char* profilePtr, int profileLen, int conversation_id);
extern void c_BlockContact(char* profilePtr, int profileLen, int conversation_id);
extern void c_UnblockContact(char* profilePtr, int profileLen, int conversation_id);
// the pointer returned from this function **must** be Freed by c_Free
extern char* c_GetMessage(char* profile_ptr, int profile_len, int conversation_id, int message_index);
// the pointer returned from this function **must** be Freed by c_Free
extern char* c_GetMessageByID(char* profile_ptr, int profile_len, int conversation_id, int message_index);
// the pointer returned from this function **must** be freed by calling c_Free
extern char* c_GetMessagesByContentHash(char* profile_ptr, int profile_len, int conversation_id, char* contenthash_ptr, int contenthash_len);
// the pointer returned from this function **must** be Freed by c_Free
extern char* c_GetMessages(char* profile_ptr, int profile_len, int conversation_id, int message_index, int count);
// Dangerous function. Should only be used as documented in `MEMORY.md` // Dangerous function. Should only be used as documented in `MEMORY.md`
//
extern void c_FreePointer(char* ptr); extern void c_FreePointer(char* ptr);
extern char* c_SendMessage(char* profile_ptr, int profile_len, int conversation_id, char* msg_ptr, int msg_len); extern int c_Started();
extern char* c_SendInvitation(char* profile_ptr, int profile_len, int conversation_id, int target_id); extern int c_StartCwtch(char* dir_c, int len, char* tor_c, int torLen);
extern char* c_ShareFile(char* profile_ptr, int profile_len, int conversation_id, char* filepath_ptr, int filepath_len);
extern void c_DownloadFile(char* profile_ptr, int profile_len, int conversation_id, char* filepath_ptr, int filepath_len, char* manifestpath_ptr, int manifestpath_len, char* filekey_ptr, int filekey_len); // the pointer returned from this function **must** be freed using c_Free
extern void c_CheckDownloadStatus(char* profilePtr, int profileLen, char* fileKeyPtr, int fileKeyLen); //
extern void c_VerifyOrResumeDownload(char* profile_ptr, int profile_len, int conversation_id, char* filekey_ptr, int filekey_len); extern char* c_GetAppBusEvent();
extern void c_ResetTor(); extern void c_ReconnectCwtchForeground();
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_ShutdownCwtch();
extern void c_DeleteProfile(char* profile_ptr, int profile_len, char* password_ptr, int password_len);
extern void c_ArchiveConversation(char* profile_ptr, int profile_len, int conversation_id);
extern void c_DeleteContact(char* profile_ptr, int profile_len, int conversation_id);
extern void c_ImportBundle(char* profile_ptr, int profile_len, char* bundle_ptr, int bundle_len);
extern void c_SetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len, char* val_ptr, int val_len); extern void c_SetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len, char* val_ptr, int val_len);
extern char* c_GetProfileAttribute(char* profile_ptr, int profile_len, char* key_ptr, int key_len); extern 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 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 char* c_GetConversationAttribute(char* profile_ptr, int profile_len, int conversation_id, char* key_ptr, int key_len);
extern void c_SetMessageAttribute(char* profile_ptr, int profile_len, int conversation_id, int channel_id, int message_id, char* key_ptr, int key_len, char* val_ptr, int val_len); extern void c_ResetTor();
extern void c_ChangePassword(char* profile_ptr, int profile_len, char* oldpassword_ptr, int oldpassword_len, char* newpassword_ptr, int newpassword_len, char* newpassword_again_ptr, int newpassword_again_len); extern void c_UpdateSettings(char* json_ptr, int json_len);
extern void c_ExportProfile(char* profile_ptr, int profile_len, char* file_ptr, int file_len); extern char* c_GetDebugInfo();
extern char* c_ImportProfile(char* file_ptr, int file_len, char* passwordPtr, int passwordLen); extern void c_ActivatePeerEngine(char* onion_ptr, int onion_len);
extern void c_ShutdownCwtch(); extern void c_DeactivatePeerEngine(char* onion_ptr, int onion_len);
extern void c_LoadServers(char* passwordPtr, int passwordLen); extern void c_ConfigureConnections(char* onion_ptr, int onion_len, char listen1, char peers2, char servers3);
extern void c_CreateServer(char* passwordPtr, int passwordLen, char* descPtr, int descLen, char autostart); extern void c_CreateProfile(char* name_ptr, int name_len, char* password_ptr, int password_len, char autostart4);
extern void c_DeleteServer(char* onionPtr, int onionLen, char* currentPasswordPtr, int currentPasswordLen); 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_LaunchServers();
extern void c_LaunchServer(char* onionPtr, int onionLen); extern void c_LaunchServer(char* handle37_ptr, int handle37_len);
extern void c_StopServer(char* onionPtr, int onionLen); extern void c_StopServer(char* handle38_ptr, int handle38_len);
extern void c_StopServers(); extern void c_StopServers();
extern void c_DestroyServers(); extern void c_DestroyServers();
extern void c_SetServerAttribute(char* onionPtr, int onionLen, char* keyPtr, int keyLen, char* valPtr, int valLen); extern void c_DeleteServer(char* handle39_ptr, int handle39_len, char* password_ptr, int password_len);
extern char* c_GetDebugInfo();
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -8,10 +8,21 @@ use std::ffi::CString;
use super::CwtchLib; use super::CwtchLib;
use crate::cwtchlib_go::bindings; use crate::cwtchlib_go::bindings;
use crate::{CwtchError, structs::*}; 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 { struct c_str_wrap {
raw: *mut i8, raw: *mut core::ffi::c_char,
len: i32, len: i32,
} }
@ -84,44 +95,208 @@ 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) // 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 // so we pre define the real binding here as a _helper function and in the impl for CwtchLib define the wrapper
impl CwtchLibGo { 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_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_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);
} }
impl CwtchLib for CwtchLibGo { impl CwtchLib for CwtchLibGo {
c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> i32); c_bind!(start_cwtch(app_dir: &str, tor_path: &str;;) c_StartCwtch -> i32);
c_bind!(started(;;) c_Started -> i32); c_bind!(started(;;) c_Started -> i32);
c_bind!(send_app_event(event_json: &str;;) c_SendAppEvent); fn update_settings(&self, settings: &Settings) {
c_bind!(send_profile_event(profile: &str, event_jason: &str;;) c_SendProfileEvent); let settings_json = match serde_json::to_string(settings) {
c_bind!(get_appbus_event(;;) c_GetAppBusEvent -> String); Ok(s) => s,
c_bind!(create_profile(nick: &str, pass: &str;;) c_CreateProfile); 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); c_bind!(load_profiles(pass: &str;;) c_LoadProfiles);
c_bind!(accept_conversation(profile: &str ; conversation_id: i32 ;) c_AcceptConversation); fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
c_bind!(block_contact(profile: &str ; conversation_id: i32; ) c_BlockContact); self._accept_conversation(profile.as_str(), conversation_id.into())
c_bind!(unblock_contact(profile: &str ; conversation_id: i32; ) c_UnblockContact); }
c_bind!(get_message(profile: &str; conversation_id: i32, message_index: i32 ;) c_GetMessage -> String);
c_bind!(get_message_by_id(profile: &str ; conversation_id: i32, message_id: i32 ;) c_GetMessageByID -> String); fn peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str) {
c_bind!(get_message_by_content_hash(profile: &str ; conversation_id: i32 ; hash: &str) c_GetMessagesByContentHash -> String); self._peer_with(profile.as_str(), new_peer_address)
c_bind!(get_messages(profile: &str; conversation_id: i32, message_index: i32, count: i32 ;) c_GetMessages -> String); }
c_bind!(send_message(profile: &str; conversation_id: i32; msg: &str) c_SendMessage -> String);
c_bind!(send_invitation(profile: &str; conversation_id: i32, target_id: i32;) c_SendInvitation -> String); fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
c_bind!(share_file(profile: &str; conversation_id: i32; file_path: &str) c_ShareFile -> String); self._block_conversation(String::from(profile).as_str(), conversation_id.into())
c_bind!(download_file(profile: &str; conversation_id: i32; file_path: &str, manifest_path: &str, file_key: &str) c_DownloadFile); }
c_bind!(check_download_status(profile: &str, file_key: &str;;) c_CheckDownloadStatus); fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID) {
c_bind!(verify_or_resume_download(profile: &str; conversation_id: i32; file_key: &str) c_VerifyOrResumeDownload); 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())
}
fn reset_tor(&self) { fn reset_tor(&self) {
unsafe { unsafe {
bindings::c_ResetTor(); bindings::c_ResetTor();
} }
} }
c_bind!(create_group(profile: &str, server: &str, name: &str;;) c_CreateGroup); fn start_group(&self, profile: &ProfileIdentity, server: &str, name: &str) {
c_bind!(delete_profile(profile: &str, pass: &str;;) c_DeleteProfile); self._start_group(String::from(profile).as_str(), server, name)
c_bind!(archive_conversation(profile: &str; conversation_id: i32;) c_ArchiveConversation); }
c_bind!(delete_contact(profile: &str; conversation_id: i32;) c_DeleteContact); fn queue_join_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
c_bind!(import_bundle(profile: &str, bundle: &str;;) c_ImportBundle); self._queue_join_server(profile.as_str(), server.as_str())
c_bind!(set_profile_attribute(profile: &str, key: &str, val: &str;;) c_SetProfileAttribute); }
fn get_profile_attribute(&self, profile: &str, key: &str) -> Result<Option<String>, CwtchError> { fn disconnect_from_server(&self, profile: &ProfileIdentity, server: &ServerIdentity) {
let resp = self._get_profile_attribute(profile, key); 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) { let attr: Attribute = match serde_json::from_str(&resp) {
Ok(attr) => attr, Ok(attr) => attr,
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
@ -131,9 +306,11 @@ impl CwtchLib for CwtchLibGo {
false => Ok(None), false => Ok(None),
} }
} }
c_bind!(set_conversation_attribute(profile: &str; conversation_id: i32; key: &str, val: &str) c_SetConversationAttribute); fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str) {
fn get_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str) -> Result<Option<String>, CwtchError> { self._set_conversation_attribute(String::from(profile).as_str(), conversation_id.into(), key, val)
let resp = self._get_conversation_attribute(profile, conversation_id, key); }
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) { let attr: Attribute = match serde_json::from_str(&resp) {
Ok(attr) => attr, Ok(attr) => attr,
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
@ -143,11 +320,19 @@ impl CwtchLib for CwtchLibGo {
false => Ok(None), false => Ok(None),
} }
} }
c_bind!(set_message_attribute(profile: &str; conversation_id: i32, channel_id: i32, message_id: i32; key: &str, val: &str) c_SetMessageAttribute); fn update_message_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, channel_id: i32, message_id: i32, key: &str, val: &str) {
c_bind!(change_password(profile: &str, old_pass: &str, new_pass: &str, new_pass_again: &str;;) c_ChangePassword); self._update_message_attribute(String::from(profile).as_str(), conversation_id.into(), channel_id, message_id, key, val)
c_bind!(export_profile(profile: &str, filename: &str;;) c_ExportProfile); }
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!(import_profile(filename: &str, password: &str;;) c_ImportProfile -> String);
fn shutdown_cwtch(&self) { fn shutdown_cwtch(&self) {
unsafe { unsafe {
bindings::c_ShutdownCwtch(); bindings::c_ShutdownCwtch();
@ -155,13 +340,30 @@ impl CwtchLib for CwtchLibGo {
} }
c_bind!(load_servers(password: &str;;) c_LoadServers); c_bind!(load_servers(password: &str;;) c_LoadServers);
c_bind!(create_server(password: &str, description: &str; autostart: i8;) c_CreateServer); fn create_server(&self, password: &str, description: &str , autostart: bool) {
c_bind!(delete_server(onion: &str, current_password: &str;;) c_DeleteServer); 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); c_bind!(launch_servers(;;) c_LaunchServers);
c_bind!(launch_server(onion: &str;;) c_LaunchServer); fn launch_server(&self, server: ServerIdentity) {
c_bind!(stop_server(onion: &str;;) c_StopServer); 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!(stop_servers(;;) c_StopServers);
c_bind!(destroy_servers(;;) c_DestroyServers); c_bind!(destroy_servers(;;) c_DestroyServers);
c_bind!(set_server_attribute(onion: &str, key: &str, val: &str;;) c_SetServerAttribute); 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); 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.59.2 */ /* automatically generated by rust-bindgen 0.65.1 */
#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)] #[repr(C)]
@ -6,7 +6,6 @@ pub struct __BindgenComplex<T> {
pub re: T, pub re: T,
pub im: T, pub im: T,
} }
pub type size_t = ::std::os::raw::c_ulong;
pub type wchar_t = ::std::os::raw::c_int; pub type wchar_t = ::std::os::raw::c_int;
#[repr(C)] #[repr(C)]
#[repr(align(16))] #[repr(align(16))]
@ -18,6 +17,8 @@ pub struct max_align_t {
} }
#[test] #[test]
fn bindgen_test_layout_max_align_t() { 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!( assert_eq!(
::std::mem::size_of::<max_align_t>(), ::std::mem::size_of::<max_align_t>(),
32usize, 32usize,
@ -29,9 +30,7 @@ fn bindgen_test_layout_max_align_t() {
concat!("Alignment of ", stringify!(max_align_t)) concat!("Alignment of ", stringify!(max_align_t))
); );
assert_eq!( assert_eq!(
unsafe { unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce1) as usize - ptr as usize },
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce1 as *const _ as usize
},
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -41,9 +40,7 @@ fn bindgen_test_layout_max_align_t() {
) )
); );
assert_eq!( assert_eq!(
unsafe { unsafe { ::std::ptr::addr_of!((*ptr).__clang_max_align_nonce2) as usize - ptr as usize },
&(*(::std::ptr::null::<max_align_t>())).__clang_max_align_nonce2 as *const _ as usize
},
16usize, 16usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -61,6 +58,8 @@ pub struct _GoString_ {
} }
#[test] #[test]
fn bindgen_test_layout__GoString_() { fn bindgen_test_layout__GoString_() {
const UNINIT: ::std::mem::MaybeUninit<_GoString_> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<_GoString_>(), ::std::mem::size_of::<_GoString_>(),
16usize, 16usize,
@ -72,7 +71,7 @@ fn bindgen_test_layout__GoString_() {
concat!("Alignment of ", stringify!(_GoString_)) concat!("Alignment of ", stringify!(_GoString_))
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<_GoString_>())).p as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize },
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -82,7 +81,7 @@ fn bindgen_test_layout__GoString_() {
) )
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<_GoString_>())).n as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).n) as usize - ptr as usize },
8usize, 8usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -102,7 +101,7 @@ pub type GoInt64 = ::std::os::raw::c_longlong;
pub type GoUint64 = ::std::os::raw::c_ulonglong; pub type GoUint64 = ::std::os::raw::c_ulonglong;
pub type GoInt = GoInt64; pub type GoInt = GoInt64;
pub type GoUint = GoUint64; pub type GoUint = GoUint64;
pub type GoUintptr = ::std::os::raw::c_ulong; pub type GoUintptr = usize;
pub type GoFloat32 = f32; pub type GoFloat32 = f32;
pub type GoFloat64 = f64; pub type GoFloat64 = f64;
pub type GoComplex64 = __BindgenComplex<f32>; pub type GoComplex64 = __BindgenComplex<f32>;
@ -119,6 +118,8 @@ pub struct GoInterface {
} }
#[test] #[test]
fn bindgen_test_layout_GoInterface() { fn bindgen_test_layout_GoInterface() {
const UNINIT: ::std::mem::MaybeUninit<GoInterface> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<GoInterface>(), ::std::mem::size_of::<GoInterface>(),
16usize, 16usize,
@ -130,7 +131,7 @@ fn bindgen_test_layout_GoInterface() {
concat!("Alignment of ", stringify!(GoInterface)) concat!("Alignment of ", stringify!(GoInterface))
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<GoInterface>())).t as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).t) as usize - ptr as usize },
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -140,7 +141,7 @@ fn bindgen_test_layout_GoInterface() {
) )
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<GoInterface>())).v as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize },
8usize, 8usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -159,6 +160,8 @@ pub struct GoSlice {
} }
#[test] #[test]
fn bindgen_test_layout_GoSlice() { fn bindgen_test_layout_GoSlice() {
const UNINIT: ::std::mem::MaybeUninit<GoSlice> = ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<GoSlice>(), ::std::mem::size_of::<GoSlice>(),
24usize, 24usize,
@ -170,7 +173,7 @@ fn bindgen_test_layout_GoSlice() {
concat!("Alignment of ", stringify!(GoSlice)) concat!("Alignment of ", stringify!(GoSlice))
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).data as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize },
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -180,7 +183,7 @@ fn bindgen_test_layout_GoSlice() {
) )
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).len as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize },
8usize, 8usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -190,7 +193,7 @@ fn bindgen_test_layout_GoSlice() {
) )
); );
assert_eq!( assert_eq!(
unsafe { &(*(::std::ptr::null::<GoSlice>())).cap as *const _ as usize }, unsafe { ::std::ptr::addr_of!((*ptr).cap) as usize - ptr as usize },
16usize, 16usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
@ -200,6 +203,12 @@ fn bindgen_test_layout_GoSlice() {
) )
); );
} }
extern "C" {
pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char);
}
extern "C" {
pub fn c_Started() -> ::std::os::raw::c_int;
}
extern "C" { extern "C" {
pub fn c_StartCwtch( pub fn c_StartCwtch(
dir_c: *mut ::std::os::raw::c_char, dir_c: *mut ::std::os::raw::c_char,
@ -209,195 +218,13 @@ extern "C" {
) -> ::std::os::raw::c_int; ) -> ::std::os::raw::c_int;
} }
extern "C" { extern "C" {
pub fn c_Started() -> ::std::os::raw::c_int; pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char;
} }
extern "C" { extern "C" {
pub fn c_ReconnectCwtchForeground(); pub fn c_ReconnectCwtchForeground();
} }
extern "C" { extern "C" {
pub fn c_SendAppEvent(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int); pub fn c_ShutdownCwtch();
}
extern "C" {
pub fn c_SendProfileEvent(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
json_ptr: *mut ::std::os::raw::c_char,
json_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_GetAppBusEvent() -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_CreateProfile(
nick_ptr: *mut ::std::os::raw::c_char,
nick_len: ::std::os::raw::c_int,
pass_ptr: *mut ::std::os::raw::c_char,
pass_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_LoadProfiles(
passwordPtr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_AcceptConversation(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_BlockContact(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_UnblockContact(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_GetMessage(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
message_index: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_GetMessageByID(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
message_index: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_GetMessagesByContentHash(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
contenthash_ptr: *mut ::std::os::raw::c_char,
contenthash_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_GetMessages(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
message_index: ::std::os::raw::c_int,
count: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_FreePointer(ptr: *mut ::std::os::raw::c_char);
}
extern "C" {
pub fn c_SendMessage(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
msg_ptr: *mut ::std::os::raw::c_char,
msg_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_SendInvitation(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
target_id: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_ShareFile(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filepath_ptr: *mut ::std::os::raw::c_char,
filepath_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char;
}
extern "C" {
pub fn c_DownloadFile(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filepath_ptr: *mut ::std::os::raw::c_char,
filepath_len: ::std::os::raw::c_int,
manifestpath_ptr: *mut ::std::os::raw::c_char,
manifestpath_len: ::std::os::raw::c_int,
filekey_ptr: *mut ::std::os::raw::c_char,
filekey_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_CheckDownloadStatus(
profilePtr: *mut ::std::os::raw::c_char,
profileLen: ::std::os::raw::c_int,
fileKeyPtr: *mut ::std::os::raw::c_char,
fileKeyLen: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_VerifyOrResumeDownload(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
filekey_ptr: *mut ::std::os::raw::c_char,
filekey_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ResetTor();
}
extern "C" {
pub fn c_CreateGroup(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
server_ptr: *mut ::std::os::raw::c_char,
server_len: ::std::os::raw::c_int,
name_ptr: *mut ::std::os::raw::c_char,
name_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DeleteProfile(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
password_ptr: *mut ::std::os::raw::c_char,
password_len: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ArchiveConversation(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_DeleteContact(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
conversation_id: ::std::os::raw::c_int,
);
}
extern "C" {
pub fn c_ImportBundle(
profile_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int,
bundle_ptr: *mut ::std::os::raw::c_char,
bundle_len: ::std::os::raw::c_int,
);
} }
extern "C" { extern "C" {
pub fn c_SetProfileAttribute( pub fn c_SetProfileAttribute(
@ -438,80 +265,372 @@ extern "C" {
) -> *mut ::std::os::raw::c_char; ) -> *mut ::std::os::raw::c_char;
} }
extern "C" { extern "C" {
pub fn c_SetMessageAttribute( pub fn c_ResetTor();
profile_ptr: *mut ::std::os::raw::c_char, }
profile_len: ::std::os::raw::c_int, extern "C" {
conversation_id: ::std::os::raw::c_int, pub fn c_UpdateSettings(json_ptr: *mut ::std::os::raw::c_char, json_len: ::std::os::raw::c_int);
channel_id: ::std::os::raw::c_int, }
message_id: ::std::os::raw::c_int, extern "C" {
key_ptr: *mut ::std::os::raw::c_char, pub fn c_GetDebugInfo() -> *mut ::std::os::raw::c_char;
key_len: ::std::os::raw::c_int, }
val_ptr: *mut ::std::os::raw::c_char, extern "C" {
val_len: ::std::os::raw::c_int, pub fn c_ActivatePeerEngine(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
); );
} }
extern "C" { extern "C" {
pub fn c_ChangePassword( pub fn c_DeactivatePeerEngine(
profile_ptr: *mut ::std::os::raw::c_char, onion_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int, onion_len: ::std::os::raw::c_int,
oldpassword_ptr: *mut ::std::os::raw::c_char,
oldpassword_len: ::std::os::raw::c_int,
newpassword_ptr: *mut ::std::os::raw::c_char,
newpassword_len: ::std::os::raw::c_int,
newpassword_again_ptr: *mut ::std::os::raw::c_char,
newpassword_again_len: ::std::os::raw::c_int,
); );
} }
extern "C" { extern "C" {
pub fn c_ExportProfile( pub fn c_ConfigureConnections(
profile_ptr: *mut ::std::os::raw::c_char, onion_ptr: *mut ::std::os::raw::c_char,
profile_len: ::std::os::raw::c_int, onion_len: ::std::os::raw::c_int,
file_ptr: *mut ::std::os::raw::c_char, listen1: ::std::os::raw::c_char,
file_len: ::std::os::raw::c_int, 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" { extern "C" {
pub fn c_ImportProfile( pub fn c_ImportProfile(
file_ptr: *mut ::std::os::raw::c_char, file5_ptr: *mut ::std::os::raw::c_char,
file_len: ::std::os::raw::c_int, file5_len: ::std::os::raw::c_int,
passwordPtr: *mut ::std::os::raw::c_char, password_ptr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int, password_len: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_char; ) -> *mut ::std::os::raw::c_char;
} }
extern "C" { extern "C" {
pub fn c_ShutdownCwtch(); pub fn c_ChangePassword(
onion_ptr: *mut ::std::os::raw::c_char,
onion_len: ::std::os::raw::c_int,
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" { extern "C" {
pub fn c_LoadServers( pub fn c_ExportProfile(
passwordPtr: *mut ::std::os::raw::c_char, onion_ptr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int, 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" { extern "C" {
pub fn c_CreateServer( pub fn c_CreateServer(
passwordPtr: *mut ::std::os::raw::c_char, password_ptr: *mut ::std::os::raw::c_char,
passwordLen: ::std::os::raw::c_int, password_len: ::std::os::raw::c_int,
descPtr: *mut ::std::os::raw::c_char, description32_ptr: *mut ::std::os::raw::c_char,
descLen: ::std::os::raw::c_int, description32_len: ::std::os::raw::c_int,
autostart: ::std::os::raw::c_char, autostart33: ::std::os::raw::c_char,
); );
} }
extern "C" { extern "C" {
pub fn c_DeleteServer( pub fn c_SetServerAttribute(
onionPtr: *mut ::std::os::raw::c_char, handle34_ptr: *mut ::std::os::raw::c_char,
onionLen: ::std::os::raw::c_int, handle34_len: ::std::os::raw::c_int,
currentPasswordPtr: *mut ::std::os::raw::c_char, key35_ptr: *mut ::std::os::raw::c_char,
currentPasswordLen: ::std::os::raw::c_int, 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" { extern "C" {
pub fn c_LaunchServers(); pub fn c_LaunchServers();
} }
extern "C" { extern "C" {
pub fn c_LaunchServer(onionPtr: *mut ::std::os::raw::c_char, onionLen: ::std::os::raw::c_int); pub fn c_LaunchServer(
handle37_ptr: *mut ::std::os::raw::c_char,
handle37_len: ::std::os::raw::c_int,
);
} }
extern "C" { extern "C" {
pub fn c_StopServer(onionPtr: *mut ::std::os::raw::c_char, onionLen: ::std::os::raw::c_int); pub fn c_StopServer(
handle38_ptr: *mut ::std::os::raw::c_char,
handle38_len: ::std::os::raw::c_int,
);
} }
extern "C" { extern "C" {
pub fn c_StopServers(); pub fn c_StopServers();
@ -520,15 +639,10 @@ extern "C" {
pub fn c_DestroyServers(); pub fn c_DestroyServers();
} }
extern "C" { extern "C" {
pub fn c_SetServerAttribute( pub fn c_DeleteServer(
onionPtr: *mut ::std::os::raw::c_char, handle39_ptr: *mut ::std::os::raw::c_char,
onionLen: ::std::os::raw::c_int, handle39_len: ::std::os::raw::c_int,
keyPtr: *mut ::std::os::raw::c_char, password_ptr: *mut ::std::os::raw::c_char,
keyLen: ::std::os::raw::c_int, password_len: ::std::os::raw::c_int,
valPtr: *mut ::std::os::raw::c_char,
valLen: ::std::os::raw::c_int,
); );
} }
extern "C" {
pub fn c_GetDebugInfo() -> *mut ::std::os::raw::c_char;
}

845
src/event.rs Normal file
View File

@ -0,0 +1,845 @@
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,11 +3,16 @@
#![doc(html_root_url = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs")] #![doc(html_root_url = "https://git.openprivacy.ca/cwtch.im/libcwtch-rs")]
#![deny(missing_docs)] #![deny(missing_docs)]
use crate::event::{ConversationID, Event, FileKey, ProfileIdentity, ServerIdentity};
use crate::structs::{ACL, MessageWrapper, Settings, SharedFile};
mod bindings_go; mod bindings_go;
mod cwtchlib_go; mod cwtchlib_go;
/// Basic structs using data from Cwtch and for deserializing JSON and serializing to JSON to communicate with Cwtch /// Basic structs using data from Cwtch and for deserializing JSON and serializing to JSON to communicate with Cwtch
pub mod structs; 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 /// Error type for Cwtch lib related errors, intended for use with Result
pub type CwtchError = String; pub type CwtchError = String;
@ -20,104 +25,153 @@ pub trait CwtchLib {
/// Return 1 if cwtch has been started and 0 if not /// Return 1 if cwtch has been started and 0 if not
fn started(&self) -> i32; fn started(&self) -> i32;
/// Send json of a structs::CwtchEvent to the cwtch app bus /// Like StartCwtch, but StartCwtch has already been called so we don't need to restart Tor etc (probably)
fn send_app_event(&self, event_json: &str); /// Do need to re-send initial state tho, eg profiles that are already loaded (used by android when ui state is lost)
fn reconnect_cwtch_foreground(&self);
/// Send json of a structs::CwtchEvent to a cwtch profile /// Save and update the settings based on this settings
fn send_profile_event(&self, profile: &str, event_json: &str); fn update_settings(&self, settings: &Settings);
/// Activate the networking engine of a profile so it can send and listen to/for messages
fn activate_peer_engine(&self, profile: &ProfileIdentity);
/// Deactivate the networking engine of a profile so it cannot send and listen to/for messages
fn deactivate_peer_engine(&self, profile: &ProfileIdentity);
/// Pull json of a structs::CwtchEvent off the appbus for responding to /// Pull json of a structs::CwtchEvent off the appbus for responding to
fn get_appbus_event(&self) -> String; 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);
/// Create a new profile encrypted with pass /// Create a new profile encrypted with pass
fn create_profile(&self, nick: &str, pass: &str); fn create_profile(&self, nick: &str, pass: &str, autostart: bool);
/// Load any profiles encrypted by pass /// Load any profiles encrypted by pass
fn load_profiles(&self, pass: &str); fn load_profiles(&self, pass: &str);
/// Cause profile to accept conversation /// Cause profile to accept conversation
fn accept_conversation(&self, profile: &str, conversation_id: i32); fn accept_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to block conversation /// Cause profile to block conversation
fn block_contact(&self, profile: &str, conversation_id: i32); fn block_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to unblock contact /// Cause profile to unblock conversation
fn unblock_contact(&self, profile: &str, conversation_id: i32); fn unblock_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Get a specific message for conversation of profile by index /// Attempt to peer with a a new peer
fn get_message(&self, profile: &str, conversation_id: i32, message_index: i32) -> String; fn peer_with(&self, profile: &ProfileIdentity, new_peer_address: &str);
/// manually disconnect from a conversation
fn disconnect_from_peer(&self, profile: &ProfileIdentity, peer_id: &str);
/// 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 a conversation by its id /// Get a specific message for a conversation by its id
fn get_message_by_id(&self, profile: &str, conversation_id: i32, message_id: i32) -> String; fn get_message_by_id(&self, profile: &ProfileIdentity, conversation_id: ConversationID, message_id: i32) -> String;
/// Get a specific message for conversation of profile by hash /// Get a specific message for conversation of profile by hash
fn get_message_by_content_hash( fn get_message_by_content_hash(
&self, &self,
profile: &str, profile: &ProfileIdentity,
conversation_id: i32, conversation_id: ConversationID,
hash: &str, hash: &str,
) -> String; ) -> String;
/// Bulk get messages starting at message index and of count amoung /// Bulk get messages starting at message index and of count amoung
fn get_messages(&self, profile: &str, conversation_id: i32, message_index: i32, count: i32) -> String; 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) /// Send json of a structs::Message from profile to contact. Returns computed sent message (including index and hash values)
fn send_message(&self, profile: &str, conversation_id: i32, msg: &str) -> String; 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) /// Send profile's contact an invite for/to target. Returns computed sent message (including index and hash values)
fn send_invitation(&self, profile: &str, conversation_id: i32, target_id: i32) -> String; 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) /// share a file file_path with a conersation. Returns computed sent message (including index and hash values)
fn share_file(&self, profile: &str, conversation_id: i32, file_path: &str) -> String; 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 /// download a file from a conversation to the file_path
fn download_file( fn download_file_default_limit(
&self, &self,
profile: &str, profile: &ProfileIdentity,
conversation_id: i32, conversation_id: ConversationID,
file_path: &str, file_path: &str,
manifest_path: &str, manifest_path: &str,
file_key: &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 /// Query the status of a download
fn check_download_status(&self, profile: &str, file_key: &str); fn check_download_status(&self, profile: &ProfileIdentity, file_key: &FileKey);
/// Verufy a download is done, and if not, resume it /// Verufy a download is done, and if not, resume it
fn verify_or_resume_download(&self, profile: &str, conversation_id: i32, file_key: &str); fn verify_or_resume_download(&self, profile: &ProfileIdentity, conversation_id: ConversationID, file_key: &FileKey);
/// Ask the ACN inside the Cwtch app to restart the tor connection /// 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 /// Cause profile to create a group on server with name
fn create_group(&self, profile: &str, server: &str, name: &str); 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);
/// Delete profile with encryption/password check of pass /// Delete profile with encryption/password check of pass
fn delete_profile(&self, profile: &str, pass: &str); fn delete_profile(&self, profile: &ProfileIdentity, pass: &str);
/// Cause profile to archive conversation with contact /// Cause profile to archive conversation with contact
fn archive_conversation(&self, profile: &str, conversation_id: i32); fn archive_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cause profile to delete contact/group identified by handle /// Cause profile to delete contact/group identified by handle
fn delete_contact(&self, profile: &str, conversation_id: i32); fn delete_conversation(&self, profile: &ProfileIdentity, conversation_id: ConversationID);
/// Cuase profile to attempt to import a contact/group/keybundle identified by bundle /// Cuase profile to attempt to import a contact/group/keybundle identified by bundle
fn import_bundle(&self, profile: &str, bundle: &str); fn import_bundle(&self, profile: &ProfileIdentity, bundle: &str);
/// Set a profile attribute key to val /// Set a profile attribute key to val
fn set_profile_attribute(&self, profile: &str, key: &str, val: &str); fn set_profile_attribute(&self, profile: &ProfileIdentity, key: &str, val: &str);
/// Get a profile attribute /// Get a profile attribute
fn get_profile_attribute(&self, profile: &str, key: &str) -> Result<Option<String>, CwtchError>; fn get_profile_attribute(&self, profile: &ProfileIdentity, key: &str) -> Result<Option<String>, CwtchError>;
/// Set a profile's contact's attribute of key to val /// Set a profile's contact's attribute of key to val
fn set_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str, val: &str); fn set_conversation_attribute(&self, profile: &ProfileIdentity, conversation_id: ConversationID, key: &str, val: &str);
/// Set an attribute on a message in a conversation /// Update an attribute on a message in a conversation
fn set_message_attribute( fn update_message_attribute(
&self, &self,
profile: &str, profile: &ProfileIdentity,
conversation_id: i32, conversation_id: ConversationID,
channel_id: i32, channel_id: i32,
message_id: i32, message_id: i32,
attribute_key: &str, attribute_key: &str,
@ -125,13 +179,13 @@ pub trait CwtchLib {
); );
/// Get an attribute for a conversation /// Get an attribute for a conversation
fn get_conversation_attribute(&self, profile: &str, conversation_id: i32, key: &str) -> Result<Option<String>, CwtchError>; 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 /// Change a profile's password to new_pass if old_pass is correct
fn change_password(&self, profile: &str, old_pass: &str, new_pass: &str, new_pass_again: &str); fn change_password(&self, profile: &ProfileIdentity, old_pass: &str, new_pass: &str, new_pass_again: &str);
/// Export a profile to filename /// Export a profile to filename
fn export_profile(&self, profile: &str, filename: &str); 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 /// 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; fn import_profile(&self, filename: &str, password: &str) -> String;
@ -144,20 +198,20 @@ pub trait CwtchLib {
/// Load all servers encrypted by password /// Load all servers encrypted by password
fn load_servers(&self, password: &str); fn load_servers(&self, password: &str);
/// Create a new server, encrypted with password, autostart i8 used as bool /// Create a new server, encrypted with password
fn create_server(&self, password: &str, description: &str, autostart: i8); fn create_server(&self, password: &str, description: &str, autostart: bool);
/// Delete the specified server (if password is correct) /// Delete the specified server (if password is correct)
fn delete_server(&self, onion: &str, current_password: &str); fn delete_server(&self, server: ServerIdentity, current_password: &str);
/// Launch all loaded servers /// Launch all loaded servers
fn launch_servers(&self); fn launch_servers(&self);
/// Launch the specified server /// Launch the specified server
fn launch_server(&self, onion: &str); fn launch_server(&self, server: ServerIdentity);
/// Stop the specified server /// Stop the specified server
fn stop_server(&self, onion: &str); fn stop_server(&self, server: ServerIdentity);
/// Stop all running servers /// Stop all running servers
fn stop_servers(&self); fn stop_servers(&self);
@ -166,7 +220,7 @@ pub trait CwtchLib {
fn destroy_servers(&self); fn destroy_servers(&self);
/// Set the specified server's attribute of key to val /// Set the specified server's attribute of key to val
fn set_server_attribute(&self, onion: &str, key: &str, val: &str); fn set_server_attribute(&self, server: ServerIdentity, key: &str, val: &str);
/// Get debug info (mem, goroutine stats) from lcg in json /// Get debug info (mem, goroutine stats) from lcg in json
fn get_debug_info(&self) -> String; fn get_debug_info(&self) -> String;

View File

@ -1,10 +1,12 @@
use crate::structs::ConnectionState::Disconnected; use crate::structs::ConnectionState::Disconnected;
use crate::CwtchLib; use crate::{ConversationID, CwtchLib, ProfileIdentity};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DefaultOnError}; use serde_with::{serde_as, DefaultOnError};
use serde_repr::*;
use std::collections::HashMap; use std::collections::HashMap;
use crate::event::{ContactIdentity, FileKey};
#[derive(Serialize, Deserialize, Debug)] #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
/// Defines the states a Cwtch connection can be in /// Defines the states a Cwtch connection can be in
pub enum ConnectionState { pub enum ConnectionState {
/// The Cwtch connection is not conected at all /// The Cwtch connection is not conected at all
@ -29,9 +31,9 @@ impl Default for ConnectionState {
} }
} }
impl ConnectionState { impl From<&str> for ConnectionState {
/// Creates a ConnectionState from a string sent from libcwtch-go /// Creates a ConnectionState from a string sent from libcwtch-go
pub fn new(name: &str) -> Self { fn from(name: &str) -> Self {
match name { match name {
"Disconnected" => ConnectionState::Disconnected, "Disconnected" => ConnectionState::Disconnected,
"Connecting" => ConnectionState::Connecting, "Connecting" => ConnectionState::Connecting,
@ -81,7 +83,7 @@ pub struct CwtchEvent {
pub data: HashMap<String, String>, pub data: HashMap<String, String>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
#[allow(non_snake_case)] #[allow(non_snake_case)]
/// AccessControl is a type determining client assigned authorization to a peer /// AccessControl is a type determining client assigned authorization to a peer
@ -92,21 +94,33 @@ pub struct AccessControl {
pub read: bool, pub read: bool,
/// Allows a handle to append new messages to the conversation /// Allows a handle to append new messages to the conversation
pub append: bool, 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 /// represents an access control list for a conversation. Mapping handles to conversation functions
pub type ACL = HashMap<String, AccessControl>; pub type ACL = HashMap<String, AccessControl>;
#[serde_as] #[serde_as]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
/// Struct to serialize/deserialize conversations coming from libcwtch-go /// Struct to serialize/deserialize conversations coming from libcwtch-go
pub struct Conversation { pub struct Conversation {
/// onion address / id of the conversation /// onion address / id of the conversation
#[serde(alias = "onion")] #[serde(alias = "onion")]
pub handle: String, pub contact_id: ContactIdentity,
/// unique identifier of the contact/conversation to be used in API access /// unique identifier of the contact/conversation to be used in API access
pub identifier: i32, 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 /// display name of the conversation, as determined in libcwtch-go from name specified by contact
pub name: String, pub name: String,
#[serde_as(deserialize_as = "DefaultOnError")] #[serde_as(deserialize_as = "DefaultOnError")]
@ -125,7 +139,7 @@ pub struct Conversation {
//attr: HashMap<String, String>, //attr: HashMap<String, String>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, Clone)]
/// Struct to serialize/deserialize servers coming from libcwtch-go /// Struct to serialize/deserialize servers coming from libcwtch-go
pub struct Server { pub struct Server {
/// onion address of the server /// onion address of the server
@ -134,13 +148,11 @@ pub struct Server {
pub status: ConnectionState, pub status: ConnectionState,
} }
#[serde_as] #[derive(Debug, Clone)]
#[derive(Debug, Serialize, Deserialize)]
/// Struct to serialize/deserialize profiles coming from libcwtch-go /// Struct to serialize/deserialize profiles coming from libcwtch-go
pub struct Profile { pub struct Profile {
/// onion address / ID of the profile /// onion address / ID of the profile
#[serde(alias = "onion")] pub profile_id: ProfileIdentity,
pub handle: String,
/// nick name of the onion as supplied by libcwtch-go based on "name" attribute /// nick name of the onion as supplied by libcwtch-go based on "name" attribute
pub nick: String, pub nick: String,
/// path to a profile image, controled by "picture" attribute /// path to a profile image, controled by "picture" attribute
@ -148,22 +160,158 @@ pub struct Profile {
/// all profile attributes /// all profile attributes
pub attr: HashMap<String, String>, pub attr: HashMap<String, String>,
/// map of conversation [ onion => conversation ] /// map of conversation [ onion => conversation ]
pub conversations: HashMap<String, Conversation>, pub conversations: HashMap<ConversationID, Conversation>,
/// map of servers [ onion => server ] /// map of servers [ onion => server ]
pub servers: HashMap<String, Server>, pub servers: HashMap<String, Server>,
} }
#[derive(Debug, Serialize, Deserialize)] #[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 /// Struct to serialize/deserialize messages sent over Cwtch between profiles / conversation
pub struct Message { /// Overlay => data
/// 1 TextMessage: d = plain text message
/// 10 QuotedMessage: d = json of QuotedMessageStructure, body = plain text of message
pub struct MessageWrapper {
/// overlay id that the message is targeting as defined in cwtch/model/overlay.go /// overlay id that the message is targeting as defined in cwtch/model/overlay.go
/// [ OverlayChat = 1, OverlayInviteContact = 100, OverlayInviteGroup = 101, OverlayFileSharing = 200 ] /// [ OverlayChat = 1, OverlayInviteContact = 100, OverlayInviteGroup = 101, OverlayFileSharing = 200 ]
pub o: i64, pub o: MessageType,
/// data of the message /// data of the message, for OverlayChat, a
pub d: String, pub d: String,
} }
#[derive(Debug, Serialize, Deserialize)] 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() /// 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)] #[allow(non_snake_case)]
pub struct Settings { pub struct Settings {
@ -242,20 +390,7 @@ impl Experiments {
impl Settings { impl Settings {
/// Given a CwtchLib, handles sending an event to it with updated settings represented by this struct for saving /// 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> { pub fn save(&self, cwtch: &dyn CwtchLib) -> Result<(), String> {
let settings_json = match serde_json::to_string(&self) { cwtch.update_settings(&self);
Ok(s) => s,
Err(e) => return Err(e.to_string()),
};
let save_settings_event: CwtchEvent = CwtchEvent {
event_type: "UpdateGlobalSettings".to_string(),
event_ID: "0".to_string(),
data: HashMap::from([("Data".to_string(), settings_json)]),
};
let event_json = match serde_json::to_string(&save_settings_event) {
Ok(s) => s,
Err(e) => return Err(e.to_string()),
};
cwtch.send_app_event(&event_json);
return Ok(()); return Ok(());
} }
} }
@ -265,7 +400,7 @@ impl Profile {
/// contacts_json as supplied by libcwtch-go, a map of conversations /// contacts_json as supplied by libcwtch-go, a map of conversations
/// server_list as supplied by libcwtch-go, a map of servers /// server_list as supplied by libcwtch-go, a map of servers
pub fn new( pub fn new(
identity: &str, identity: ProfileIdentity,
name: &str, name: &str,
picture: &str, picture: &str,
conversations_json: &str, conversations_json: &str,
@ -280,7 +415,7 @@ impl Profile {
Err(e) => return Err(e), Err(e) => return Err(e),
}; };
Ok(Profile { Ok(Profile {
handle: identity.to_string(), profile_id: identity,
nick: name.to_string(), nick: name.to_string(),
image_path: picture.to_string(), image_path: picture.to_string(),
attr: Default::default(), attr: Default::default(),
@ -289,8 +424,8 @@ impl Profile {
}) })
} }
fn process_conversations(conversations_json: &str) -> Result<HashMap<String, Conversation>, String> { fn process_conversations(conversations_json: &str) -> Result<HashMap<ConversationID, Conversation>, String> {
let mut conversations: HashMap<String, Conversation> = HashMap::new(); let mut conversations: HashMap<ConversationID, Conversation> = HashMap::new();
if conversations_json == "null" { if conversations_json == "null" {
return Ok(conversations); return Ok(conversations);
} }
@ -299,7 +434,7 @@ impl Profile {
Err(e) => return Err(format!("invalid json: {:?}", e)), Err(e) => return Err(format!("invalid json: {:?}", e)),
}; };
for conversation in conversations_map { for conversation in conversations_map {
conversations.insert(conversation.handle.clone(), conversation); conversations.insert(conversation.identifier, conversation);
} }
Ok(conversations) Ok(conversations)
} }
@ -318,4 +453,12 @@ impl Profile {
} }
Ok(servers) Ok(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
}
}
} }