diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3961e91 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/target +threematrix_cfg.toml +.idea +.DS_Store + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1bee635 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3148 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "actix-codec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "log", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "actix-http" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2e9f6794b5826aff6df65e3a0d0127b271d1c03629c774238f3582e903d4e4" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand 0.8.5", + "sha1", + "smallvec", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "actix-router" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb60846b52c118f2f04a56cc90880a274271c489b2498623d58176f8ca21fa80" +dependencies = [ + "bytestring", + "firestorm", + "http", + "log", + "regex", + "serde", +] + +[[package]] +name = "actix-rt" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "num_cpus", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2", + "time", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", + "rand_core 0.6.3", +] + +[[package]] +name = "aes" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe0133578c0986e1fe3dfcd4af1cc5b2dd6c3dbf534d69916ce16a2701d40ba" +dependencies = [ + "cfg-if", + "cipher 0.4.3", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.7", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" + +[[package]] +name = "anymap2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +dependencies = [ + "serde", +] + +[[package]] +name = "assign" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-once-cell" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72faff1fdc615a0199d7bf71e6f389af54d46a66e9beb5d76c39e48eda93ecce" + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "futures-core", + "getrandom 0.2.7", + "instant", + "pin-project-lite", + "rand 0.8.5", + "tokio", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "base64ct" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake3" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.3", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[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 = "block-padding" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a90ec2df9600c28a01c56c4784c9207a96d2451833aeceb8cc97e4c9548bb78" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "bytestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b6a75fd3048808ef06af5cd79712be8111960adaf89d90250974b38fc3928a" +dependencies = [ + "bytes", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher 0.4.3", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" +dependencies = [ + "aead", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "once_cell", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[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 = "ctr" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d14f329cfbaf5d0e06b5e87fff7e265d2673c5ea7d2c27691a2c107db1442a0" +dependencies = [ + "cipher 0.4.3", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "dashmap" +version = "5.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" +dependencies = [ + "cfg-if", + "hashbrown 0.12.1", + "lock_api", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "data-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" + +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid 0.6.2", +] + +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid 0.7.1", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ed25519" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +dependencies = [ + "serde", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "serde_bytes", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "firestorm" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c5f6c2c942da57e2aaaa84b8a521489486f14e75e7fa91dab70aba913975f98" + +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flexi_logger" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee9a6796ff68a1014f6665dac55341820f26e63ec706e58bfaee468cf0ac174f" +dependencies = [ + "ansi_term", + "atty", + "glob", + "lazy_static", + "log", + "regex", + "rustversion", + "thiserror", + "time", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[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 = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "h2" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.3", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexed_db_futures" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26ac735f676c52305becf53264b91cea9866a8de61ccbf464405b377b9cbca9" +dependencies = [ + "cfg-if", + "js-sys", + "uuid 0.8.2", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown 0.12.1", + "serde", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "js_int" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d937f95470b270ce8b8950207715d71aa8e153c0d44c6684d59397ed4949160a" +dependencies = [ + "serde", +] + +[[package]] +name = "js_option" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68421373957a1593a767013698dbf206e2b221eefe97a44d98d18672ff38423c" +dependencies = [ + "serde", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "libsodium-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd" +dependencies = [ + "cc", + "libc", + "pkg-config", + "walkdir", +] + +[[package]] +name = "local-channel" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" +dependencies = [ + "futures-core", + "futures-sink", + "futures-util", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lru" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c84e6fe5655adc6ce00787cf7dcaf8dc4f998a0565d23eafc207a8b08ca3349a" +dependencies = [ + "hashbrown 0.11.2", +] + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "matrix-sdk" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afed7115d3dbf0c91c062b2904c964e2405b2e1f8de5511c5eeae7583b70ebe" +dependencies = [ + "anymap2", + "async-once-cell", + "async-stream", + "async-trait", + "backoff", + "bytes", + "dashmap", + "event-listener", + "futures-core", + "futures-util", + "http", + "matrix-sdk-base", + "matrix-sdk-common", + "matrix-sdk-indexeddb", + "matrix-sdk-sled", + "mime", + "reqwest", + "ruma", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "url", + "wasm-timer", + "zeroize", +] + +[[package]] +name = "matrix-sdk-base" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59a52c744df124832643ecfc03ffb468023e9c3644477f41bf316d500df9504" +dependencies = [ + "async-stream", + "async-trait", + "dashmap", + "futures-channel", + "futures-core", + "futures-util", + "lru", + "matrix-sdk-common", + "matrix-sdk-crypto", + "ruma", + "serde", + "serde_json", + "thiserror", + "tracing", + "zeroize", +] + +[[package]] +name = "matrix-sdk-common" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a8af49e5b15c2dee4c0e867cd8065bb999cc63ff2500a0d35331188a9acbae" +dependencies = [ + "async-lock", + "futures-util", + "instant", + "ruma", + "serde", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "matrix-sdk-crypto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ed05a03bcceec396d594df8b6bf8601db8d017611c5ede0ba27f59aee24480" +dependencies = [ + "aes", + "async-trait", + "atomic", + "base64", + "byteorder", + "ctr", + "dashmap", + "futures-util", + "hmac", + "matrix-sdk-common", + "pbkdf2", + "rand 0.8.5", + "ruma", + "serde", + "serde_json", + "sha2 0.10.2", + "thiserror", + "tracing", + "vodozemac", + "zeroize", +] + +[[package]] +name = "matrix-sdk-indexeddb" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad42c7e9fdbb9373c08ef1f4fd4a15d6000f2fe35aefae20b3be50a3fac91a4a" +dependencies = [ + "anyhow", + "async-trait", + "base64", + "dashmap", + "futures-util", + "getrandom 0.2.7", + "indexed_db_futures", + "matrix-sdk-base", + "matrix-sdk-crypto", + "matrix-sdk-store-encryption", + "ruma", + "serde", + "serde_json", + "thiserror", + "tracing", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "matrix-sdk-sled" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b9fea0772f3ccf7b82b3b35db7687a18fc9e8dbf3daeb57214b1a023ddf5be" +dependencies = [ + "async-stream", + "async-trait", + "dashmap", + "futures-core", + "futures-util", + "matrix-sdk-base", + "matrix-sdk-common", + "matrix-sdk-crypto", + "matrix-sdk-store-encryption", + "ruma", + "serde", + "serde_json", + "sled", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "matrix-sdk-store-encryption" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd87e2c3e266dc9512d03b45f0771005c621c8fae12c74c766c97b1c756b942" +dependencies = [ + "blake3", + "chacha20poly1305", + "displaydoc", + "hmac", + "pbkdf2", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.10.2", + "thiserror", + "zeroize", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "password-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e029e94abc8fb0065241c308f1ac6bc8d20f450e8f7c5f0b25cd9b8d526ba294" +dependencies = [ + "base64ct", + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.3", + "hmac", + "password-hash", + "sha2 0.10.2", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs7" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7364e6d0e236473de91e042395d71e0e64715f99a60620b014a4a4c7d1619b" +dependencies = [ + "der 0.5.1", + "spki 0.5.4", +] + +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +dependencies = [ + "der 0.4.5", + "spki 0.4.1", + "zeroize", +] + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.7", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ruma" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6602cb2ef70629013d1bfade5aeb775d971a5d87f008dd6a8c99566235fa1933" +dependencies = [ + "assign", + "js_int", + "ruma-client-api", + "ruma-common", + "ruma-federation-api", + "ruma-signatures", + "ruma-state-res", +] + +[[package]] +name = "ruma-client-api" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4339827423dbb3b4f86cb191a38621f12daef73cb304ffd4e050c9ee553ecbd6" +dependencies = [ + "assign", + "bytes", + "http", + "js_int", + "maplit", + "percent-encoding", + "ruma-common", + "serde", + "serde_json", +] + +[[package]] +name = "ruma-common" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec5360fd23ff56310f9eb571927614feeecceba91fe2d4937f031c236c0e86e" +dependencies = [ + "base64", + "bytes", + "form_urlencoded", + "getrandom 0.2.7", + "http", + "indexmap", + "itoa", + "js-sys", + "js_int", + "js_option", + "percent-encoding", + "rand 0.8.5", + "ruma-identifiers-validation", + "ruma-macros", + "serde", + "serde_json", + "thiserror", + "tracing", + "url", + "uuid 1.1.2", + "wildmatch", +] + +[[package]] +name = "ruma-federation-api" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa53fa447e3ef04889f3f804d49a27045da79e8055f6fd4257c21be6f65edca" +dependencies = [ + "js_int", + "ruma-common", + "serde", + "serde_json", +] + +[[package]] +name = "ruma-identifiers-validation" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c3b1d01b5ddd8746f25d5971bc1cac5d7f1f455de839a2f817b9e04953a139" +dependencies = [ + "thiserror", +] + +[[package]] +name = "ruma-macros" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1a4faf04110071ce7ca438ad0763bdaa5514395593596320c0ca0936519656" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "ruma-identifiers-validation", + "syn", +] + +[[package]] +name = "ruma-signatures" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c747652a4f8c5fd83a703f183c73738b2ed8565a740636c045e064ae77f9b51" +dependencies = [ + "base64", + "ed25519-dalek", + "pkcs8", + "rand 0.7.3", + "ruma-common", + "serde_json", + "sha2 0.9.9", + "thiserror", + "tracing", +] + +[[package]] +name = "ruma-state-res" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9b742ca53b37ec3b3cfba1f27bf64be775550aeadf971deb05e4b93cdd27fbe" +dependencies = [ + "itertools", + "js_int", + "ruma-common", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "signal-hook-tokio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213241f76fb1e37e27de3b6aa1b068a2c333233b59cca6634f634b80a27ecf1e" +dependencies = [ + "futures-core", + "libc", + "signal-hook", + "tokio", +] + +[[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + +[[package]] +name = "slab" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" + +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + +[[package]] +name = "smallvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "sodiumoxide" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028" +dependencies = [ + "ed25519", + "libc", + "libsodium-sys", + "serde", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +dependencies = [ + "der 0.4.5", +] + +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "der 0.5.1", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "threema-gateway" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5155a6752d66396b91b85b7a2c14bc02cd843212a219db067468ed2b7bc691b7" +dependencies = [ + "byteorder", + "data-encoding", + "form_urlencoded", + "log", + "mime", + "reqwest", + "serde", + "serde_json", + "serde_urlencoded", + "sodiumoxide", + "thiserror", +] + +[[package]] +name = "threematrix" +version = "0.1.0" +dependencies = [ + "actix-web", + "flexi_logger", + "futures", + "log", + "matrix-sdk", + "rand 0.8.5", + "serde", + "serde_derive", + "signal-hook", + "signal-hook-tokio", + "thiserror", + "threema-gateway", + "tokio", + "toml", +] + +[[package]] +name = "time" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot 0.12.1", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "unicode-normalization" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.7", +] + +[[package]] +name = "uuid" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +dependencies = [ + "getrandom 0.2.7", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vodozemac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a42265bb5d65ba2807e477741ca3147a58d25ee5463860491fe0c24f4d21c1a" +dependencies = [ + "aes", + "arrayvec", + "base64", + "cbc", + "ed25519-dalek", + "hkdf", + "hmac", + "pkcs7", + "prost", + "rand 0.7.3", + "serde", + "serde_json", + "sha2 0.10.2", + "thiserror", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +dependencies = [ + "cfg-if", + "serde", + "serde_json", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "wildmatch" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0" + +[[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-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "x25519-dalek" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "serde", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.1+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +dependencies = [ + "cc", + "libc", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0d42ab3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "threematrix" +version = "0.1.0" +edition = "2021" + +[dependencies] +threema-gateway = "0.15.1" +tokio = { version = "1", features = ["full"] } +actix-web = "4" +rand = "0.8.5" +toml = "0.5.9" +serde = "1.0.137" +serde_derive = "^1.0" +matrix-sdk = "0.5.0" +signal-hook = "0.3.14" +signal-hook-tokio = { features = ["futures-v0_3"], version = "0.3.1" } +futures = "0.3.21" +log = "0.4.17" +flexi_logger = "0.22.5" +thiserror="1.0.31" \ No newline at end of file diff --git a/README.md b/README.md index c4d1593..46078c5 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,67 @@ # Threematrix ![Mastodon Follow](https://img.shields.io/mastodon/follow/107838426834517530?domain=https%3A%2F%2Fmastodon.social&style=social) ![Matrix](https://img.shields.io/matrix/threematrix:matrix.org?label=Chat%20on%20Matrix&style=social) -> Threematrix is a proposed bridge between the Threema messenger and the Matrix protocol. It is currently a work-in-progress project and is being funded via the Prototype Fund. +> Threematrix is a work-in-progress bridge software – written in Rust – between the Threema messenger (based on the Threema Gateway API) and the Matrix protocol. It's currently being funded via the German Prototype Fund. + +![threematrix_hero](https://user-images.githubusercontent.com/4677417/179420224-af18f988-34b0-43e5-a9bd-7abbe22f70f4.png) ## Status -This project was submitted and accepted for funding via the 11th round of the [German Prototype Fund](https://prototypefund.de/), which aims to fund public interest technologies under open source licenses. The funding period started on **March 1st 2022** and will last for 6 months. +This project was submitted and accepted for funding via the 11th round of the [German Prototype Fund](https://prototypefund.de/), which aims to fund public interest technologies under open source licenses. The funding period started on **March 1st 2022** and will last for six months until the end of August 2022. The software is currently in Alpha stadium (meaning it can be tested, but shouldn't be used in production, yet). + +## Cost Disclaimer +Currently this software is built to work with Threemas commercial Gateway API product – which uses a [per-message pricing model](https://gateway.threema.ch/en/products) and has a one-time setup fee of around 64 Euro. Their **pricing model is not well suited for the use with a messsenger bridge**, because typically controlling the amount of messages is out of the hand of the bridge admin. Also, group messages are just implemented as regular text messages to every group member. So for the bridge to receive a single message from Matrix and forward it to a 100 member Threema group, will be equal to sending 100 single text messages (costing you 100 credits which equals a price between 2 and 5 Euro – depending on how much credits you bought). **BE AWARE THAT THE BRIDGE MIGHT USE UP YOUR THREEMA CREDITS VERY FAST – DON'T PUT LARGE AMOUNTS OF CREDITS/MONEY IN YOUR ACCOUNT AND BE VERY CAREFUL WHEN ADDING THE BRIDGE TO LARGE THREEMA GROUPS.** + +We have been in contact with Threema and have told them how unfortunate the current pricing model is for use in a messenger bridge – especially for private/hobbyist use. They seemed to understand our problem and they will think about possible solutions for this problem. We hope that we will be able to find a (more affordable) pricing solution for future use of our bridge. + +## Security Disclaimer +Both Threema and Matrix are products known for their E2E Encryption capabilities. While "both sides" might offer strong encryption, a messenger bridge is conceptually always a weak point in encryption. To forward messages the bridge needs to decrypt the incoming message and encrypt it again for the outgoing side. This means that the bridge is capable of reading the content of messages passing through it. **Please don't use a bridge for sensitive communication and make sure you know who has access to the bridge server.** + +## Setup instructions + + +### Getting a Threema Gateway Account and Threema ID +Sign up for a [Threema Gateway account](https://gateway.threema.ch/en/signup), charge it up with at least 1600 credits (the setup fee to get a Threema ID) and request a new "End-to-End" Threema ID in the backend (enter your desired ID and username and generate a key pair according to their instructions – you can leave the URL empty for now). + +### Create Matrix bot account on your Matrix Homeserver +Sign up for a new user account on your favorite Matrix homeserver, e.g. via Element. Take note of your username and password, you will need to add it to the `threematrix_config.toml` file. + +### Set up reverse proxy +Threema calls a `/callback` HTTPS endpoint on your server, every time you receive a message. So you need to make sure that your server can be reached from the internet via a domain name (IP address will not work, because it needs to have a TLS certificate – which is only available for domain names, not for IP addresses). You need to set up a reverse proxy to accept and terminate TLS connections. As an example, you could use [Caddy](https://caddyserver.com/) as a reverse proxy with the following command: + +``` +caddy reverse-proxy --from mydomain.com --to localhost:8888 +``` + +### Clone repo and build project +Clone the repository to your server and install rust (we recommend using [rustup](https://rustup.rs/)), then build the binary via `cargo build --release` + +### Edit config file +Add Threema Gateway data (`secret`, `private_key`, `gateway_own_id`) and Matrix config (`homeserver_url`, `user`, `password`) to the config file. See the `threematrix_cfg_example.toml` for example data. + +### Run the binary +From your root folder (the folder where you cloned the repo), run `./target/release/threematrix` and hopefully you should see output like this: + +``` +INFO [threematrix] Starting Threematrix Server v0.1.0. Waiting for Threema callback on localhost:8888 +``` + +### Invite Bot to the Rooms +Now you can invite the Threema user to your Threema group, and also invite the bot user to your desired Matrix room. **Also, you need to give the bot user moderator rights (power level >= 50).** -First code will be committed some time during April 2022. +### Bind rooms +Send `!threematrix bind !a1b2c3:myserver.com` via Threema to bind two rooms together. It is not necessary to rebind after the bridge has crashed or restarted, but it is required to send a Message from the Threema side first. If you don't do this, Matrix messages might get lost – even though the bridge is running. ## Motivation While Threema is a great messenger app for many purposes, it can become difficult to use for larger organizations. The lack of room directories or the limitation of groups only having a single admin user are hard to work around once your organization grows bigger. For users it's very hard to leave Threema behind, even though theoretically it is an Open Source project, because in reality there are very few 3rd-party-integrations of the Threema protocol. We're trying to open Threema up to the world of Matrix. ## Team -We are Fabian and Moritz, two software developers from Hamburg, Germany. We initially met during our Computer Science bachelor programme at HAW Hamburg and have been developing various freelance software projects since then. +We are Fabian and Moritz, two software developers from Hamburg, Germany. We initially met during our Computer Science bachelor programme at HAW Hamburg and have been developing various freelance software projects under our brand name **bitbetter** since then. ## Community Feel free to join our Matrix room [#threema-bridge:matrix.org](https://matrix.to/#/#threema-bridge:matrix.org) if you want to follow our development process. Also, you can follow our [Mastodon-Account @threematrix@mastodon.social](https://mastodon.social/web/@threematrix) to stay up to date. ## Legal Disclaimer -This project has no connection or affiliation with Threema or Threema GmbH. +This project has no connection or affiliation with any of the involved "sides" – neither Threema, Threema GmbH nor Matrix. ## Funding
diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..6370cab --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,39 @@ +use std::num::ParseIntError; +use std::string::FromUtf8Error; +use thiserror::Error; +use threema_gateway::errors::{ApiError, CryptoError}; + +#[derive(Debug, Error)] +pub enum SendGroupMessageError { + #[error("Members of group are unknown, because we haven't received any message in this group yet. Try sending a Threema message first.")] + GroupNotInCache, + #[error("{0}")] + ApiError(ApiError), +} + +#[derive(Debug, Error)] +pub enum ProcessIncomingMessageError { + #[error("{0}")] + CryptoError(CryptoError), + #[error("{0}")] + ApiError(ApiError), + #[error("{0}")] + Utf8ConvertError(FromUtf8Error), + #[error("Unknown Message Type")] + UnknownMessageTypeError, +} + + +#[derive(Debug, Error)] +pub enum StringifyGroupIdError { + #[error("Group Id is empty")] + EmptyGroupId, +} + +#[derive(Debug, Error)] +pub enum ParseGroupIdError { + #[error("Group Id should consist of 8 x u8 chars, separated by spaces")] + InvalidGroupIdLength, + #[error("Group Id chars should be between 0 and 255 : {0}")] + EncodingError(ParseIntError), +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9f362a2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,365 @@ +use std::fs::read_to_string; + +use actix_web::{http::header::ContentType, web, HttpResponse, Responder}; +use log::{debug, error, info, warn}; +use matrix_sdk::event_handler::Ctx; +use matrix_sdk::room::{Joined, Room}; +use matrix_sdk::ruma::events::room::message::{ + MessageType, RoomMessageEventContent, TextMessageEventContent, +}; +use matrix_sdk::ruma::events::OriginalSyncMessageLikeEvent; +use matrix_sdk::ruma::TransactionId; +use matrix_sdk::Client; +use serde_derive::{Deserialize, Serialize}; +use threema_gateway::IncomingMessage; +use tokio::sync::Mutex; + +use threema::types::Message; + +use crate::matrix::util::{ + get_threematrix_room_state, set_threematrix_room_state, ThreematrixStateEventContent, +}; +use crate::threema::util::{ + convert_group_id_from_readable_string, convert_group_id_to_readable_string, +}; +use crate::threema::ThreemaClient; + +pub mod errors; +pub mod matrix; +pub mod threema; +pub mod util; + +pub struct AppState { + pub threema_client: ThreemaClient, + pub matrix_client: Mutex, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ThreemaConfig { + pub secret: String, + pub private_key: String, + pub gateway_own_id: String, + pub port: Option, + pub host: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct MatrixConfig { + pub homeserver_url: String, + pub user: String, + pub password: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct LoggerConfig { + pub level: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ThreematrixConfig { + pub threema: ThreemaConfig, + pub matrix: MatrixConfig, + pub logger: Option, +} + +impl ThreematrixConfig { + pub fn new(path: &str) -> ThreematrixConfig { + let toml_string = read_to_string(path).unwrap(); + return toml::from_str(&toml_string).unwrap(); + } +} + +pub async fn threema_incoming_message_handler( + incoming_message: web::Form, + app_state: web::Data, +) -> impl Responder { + let threema_client = &app_state.threema_client; + let decrypted_message = threema_client.process_incoming_msg(&incoming_message).await; + + match decrypted_message { + Ok(message) => match message { + Message::GroupTextMessage(group_text_msg) => { + let matrix_client = app_state.matrix_client.lock().await; + + if group_text_msg.text.starts_with("!threematrix") { + let split_text: Vec<&str> = group_text_msg.text.split(" ").collect(); + match split_text.get(1).map(|str| *str) { + Some("bind") => { + let rooms = matrix_client.joined_rooms(); + let matrix_room_id = split_text.get(2); + + if let Some(matrix_room_id) = matrix_room_id { + if let Some(room) = + rooms.iter().find(|r| r.room_id() == matrix_room_id) + { + if let Ok(r) = convert_group_id_to_readable_string( + &group_text_msg.group_id, + ) { + let content: ThreematrixStateEventContent = + ThreematrixStateEventContent { + threematrix_threema_group_id: r, + }; + + if let Err(e) = + set_threematrix_room_state(content, room).await + { + let err_text = + format!("Could not set Matrix room state: {}", e); + send_error_message_to_threema_group( + threema_client, + err_text, + group_text_msg.group_id.as_slice(), + false, + ) + .await; + } else { + let succ_text = format!("Group has been successfully bound to Matrix room: {}", matrix_room_id); + if let Err(e) = threema_client + .send_group_msg_by_group_id( + succ_text.as_str(), + group_text_msg.group_id.as_slice(), + ) + .await + { + error!("Threema: Could not send bind text: {}", e) + } + }; + } else { + error!("Threema: Group Id not valid!"); + } + } else { + let err_text = format!("Matrix room not found. Maybe the bot is not invited or the room id has wrong format!"); + send_error_message_to_threema_group( + threema_client, + err_text, + group_text_msg.group_id.as_slice(), + false, + ) + .await; + } + } else { + let err_text = format!("Missing Matrix room id!"); + send_error_message_to_threema_group( + threema_client, + err_text, + group_text_msg.group_id.as_slice(), + false, + ) + .await; + } + } + Some("help") => { + let help_txt = r#"To bind this Threema Group to a Matrix Room, please use the command "!threematrix bind !abc123:homeserver.org". +You can find the required room id in your Matrix client. Attention: This is NOT a "human readable" room alias, but an "internal" room id, which consists of random characters."#; + if let Err(e) = threema_client + .send_group_msg_by_group_id( + help_txt, + group_text_msg.group_id.as_slice(), + ) + .await + { + error!("Threema: Could not send help text: {}", e) + } + } + _ => { + let err_text = format!( + "Command not found! Use *!threematrix help* for more information" + ); + send_error_message_to_threema_group( + threema_client, + err_text, + group_text_msg.group_id.as_slice(), + false, + ) + .await; + } + } + } else { + let sender_name = group_text_msg + .base + .push_from_name + .unwrap_or("UNKNOWN".to_owned()); + let content = RoomMessageEventContent::text_html( + format!("{}: {}", sender_name, group_text_msg.text.as_str()), + format!( + "{}: {}", + sender_name, + group_text_msg.text.as_str() + ), + ); + for room in matrix_client.joined_rooms() { + match get_threematrix_room_state(&room).await { + Ok(None) => debug!( + "Matrix: Room {:?} does not have proper room state", + &room.display_name().await.unwrap_or( + matrix_sdk::DisplayName::Named("UNKNOWN".to_owned()) + ) + ), + Ok(Some(state)) => { + if let Ok(group_id) = + convert_group_id_to_readable_string(&group_text_msg.group_id) + { + if state.threematrix_threema_group_id == group_id { + let txn_id = TransactionId::new(); + if let Err(e) = + room.send(content.clone(), Some(&txn_id)).await + { + let err_txt = format!( + "Could not send message to Matrix room: {}", + e + ); + send_error_message_to_threema_group( + threema_client, + err_txt, + group_text_msg.group_id.as_slice(), + true, + ) + .await; + } + } + } + } + Err(e) => warn!("Matrix: Could not retrieve room state: {}", e), + } + } + } + } + Message::GroupCreateMessage(group_create_msg) => { + info!( + "Got group create message with members: {:?}", + group_create_msg.members + ); + } + Message::GroupRenameMessage(group_rename_msg) => { + info!( + "Got group rename message for: {:?}", + group_rename_msg.group_name + ); + } + _ => {} + }, + Err(err) => { + error!("Threema: Incoming Message Error: {}", err); + } + } + + HttpResponse::Ok() + .content_type(ContentType::plaintext()) + .body(()) +} + +async fn send_error_message_to_threema_group( + threema_client: &ThreemaClient, + err_text: String, + group_id: &[u8], + log_level_error: bool, +) { + if log_level_error { + error!("Threema: {}", err_text); + } else { + warn!("Threema: {}", err_text); + } + if let Err(e) = threema_client + .send_group_msg_by_group_id(err_text.as_str(), group_id) + .await + { + error!( + "Threema: Could not send error message: \"{}\". {}", + err_text, e + ) + } +} + +pub async fn matrix_incoming_message_handler( + event: OriginalSyncMessageLikeEvent, + room: Room, + threema_client: Ctx, + matrix_client: Client, +) -> () { + match room { + Room::Joined(room) => { + if let OriginalSyncMessageLikeEvent { + content: + RoomMessageEventContent { + msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }), + .. + }, + sender, + .. + } = event + { + debug!("Matrix: Incoming message: {}", msg_body); + + let sender_member = room.get_member(&sender).await; + match sender_member { + Ok(Some(sender_member)) => { + let sender_name = sender_member + .display_name() + .unwrap_or_else(|| sender_member.user_id().as_str()); + + // Filter out messages coming from our own bridge user + if sender != matrix_client.user_id().await.unwrap() { + match get_threematrix_room_state(&room).await { + Ok(None) => { + let err_txt = format!("Room {} does not have proper room state. Have you bound the room to a Threema group?", + &room.display_name().await.unwrap_or(matrix_sdk::DisplayName::Named("UNKNOWN".to_owned()))); + send_error_message_to_matrix_room(&room, err_txt, false).await; + } + Ok(Some(threematrix_state)) => { + let group_id = convert_group_id_from_readable_string( + threematrix_state.threematrix_threema_group_id.as_str(), + ); + + if let Ok(group_id) = group_id { + if let Err(e) = threema_client + .send_group_msg_by_group_id( + format!("*{}*: {}", sender_name, msg_body).as_str(), + group_id.as_slice(), + ) + .await + { + let err_txt = format!( + "Couldn't send message to Threema group: {}", + e + ); + send_error_message_to_matrix_room(&room, err_txt, true) + .await; + } + } + } + Err(e) => { + let err_txt = format!("Could not retrieve room state: {}", e); + send_error_message_to_matrix_room(&room, err_txt, true).await; + } + } + } + } + _ => { + error!("Matrix: Could not resolve room member!"); + } + } + } + } + _ => { + // If bot not member of room, ignore incoming message + } + } +} + +async fn send_error_message_to_matrix_room(room: &Joined, err_txt: String, log_level_err: bool) { + if log_level_err { + error!("Matrix: {}", err_txt); + } else { + warn!("Matrix: {}", err_txt); + } + + let content = RoomMessageEventContent::text_plain(err_txt.clone()); + let txn_id = TransactionId::new(); + + if let Err(e) = room.send(content, Some(&txn_id)).await { + error!( + "Matrix: Could not send error message: \"{}\". {}", + err_txt, e + ) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e3c84a7 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,108 @@ +use actix_web::{web, App, HttpServer}; +use flexi_logger::Logger; +use futures::stream::StreamExt; +use log::info; +use matrix_sdk::config::SyncSettings; +use matrix_sdk::reqwest::Url; +use matrix_sdk::Client; +use signal_hook::consts::{SIGINT, SIGQUIT, SIGTERM}; +use signal_hook_tokio::Signals; +use std::error::Error; +use std::process; +use tokio::sync::Mutex; + +use threematrix::matrix::on_stripped_state_member; +use threematrix::threema::ThreemaClient; +use threematrix::{ + matrix_incoming_message_handler, threema_incoming_message_handler, AppState, LoggerConfig, + ThreematrixConfig, +}; + +const VERSION: &str = env!("CARGO_PKG_VERSION"); +const CRATE_NAME: &str = env!("CARGO_CRATE_NAME"); + +#[actix_web::main] +async fn main() -> Result<(), Box> { + let mut logger = Logger::try_with_str(format!("{}=info", CRATE_NAME))?.start()?; + + let cfg = ThreematrixConfig::new("./threematrix_cfg.toml"); + info!( + "Starting Threematrix Server v{}. Waiting for Threema callback on {}:{}", + VERSION, + cfg.threema.host.clone().unwrap_or("localhost".to_owned()), + cfg.threema.port.clone().unwrap_or(443) + ); + + let mut signals = Signals::new(&[SIGTERM, SIGINT, SIGQUIT])?; + + if let Some(LoggerConfig { level }) = cfg.logger { + logger.parse_new_spec(format!("{}={}", CRATE_NAME, level.as_str()).as_str())? + } + + let threema_client = ThreemaClient::new( + &cfg.threema.gateway_own_id, + &cfg.threema.secret, + &cfg.threema.private_key, + )?; + + let homeserver_url = Url::parse(&cfg.matrix.homeserver_url)?; + let matrix_client = Client::new(homeserver_url).await?; + + let app_state = web::Data::new(AppState { + threema_client: threema_client.clone(), + matrix_client: Mutex::new(matrix_client.clone()), + }); + + matrix_client + .login( + &cfg.matrix.user, + &cfg.matrix.password, + None, + Some("command bot"), + ) + .await?; + + matrix_client + .sync_once(SyncSettings::default()) + .await + .unwrap(); + matrix_client + .register_event_handler_context(threema_client.clone()) + .register_event_handler(matrix_incoming_message_handler) + .await; + + matrix_client + .register_event_handler(on_stripped_state_member) + .await; + + let settings = SyncSettings::default().token(matrix_client.sync_token().await.unwrap()); + + let threema_server = tokio::spawn( + HttpServer::new(move || { + App::new().app_data(app_state.clone()).route( + "/callback", + web::post().to(threema_incoming_message_handler), + ) + }) + .bind(( + cfg.threema.host.unwrap_or("localhost".to_owned()), + cfg.threema.port.unwrap_or(443), + ))? + .run(), + ); + + let matrix_server = tokio::spawn(async move { matrix_client.sync(settings).await }); + + while let Some(signal) = signals.next().await { + match signal { + SIGTERM | SIGINT | SIGQUIT => { + matrix_server.abort(); + threema_server.abort(); + process::exit(1); + } + _ => unreachable!(), + } + } + + Ok(()) +} diff --git a/src/matrix/mod.rs b/src/matrix/mod.rs new file mode 100644 index 0000000..2bcff54 --- /dev/null +++ b/src/matrix/mod.rs @@ -0,0 +1,42 @@ +pub mod util; + +use log::{debug, error, info}; +use matrix_sdk::{room::Room, ruma::events::room::member::StrippedRoomMemberEvent, Client}; +use tokio::time::{sleep, Duration}; + +// Source: https://github.com/matrix-org/matrix-rust-sdk/blob/matrix-sdk-0.5.0/crates/matrix-sdk/examples/autojoin.rs +pub async fn on_stripped_state_member( + room_member: StrippedRoomMemberEvent, + client: Client, + room: Room, +) { + if room_member.state_key != client.user_id().await.unwrap() { + return; + } + + if let Room::Invited(room) = room { + debug!("Matrix: Autojoining room {}", room.room_id()); + let mut delay = 2; + + while let Err(err) = room.accept_invitation().await { + // retry autojoin due to synapse sending invites, before the + // invited user can join for more information see + // https://github.com/matrix-org/synapse/issues/4345 + error!( + "Matrix: Failed to join room {} ({:?}), retrying in {}s", + room.room_id(), + err, + delay + ); + + sleep(Duration::from_secs(delay)).await; + delay *= 2; + + if delay > 3600 { + error!("Matrix: Can't join room {} ({:?})", room.room_id(), err); + break; + } + } + info!("Matrix: Successfully joined room {}", room.room_id()); + } +} diff --git a/src/matrix/util.rs b/src/matrix/util.rs new file mode 100644 index 0000000..88cc7b0 --- /dev/null +++ b/src/matrix/util.rs @@ -0,0 +1,44 @@ +use log::debug; +use matrix_sdk::room::Joined; +use matrix_sdk::ruma::events::macros::EventContent; +use matrix_sdk::ruma::events::SyncStateEvent::Original; + +use serde_derive::{Deserialize, Serialize}; + +use crate::util::retry_request; + +#[derive(Clone, Debug, Deserialize, Serialize, EventContent)] +#[ruma_event(type = "m.threematrix", kind = State, state_key_type = String)] +pub struct ThreematrixStateEventContent { + pub threematrix_threema_group_id: String, +} + +pub async fn set_threematrix_room_state( + threematrix_state: ThreematrixStateEventContent, + room: &Joined, +) -> Result<(), matrix_sdk::Error> { + retry_request( + || async { room.send_state_event(threematrix_state.clone(), "").await }, + 20000, + 6, + ) + .await?; + debug!("Matrix: Succesfully set room state"); + return Ok(()); +} + +pub async fn get_threematrix_room_state( + room: &Joined, +) -> Result, matrix_sdk::Error> { + let sync_state = + retry_request(|| async { room.get_state_event_static("").await }, 20000, 6).await?; + + if let Some(raw) = sync_state { + let sync_state = raw.deserialize().unwrap(); + + if let Original(event) = sync_state { + return Ok(Some(event.content)); + } + } + return Ok(None); +} diff --git a/src/threema/mod.rs b/src/threema/mod.rs new file mode 100644 index 0000000..a6785b5 --- /dev/null +++ b/src/threema/mod.rs @@ -0,0 +1,297 @@ +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +use threema_gateway::{ApiBuilder, E2eApi, IncomingMessage, PublicKey}; +use tokio::sync::Mutex; + +use crate::errors::{ProcessIncomingMessageError, SendGroupMessageError}; +use log::{debug, info}; +use threema_gateway::errors::{ApiBuilderError, ApiError}; + +use crate::threema::serialization::encrypt_group_sync_req_msg; +use crate::threema::types::{ + GroupCreateMessage, GroupRenameMessage, GroupTextMessage, MessageBase, MessageType, TextMessage, +}; +use crate::util::retry_request; + +use self::serialization::encrypt_group_text_msg; +use self::types::{Message, MessageGroup}; + +pub mod serialization; +pub mod types; +pub mod util; + +#[derive(Clone)] +pub struct ThreemaClient { + api: Arc>, + groups: Arc, MessageGroup>>>, +} + +pub const GROUP_ID_NUM_BYTES: usize = 8; +pub const GROUP_CREATOR_NUM_BYTES: usize = 8; +pub const MESSAGE_TYPE_NUM_BYTES: usize = 1; +pub const THREEMA_ID_LENGTH: usize = 8; + +impl ThreemaClient { + pub fn new( + own_id: &str, + secret: &str, + private_key: &str, + ) -> Result { + let api = ApiBuilder::new(own_id, secret) + .with_private_key_str(private_key.as_ref()) + .and_then(|builder| builder.into_e2e())?; + return Ok(ThreemaClient { + api: Arc::new(Mutex::new(api)), + groups: Arc::new(Mutex::new(HashMap::new())), + }); + } + + pub async fn send_group_msg_by_group_id( + &self, + text: &str, + group_id: &[u8], + ) -> Result<(), SendGroupMessageError> { + let groups = self.groups.lock().await; + if let Some(group) = groups.get(group_id) { + let receiver: Vec<&str> = group.members.iter().map(|str| str.as_str()).collect(); + return self + .send_group_msg(text, &group.group_creator, group_id, receiver.as_slice()) + .await + .map_err(|e| SendGroupMessageError::ApiError(e)); + } else { + return Err(SendGroupMessageError::GroupNotInCache); + } + } + + pub async fn send_group_msg( + &self, + text: &str, + group_creator: &str, + group_id: &[u8], + receivers: &[&str], + ) -> Result<(), ApiError> { + let api = self.api.lock().await; + for user_id in receivers { + debug!("Threema: Sending message to: {}", user_id); + let public_key = self.lookup_pubkey_with_retry(user_id, &api).await?; //TODO cache + + let encrypted_msg = + encrypt_group_text_msg(text, group_creator, group_id, &public_key.into(), &api); + + retry_request( + || async { api.send(&user_id, &encrypted_msg, false).await }, + 20 * 1000, + 6, + ) + .await?; + debug!("Threema: Message sent successfully"); + } + return Ok(()); + } + + async fn lookup_pubkey_with_retry( + &self, + user_id: &str, + api: &E2eApi, + ) -> Result { + retry_request(|| async { api.lookup_pubkey(user_id).await }, 20 * 1000, 6).await + } + + pub async fn send_group_sync_req_msg( + &self, + group_id: &[u8], + receiver: &str, + ) -> Result<(), ApiError> { + let api = self.api.lock().await; + let public_key = self.lookup_pubkey_with_retry(receiver, &api).await?; + let encrypted_message = encrypt_group_sync_req_msg(group_id, &public_key.into(), &api); + + retry_request( + || async { api.send(receiver, &encrypted_message, false).await }, + 20 * 1000, + 6, + ) + .await?; + debug!("Threema: Group sync message sent successfully"); + return Ok(()); + } + + pub async fn process_incoming_msg( + &self, + incoming_message: &IncomingMessage, + ) -> Result { + + let data; + { + let api = self.api.lock().await; + let pubkey = self + .lookup_pubkey_with_retry(&incoming_message.from, &api) + .await + .map_err(|e| ProcessIncomingMessageError::ApiError(e))?; + + data = api + .decrypt_incoming_message(&incoming_message, &pubkey) + .map_err(|e| ProcessIncomingMessageError::CryptoError(e))?; + } + let message_type: u8 = &data[0] & 0xFF; + debug!("Threema: Parsed and validated message from request:\nFrom: {}\nSender nickname: {:?}\nTo: {}\nTimestamp: {}\nMessage type: {:#02x}", incoming_message.from,incoming_message.nickname,incoming_message.to,incoming_message.date, message_type); + + let base = MessageBase { + from_identity: incoming_message.from.clone(), + to_identity: incoming_message.to.clone(), + push_from_name: incoming_message.nickname.clone(), + message_id: incoming_message.message_id.clone(), + date: incoming_message.date as u64, + }; + + match MessageType::from(message_type) { + MessageType::Text => { + let text = String::from_utf8(data[MESSAGE_TYPE_NUM_BYTES..].to_vec()) + .map_err(|e| ProcessIncomingMessageError::Utf8ConvertError(e))?; + debug!("Threema: text: {}", text); + return Ok(Message::TextMessage(TextMessage { base, text })); + } + MessageType::GroupText => { + let group_creator = String::from_utf8( + data[MESSAGE_TYPE_NUM_BYTES..MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES] + .to_vec(), + ) + .map_err(|e| ProcessIncomingMessageError::Utf8ConvertError(e))?; + let group_id = &data[MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES + ..MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES + GROUP_ID_NUM_BYTES]; + let text = String::from_utf8( + data[MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES + GROUP_ID_NUM_BYTES..] + .to_vec(), + ) + .map_err(|e| ProcessIncomingMessageError::Utf8ConvertError(e))?; + + // Show result + debug!( + "Threema: GroupCreator: {}\ngroupId: {:?}\ntext: {}", + group_creator, group_id, text + ); + + { + let groups = self.groups.lock().await; + if let None = groups.get(group_id) { + debug!("Threema: Unknown group, sending sync req"); + self.send_group_sync_req_msg(group_id, group_creator.as_str()) + .await + .map_err(|e| ProcessIncomingMessageError::ApiError(e))?; + } + } + + return Ok(Message::GroupTextMessage(GroupTextMessage { + base, + text, + group_creator, + group_id: group_id.to_vec(), + })); + } + MessageType::GroupCreate => { + let group_id = + &data[MESSAGE_TYPE_NUM_BYTES..MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES]; + let mut members: HashSet = HashSet::new(); + + let mut counter = 0; + let mut current_member_id = "".to_owned(); + for char in &data[MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES..] { + current_member_id = current_member_id + + String::from_utf8(vec![*char]) + .map_err(|e| ProcessIncomingMessageError::Utf8ConvertError(e))? + .as_str(); + counter = counter + 1; + if counter == THREEMA_ID_LENGTH { + members.insert(current_member_id.clone()); + + current_member_id = "".to_owned(); + counter = 0; + } + } + + let me_in_group = members + .iter() + .find(|member| **member == incoming_message.to) + .is_some(); + + let mut members_without_me: HashSet<&String> = members + .iter() + .filter(|member| *member != &incoming_message.to) + .collect(); + + if members_without_me.len() != 0 && me_in_group { + // Make sure to always add sender/group creator (different behavior between Android and iOS) + members_without_me.insert(&incoming_message.from); + + { + let mut groups = self.groups.lock().await; + let new_members: Vec = members_without_me + .iter() + .map(|member| (*member).to_owned()) + .collect(); + groups + .entry(group_id.to_vec()) + .and_modify(|group| { + group.members = new_members.clone(); + }) + .or_insert(MessageGroup { + members: new_members, + name: "".to_owned(), + group_creator: incoming_message.from.clone(), + }); + } + } else { + let mut groups = self.groups.lock().await; + info!("Threema: Leaving group"); + groups.remove(group_id); + } + + return Ok(Message::GroupCreateMessage(GroupCreateMessage { + base, + members: members_without_me + .iter() + .map(|member| (*member).to_owned()) + .collect(), + group_id: group_id.to_vec(), + })); + } + MessageType::GroupRename => { + let group_id = + &data[MESSAGE_TYPE_NUM_BYTES..MESSAGE_TYPE_NUM_BYTES + GROUP_ID_NUM_BYTES]; + let group_name = String::from_utf8( + data[MESSAGE_TYPE_NUM_BYTES + GROUP_CREATOR_NUM_BYTES..].to_vec(), + ) + .map_err(|e| ProcessIncomingMessageError::Utf8ConvertError(e))?; + + { + let mut groups = self.groups.lock().await; + groups + .entry(group_id.to_vec()) + .and_modify(|group| group.name = group_name.clone()) + .or_insert(MessageGroup { + members: Vec::new(), + name: group_name.clone(), + group_creator: incoming_message.from.clone(), + }); + } + + return Ok(Message::GroupRenameMessage(GroupRenameMessage { + base, + group_name, + group_id: group_id.to_vec(), + })); + } + // MessageType::GroupRequestSync => {} + // MessageType::Image => {} + // MessageType::Video => {} + // MessageType::File => {} + // MessageType::DeliveryReceipt => {} + _ => { + info!("Unknown message type received"); + info!("content: {:?}", &data[1..]); + Err(ProcessIncomingMessageError::UnknownMessageTypeError) + } + } + } +} diff --git a/src/threema/serialization.rs b/src/threema/serialization.rs new file mode 100644 index 0000000..d268c2c --- /dev/null +++ b/src/threema/serialization.rs @@ -0,0 +1,54 @@ +use std::iter::repeat; + +use rand::Rng; +use threema_gateway::{E2eApi, EncryptedMessage, RecipientKey}; + +use crate::threema::types::MessageType; + +pub fn encrypt_group_sync_req_msg( + group_id: &[u8], + recipient_key: &RecipientKey, + threema_api: &E2eApi, +) -> EncryptedMessage { + let padding_amount = random_padding_amount(); + let padding = repeat(padding_amount).take(padding_amount as usize); + let msgtype_byte = repeat(MessageType::GroupRequestSync.into()).take(1); + + let padded_plaintext: Vec = msgtype_byte + .chain(group_id.iter().cloned()) + .chain(padding) + .collect(); + + threema_api.encrypt_raw(&padded_plaintext, &recipient_key) +} + +pub fn encrypt_group_text_msg( + text: &str, + group_creator: &str, + group_id: &[u8], + recipient_key: &RecipientKey, + threema_api: &E2eApi, +) -> EncryptedMessage { + let padding_amount = random_padding_amount(); + let padding = repeat(padding_amount).take(padding_amount as usize); + let msgtype_byte = repeat(MessageType::GroupText.into()).take(1); + + let data: Vec = group_creator + .as_bytes() + .iter() + .cloned() + .chain(group_id.iter().cloned()) + .chain(text.as_bytes().iter().cloned()) + .collect(); + let padded_plaintext: Vec = msgtype_byte + .chain(data.iter().cloned()) + .chain(padding) + .collect(); + + threema_api.encrypt_raw(&padded_plaintext, &recipient_key) +} + +fn random_padding_amount() -> u8 { + let mut rng = rand::thread_rng(); + return rng.gen_range(1..255); +} diff --git a/src/threema/types.rs b/src/threema/types.rs new file mode 100644 index 0000000..7a73ae7 --- /dev/null +++ b/src/threema/types.rs @@ -0,0 +1,96 @@ +// Custom internal types +#[derive(Debug)] +pub struct MessageGroup { + pub members: Vec, + pub group_creator: String, + pub name: String, +} + +// Threema types +pub enum Message { + GroupTextMessage(GroupTextMessage), + TextMessage(TextMessage), + GroupCreateMessage(GroupCreateMessage), + GroupRenameMessage(GroupRenameMessage), +} + +pub struct GroupRenameMessage { + pub base: MessageBase, + pub group_id: Vec, + pub group_name: String, +} + +pub struct GroupCreateMessage { + pub base: MessageBase, + pub group_id: Vec, + pub members: Vec, +} + +pub struct TextMessage { + pub base: MessageBase, + pub text: String, +} + +#[derive(Clone)] +pub struct GroupTextMessage { + pub base: MessageBase, + pub text: String, + pub group_creator: String, + pub group_id: Vec, +} + +#[derive(Clone)] +pub struct MessageBase { + pub from_identity: String, + pub to_identity: String, + pub message_id: String, + pub push_from_name: Option, + pub date: u64, +} + +pub enum MessageType { + Text, + GroupText, + GroupCreate, + GroupRename, + GroupRequestSync, + Image, + Video, + File, + DeliveryReceipt, +} + +impl From for MessageType { + fn from(value: u8) -> Self { + match value { + 0x01 => MessageType::Text, + 0x41 => MessageType::GroupText, + 0x4a => MessageType::GroupCreate, + 0x4b => MessageType::GroupRename, + 0x51 => MessageType::GroupRequestSync, + 0x02 => MessageType::Image, + 0x13 => MessageType::Video, + 0x17 => MessageType::File, + 0x80 => MessageType::DeliveryReceipt, + _ => { + panic!("Message type not implemented!"); + } + } + } +} + +impl Into for MessageType { + fn into(self) -> u8 { + match self { + MessageType::Text => 0x01, + MessageType::GroupText => 0x41, + MessageType::GroupCreate => 0x4a, + MessageType::GroupRename => 0x4b, + MessageType::GroupRequestSync => 0x51, + MessageType::Image => 0x02, + MessageType::Video => 0x13, + MessageType::File => 0x17, + MessageType::DeliveryReceipt => 0x80, + } + } +} diff --git a/src/threema/util.rs b/src/threema/util.rs new file mode 100644 index 0000000..eb61c59 --- /dev/null +++ b/src/threema/util.rs @@ -0,0 +1,22 @@ +use crate::errors::{ParseGroupIdError, StringifyGroupIdError}; +use crate::threema::GROUP_ID_NUM_BYTES; + +pub fn convert_group_id_to_readable_string(group_id: &[u8]) -> Result { + let result = group_id + .iter() + .map(|value| format!("{}", value)) + .reduce(|a, b| a + " " + b.as_str()); + if let Some(result) = result { + return Ok(result); + } + return Err(StringifyGroupIdError::EmptyGroupId); +} + +pub fn convert_group_id_from_readable_string(group_id_string: &str) -> Result, ParseGroupIdError> { + let group_id_vec: Vec<&str> = group_id_string.split(" ").collect(); + if group_id_vec.len() != GROUP_ID_NUM_BYTES { + return Err(ParseGroupIdError::InvalidGroupIdLength); + } + + return group_id_vec.iter().map(|id_part| id_part.parse::().map_err(|e| ParseGroupIdError::EncodingError(e))).collect(); +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..041029d --- /dev/null +++ b/src/util.rs @@ -0,0 +1,23 @@ +use log::debug; +use std::{error::Error, future::Future}; +use tokio::time::{sleep, Duration}; + +pub async fn retry_request>, T, E: Error>( + callback: impl Fn() -> B, + delay_in_ms: u64, + retries: u32, +) -> Result { + let mut result = callback().await; + let mut retry_counter = retries; + + while let Err(msg) = &result { + if retry_counter == 0 { + break; + } + debug!("Retrying due to error: {}", msg); + sleep(Duration::from_millis(delay_in_ms)).await; + retry_counter = retry_counter - 1; + result = callback().await; + } + return result; +} diff --git a/threematrix_cfg_example.toml b/threematrix_cfg_example.toml new file mode 100644 index 0000000..9b2e713 --- /dev/null +++ b/threematrix_cfg_example.toml @@ -0,0 +1,16 @@ +[threema] +secret = "abc123" +private_key = "abcd1234" +gateway_own_id ="*CUSTOM1" +# Optional (Default is 443) +port = 8888 +# Optional (Default is localhost) +host = localhost + +[matrix] +homeserver_url = "https://matrix.myserver.com" +user = "myuser" +password = "abc123" + +[logger] +level = "info" \ No newline at end of file