From b2a22456ff88a5ab26d63213c7b6aee31e009881 Mon Sep 17 00:00:00 2001 From: Alex Emmet <111742636+Alex-Emmet@users.noreply.github.com> Date: Sun, 28 Jun 2026 13:44:58 +0200 Subject: [PATCH] Initial MTP Migration [Broken] --- .cargo/config.toml | 2 + Cargo.lock | 807 +++++++++--------- client/Cargo.toml | 3 +- client/src/client_connection.rs | 383 +++++---- communities/Cargo.toml | 3 +- communities/src/community.rs | 6 +- communities/src/community_connection.rs | 72 +- communities/src/interactables/category.rs | 242 +++--- communities/src/interactables/interactable.rs | 2 +- communities/src/interactables/text_chat.rs | 528 ++++++------ communities/src/interactables/voice_chat.rs | 374 ++++---- flake.nix | 2 +- iota-auth/Cargo.toml | 3 +- iota-cli/Cargo.toml | 3 +- iota-cli/src/elements/console_card.rs | 6 +- iota-core/Cargo.toml | 3 +- iota-logger/Cargo.toml | 2 +- iota-logger/src/lib.rs | 26 +- iota-state/Cargo.toml | 2 +- iota-storage/Cargo.toml | 3 +- iota-updater/Cargo.toml | 3 +- iota-util/Cargo.toml | 3 +- omikron-connector/Cargo.toml | 4 +- omikron-connector/src/omikron_connection.rs | 682 ++++++++------- omikron-connector/src/ping_pong_task.rs | 12 +- omikron-connector/src/user_ops.rs | 24 +- other-iota/Cargo.toml | 3 +- type-maps.yaml | 241 ++++++ web-server/Cargo.toml | 3 +- web-ui/Cargo.toml | 13 +- 30 files changed, 1886 insertions(+), 1574 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 type-maps.yaml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d363b83 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[env] +MTP_TYPE_MAPS = { value = "type-maps.yaml", relative = true } diff --git a/Cargo.lock b/Cargo.lock index dfa84c5..1fff38f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de7fa236829ba0841304542f7614c42b80fca007455315c45c785ccfa873a85b" dependencies = [ "actix-rt", - "bitflags 2.12.1", + "bitflags 2.13.0", "bytes", "crossbeam-channel", "futures-core", @@ -31,7 +31,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "bytes", "futures-core", "futures-sink", @@ -44,9 +44,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.12.1" +version = "3.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93acb4a42f64936f9b8cae4a433b237599dd6eb6ed06124eb67132ef8cc90662" +checksum = "48e2faa3e7418ed780cca54829d32782a4008a077230f67457caa063415e99c2" dependencies = [ "actix-codec", "actix-rt", @@ -54,14 +54,14 @@ dependencies = [ "actix-tls", "actix-utils", "base64", - "bitflags 2.12.1", + "bitflags 2.13.0", "brotli", "bytes", "bytestring", "derive_more", "encoding_rs", "flate2", - "foldhash 0.1.5", + "foldhash", "futures-core", "h2 0.3.27", "http 0.2.12", @@ -89,7 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -154,7 +154,7 @@ dependencies = [ "actix-service", "actix-utils", "futures-core", - "impl-more", + "impl-more 0.1.9", "pin-project-lite", "rustls-pki-types", "tokio", @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.13.0" +version = "4.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff87453bc3b56e9b2b23c1cc0b1be8797184accf51d2abe0f8a33ec275d316bf" +checksum = "df09e2d9239703dd64056359c920c7f3fba6535ec61a0059e0f44e095ffe02b4" dependencies = [ "actix-codec", "actix-http", @@ -195,10 +195,10 @@ dependencies = [ "cookie", "derive_more", "encoding_rs", - "foldhash 0.1.5", + "foldhash", "futures-core", "futures-util", - "impl-more", + "impl-more 0.3.1", "itoa", "language-tags", "log", @@ -244,7 +244,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -305,9 +305,9 @@ checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ "alloc-no-stdlib", ] @@ -329,9 +329,18 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] [[package]] name = "arbitrary" @@ -366,7 +375,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] @@ -378,7 +387,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -389,7 +398,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -474,9 +483,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "block-buffer" @@ -489,18 +498,18 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ "hybrid-array", ] [[package]] name = "brotli" -version = "8.0.3" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -509,9 +518,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -523,6 +532,12 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "bytemuck" version = "1.25.0" @@ -537,9 +552,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "bytestring" @@ -570,9 +585,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.63" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -594,9 +609,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures 0.3.0", @@ -605,9 +620,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "js-sys", @@ -651,6 +666,7 @@ dependencies = [ "iota-util", "json", "lazy_static", + "mtp", "once_cell", "open", "pnet", @@ -668,8 +684,6 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", - "ttp-core", - "ttp-native", "tungstenite", "uuid", "walkdir", @@ -811,6 +825,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-channel" version = "0.5.15" @@ -832,7 +852,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -912,7 +932,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -923,7 +943,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -977,9 +997,6 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] [[package]] name = "derive_arbitrary" @@ -989,7 +1006,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1011,7 +1028,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", "unicode-xid", ] @@ -1032,7 +1049,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.12.0", + "block-buffer 0.12.1", "const-oid", "crypto-common 0.2.2", ] @@ -1045,7 +1062,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1136,6 +1153,12 @@ dependencies = [ "regex", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "2.4.1" @@ -1194,12 +1217,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -1292,7 +1309,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1363,16 +1380,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", "rand_core 0.10.1", - "wasip2", - "wasip3", ] [[package]] @@ -1412,16 +1427,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.4.1", + "http 1.4.2", "indexmap", "slab", "tokio", @@ -1435,15 +1450,6 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -1452,7 +1458,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", + "foldhash", ] [[package]] @@ -1460,12 +1466,17 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hashlink" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" +checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" dependencies = [ "hashbrown 0.16.1", ] @@ -1479,7 +1490,7 @@ dependencies = [ "base64", "bytes", "headers-core", - "http 1.4.1", + "http 1.4.2", "httpdate", "mime", "sha1 0.10.6", @@ -1491,7 +1502,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.4.1", + "http 1.4.2", ] [[package]] @@ -1543,9 +1554,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1558,7 +1569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.4.1", + "http 1.4.2", ] [[package]] @@ -1569,7 +1580,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.4.1", + "http 1.4.2", "http-body", "pin-project-lite", ] @@ -1588,9 +1599,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] @@ -1605,8 +1616,8 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.14", - "http 1.4.1", + "h2 0.4.15", + "http 1.4.2", "http-body", "httparse", "httpdate", @@ -1623,7 +1634,7 @@ version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "http 1.4.1", + "http 1.4.2", "hyper", "hyper-util", "rustls", @@ -1642,7 +1653,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.4.1", + "http 1.4.2", "http-body", "hyper", "ipnet", @@ -1763,12 +1774,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -1802,6 +1807,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" +[[package]] +name = "impl-more" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a84fd5aa25fae5c0f4a33d9cac2ca017fc622cbd089be2229993514990f870" + [[package]] name = "indexmap" version = "2.14.0" @@ -1810,8 +1821,6 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", - "serde", - "serde_core", ] [[package]] @@ -1842,7 +1851,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1867,6 +1876,7 @@ dependencies = [ "iota-util", "json", "lazy_static", + "mtp", "once_cell", "open", "pnet", @@ -1884,8 +1894,6 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", - "ttp-core", - "ttp-native", "tungstenite", "uuid", "walkdir", @@ -1919,6 +1927,7 @@ dependencies = [ "iota-util", "json", "lazy_static", + "mtp", "omikron-connector", "once_cell", "open", @@ -1937,8 +1946,6 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", - "ttp-core", - "ttp-native", "tungstenite", "uuid", "walkdir", @@ -1960,14 +1967,13 @@ dependencies = [ "iota-updater", "iota-util", "json", + "mtp", "omikron-connector", "once_cell", "pnet", "ratatui", "reqwest", "tokio", - "ttp-core", - "ttp-native", "web-server", "web-ui", ] @@ -1979,9 +1985,9 @@ dependencies = [ "iota-state", "iota-util", "json", + "mtp", "once_cell", "ratatui", - "ttp-core", ] [[package]] @@ -1990,10 +1996,10 @@ version = "0.1.0" dependencies = [ "dashmap", "json", + "mtp", "once_cell", "sysinfo", "tokio", - "ttp-core", ] [[package]] @@ -2008,6 +2014,7 @@ dependencies = [ "iota-state", "iota-util", "json", + "mtp", "once_cell", "rand 0.8.6", "rand_core 0.6.4", @@ -2017,8 +2024,6 @@ dependencies = [ "sha2 0.10.9", "sysinfo", "tokio", - "ttp-core", - "ttp-native", "uuid", "walkdir", "x448", @@ -2046,6 +2051,7 @@ dependencies = [ "hkdf", "iota-logger", "json", + "mtp", "once_cell", "pnet", "rand_core 0.6.4", @@ -2058,8 +2064,6 @@ dependencies = [ "sysinfo", "tempfile", "tokio", - "ttp-core", - "ttp-native", "uuid", "walkdir", "x448", @@ -2074,13 +2078,12 @@ dependencies = [ "base64", "hex", "hkdf", + "mtp", "rand_core 0.6.4", "reqwest", "sha2 0.10.9", "sysinfo", "tokio", - "ttp-core", - "ttp-native", "uuid", "walkdir", "x448", @@ -2163,7 +2166,7 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2182,7 +2185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2197,13 +2200,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -2242,12 +2244,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libbz2-rs-sys" version = "0.2.5" @@ -2260,6 +2256,12 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libsqlite3-sys" version = "0.37.0" @@ -2276,7 +2278,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", ] [[package]] @@ -2325,17 +2327,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" -version = "0.16.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -2366,9 +2368,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memmem" @@ -2429,6 +2431,63 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "mtp" +version = "0.1.0" +source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" +dependencies = [ + "mtp-codec", + "mtp-common", + "mtp-transport", + "mtp-type-map", +] + +[[package]] +name = "mtp-codec" +version = "0.1.0" +source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" +dependencies = [ + "base64", + "byteorder", + "mtp-common", + "mtp-type-map", + "rand 0.8.6", +] + +[[package]] +name = "mtp-common" +version = "0.1.0" +source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" +dependencies = [ + "quinn", + "rustls", + "thiserror 2.0.18", + "wtransport", +] + +[[package]] +name = "mtp-transport" +version = "0.1.0" +source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" +dependencies = [ + "log", + "mtp-codec", + "mtp-common", + "rustls", + "rustls-native-certs", + "tokio", + "wtransport", +] + +[[package]] +name = "mtp-type-map" +version = "0.1.0" +source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" +dependencies = [ + "serde", + "serde_yaml", +] + [[package]] name = "native-tls" version = "0.2.18" @@ -2452,7 +2511,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -2508,7 +2567,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2544,7 +2603,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", ] [[package]] @@ -2584,11 +2643,11 @@ dependencies = [ "iota-storage", "iota-util", "json", + "mtp", + "rand 0.8.6", "rand_core 0.6.4", "sha2 0.10.9", "tokio", - "ttp-core", - "ttp-native", "uuid", "x448", ] @@ -2618,11 +2677,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.80" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "cfg-if", "foreign-types", "libc", @@ -2638,7 +2697,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2649,9 +2708,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.116" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -2693,6 +2752,7 @@ dependencies = [ "iota-util", "json", "lazy_static", + "mtp", "once_cell", "open", "pnet", @@ -2710,8 +2770,6 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", - "ttp-core", - "ttp-native", "tungstenite", "uuid", "walkdir", @@ -2720,6 +2778,30 @@ dependencies = [ "zip", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -2805,7 +2887,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2858,7 +2940,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2887,7 +2969,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2947,7 +3029,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3041,16 +3123,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -3062,9 +3134,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -3082,9 +3154,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" dependencies = [ "aws-lc-rs", "bytes", @@ -3118,9 +3190,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -3165,7 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", - "getrandom 0.4.2", + "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -3221,32 +3293,36 @@ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "ratatui" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" dependencies = [ "instability", "ratatui-core", "ratatui-crossterm", "ratatui-macros", + "ratatui-termina", "ratatui-termwiz", "ratatui-widgets", + "serde", ] [[package]] name = "ratatui-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "compact_str", - "hashbrown 0.16.1", - "indoc", + "critical-section", + "hashbrown 0.17.1", "itertools", "kasuari", "lru", - "strum 0.27.2", + "palette", + "serde", + "strum 0.28.0", "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", @@ -3255,9 +3331,9 @@ dependencies = [ [[package]] name = "ratatui-crossterm" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" dependencies = [ "cfg-if", "crossterm", @@ -3267,19 +3343,30 @@ dependencies = [ [[package]] name = "ratatui-macros" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" dependencies = [ "ratatui-core", "ratatui-widgets", ] [[package]] -name = "ratatui-termwiz" +name = "ratatui-termina" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" dependencies = [ "ratatui-core", "termwiz", @@ -3287,18 +3374,19 @@ dependencies = [ [[package]] name = "ratatui-widgets" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.12.1", - "hashbrown 0.16.1", + "bitflags 2.13.0", + "hashbrown 0.17.1", "indoc", "instability", "itertools", "line-clipping", "ratatui-core", - "strum 0.27.2", + "serde", + "strum 0.28.0", "time", "unicode-segmentation", "unicode-width", @@ -3323,14 +3411,14 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -3357,9 +3445,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -3371,8 +3459,8 @@ dependencies = [ "bytes", "encoding_rs", "futures-core", - "h2 0.4.14", - "http 1.4.1", + "h2 0.4.15", + "http 1.4.2", "http-body", "http-body-util", "hyper", @@ -3429,7 +3517,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -3468,7 +3556,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -3477,9 +3565,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "aws-lc-rs", "log", @@ -3609,7 +3697,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3670,7 +3758,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3698,6 +3786,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -3815,9 +3916,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" @@ -3874,15 +3975,15 @@ name = "strum" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] [[package]] name = "strum" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] [[package]] name = "strum_macros" @@ -3893,7 +3994,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3905,7 +4006,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3927,9 +4028,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3953,7 +4054,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3976,7 +4077,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -3998,12 +4099,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys 0.61.2", ] +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.0", + "parking_lot", + "rustix", + "signal-hook", + "windows-sys 0.61.2", +] + [[package]] name = "terminfo" version = "0.9.0" @@ -4033,7 +4147,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64", - "bitflags 2.12.1", + "bitflags 2.13.0", "fancy-regex", "filedescriptor", "finl_unicode", @@ -4093,7 +4207,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4104,17 +4218,16 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" dependencies = [ "deranged", - "itoa", "libc", "num-conv", "num_threads", @@ -4126,15 +4239,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" dependencies = [ "num-conv", "time-core", @@ -4190,7 +4303,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4261,10 +4374,10 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.12.1", + "bitflags 2.13.0", "bytes", "futures-util", - "http 1.4.1", + "http 1.4.2", "http-body", "pin-project-lite", "tower", @@ -4305,7 +4418,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4323,33 +4436,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "ttp-core" -version = "0.1.0" -source = "git+https://git.methanium.net/Tensamin/TTP.git#23438fa8f884e6ad0d32ca1004c0dedcce0cc8d2" -dependencies = [ - "base64", - "byteorder", - "rand 0.8.6", - "serde_json", - "strum 0.28.0", - "strum_macros 0.28.0", -] - -[[package]] -name = "ttp-native" -version = "0.1.0" -source = "git+https://git.methanium.net/Tensamin/TTP.git#23438fa8f884e6ad0d32ca1004c0dedcce0cc8d2" -dependencies = [ - "quinn", - "rustls", - "rustls-native-certs", - "thiserror 2.0.18", - "tokio", - "ttp-core", - "wtransport", -] - [[package]] name = "tungstenite" version = "0.29.0" @@ -4358,7 +4444,7 @@ checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" dependencies = [ "bytes", "data-encoding", - "http 1.4.1", + "http 1.4.2", "httparse", "log", "native-tls", @@ -4430,6 +4516,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" @@ -4468,12 +4560,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.2" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "atomic", - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] @@ -4527,7 +4619,7 @@ dependencies = [ "bytes", "futures-util", "headers", - "http 1.4.1", + "http 1.4.2", "http-body", "http-body-util", "log", @@ -4553,27 +4645,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -4584,9 +4667,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.72" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -4594,9 +4677,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4604,73 +4687,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.12.1", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "web-server" version = "0.1.0" dependencies = [ - "ttp-core", - "ttp-native", + "mtp", ] [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4710,6 +4758,7 @@ dependencies = [ "iota-util", "json", "lazy_static", + "mtp", "omikron-connector", "once_cell", "open", @@ -4728,8 +4777,6 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", - "ttp-core", - "ttp-native", "tungstenite", "uuid", "walkdir", @@ -4740,9 +4787,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] @@ -4903,7 +4950,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4914,7 +4961,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5127,100 +5174,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.12.1", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -5304,9 +5263,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -5321,28 +5280,28 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5362,28 +5321,28 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5416,7 +5375,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -5448,9 +5407,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" +checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3" [[package]] name = "zmij" diff --git a/client/Cargo.toml b/client/Cargo.toml index f38c0b4..72cb4d6 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } iota-logger = { path = "../iota-logger" } iota-util = { path = "../iota-util" } iota-storage = { path = "../iota-storage" } diff --git a/client/src/client_connection.rs b/client/src/client_connection.rs index ea238a5..56bdf6a 100644 --- a/client/src/client_connection.rs +++ b/client/src/client_connection.rs @@ -10,14 +10,25 @@ use iota_storage::util::{chat_files, chats_util}; use iota_util::crypto_helper; use iota_util::crypto_util::{DataFormat, SecurePayload}; use iota_util::file_util::{get_children, load_file, save_file}; +use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue}; +use mtp::transport::{Receiver, Sender}; use std::sync::Arc; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use tokio::sync::{Mutex, RwLock, mpsc, watch}; use tokio::task::JoinHandle; -use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue}; -use ttp_native::{Receiver, Sender}; use uuid::Uuid; +fn typed_container(items: Vec<(DataType, DataValue)>) -> DataValue { + use mtp::type_map::{DataTypeId, TypeMap}; + let tm = TypeMap::latest(); + DataValue::Container( + items + .into_iter() + .filter_map(|(dt, dv)| tm.data_id_enum(dt).map(|id| (DataTypeId(id), dv))) + .collect(), + ) +} + // ============================================================================ // Waiting Task System // ============================================================================ @@ -97,76 +108,76 @@ impl ClientConnection { // ------------------------------------------------------------------------- async fn handle_ping(self: Arc, cv: CommunicationValue) { // Update our ping if provided - if let DataValue::Number(last_ping) = cv.get_data(DataTypes::last_ping) { + if let DataValue::SignedNumber(last_ping) = cv.get_data(DataType::LastPing) { let current = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_millis(); let mut ping_guard = self.ping.write().await; - *ping_guard = current as i64 - last_ping; + *ping_guard = current as i64 - *last_ping as i64; } // Send pong response - let response = CommunicationValue::new(CommunicationType::pong) + let response = CommunicationValue::new(CommunicationType::Pong) .with_id(cv.get_id()) - .add_data(DataTypes::ping_iota, DataValue::Number(0)); + .add_typed_default(DataType::PingIota, DataValue::SignedNumber(0)); self.send_message(&response).await; } pub async fn handle_message(self: Arc, cv: CommunicationValue) { - if !cv.is_type(CommunicationType::ping) && !cv.is_type(CommunicationType::pong) { + if !cv.is_type(CommunicationType::Ping) && !cv.is_type(CommunicationType::Pong) { log_cv_in!(&cv); } let _msg_id = cv.get_id(); - if cv.is_type(CommunicationType::ping) { + if cv.is_type(CommunicationType::Ping) { self.handle_ping(cv).await; return; } - if cv.is_type(CommunicationType::challenge) { + if cv.is_type(CommunicationType::Challenge) { self.handle_challenge(&cv).await; return; } - if cv.is_type(CommunicationType::save_app_data) { + if cv.is_type(CommunicationType::SaveAppData) { let sender_id = cv.get_sender(); let _app_data = cv - .get_data(DataTypes::app_data) + .get_data(DataType::AppData) .as_str() .unwrap_or("") .to_string(); - let res = CommunicationValue::new(CommunicationType::save_app_data) + let res = CommunicationValue::new(CommunicationType::SaveAppData) .with_id(cv.get_id()) .with_receiver(sender_id); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::load_app_data) { + if cv.is_type(CommunicationType::LoadAppData) { let sender_id = cv.get_sender(); let app_data = String::new(); - let res = CommunicationValue::new(CommunicationType::load_app_data) + let res = CommunicationValue::new(CommunicationType::LoadAppData) .with_id(cv.get_id()) .with_receiver(sender_id) - .add_data(DataTypes::app_data, DataValue::Str(app_data)); + .add_typed_default(DataType::AppData, DataValue::Str(app_data)); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::create_app) { + if cv.is_type(CommunicationType::CreateApp) { let sender_id = cv.get_sender() as i64; let app_identifier = cv - .get_data(DataTypes::app_identifier) + .get_data(DataType::AppIdentifier) .as_str() .unwrap_or("") .to_string(); let app_public_key = cv - .get_data(DataTypes::app_public_key) + .get_data(DataType::AppPublicKey) .as_str() .unwrap_or("") .to_string(); @@ -180,17 +191,17 @@ impl ClientConnection { } } - let res = CommunicationValue::new(CommunicationType::create_app) + let res = CommunicationValue::new(CommunicationType::CreateApp) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::delete_app) { + if cv.is_type(CommunicationType::DeleteApp) { let sender_id = cv.get_sender() as i64; let app_identifier = cv - .get_data(DataTypes::app_identifier) + .get_data(DataType::AppIdentifier) .as_str() .unwrap_or("") .to_string(); @@ -204,30 +215,30 @@ impl ClientConnection { } } - let res = CommunicationValue::new(CommunicationType::delete_app) + let res = CommunicationValue::new(CommunicationType::DeleteApp) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::client_connected) { - let user_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0) as i64; - let _session_id = cv.get_data(DataTypes::session_id).as_number().unwrap_or(0) as i64; + if cv.is_type(CommunicationType::ClientConnected) { + let user_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0) as i64; + let _session_id = cv.get_data(DataType::SessionId).as_number().unwrap_or(0) as i64; let contacts = chats_util::get_users(user_id); let mut contacts_array = Vec::new(); for (i, contact) in contacts.iter().enumerate() { let mut contact_container = Vec::new(); - contact_container.push((DataTypes::user_id, DataValue::Number(contact.user_id))); + contact_container.push((DataType::UserId, DataValue::SignedNumber(contact.user_id as i128))); contact_container.push(( - DataTypes::last_message_at, - DataValue::Number(contact.last_message_at.unwrap_or(0)), + DataType::LastMessageAt, + DataValue::SignedNumber(contact.last_message_at.unwrap_or(0) as i128), )); if let Some(ref name) = contact.user_name { - contact_container.push((DataTypes::username, DataValue::Str(name.clone()))); + contact_container.push((DataType::Username, DataValue::Str(name.clone()))); } let amount = if i < 10 { 20 } else { 1 }; @@ -242,12 +253,12 @@ impl ClientConnection { let message_state = m["message_state"].as_str().unwrap_or("").to_string(); let mut msg_container = Vec::new(); - msg_container.push((DataTypes::send_time, DataValue::Number(message_time))); - msg_container.push((DataTypes::content, DataValue::Str(content.clone()))); - msg_container.push((DataTypes::message_state, DataValue::Str(message_state))); - msg_container.push((DataTypes::height, DataValue::Number(height))); - msg_container.push((DataTypes::sent_by_self, DataValue::Bool(sent_by_self))); - msg_array.push(DataValue::Container(msg_container)); + msg_container.push((DataType::SendTime, DataValue::SignedNumber(message_time as i128))); + msg_container.push((DataType::Content, DataValue::Str(content.clone()))); + msg_container.push((DataType::MessageState, DataValue::Str(message_state))); + msg_container.push((DataType::Height, DataValue::SignedNumber(height as i128))); + msg_container.push((DataType::SentBySelf, DataValue::Bool(sent_by_self))); + msg_array.push(typed_container(msg_container)); if msg_array.len() == 1 { let sender_id = if sent_by_self { @@ -256,19 +267,19 @@ impl ClientConnection { contact.user_id }; let mut last_msg = Vec::new(); - last_msg.push((DataTypes::content, DataValue::Str(content))); - last_msg.push((DataTypes::sender_id, DataValue::Number(sender_id))); + last_msg.push((DataType::Content, DataValue::Str(content))); + last_msg.push((DataType::SenderId, DataValue::SignedNumber(sender_id as i128))); contact_container - .push((DataTypes::last_message, DataValue::Container(last_msg))); + .push((DataType::LastMessage, typed_container(last_msg))); } } - contact_container.push((DataTypes::messages, DataValue::Array(msg_array))); - contacts_array.push(DataValue::Container(contact_container)); + contact_container.push((DataType::Messages, DataValue::Array(msg_array))); + contacts_array.push(typed_container(contact_container)); } - let resp = CommunicationValue::new(CommunicationType::client_connected) + let resp = CommunicationValue::new(CommunicationType::ClientConnected) .with_id(cv.get_id()) - .add_data(DataTypes::contacts, DataValue::Array(contacts_array)); + .add_typed_default(DataType::Contacts, DataValue::Array(contacts_array)); self.send_message(&resp).await; return; } @@ -277,15 +288,15 @@ impl ClientConnection { // Direct messages // // ************************************************ // - if cv.is_type(CommunicationType::message_state) { + if cv.is_type(CommunicationType::MessageState) { let sender_id = &cv.get_sender(); - let receiver_id = match cv.get_data(DataTypes::chat_partner_id).as_number() { + let receiver_id = match cv.get_data(DataType::ChatPartnerId).as_number() { Some(id) => id, _ => return, }; // Parse send_time robustly: accept numeric or string, fallback to current time - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -302,28 +313,25 @@ impl ClientConnection { timestamp_i64, receiver_id as i64, *sender_id as i64, - MessageState::from_str( - cv.get_data(DataTypes::message_state).as_str().unwrap_or(""), - ), + MessageState::from_str(cv.get_data(DataType::MessageState).as_str().unwrap_or("")), ); } // Incoming storsed message: store for the recipient, attempt local delivery, notify sender. - if cv.is_type(CommunicationType::message_send) { + if cv.is_type(CommunicationType::MessageSend) { let sender_id: u64 = cv.get_sender(); // parse receiver_id (the storage owner for this incoming message) - let receiver_id: i64 = if let Some(n) = cv.get_data(DataTypes::receiver_id).as_number() - { + let receiver_id: i64 = if let Some(n) = cv.get_data(DataType::ReceiverId).as_number() { n as i64 - } else if let Some(s) = cv.get_data(DataTypes::receiver_id).as_str() { + } else if let Some(s) = cv.get_data(DataType::ReceiverId).as_str() { s.parse::().unwrap_or(0) } else { 0 }; // parse send_time robustly (number or string), fallback to now - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -339,12 +347,12 @@ impl ClientConnection { // content may be missing; default to empty string let content = cv - .get_data(DataTypes::content) + .get_data(DataType::Content) .as_str() .unwrap_or("") .to_string(); - let height = cv.get_data(DataTypes::height).as_number().unwrap_or(0) as i64; + let height = cv.get_data(DataType::Height).as_number().unwrap_or(0) as i64; let is_local = iota_storage::users::user_manager::get_user(receiver_id).is_some(); @@ -371,19 +379,19 @@ impl ClientConnection { ); // send confirmation back to sender - let conf_msg = CommunicationValue::new(CommunicationType::message_send) + let conf_msg = CommunicationValue::new(CommunicationType::MessageSend) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&conf_msg).await; if !is_local { - let fw_msg = CommunicationValue::new(CommunicationType::message_other_iota) + let fw_msg = CommunicationValue::new(CommunicationType::MessageOtherIota) .with_id(cv.get_id()) .with_receiver(receiver_id as u64) .with_sender(sender_id as u64) - .add_data(DataTypes::height, DataValue::Number(height)) - .add_data(DataTypes::content, DataValue::Str(content)) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)); + .add_typed_default(DataType::Height, DataValue::SignedNumber(height as i128)) + .add_typed_default(DataType::Content, DataValue::Str(content)) + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)); let other_iota_resp = self .clone() @@ -392,7 +400,7 @@ impl ClientConnection { if let Ok(resp) = other_iota_resp { let ms_raw = resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -405,17 +413,17 @@ impl ClientConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)) + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -429,17 +437,17 @@ impl ClientConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)) + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -448,16 +456,16 @@ impl ClientConnection { return; } else { // Build a live-delivery message for the local client (recipient) - let user_forward = CommunicationValue::new(CommunicationType::message_live) + let user_forward = CommunicationValue::new(CommunicationType::MessageLive) .with_id(cv.get_id()) .with_receiver(receiver_id as u64) - .add_data(DataTypes::sender_id, DataValue::Number(sender_id as i64)) - .add_data( - DataTypes::message, - DataValue::Container(vec![ - (DataTypes::content, DataValue::Str(content.clone())), - (DataTypes::send_time, DataValue::Number(timestamp_i64)), - (DataTypes::height, DataValue::Number(height)), + .add_typed_default(DataType::SenderId, DataValue::SignedNumber(sender_id as i128)) + .add_typed_default( + DataType::Message, + typed_container(vec![ + (DataType::Content, DataValue::Str(content.clone())), + (DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)), + (DataType::Height, DataValue::SignedNumber(height as i128)), ]), ); @@ -469,7 +477,7 @@ impl ClientConnection { if let Ok(user_resp) = user_resp { let ms_raw = user_resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -492,17 +500,17 @@ impl ClientConnection { // notify original sender about the delivered/read state self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)) + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -525,17 +533,17 @@ impl ClientConnection { // notify sender self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp_i64 as i128)) + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -545,12 +553,12 @@ impl ClientConnection { } } - if cv.is_type(CommunicationType::message_other_iota) { + if cv.is_type(CommunicationType::MessageOtherIota) { let sender_id = &cv.get_sender(); let receiver_id = &cv.get_receiver(); // parse send_time safely (number or string), fallback to now - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -565,12 +573,12 @@ impl ClientConnection { // content may be missing or non-string; default to empty string let content = cv - .get_data(DataTypes::content) + .get_data(DataType::Content) .as_str() .unwrap_or("") .to_string(); - let height = cv.get_data(DataTypes::height).as_number().unwrap_or(0) as i64; + let height = cv.get_data(DataType::Height).as_number().unwrap_or(0) as i64; chat_files::add_message( timestamp as u128, @@ -582,16 +590,16 @@ impl ClientConnection { ); // Build user_forward using the parsed numeric timestamp and safe content string - let user_forward = CommunicationValue::new(CommunicationType::message_live) + let user_forward = CommunicationValue::new(CommunicationType::MessageLive) .with_id(cv.get_id()) .with_receiver(*receiver_id) - .add_data(DataTypes::sender_id, DataValue::Number(*sender_id as i64)) - .add_data( - DataTypes::message, - DataValue::Container(vec![ - (DataTypes::content, DataValue::Str(content.clone())), - (DataTypes::send_time, DataValue::Number(timestamp)), - (DataTypes::height, DataValue::Number(height)), + .add_typed_default(DataType::SenderId, DataValue::SignedNumber(*sender_id as i128)) + .add_typed_default( + DataType::Message, + typed_container(vec![ + (DataType::Content, DataValue::Str(content.clone())), + (DataType::SendTime, DataValue::SignedNumber(timestamp as i128)), + (DataType::Height, DataValue::SignedNumber(height as i128)), ]), ); @@ -602,7 +610,7 @@ impl ClientConnection { if let Ok(user_resp) = user_resp { let ms_raw = user_resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -615,17 +623,17 @@ impl ClientConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(*sender_id) .with_sender(*receiver_id) - .add_data(DataTypes::send_time, DataValue::Number(timestamp)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(*sender_id as i64), + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp as i128)) + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(*sender_id as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -640,17 +648,17 @@ impl ClientConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(*sender_id) .with_sender(*receiver_id) - .add_data(DataTypes::send_time, DataValue::Number(timestamp)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(*receiver_id as i64), + .add_typed_default(DataType::SendTime, DataValue::SignedNumber(timestamp as i128)) + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(*receiver_id as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -659,12 +667,12 @@ impl ClientConnection { return; } - if cv.is_type(CommunicationType::messages_get) { + if cv.is_type(CommunicationType::MessagesGet) { let my_id = cv.get_sender(); - let partner_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0); - let offset = cv.get_data(DataTypes::offset).as_number().unwrap_or(0); - let amount = cv.get_data(DataTypes::amount).as_number().unwrap_or(0); - let messages = chat_files::get_messages(my_id as i64, partner_id, offset, amount); + let partner_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0); + let offset = cv.get_data(DataType::Offset).as_number().unwrap_or(0); + let amount = cv.get_data(DataType::Amount).as_number().unwrap_or(0); + let messages = chat_files::get_messages(my_id as i64, partner_id as i64, offset as i64, amount as i64); let mut msg_array: Vec = Vec::new(); for m in messages.members() { let message_time: i64 = m["message_time"].as_i64().unwrap_or(0); @@ -674,9 +682,9 @@ impl ClientConnection { let sender_id: i64 = if sent_by_self { my_id as i64 } else { - if let Some(n) = cv.get_data(DataTypes::chat_partner_id).as_number() { + if let Some(n) = cv.get_data(DataType::ChatPartnerId).as_number() { n as i64 - } else if let Some(s) = cv.get_data(DataTypes::chat_partner_id).as_str() { + } else if let Some(s) = cv.get_data(DataType::ChatPartnerId).as_str() { s.parse::().unwrap_or(partner_id as i64) } else { partner_id as i64 @@ -685,53 +693,53 @@ impl ClientConnection { let message_state: String = m["message_state"].as_str().unwrap_or("").to_string(); let mut container = Vec::new(); - container.push((DataTypes::send_time, DataValue::Number(message_time))); - container.push((DataTypes::content, DataValue::Str(content))); - container.push((DataTypes::sender_id, DataValue::Number(sender_id))); - container.push((DataTypes::message_state, DataValue::Str(message_state))); - container.push((DataTypes::height, DataValue::Number(height))); - container.push((DataTypes::sent_by_self, DataValue::Bool(sent_by_self))); - msg_array.push(DataValue::Container(container)); + container.push((DataType::SendTime, DataValue::SignedNumber(message_time as i128))); + container.push((DataType::Content, DataValue::Str(content))); + container.push((DataType::SenderId, DataValue::SignedNumber(sender_id as i128))); + container.push((DataType::MessageState, DataValue::Str(message_state))); + container.push((DataType::Height, DataValue::SignedNumber(height as i128))); + container.push((DataType::SentBySelf, DataValue::Bool(sent_by_self))); + msg_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::messages_get) + let resp = CommunicationValue::new(CommunicationType::MessagesGet) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::messages, DataValue::Array(msg_array)); + .add_typed_default(DataType::Messages, DataValue::Array(msg_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::get_chats) { + if cv.is_type(CommunicationType::GetChats) { let user_id = cv.get_sender(); let users = chats_util::get_users(user_id as i64); let mut user_array = Vec::new(); for user in users { let mut container = Vec::new(); - container.push((DataTypes::user_id, DataValue::Number(user.user_id))); + container.push((DataType::UserId, DataValue::SignedNumber(user.user_id as i128))); if let Some(name) = user.user_name { - container.push((DataTypes::username, DataValue::Str(name))); + container.push((DataType::Username, DataValue::Str(name))); } if let Some(ts) = user.last_message_at { - container.push((DataTypes::last_message_at, DataValue::Number(ts))); + container.push((DataType::LastMessageAt, DataValue::SignedNumber(ts as i128))); } - user_array.push(DataValue::Container(container)); + user_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::get_chats) + let resp = CommunicationValue::new(CommunicationType::GetChats) .with_id(cv.get_id()) .with_receiver(user_id) - .add_data(DataTypes::user_ids, DataValue::Array(user_array)); + .add_typed_default(DataType::UserIds, DataValue::Array(user_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::add_conversation) { + if cv.is_type(CommunicationType::AddConversation) { let user_id = cv.get_sender(); - let other_id = match cv.get_data(DataTypes::chat_partner_id).as_number() { + let other_id = match cv.get_data(DataType::ChatPartnerId).as_number() { Some(n) => n as i64, None => cv - .get_data(DataTypes::chat_partner_id) + .get_data(DataType::ChatPartnerId) .as_str() .unwrap_or("0") .parse() @@ -739,7 +747,7 @@ impl ClientConnection { }; let mut contact = get_user(user_id as i64, other_id).unwrap_or(Contact::new(other_id)); - if let Some(name) = cv.get_data(DataTypes::chat_partner_name).as_str() { + if let Some(name) = cv.get_data(DataType::ChatPartnerName).as_str() { contact.user_name = Some(name.to_string()); } @@ -750,85 +758,82 @@ impl ClientConnection { .as_millis() as i64, ); mod_user(user_id as i64, &contact); - let resp = CommunicationValue::new(CommunicationType::add_conversation) + let resp = CommunicationValue::new(CommunicationType::AddConversation) .with_id(cv.get_id()) .with_receiver(user_id); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::add_community) { + if cv.is_type(CommunicationType::AddCommunity) { CommunitiesUtil::add_community( cv.get_sender() as i64, - cv.get_data(DataTypes::community_address) + cv.get_data(DataType::CommunityAddress) .as_str() .unwrap() .to_string(), - cv.get_data(DataTypes::community_title) + cv.get_data(DataType::CommunityTitle) .as_str() .unwrap() .to_string(), - cv.get_data(DataTypes::position) + cv.get_data(DataType::Position) .as_str() .unwrap() .to_string(), ); - let resp = CommunicationValue::new(CommunicationType::add_community) + let resp = CommunicationValue::new(CommunicationType::AddCommunity) .with_id(cv.get_id()) .with_receiver(cv.get_sender()); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::get_communities) { + if cv.is_type(CommunicationType::GetCommunities) { let mut comm_array = Vec::new(); for c in CommunitiesUtil::get_communities(cv.get_sender() as i64) { - let mut container: Vec<(DataTypes, DataValue)> = Vec::new(); + let mut container: Vec<(DataType, DataValue)> = Vec::new(); if let Some(address) = c["address"].as_str() { container.push(( - DataTypes::community_address, + DataType::CommunityAddress, DataValue::Str(address.to_string()), )); } if let Some(title) = c["title"].as_str() { - container.push(( - DataTypes::community_title, - DataValue::Str(title.to_string()), - )); + container.push((DataType::CommunityTitle, DataValue::Str(title.to_string()))); } if let Some(position) = c["position"].as_str() { - container.push((DataTypes::position, DataValue::Str(position.to_string()))); + container.push((DataType::Position, DataValue::Str(position.to_string()))); } - comm_array.push(DataValue::Container(container)); + comm_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::get_communities) + let resp = CommunicationValue::new(CommunicationType::GetCommunities) .with_id(cv.get_id()) .with_receiver(cv.get_sender()) - .add_data(DataTypes::communities, DataValue::Array(comm_array)); + .add_typed_default(DataType::Communities, DataValue::Array(comm_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::remove_community) { + if cv.is_type(CommunicationType::RemoveCommunity) { CommunitiesUtil::remove_community( cv.get_sender() as i64, - cv.get_data(DataTypes::community_address) + cv.get_data(DataType::CommunityAddress) .as_str() .unwrap() .to_string(), ); - let resp = CommunicationValue::new(CommunicationType::remove_community) + let resp = CommunicationValue::new(CommunicationType::RemoveCommunity) .with_id(cv.get_id()) .with_receiver(cv.get_sender()); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::settings_save) { + if cv.is_type(CommunicationType::SettingsSave) { let my_id = cv.get_sender(); - let settings_name = cv.get_data(DataTypes::settings_name).as_str().unwrap(); - let settings_value = cv.get_data(DataTypes::payload).as_str().unwrap(); + let settings_name = cv.get_data(DataType::SettingsName).as_str().unwrap(); + let settings_value = cv.get_data(DataType::Payload).as_str().unwrap(); save_file( &format!("users/{}/settings/", my_id), @@ -836,7 +841,7 @@ impl ClientConnection { &settings_value, ); - let response = CommunicationValue::new(CommunicationType::settings_save) + let response = CommunicationValue::new(CommunicationType::SettingsSave) .with_receiver(my_id) .with_id(cv.get_id()); @@ -844,24 +849,24 @@ impl ClientConnection { return; } - if cv.is_type(CommunicationType::settings_load) { + if cv.is_type(CommunicationType::SettingsLoad) { let my_id = cv.get_sender(); - let settings_name = cv.get_data(DataTypes::settings_name).as_string().unwrap(); + let settings_name = cv.get_data(DataType::SettingsName).as_string().unwrap(); let settings_value_str = load_file( &format!("users/{}/settings/", my_id), &format!("{}.settings", settings_name), ); - let response = CommunicationValue::new(CommunicationType::settings_load) + let response = CommunicationValue::new(CommunicationType::SettingsLoad) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::payload, DataValue::Str(settings_value_str)) - .add_data(DataTypes::settings_name, DataValue::Str(settings_name)); + .add_typed_default(DataType::Payload, DataValue::Str(settings_value_str)) + .add_typed_default(DataType::SettingsName, DataValue::Str(settings_name)); self.send_message(&response).await; return; } - if cv.is_type(CommunicationType::settings_list) { + if cv.is_type(CommunicationType::SettingsList) { let my_id = cv.get_sender(); let settings = get_children(&format!("users/{}/settings/", my_id)); let mut settings_json = Vec::new(); @@ -872,10 +877,10 @@ impl ClientConnection { } let _ = settings_json.push(DataValue::Str(s)); } - let response = CommunicationValue::new(CommunicationType::settings_list) + let response = CommunicationValue::new(CommunicationType::SettingsList) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::settings, DataValue::Array(settings_json)); + .add_typed_default(DataType::Settings, DataValue::Array(settings_json)); self.send_message(&response).await; return; @@ -887,8 +892,8 @@ impl ClientConnection { let private_key = conf.get_private_key().unwrap(); drop(conf); - let omikron_public_key = cv.get_data(DataTypes::public_key).as_str().unwrap(); - let encrypted_challenge = cv.get_data(DataTypes::challenge).as_str().unwrap(); + let omikron_public_key = cv.get_data(DataType::PublicKey).as_str().unwrap(); + let encrypted_challenge = cv.get_data(DataType::Challenge).as_str().unwrap(); let solved_challenge = { if let Ok(decrypted) = SecurePayload::new( @@ -911,9 +916,9 @@ impl ClientConnection { if let Some(decrypted) = solved_challenge { let solved = decrypted.export(DataFormat::Raw); - let response = CommunicationValue::new(CommunicationType::challenge_response) + let response = CommunicationValue::new(CommunicationType::ChallengeResponse) .with_id(cv.get_id()) - .add_data(DataTypes::challenge, DataValue::Str(solved)); + .add_typed_default(DataType::Challenge, DataValue::Str(solved)); self.send_message(&response).await; } @@ -943,7 +948,7 @@ impl ClientConnection { let sender_clone = Arc::clone(sender); drop(sender_guard); - if !cv.is_type(CommunicationType::ping) && !cv.is_type(CommunicationType::pong) { + if !cv.is_type(CommunicationType::Ping) && !cv.is_type(CommunicationType::Pong) { log_cv_out!(&cv); } diff --git a/communities/Cargo.toml b/communities/Cargo.toml index b930ed5..812ff55 100644 --- a/communities/Cargo.toml +++ b/communities/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } iota-logger = { path = "../iota-logger" } iota-util = { path = "../iota-util" } iota-storage = { path = "../iota-storage" } diff --git a/communities/src/community.rs b/communities/src/community.rs index fb79ba8..69ba273 100644 --- a/communities/src/community.rs +++ b/communities/src/community.rs @@ -210,7 +210,7 @@ impl Community { for interactable in target_interactables.iter() { if interactable.get_name() == name { if interactable.get_codec() == "category" { - return CommunicationValue::new(CommunicationType::error_internal); + return CommunicationValue::new(CommunicationType::ErrorInternal); } else { // cannot move a value of type dyn Interactable the size of dyn Interactable cannot be statically determined (rustc E0161) return interactable.run_function(cv.clone()).await; @@ -231,12 +231,12 @@ impl Community { .run_function(cv.clone()) .await; } else { - return CommunicationValue::new(CommunicationType::error_internal); + return CommunicationValue::new(CommunicationType::ErrorInternal); } } } } - CommunicationValue::new(CommunicationType::add_conversation) + CommunicationValue::new(CommunicationType::AddConversation) } pub async fn save(&self) { diff --git a/communities/src/community_connection.rs b/communities/src/community_connection.rs index 5ed5ef8..3ceca2b 100644 --- a/communities/src/community_connection.rs +++ b/communities/src/community_connection.rs @@ -70,12 +70,12 @@ impl CommunityConnection { let user_id = self.get_user_id().await; cv = cv.with_sender(user_id); - if cv.is_type(CommunicationType::identification) && !self.is_identified().await { + if cv.is_type(CommunicationType::Identification) && !self.is_identified().await { self.handle_identification(cv).await; return; } - if cv.is_type(CommunicationType::challenge_response) && !self.is_identified().await { + if cv.is_type(CommunicationType::ChallengeResponse) && !self.is_identified().await { self.handle_challenge_response(cv).await; return; } @@ -84,25 +84,25 @@ impl CommunityConnection { return; } - if cv.is_type(CommunicationType::ping) { + if cv.is_type(CommunicationType::Ping) { self.handle_ping(cv).await; return; } - if cv.is_type(CommunicationType::client_changed) { + if cv.is_type(CommunicationType::ClientChanged) { //self.handle_client_changed(cv).await; return; } - if cv.is_type(CommunicationType::function) { + if cv.is_type(CommunicationType::Function) { self.handle_function(cv).await; return; } } async fn handle_function(&self, cv: CommunicationValue) { - let name = cv.get_data(DataTypes::name).unwrap().as_str().unwrap(); - let path = cv.get_data(DataTypes::path).unwrap().as_str().unwrap(); - let function = cv.get_data(DataTypes::function).unwrap().as_str().unwrap(); + let name = cv.get_data(DataType::Name).unwrap().as_str().unwrap(); + let path = cv.get_data(DataType::Path).unwrap().as_str().unwrap(); + let function = cv.get_data(DataType::Function).unwrap().as_str().unwrap(); let result = self .get_community() @@ -115,13 +115,13 @@ impl CommunityConnection { } async fn handle_identification(&self, cv: CommunicationValue) { let user_id = cv - .get_data(DataTypes::user_id) + .get_data(DataType::UserId) .unwrap_or(&JsonValue::Number(Number::from(0))) .as_i64() .unwrap_or(0); let Some(user) = get_user(user_id) else { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_user_id) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidUserId) .await; return; }; @@ -151,7 +151,7 @@ impl CommunityConnection { let user_public_key_bytes = match STANDARD.decode(&user.public_key) { Ok(bytes) => bytes, Err(_) => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_user_id) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidUserId) .await; return; } @@ -160,14 +160,14 @@ impl CommunityConnection { let user_pub_key: PublicKey = match PublicKey::from_bytes(&user_public_key_bytes) { Some(key) => key, __ => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_user_id) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidUserId) .await; return; } }; let Some(community) = self.community.read().await.clone() else { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; }; @@ -178,7 +178,7 @@ impl CommunityConnection { let shared_secret = match community_private_key.to_diffie_hellman(&user_pub_key) { Some(secret) => secret, _ => { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; } @@ -200,7 +200,7 @@ impl CommunityConnection { let encrypted_challenge = match cipher.encrypt(nonce, challenge_str.as_bytes()) { Ok(data) => data, Err(_) => { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; } @@ -209,21 +209,21 @@ impl CommunityConnection { let mut encrypted_out = nonce_bytes.to_vec(); encrypted_out.extend(encrypted_challenge); - let response = CommunicationValue::new(CommunicationType::challenge) + let response = CommunicationValue::new(CommunicationType::Challenge) .add_data_str( - DataTypes::public_key, + DataType::PublicKey, STANDARD.encode(community_public_key.as_bytes()), ) - .add_data_str(DataTypes::challenge, STANDARD.encode(&encrypted_out)) + .add_data_str(DataType::Challenge, STANDARD.encode(&encrypted_out)) .with_id(cv.get_id()); self.send_message(&response).await; } async fn handle_challenge_response(self: Arc, cv: CommunicationValue) { - let client_challenge_response_b64 = match cv.get_data(DataTypes::challenge) { + let client_challenge_response_b64 = match cv.get_data(DataType::Challenge) { Some(data) => data.to_string(), _ => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_data) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidData) .await; return; } @@ -232,38 +232,38 @@ impl CommunityConnection { let challenge_response_bytes = match STANDARD.decode(&client_challenge_response_b64) { Ok(bytes) => bytes, Err(_) => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_data) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidData) .await; return; } }; if challenge_response_bytes.len() < 12 { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_data) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidData) .await; return; } let Some(user) = self.auth.read().await.clone() else { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; }; let Some(user_pub_bytes) = STANDARD.decode(&user.public_key).ok() else { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_data) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidData) .await; return; }; let Some(user_pub_key) = PublicKey::from_bytes(&user_pub_bytes) else { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_public_key) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidPublicKey) .await; return; }; let Some(community) = self.community.read().await.clone() else { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; }; @@ -273,7 +273,7 @@ impl CommunityConnection { let shared_secret = match community_private_key.to_diffie_hellman(&user_pub_key) { Some(secret) => secret, _ => { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; } @@ -297,7 +297,7 @@ impl CommunityConnection { let decrypted_bytes = match cipher.decrypt(nonce, ciphertext) { Ok(pt) => pt, Err(_) => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_challenge) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidChallenge) .await; return; } @@ -306,7 +306,7 @@ impl CommunityConnection { let client_response = match String::from_utf8(decrypted_bytes) { Ok(str) => str, Err(_) => { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_data) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidData) .await; return; } @@ -315,7 +315,7 @@ impl CommunityConnection { let expected_challenge = self.challenge.read().await.clone(); if client_response != expected_challenge { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_challenge) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidChallenge) .await; self.close().await; return; @@ -327,7 +327,7 @@ impl CommunityConnection { } let Some(community) = self.community.read().await.clone() else { - self.send_error_response(&cv.get_id(), CommunicationType::error_internal) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInternal) .await; return; }; @@ -335,15 +335,15 @@ impl CommunityConnection { let user_id = self.get_user_id().await; if user_id == 0 { - self.send_error_response(&cv.get_id(), CommunicationType::error_invalid_user_id) + self.send_error_response(&cv.get_id(), CommunicationType::ErrorInvalidUserId) .await; return; } arc.add_connection(self.clone()).await; - let response = CommunicationValue::new(CommunicationType::identification_response) - .add_data(DataTypes::interactables, { + let response = CommunicationValue::new(CommunicationType::IdentificationResponse) + .add_data(DataType::Interactables, { let a: Vec>> = arc.get_interactables(user_id).await; let mut c: JsonValue = JsonValue::new_object(); for b in a { @@ -382,14 +382,14 @@ impl CommunityConnection { } async fn handle_ping(&self, cv: CommunicationValue) { - if let Some(last_ping) = cv.get_data(DataTypes::last_ping) { + if let Some(last_ping) = cv.get_data(DataType::LastPing) { if let Ok(ping_val) = last_ping.to_string().parse::() { let mut ping_guard = self.ping.write().await; *ping_guard = ping_val; } } - let response = CommunicationValue::new(CommunicationType::pong).with_id(cv.get_id()); + let response = CommunicationValue::new(CommunicationType::Pong).with_id(cv.get_id()); self.send_message(&response).await; } diff --git a/communities/src/interactables/category.rs b/communities/src/interactables/category.rs index c709014..f2836ed 100644 --- a/communities/src/interactables/category.rs +++ b/communities/src/interactables/category.rs @@ -1,121 +1,121 @@ -use crate::communities::{community::Community, interactables::interactable::Interactable}; -use async_trait::async_trait; -use json::JsonValue; -use std::any::Any; -use std::sync::Arc; -use ttp_core::CommunicationValue; -use uuid::Uuid; - -pub struct Category { - id: Uuid, - name: String, - path: String, - community: Arc, - children: Vec>>, -} -impl Category { - pub fn new() -> Category { - Category { - id: Uuid::new_v4(), - name: String::new(), - path: String::new(), - community: Arc::new(Community::new()), - children: Vec::new(), - } - } - pub fn get_child(&self, path: String, name: String) -> Option>> { - if path.is_empty() { - self.children - .iter() - .find(|child| child.get_name() == &name) - .cloned() - } else { - let sub_module = path.split("/").next().unwrap(); - let next = self - .children - .iter() - .find(|child| child.get_name() == sub_module) - .unwrap(); - if next.get_codec() == "category" { - let next_cat = next.as_any().downcast_ref::().unwrap(); - next_cat.get_child(path, name) - } else { - Some(next.clone()) - } - } - } - pub fn get_children(&self) -> Vec>> { - self.children.iter().map(|child| child.clone()).collect() - } -} - -#[async_trait] -impl Interactable for Category { - fn get_id(&self) -> &Uuid { - &self.id - } - fn as_any(&self) -> &dyn Any { - self - } - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - fn get_codec(&self) -> String { - "category".to_string() - } - fn set_name(&mut self, name: String) { - self.name = name; - } - fn set_path(&mut self, path: String) { - self.path = path; - } - fn get_community(&self) -> &Arc { - &self.community - } - fn set_community(&mut self, community: Arc) { - self.community = community; - } - fn get_name(&self) -> &String { - &self.name - } - fn get_path(&self) -> &String { - &self.path - } - fn get_total_path(&self) -> String { - String::new() + &self.path + "/" + &self.name - } - fn get_data(&self) -> JsonValue { - let mut v = JsonValue::new_object(); - for child in &self.children { - let mut subject = JsonValue::new_object(); - subject["codec"] = JsonValue::String(child.get_codec()); - subject["data"] = child.get_data(); - v[child.get_name()] = subject; - } - v - } - async fn run_function(&self, _cv: CommunicationValue) -> CommunicationValue { - CommunicationValue::new(CommunicationType::error_internal) - } - fn to_json(&self) -> JsonValue { - let mut v = JsonValue::new_object(); - v["children"] = JsonValue::new_array(); - for child in &self.children { - let _ = v["children"].push(child.to_json()); - } - v - } - fn load( - &mut self, - community: Arc, - id: Uuid, - path: String, - name: String, - _json: &JsonValue, - ) { - self.community = community; - self.id = id; - self.name = name; - self.path = path; - } -} +use crate::communities::{community::Community, interactables::interactable::Interactable}; +use async_trait::async_trait; +use json::JsonValue; +use std::any::Any; +use std::sync::Arc; +use mtp::codec::CommunicationValue; +use uuid::Uuid; + +pub struct Category { + id: Uuid, + name: String, + path: String, + community: Arc, + children: Vec>>, +} +impl Category { + pub fn new() -> Category { + Category { + id: Uuid::new_v4(), + name: String::new(), + path: String::new(), + community: Arc::new(Community::new()), + children: Vec::new(), + } + } + pub fn get_child(&self, path: String, name: String) -> Option>> { + if path.is_empty() { + self.children + .iter() + .find(|child| child.get_name() == &name) + .cloned() + } else { + let sub_module = path.split("/").next().unwrap(); + let next = self + .children + .iter() + .find(|child| child.get_name() == sub_module) + .unwrap(); + if next.get_codec() == "category" { + let next_cat = next.as_any().downcast_ref::().unwrap(); + next_cat.get_child(path, name) + } else { + Some(next.clone()) + } + } + } + pub fn get_children(&self) -> Vec>> { + self.children.iter().map(|child| child.clone()).collect() + } +} + +#[async_trait] +impl Interactable for Category { + fn get_id(&self) -> &Uuid { + &self.id + } + fn as_any(&self) -> &dyn Any { + self + } + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + fn get_codec(&self) -> String { + "category".to_string() + } + fn set_name(&mut self, name: String) { + self.name = name; + } + fn set_path(&mut self, path: String) { + self.path = path; + } + fn get_community(&self) -> &Arc { + &self.community + } + fn set_community(&mut self, community: Arc) { + self.community = community; + } + fn get_name(&self) -> &String { + &self.name + } + fn get_path(&self) -> &String { + &self.path + } + fn get_total_path(&self) -> String { + String::new() + &self.path + "/" + &self.name + } + fn get_data(&self) -> JsonValue { + let mut v = JsonValue::new_object(); + for child in &self.children { + let mut subject = JsonValue::new_object(); + subject["codec"] = JsonValue::String(child.get_codec()); + subject["data"] = child.get_data(); + v[child.get_name()] = subject; + } + v + } + async fn run_function(&self, _cv: CommunicationValue) -> CommunicationValue { + CommunicationValue::new(CommunicationType::ErrorInternal) + } + fn to_json(&self) -> JsonValue { + let mut v = JsonValue::new_object(); + v["children"] = JsonValue::new_array(); + for child in &self.children { + let _ = v["children"].push(child.to_json()); + } + v + } + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { + self.community = community; + self.id = id; + self.name = name; + self.path = path; + } +} diff --git a/communities/src/interactables/interactable.rs b/communities/src/interactables/interactable.rs index 0521de6..dd7f326 100644 --- a/communities/src/interactables/interactable.rs +++ b/communities/src/interactables/interactable.rs @@ -3,7 +3,7 @@ use async_trait::async_trait; use json::JsonValue; use std::any::Any; use std::sync::Arc; -use ttp_core::CommunicationValue; +use mtp::codec::CommunicationValue; use uuid::Uuid; pub type InteractableFactory = fn() -> Box; diff --git a/communities/src/interactables/text_chat.rs b/communities/src/interactables/text_chat.rs index 25eb192..967f27b 100644 --- a/communities/src/interactables/text_chat.rs +++ b/communities/src/interactables/text_chat.rs @@ -1,264 +1,264 @@ -use crate::{ - communities::{ - community::Community, community_connection::CommunityConnection, - interactables::interactable::Interactable, - }, - log, - util::file_util::{get_children, load_file, save_file}, -}; -use async_trait::async_trait; -use json::{JsonValue, array, object}; -use std::fs; -use std::path::Path; -use std::sync::Arc; -use std::{any::Any, collections::HashMap}; -use ttp_core::{CommunicationType, CommunicationValue, DataTypes}; -use uuid::Uuid; -pub struct TextChat { - id: Uuid, - name: String, - path: String, - community: Arc, -} -impl TextChat { - pub fn new() -> TextChat { - TextChat { - id: Uuid::new_v4(), - name: String::new(), - path: String::new(), - community: Arc::new(Community::new()), - } - } - pub fn add_message(&self, send_time: u128, sender: i64, message: &str) { - let user_dir = &format!( - "communities/{}/interactables/{}/{}", - self.get_community().get_name(), - self.get_path(), - self.get_name() - ); - - let working_dir = iota_util::file_util::get_directory(); - let full_dir = Path::new(&working_dir).join(user_dir); - if let Err(e) = fs::create_dir_all(&full_dir) { - log!("Failed to create chat directory: {}", e); - return; - } - - let mut chunk_index = 0; - let mut message_chunk = array![]; - - // find latest chunk not full (max 800 msgs) - loop { - let file_name = format!("msgs_{}.json", chunk_index); - let file_content = load_file(&user_dir, &file_name); - - if !file_content.is_empty() { - if let Ok(current_chunk) = json::parse(&file_content) { - if current_chunk.is_array() && current_chunk.len() < 800 { - message_chunk = current_chunk; - break; - } - } else { - log!("Failed to parse existing JSON file: {}", file_name); - } - } else { - break; - } - - chunk_index += 1; - if chunk_index > 1000 { - log!("Too many message chunks. Aborting add."); - return; - } - } - - let json_obj = object! { - "timestamp" => send_time as i64, - "content" => message, - "sender" => sender.to_string(), - }; - - if let Err(e) = message_chunk.push(json_obj) { - log!("Failed to push new message into JSON array: {}", e); - return; - } - - let file_name = format!("msgs_{}.json", chunk_index); - log!("Saving message to {}/{}", user_dir, file_name); - save_file(&user_dir, &file_name, &message_chunk.dump()); - } - pub fn get_messages(&self, loaded_messages: i64, amount: i64) -> JsonValue { - let mut messages = array![]; - - let mut latest_chunk_index: i32 = -1; - let files = get_children(&format!( - "communities/{}/interactables/{}/{}", - self.get_community().get_name(), - self.get_path(), - self.get_name() - )); - - for entry in files { - if let Some(num) = { - entry - .strip_prefix("msgs_") - .and_then(|s| s.strip_suffix(".json")) - } { - if let Ok(index) = num.parse::() { - if index > latest_chunk_index { - latest_chunk_index = index; - } - } - } - } - - if latest_chunk_index == -1 { - return messages; - } - - let mut to_skip = loaded_messages; - let mut needed = amount; - - for chunk_index in (0..=latest_chunk_index).rev() { - if needed == 0 { - break; - } - let file_name = format!("msgs_{}.json", chunk_index); - let file_content = load_file( - &format!( - "communities/{}/interactables/{}/{}", - self.get_community().get_name(), - self.get_path(), - self.get_name() - ), - &file_name, - ); - if file_content.is_empty() { - continue; - } - if let Ok(chunk) = json::parse(&file_content) { - for i in (0..chunk.len()).rev() { - if needed == 0 { - break; - } - if to_skip > 0 { - to_skip -= 1; - continue; - } - messages.push(chunk[i].clone()).unwrap(); - needed -= 1; - } - } - } - - messages - } -} -#[async_trait] -impl Interactable for TextChat { - fn get_id(&self) -> &Uuid { - &self.id - } - fn as_any(&self) -> &dyn Any { - self - } - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - fn get_codec(&self) -> String { - "text".to_string() - } - fn set_name(&mut self, name: String) { - self.name = name; - } - fn set_path(&mut self, path: String) { - self.path = path; - } - fn get_community(&self) -> &Arc { - &self.community - } - fn set_community(&mut self, community: Arc) { - self.community = community; - } - fn get_name(&self) -> &String { - &self.name - } - fn get_path(&self) -> &String { - &self.path - } - fn get_total_path(&self) -> String { - String::new() + &self.path + "/" + &self.name - } - fn get_data(&self) -> JsonValue { - JsonValue::new_object() - } - async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue { - let payload = cv.get_data(DataTypes::payload).as_container().unwrap(); - if cv.get_data(DataTypes::function).as_str().unwrap() == "get_messages" { - let amount = payload.get(DataTypes::amount).as_i64().unwrap(); - let loaded_messages = payload["loaded_messages"].as_i64().unwrap(); - let messages = self.get_messages(loaded_messages, amount).clone(); - let mut payload = JsonValue::new_object(); - payload["messages"] = messages; - return CommunicationValue::new(CommunicationType::function) - .with_id(cv.get_id()) - .add_data_str(DataTypes::name, self.name.clone()) - .add_data_str(DataTypes::path, self.path.clone()) - .add_data_str(DataTypes::result, "message_chunk".to_string()) - .add_data(DataTypes::payload, payload); - } - if cv.get_data(DataTypes::function).unwrap().as_str().unwrap() == "send_message" { - let message = payload["message"].as_str().unwrap(); - let milliseconds_timestamp: u128 = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_millis(); - self.add_message(milliseconds_timestamp, cv.get_sender(), message); - - let mut distribution_payload = JsonValue::new_object(); - distribution_payload["message"] = JsonValue::String(message.to_string()); - distribution_payload["sender_id"] = JsonValue::String(cv.get_sender().to_string()); - distribution_payload["send_time"] = - JsonValue::String(milliseconds_timestamp.to_string()); - let distribution = CommunicationValue::new(CommunicationType::update) - .with_id(cv.get_id()) - .add_data_str(DataTypes::name, self.name.clone()) - .add_data_str(DataTypes::path, self.path.clone()) - .add_data_str(DataTypes::result, "message_live".to_string()) - .add_data(DataTypes::payload, distribution_payload); - - let connections: HashMap>> = - self.get_community().get_connections().await.clone(); - - for con in connections.values() { - for c in con { - let cd: &Arc = c; - cd.send_message(&distribution).await; - } - } - return CommunicationValue::new(CommunicationType::function) - .with_id(cv.get_id()) - .add_data_str(DataTypes::name, self.name.clone()) - .add_data_str(DataTypes::path, self.path.clone()) - .add_data_str(DataTypes::result, "message_received".to_string()) - .add_data(DataTypes::payload, JsonValue::new_object()); - } - CommunicationValue::new(CommunicationType::error_internal).with_id(cv.get_id()) - } - fn to_json(&self) -> JsonValue { - JsonValue::new_object() - } - fn load( - &mut self, - community: Arc, - id: Uuid, - path: String, - name: String, - _json: &JsonValue, - ) { - self.community = community; - self.id = id; - self.name = name; - self.path = path; - } -} +use crate::{ + communities::{ + community::Community, community_connection::CommunityConnection, + interactables::interactable::Interactable, + }, + log, + util::file_util::{get_children, load_file, save_file}, +}; +use async_trait::async_trait; +use json::{JsonValue, array, object}; +use std::fs; +use std::path::Path; +use std::sync::Arc; +use std::{any::Any, collections::HashMap}; +use mtp::codec::{CommunicationType, CommunicationValue, DataType}; +use uuid::Uuid; +pub struct TextChat { + id: Uuid, + name: String, + path: String, + community: Arc, +} +impl TextChat { + pub fn new() -> TextChat { + TextChat { + id: Uuid::new_v4(), + name: String::new(), + path: String::new(), + community: Arc::new(Community::new()), + } + } + pub fn add_message(&self, send_time: u128, sender: i64, message: &str) { + let user_dir = &format!( + "communities/{}/interactables/{}/{}", + self.get_community().get_name(), + self.get_path(), + self.get_name() + ); + + let working_dir = iota_util::file_util::get_directory(); + let full_dir = Path::new(&working_dir).join(user_dir); + if let Err(e) = fs::create_dir_all(&full_dir) { + log!("Failed to create chat directory: {}", e); + return; + } + + let mut chunk_index = 0; + let mut message_chunk = array![]; + + // find latest chunk not full (max 800 msgs) + loop { + let file_name = format!("msgs_{}.json", chunk_index); + let file_content = load_file(&user_dir, &file_name); + + if !file_content.is_empty() { + if let Ok(current_chunk) = json::parse(&file_content) { + if current_chunk.is_array() && current_chunk.len() < 800 { + message_chunk = current_chunk; + break; + } + } else { + log!("Failed to parse existing JSON file: {}", file_name); + } + } else { + break; + } + + chunk_index += 1; + if chunk_index > 1000 { + log!("Too many message chunks. Aborting add."); + return; + } + } + + let json_obj = object! { + "timestamp" => send_time as i64, + "content" => message, + "sender" => sender.to_string(), + }; + + if let Err(e) = message_chunk.push(json_obj) { + log!("Failed to push new message into JSON array: {}", e); + return; + } + + let file_name = format!("msgs_{}.json", chunk_index); + log!("Saving message to {}/{}", user_dir, file_name); + save_file(&user_dir, &file_name, &message_chunk.dump()); + } + pub fn get_messages(&self, loaded_messages: i64, amount: i64) -> JsonValue { + let mut messages = array![]; + + let mut latest_chunk_index: i32 = -1; + let files = get_children(&format!( + "communities/{}/interactables/{}/{}", + self.get_community().get_name(), + self.get_path(), + self.get_name() + )); + + for entry in files { + if let Some(num) = { + entry + .strip_prefix("msgs_") + .and_then(|s| s.strip_suffix(".json")) + } { + if let Ok(index) = num.parse::() { + if index > latest_chunk_index { + latest_chunk_index = index; + } + } + } + } + + if latest_chunk_index == -1 { + return messages; + } + + let mut to_skip = loaded_messages; + let mut needed = amount; + + for chunk_index in (0..=latest_chunk_index).rev() { + if needed == 0 { + break; + } + let file_name = format!("msgs_{}.json", chunk_index); + let file_content = load_file( + &format!( + "communities/{}/interactables/{}/{}", + self.get_community().get_name(), + self.get_path(), + self.get_name() + ), + &file_name, + ); + if file_content.is_empty() { + continue; + } + if let Ok(chunk) = json::parse(&file_content) { + for i in (0..chunk.len()).rev() { + if needed == 0 { + break; + } + if to_skip > 0 { + to_skip -= 1; + continue; + } + messages.push(chunk[i].clone()).unwrap(); + needed -= 1; + } + } + } + + messages + } +} +#[async_trait] +impl Interactable for TextChat { + fn get_id(&self) -> &Uuid { + &self.id + } + fn as_any(&self) -> &dyn Any { + self + } + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + fn get_codec(&self) -> String { + "text".to_string() + } + fn set_name(&mut self, name: String) { + self.name = name; + } + fn set_path(&mut self, path: String) { + self.path = path; + } + fn get_community(&self) -> &Arc { + &self.community + } + fn set_community(&mut self, community: Arc) { + self.community = community; + } + fn get_name(&self) -> &String { + &self.name + } + fn get_path(&self) -> &String { + &self.path + } + fn get_total_path(&self) -> String { + String::new() + &self.path + "/" + &self.name + } + fn get_data(&self) -> JsonValue { + JsonValue::new_object() + } + async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue { + let payload = cv.get_data(DataType::Payload).as_container().unwrap(); + if cv.get_data(DataType::Function).as_str().unwrap() == "get_messages" { + let amount = payload.get(DataType::Amount).as_i64().unwrap(); + let loaded_messages = payload["loaded_messages"].as_i64().unwrap(); + let messages = self.get_messages(loaded_messages, amount).clone(); + let mut payload = JsonValue::new_object(); + payload["messages"] = messages; + return CommunicationValue::new(CommunicationType::Function) + .with_id(cv.get_id()) + .add_data_str(DataType::Name, self.name.clone()) + .add_data_str(DataType::Path, self.path.clone()) + .add_data_str(DataType::Result, "message_chunk".to_string()) + .add_data(DataType::Payload, payload); + } + if cv.get_data(DataType::Function).unwrap().as_str().unwrap() == "send_message" { + let message = payload["message"].as_str().unwrap(); + let milliseconds_timestamp: u128 = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_millis(); + self.add_message(milliseconds_timestamp, cv.get_sender(), message); + + let mut distribution_payload = JsonValue::new_object(); + distribution_payload["message"] = JsonValue::String(message.to_string()); + distribution_payload["sender_id"] = JsonValue::String(cv.get_sender().to_string()); + distribution_payload["send_time"] = + JsonValue::String(milliseconds_timestamp.to_string()); + let distribution = CommunicationValue::new(CommunicationType::Update) + .with_id(cv.get_id()) + .add_data_str(DataType::Name, self.name.clone()) + .add_data_str(DataType::Path, self.path.clone()) + .add_data_str(DataType::Result, "message_live".to_string()) + .add_data(DataType::Payload, distribution_payload); + + let connections: HashMap>> = + self.get_community().get_connections().await.clone(); + + for con in connections.values() { + for c in con { + let cd: &Arc = c; + cd.send_message(&distribution).await; + } + } + return CommunicationValue::new(CommunicationType::Function) + .with_id(cv.get_id()) + .add_data_str(DataType::Name, self.name.clone()) + .add_data_str(DataType::Path, self.path.clone()) + .add_data_str(DataType::Result, "message_received".to_string()) + .add_data(DataType::Payload, JsonValue::new_object()); + } + CommunicationValue::new(CommunicationType::ErrorInternal).with_id(cv.get_id()) + } + fn to_json(&self) -> JsonValue { + JsonValue::new_object() + } + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { + self.community = community; + self.id = id; + self.name = name; + self.path = path; + } +} diff --git a/communities/src/interactables/voice_chat.rs b/communities/src/interactables/voice_chat.rs index 8cf0589..5e83181 100644 --- a/communities/src/interactables/voice_chat.rs +++ b/communities/src/interactables/voice_chat.rs @@ -1,187 +1,187 @@ -use crate::communities::{community::Community, interactables::interactable::Interactable}; -use async_trait::async_trait; -use json::JsonValue; -use std::sync::Arc; -use std::{any::Any, sync::RwLock}; -use uuid::Uuid; -pub enum CallUserState { - Active, - Muted, - Deafed, -} -impl CallUserState { - pub fn parse(state: &str) -> CallUserState { - match state { - "active" => CallUserState::Active, - "muted" => CallUserState::Muted, - "deafed" => CallUserState::Deafed, - _ => CallUserState::Active, - } - } - pub fn to_string(&self) -> String { - match self { - CallUserState::Active => "active".to_string(), - CallUserState::Muted => "muted".to_string(), - CallUserState::Deafed => "deafed".to_string(), - } - } -} - -pub struct CallUser { - pub user_id: Uuid, - pub user_state: CallUserState, - pub streaming: bool, -} - -pub struct VoiceChat { - id: Uuid, - name: String, - path: String, - community: Arc, - users: RwLock>, -} -impl VoiceChat { - pub fn new() -> VoiceChat { - VoiceChat { - id: Uuid::new_v4(), - name: String::new(), - path: String::new(), - community: Arc::new(Community::new()), - users: RwLock::new(Vec::new()), - } - } - pub fn update_user_state( - self: Arc, - user_id: Uuid, - state: CallUserState, - streaming: bool, - ) { - if let Some(user) = self - .users - .write() - .unwrap() - .iter_mut() - .find(|u| u.user_id == user_id) - { - user.user_state = state; - user.streaming = streaming; - } - } -} -#[async_trait] -impl Interactable for VoiceChat { - fn get_id(&self) -> &Uuid { - &self.id - } - fn as_any(&self) -> &dyn Any { - self - } - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - fn get_codec(&self) -> String { - "voice".to_string() - } - fn set_name(&mut self, name: String) { - self.name = name; - } - fn set_path(&mut self, path: String) { - self.path = path; - } - fn get_community(&self) -> &Arc { - &self.community - } - fn set_community(&mut self, community: Arc) { - self.community = community; - } - fn get_name(&self) -> &String { - &self.name - } - fn get_path(&self) -> &String { - &self.path - } - fn get_total_path(&self) -> String { - String::new() + &self.path + "/" + &self.name - } - fn get_data(&self) -> JsonValue { - let mut data = JsonValue::new_object(); - let mut active_users = JsonValue::new_object(); - for user in self.users.read().unwrap().iter() { - let mut user_data = JsonValue::new_object(); - let _ = user_data.insert("state", JsonValue::String(user.user_state.to_string())); - let _ = user_data.insert("streaming", JsonValue::Boolean(user.streaming)); - let _ = active_users.insert(&user.user_id.to_string(), user_data); - } - let _ = data.insert("active_users", active_users); - data - } - async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue { - let payload = cv.get_data(DataTypes::payload).unwrap(); - let function = cv.get_data(DataTypes::function).unwrap().as_str().unwrap(); - - if function == "get_call" { - let sender_id = payload["sender_id"].as_str().unwrap(); - let message_id = payload["message"].as_str().unwrap(); - let send_time = payload["send_time"].as_str().unwrap(); - - let mut response_payload = JsonValue::new_object(); - response_payload["sender_id"] = JsonValue::String(sender_id.to_string()); - response_payload["message"] = JsonValue::String(message_id.to_string()); - response_payload["send_time"] = JsonValue::String(send_time.to_string()); - - return CommunicationValue::new(CommunicationType::function) - .with_id(cv.get_id()) - .add_data_str(DataTypes::name, self.name.clone()) - .add_data_str(DataTypes::path, self.path.clone()) - .add_data_str(DataTypes::result, "getting_call".to_string()) - .add_data(DataTypes::payload, response_payload); - } - - if function == "update_user_state" { - let user_id = payload["user_id"].as_str().unwrap(); - let state = payload["state"].as_str().unwrap(); - let streaming = payload["streaming"].as_bool().unwrap(); - - if let Some(user) = self - .users - .write() - .unwrap() - .iter_mut() - .find(|u| u.user_id == Uuid::parse_str(user_id).unwrap()) - { - user.user_state = CallUserState::parse(state); - user.streaming = streaming; - } - let mut response_payload = JsonValue::new_object(); - response_payload["user_id"] = JsonValue::String(user_id.to_string()); - response_payload["state"] = JsonValue::String(state.to_string()); - response_payload["streaming"] = JsonValue::Boolean(streaming); - - return CommunicationValue::new(CommunicationType::update) - .with_id(cv.get_id()) - .add_data_str(DataTypes::name, self.name.clone()) - .add_data_str(DataTypes::path, self.path.clone()) - .add_data_str(DataTypes::result, "user_changed".to_string()) - .add_data(DataTypes::payload, response_payload); - } - CommunicationValue::new(CommunicationType::error_internal).with_id(cv.get_id()) - } - - fn to_json(&self) -> JsonValue { - let v = JsonValue::new_object(); - v - } - fn load( - &mut self, - community: Arc, - id: Uuid, - path: String, - name: String, - _json: &JsonValue, - ) { - self.community = community; - self.id = id; - self.name = name; - self.path = path; - } -} +use crate::communities::{community::Community, interactables::interactable::Interactable}; +use async_trait::async_trait; +use json::JsonValue; +use std::sync::Arc; +use std::{any::Any, sync::RwLock}; +use uuid::Uuid; +pub enum CallUserState { + Active, + Muted, + Deafed, +} +impl CallUserState { + pub fn parse(state: &str) -> CallUserState { + match state { + "active" => CallUserState::Active, + "muted" => CallUserState::Muted, + "deafed" => CallUserState::Deafed, + _ => CallUserState::Active, + } + } + pub fn to_string(&self) -> String { + match self { + CallUserState::Active => "active".to_string(), + CallUserState::Muted => "muted".to_string(), + CallUserState::Deafed => "deafed".to_string(), + } + } +} + +pub struct CallUser { + pub user_id: Uuid, + pub user_state: CallUserState, + pub streaming: bool, +} + +pub struct VoiceChat { + id: Uuid, + name: String, + path: String, + community: Arc, + users: RwLock>, +} +impl VoiceChat { + pub fn new() -> VoiceChat { + VoiceChat { + id: Uuid::new_v4(), + name: String::new(), + path: String::new(), + community: Arc::new(Community::new()), + users: RwLock::new(Vec::new()), + } + } + pub fn update_user_state( + self: Arc, + user_id: Uuid, + state: CallUserState, + streaming: bool, + ) { + if let Some(user) = self + .users + .write() + .unwrap() + .iter_mut() + .find(|u| u.user_id == user_id) + { + user.user_state = state; + user.streaming = streaming; + } + } +} +#[async_trait] +impl Interactable for VoiceChat { + fn get_id(&self) -> &Uuid { + &self.id + } + fn as_any(&self) -> &dyn Any { + self + } + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + fn get_codec(&self) -> String { + "voice".to_string() + } + fn set_name(&mut self, name: String) { + self.name = name; + } + fn set_path(&mut self, path: String) { + self.path = path; + } + fn get_community(&self) -> &Arc { + &self.community + } + fn set_community(&mut self, community: Arc) { + self.community = community; + } + fn get_name(&self) -> &String { + &self.name + } + fn get_path(&self) -> &String { + &self.path + } + fn get_total_path(&self) -> String { + String::new() + &self.path + "/" + &self.name + } + fn get_data(&self) -> JsonValue { + let mut data = JsonValue::new_object(); + let mut active_users = JsonValue::new_object(); + for user in self.users.read().unwrap().iter() { + let mut user_data = JsonValue::new_object(); + let _ = user_data.insert("state", JsonValue::String(user.user_state.to_string())); + let _ = user_data.insert("streaming", JsonValue::Boolean(user.streaming)); + let _ = active_users.insert(&user.user_id.to_string(), user_data); + } + let _ = data.insert("active_users", active_users); + data + } + async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue { + let payload = cv.get_data(DataType::Payload).unwrap(); + let function = cv.get_data(DataType::Function).unwrap().as_str().unwrap(); + + if function == "get_call" { + let sender_id = payload["sender_id"].as_str().unwrap(); + let message_id = payload["message"].as_str().unwrap(); + let send_time = payload["send_time"].as_str().unwrap(); + + let mut response_payload = JsonValue::new_object(); + response_payload["sender_id"] = JsonValue::String(sender_id.to_string()); + response_payload["message"] = JsonValue::String(message_id.to_string()); + response_payload["send_time"] = JsonValue::String(send_time.to_string()); + + return CommunicationValue::new(CommunicationType::Function) + .with_id(cv.get_id()) + .add_data_str(DataType::Name, self.name.clone()) + .add_data_str(DataType::Path, self.path.clone()) + .add_data_str(DataType::Result, "getting_call".to_string()) + .add_data(DataType::Payload, response_payload); + } + + if function == "update_user_state" { + let user_id = payload["user_id"].as_str().unwrap(); + let state = payload["state"].as_str().unwrap(); + let streaming = payload["streaming"].as_bool().unwrap(); + + if let Some(user) = self + .users + .write() + .unwrap() + .iter_mut() + .find(|u| u.user_id == Uuid::parse_str(user_id).unwrap()) + { + user.user_state = CallUserState::parse(state); + user.streaming = streaming; + } + let mut response_payload = JsonValue::new_object(); + response_payload["user_id"] = JsonValue::Number(user_id); + response_payload["state"] = JsonValue::String(state.to_string()); + response_payload["streaming"] = JsonValue::Boolean(streaming); + + return CommunicationValue::new(CommunicationType::Update) + .with_id(cv.get_id()) + .add_data_str(DataType::Name, self.name.clone()) + .add_data_str(DataType::Path, self.path.clone()) + .add_data_str(DataType::Result, "user_changed".to_string()) + .add_data(DataType::Payload, response_payload); + } + CommunicationValue::new(CommunicationType::ErrorInternal).with_id(cv.get_id()) + } + + fn to_json(&self) -> JsonValue { + let v = JsonValue::new_object(); + v + } + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { + self.community = community; + self.id = id; + self.name = name; + self.path = path; + } +} diff --git a/flake.nix b/flake.nix index 8cf53d7..5fc6085 100644 --- a/flake.nix +++ b/flake.nix @@ -262,7 +262,7 @@ LockPersonality = true; MemoryDenyWriteExecute = true; Environment = [ - "TTP_BIND=${cfg.ttpBind}" + "mtp::BIND=${cfg.ttpBind}" "BIND_ADDRESS=${cfg.bindAddress}" ]; } diff --git a/iota-auth/Cargo.toml b/iota-auth/Cargo.toml index 56f6eac..5a9ad09 100644 --- a/iota-auth/Cargo.toml +++ b/iota-auth/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } iota-logger = { path = "../iota-logger" } iota-util = { path = "../iota-util" } iota-storage = { path = "../iota-storage" } diff --git a/iota-cli/Cargo.toml b/iota-cli/Cargo.toml index 60a0ce1..9fa889f 100644 --- a/iota-cli/Cargo.toml +++ b/iota-cli/Cargo.toml @@ -12,8 +12,7 @@ iota-util = { path = "../iota-util" } omikron-connector = { path = "../omikron-connector" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } actix-web = { version = "4", features = ["rustls-0_23"] } actix-web-actors = "4" diff --git a/iota-cli/src/elements/console_card.rs b/iota-cli/src/elements/console_card.rs index 295ef7a..0de1c82 100644 --- a/iota-cli/src/elements/console_card.rs +++ b/iota-cli/src/elements/console_card.rs @@ -4,6 +4,7 @@ use iota_state::{ACTIVE_TASKS, RELOAD, SHUTDOWN}; use iota_storage::users::{user_manager, user_profile::UserProfile}; use iota_storage::util::config_util::CONFIG; use iota_util::{crypto_helper, file_util}; +use mtp::codec::{CommunicationType, CommunicationValue}; use omikron_connector::omikron_connection::OMIKRON_CONNECTION; use ratatui::{ Frame, @@ -12,7 +13,6 @@ use ratatui::{ text::{Line, Span}, widgets::{Block, Borders, Paragraph}, }; -use ttp_core::{CommunicationType, CommunicationValue}; use uuid::Uuid; use std::{ @@ -442,7 +442,7 @@ pub async fn run_command(command: &str) { } ["user", "remove", username] => { if let Some(user) = user_manager::get_user_by_username(username) { - let msg = CommunicationValue::new(CommunicationType::delete_user) + let msg = CommunicationValue::new(CommunicationType::DeleteUser) .with_sender(user.user_id as u64); OMIKRON_CONNECTION.send_message(&msg).await; user_manager::remove_user(user.user_id); @@ -510,7 +510,7 @@ pub async fn ping(time: u64) { let response_cv = conn .await_response( - &CommunicationValue::new(CommunicationType::ping), + &CommunicationValue::new(CommunicationType::Ping), Some(Duration::from_secs(time)), ) .await; diff --git a/iota-core/Cargo.toml b/iota-core/Cargo.toml index a1f6de1..3f7a5f6 100644 --- a/iota-core/Cargo.toml +++ b/iota-core/Cargo.toml @@ -15,8 +15,7 @@ omikron-connector = { path = "../omikron-connector" } web-server = { path = "../web-server" } web-ui = { path = "../web-ui" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } dashmap = "6.1.0" json = "*" diff --git a/iota-logger/Cargo.toml b/iota-logger/Cargo.toml index bdfc84b..23f4a66 100644 --- a/iota-logger/Cargo.toml +++ b/iota-logger/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" iota-state = { path = "../iota-state" } iota-util = { path = "../iota-util" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } ratatui = "0.30.0" json = "0.12.4" diff --git a/iota-logger/src/lib.rs b/iota-logger/src/lib.rs index b603f1d..bfde4ce 100644 --- a/iota-logger/src/lib.rs +++ b/iota-logger/src/lib.rs @@ -8,8 +8,8 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; +use mtp::codec::{CommunicationValue, DataType, DataTypeId, DataValue, Version}; use ratatui::style::Color; -use ttp_core::{CommunicationValue, DataTypes, DataValue}; use iota_state::{APP_STATE, UNIQUE, UiLogEntry}; pub mod language_creator; @@ -317,17 +317,19 @@ pub fn format_cv(cv: &CommunicationValue) -> String { let comm_type = cv.get_type().to_string(); parts.push(format!("{}", comm_type)); - let data: &BTreeMap = cv.get_data_container(); + let data = cv.data(); - let formated_data = - format_data_container(data.iter().map(|(k, v)| (k.clone(), v.clone())).collect()); + let formated_data = format_data_container( + data.iter().map(|(k, v)| (*k, v.clone())).collect(), + Version(1, 0), + ); parts.push(format!("{}", formated_data)); parts.join(": ") } -fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String { +fn format_data_container(data: Vec<(DataTypeId, DataValue)>, version: Version) -> String { let parts: Vec = data .into_iter() .map(|(key, value)| { @@ -337,12 +339,12 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String { DataValue::Str(s) => format!("{}=\"{}\"", key_str, s), DataValue::Container(inner) => { - let inner_formatted = format_data_container(inner); + let inner_formatted = format_data_container(inner, version.clone()); format!("{}={{ {} }}", key_str, inner_formatted) } DataValue::Array(arr) => { - let arr_formatted = format_array(arr); + let arr_formatted = format_array(arr, version.clone()); format!("{}=[{}]", key_str, arr_formatted) } @@ -351,7 +353,7 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String { DataValue::BoolTrue => format!("{}=true", key_str), DataValue::BoolFalse => format!("{}=false", key_str), - DataValue::Number(num) => format!("{}={}", key_str, num), + DataValue::SignedNumber(num) => format!("{}={}", key_str, num), _ => "".to_string(), } @@ -361,19 +363,19 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String { parts.join(", ") } -fn format_array(arr: Vec) -> String { +fn format_array(arr: Vec, version: Version) -> String { let parts: Vec = arr .into_iter() .map(|value| match value { DataValue::Str(s) => format!("\"{}\"", s), DataValue::Container(inner) => { - let inner_formatted = format_data_container(inner); + let inner_formatted = format_data_container(inner, version.clone()); format!("{{ {} }}", inner_formatted) } DataValue::Array(inner_arr) => { - let formatted = format_array(inner_arr); + let formatted = format_array(inner_arr, version.clone()); format!("[{}]", formatted) } @@ -382,7 +384,7 @@ fn format_array(arr: Vec) -> String { DataValue::BoolTrue => "true".to_string(), DataValue::BoolFalse => "false".to_string(), - DataValue::Number(num) => num.to_string(), + DataValue::SignedNumber(num) => num.to_string(), _ => String::new(), }) diff --git a/iota-state/Cargo.toml b/iota-state/Cargo.toml index ce37258..e246e12 100644 --- a/iota-state/Cargo.toml +++ b/iota-state/Cargo.toml @@ -9,4 +9,4 @@ once_cell = "1.21.3" tokio = { version = "1.50.0", features = ["full"] } json = "*" sysinfo = "0.38.3" -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } diff --git a/iota-storage/Cargo.toml b/iota-storage/Cargo.toml index 2baa309..6f694a4 100644 --- a/iota-storage/Cargo.toml +++ b/iota-storage/Cargo.toml @@ -8,8 +8,7 @@ iota-logger = { path = "../iota-logger" } iota-state = { path = "../iota-state" } iota-util = { path = "../iota-util" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } aes-gcm = "0.10.3" base64 = "0.22.1" diff --git a/iota-updater/Cargo.toml b/iota-updater/Cargo.toml index 7c4ec88..4d1ef48 100644 --- a/iota-updater/Cargo.toml +++ b/iota-updater/Cargo.toml @@ -6,8 +6,7 @@ edition = "2024" [dependencies] iota-logger = { path = "../iota-logger" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } json = "*" pnet = "0.35.0" diff --git a/iota-util/Cargo.toml b/iota-util/Cargo.toml index 51d9d49..8fd86e8 100644 --- a/iota-util/Cargo.toml +++ b/iota-util/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } reqwest = "0.13.2" tokio = { version = "1.50.0", features = ["full"] } diff --git a/omikron-connector/Cargo.toml b/omikron-connector/Cargo.toml index 5b29a2f..725c990 100644 --- a/omikron-connector/Cargo.toml +++ b/omikron-connector/Cargo.toml @@ -8,8 +8,7 @@ iota-logger = { path = "../iota-logger" } iota-state = { path = "../iota-state" } iota-storage = { path = "../iota-storage" } iota-util = { path = "../iota-util" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } dashmap = "6.1.0" json = "*" @@ -17,6 +16,7 @@ tokio = { version = "1.50.0", features = ["full"] } uuid = { version = "*", features = ["v4"] } base64 = "0.22.1" hex = "*" +rand = "0.8" rand_core = { version = "0.6", features = ["getrandom", "std"] } sha2 = "0.10.9" x448 = { version = "*" } diff --git a/omikron-connector/src/omikron_connection.rs b/omikron-connector/src/omikron_connection.rs index 6e18561..1dbc346 100755 --- a/omikron-connector/src/omikron_connection.rs +++ b/omikron-connector/src/omikron_connection.rs @@ -10,16 +10,27 @@ use iota_util::crypto_helper; use iota_util::crypto_util::{DataFormat, SecurePayload}; use iota_util::file_util::{get_children, has_file, load_file, save_file}; use json::JsonValue; +use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue}; +use mtp::transport::{Policy, Receiver, SendMode, Sender}; use std::collections::HashMap; use std::sync::{Arc, LazyLock}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tokio::sync::{Mutex, RwLock, mpsc, watch}; use tokio::task::JoinHandle; use tokio::time::sleep; -use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue}; -use ttp_native::{Policy, Receiver, SendMode, Sender}; use uuid::Uuid; +fn typed_container(items: Vec<(DataType, DataValue)>) -> DataValue { + use mtp::type_map::{DataTypeId, TypeMap}; + let tm = TypeMap::latest(); + DataValue::Container( + items + .into_iter() + .filter_map(|(dt, dv)| tm.data_id_enum(dt).map(|id| (DataTypeId(id), dv))) + .collect(), + ) +} + // Helper function to check if read receipts are enabled globally async fn is_read_receipts_enabled() -> bool { // Check global config for read receipts setting @@ -240,7 +251,7 @@ impl OmikronConnection { let addr_str = format!("https://{}:{}/ws/iota/", self.host, self.port); - let (sender, mut receiver) = ttp_native::client::connect( + let (sender, mut receiver) = mtp::transport::client::connect( &addr_str, None, Policy { @@ -358,8 +369,8 @@ impl OmikronConnection { (public_key_base64, private_key_base64) }; - let register_msg = CommunicationValue::new(CommunicationType::register_iota) - .add_data(DataTypes::public_key, DataValue::Str(pub_k)); + let register_msg = CommunicationValue::new(CommunicationType::RegisterIota) + .add_typed_default(DataType::PublicKey, DataValue::Str(pub_k)); let msg_id = register_msg.get_id(); @@ -367,25 +378,28 @@ impl OmikronConnection { msg_id, WaitingTask { task: Box::new(|selfc, cv| { - if !cv.is_type(CommunicationType::success) { + if !cv.is_type(CommunicationType::Success) { return false; } - let iota_value = cv.get_data(DataTypes::iota_id); + let iota_value = cv.get_data(DataType::IotaId); let iota_id = iota_value.as_number().unwrap_or(0); if iota_id != 0 { tokio::spawn(async move { let mut conf_write = CONFIG.write().await; - conf_write.change("iota_id", JsonValue::from(iota_id)); + conf_write.change("iota_id", JsonValue::from(iota_id as i64)); conf_write.update(); drop(conf_write); log!("Registered with Iota-ID: {}", iota_id); // Send identification after registration let identify_msg = - CommunicationValue::new(CommunicationType::identification) - .add_data(DataTypes::iota_id, DataValue::Number(iota_id)); + CommunicationValue::new(CommunicationType::Identification) + .add_typed_default( + DataType::IotaId, + DataValue::SignedNumber(iota_id as i128), + ); selfc.send_message(&identify_msg).await; }); } else { @@ -399,8 +413,8 @@ impl OmikronConnection { self.send_message(®ister_msg).await; } else { - let identify_msg = CommunicationValue::new(CommunicationType::identification) - .add_data(DataTypes::iota_id, DataValue::Number(iota_id)); + let identify_msg = CommunicationValue::new(CommunicationType::Identification) + .add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id as i128)); self.send_message(&identify_msg).await; } } @@ -461,7 +475,7 @@ impl OmikronConnection { // ------------------------------------------------------------------------- pub async fn handle_message(self: Arc, cv: CommunicationValue) { - if !cv.is_type(CommunicationType::ping) && !cv.is_type(CommunicationType::pong) { + if !cv.is_type(CommunicationType::Ping) && !cv.is_type(CommunicationType::Pong) { log_cv_in!(&cv); } @@ -474,29 +488,29 @@ impl OmikronConnection { } } - if cv.is_type(CommunicationType::pong) { + if cv.is_type(CommunicationType::Pong) { self.handle_pong(&cv).await; return; } - if cv.is_type(CommunicationType::challenge) { + if cv.is_type(CommunicationType::Challenge) { self.handle_challenge(&cv).await; return; } - if cv.is_type(CommunicationType::app_identification) { + if cv.is_type(CommunicationType::AppIdentification) { let sender_id = cv.get_sender(); let app_identifier = cv - .get_data(DataTypes::app_identifier) + .get_data(DataType::AppIdentifier) .as_str() .unwrap_or("") .to_string(); let app_public_key = cv - .get_data(DataTypes::app_public_key) + .get_data(DataType::AppPublicKey) .as_str() .unwrap_or("") .to_string(); - let user_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0) as i64; + let user_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0) as i64; let mut trusted = false; if let Some(user) = iota_storage::users::user_manager::get_user(user_id) { @@ -535,11 +549,14 @@ impl OmikronConnection { .unwrap() .export(DataFormat::Base64); - let res = CommunicationValue::new(CommunicationType::app_challenge) + let res = CommunicationValue::new(CommunicationType::AppChallenge) .with_id(cv.get_id()) .with_receiver(sender_id) - .add_data(DataTypes::public_key, DataValue::Str(pub_k_str)) - .add_data(DataTypes::challenge, DataValue::Str(encrypted_challenge)); + .add_typed_default(DataType::PublicKey, DataValue::Str(pub_k_str)) + .add_typed_default( + DataType::Challenge, + DataValue::Str(encrypted_challenge), + ); self.send_message(&res).await; return; @@ -547,21 +564,21 @@ impl OmikronConnection { } } - let res = CommunicationValue::new(CommunicationType::error_invalid_challenge) + let res = CommunicationValue::new(CommunicationType::ErrorInvalidChallenge) .with_id(cv.get_id()) .with_receiver(sender_id); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::app_challenge_response) { + if cv.is_type(CommunicationType::AppChallengeResponse) { let sender_id = cv.get_sender(); let mut challenges = self.app_challenges.write().await; if let Some(expected) = challenges.remove(&sender_id) { - if let DataValue::Str(response) = cv.get_data(DataTypes::challenge) { + if let DataValue::Str(response) = cv.get_data(DataType::Challenge) { if expected == *response { let res = - CommunicationValue::new(CommunicationType::app_identification_response) + CommunicationValue::new(CommunicationType::AppIdentificationResponse) .with_id(cv.get_id()) .with_receiver(sender_id); self.send_message(&res).await; @@ -569,17 +586,17 @@ impl OmikronConnection { } } } - let res = CommunicationValue::new(CommunicationType::error_invalid_challenge) + let res = CommunicationValue::new(CommunicationType::ErrorInvalidChallenge) .with_id(cv.get_id()) .with_receiver(sender_id); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::save_app_data) { + if cv.is_type(CommunicationType::SaveAppData) { let sender_id = cv.get_sender(); let app_data = cv - .get_data(DataTypes::app_data) + .get_data(DataType::AppData) .as_str() .unwrap_or("") .to_string(); @@ -593,14 +610,14 @@ impl OmikronConnection { ); } - let res = CommunicationValue::new(CommunicationType::save_app_data) + let res = CommunicationValue::new(CommunicationType::SaveAppData) .with_id(cv.get_id()) .with_receiver(sender_id); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::load_app_data) { + if cv.is_type(CommunicationType::LoadAppData) { let sender_id = cv.get_sender(); let mut app_data = String::new(); @@ -610,23 +627,23 @@ impl OmikronConnection { iota_storage::users::user_manager::load_app_data(*user_id, app_identifier); } - let res = CommunicationValue::new(CommunicationType::load_app_data) + let res = CommunicationValue::new(CommunicationType::LoadAppData) .with_id(cv.get_id()) .with_receiver(sender_id) - .add_data(DataTypes::app_data, DataValue::Str(app_data)); + .add_typed_default(DataType::AppData, DataValue::Str(app_data)); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::create_app) { + if cv.is_type(CommunicationType::CreateApp) { let sender_id = cv.get_sender() as i64; let app_identifier = cv - .get_data(DataTypes::app_identifier) + .get_data(DataType::AppIdentifier) .as_str() .unwrap_or("") .to_string(); let app_public_key = cv - .get_data(DataTypes::app_public_key) + .get_data(DataType::AppPublicKey) .as_str() .unwrap_or("") .to_string(); @@ -640,17 +657,17 @@ impl OmikronConnection { } } - let res = CommunicationValue::new(CommunicationType::create_app) + let res = CommunicationValue::new(CommunicationType::CreateApp) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::delete_app) { + if cv.is_type(CommunicationType::DeleteApp) { let sender_id = cv.get_sender() as i64; let app_identifier = cv - .get_data(DataTypes::app_identifier) + .get_data(DataType::AppIdentifier) .as_str() .unwrap_or("") .to_string(); @@ -664,30 +681,33 @@ impl OmikronConnection { } } - let res = CommunicationValue::new(CommunicationType::delete_app) + let res = CommunicationValue::new(CommunicationType::DeleteApp) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&res).await; return; } - if cv.is_type(CommunicationType::client_connected) { - let user_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0) as i64; - let _session_id = cv.get_data(DataTypes::session_id).as_number().unwrap_or(0) as i64; + if cv.is_type(CommunicationType::ClientConnected) { + let user_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0) as i64; + let _session_id = cv.get_data(DataType::SessionId).as_number().unwrap_or(0) as i64; let contacts = chats_util::get_users(user_id); let mut contacts_array = Vec::new(); for (i, contact) in contacts.iter().enumerate() { let mut contact_container = Vec::new(); - contact_container.push((DataTypes::user_id, DataValue::Number(contact.user_id))); contact_container.push(( - DataTypes::last_message_at, - DataValue::Number(contact.last_message_at.unwrap_or(0)), + DataType::UserId, + DataValue::SignedNumber(contact.user_id as i128), + )); + contact_container.push(( + DataType::LastMessageAt, + DataValue::SignedNumber(contact.last_message_at.unwrap_or(0) as i128), )); if let Some(ref name) = contact.user_name { - contact_container.push((DataTypes::username, DataValue::Str(name.clone()))); + contact_container.push((DataType::Username, DataValue::Str(name.clone()))); } let amount = if i < 10 { 20 } else { 1 }; @@ -702,12 +722,15 @@ impl OmikronConnection { let message_state = m["message_state"].as_str().unwrap_or("").to_string(); let mut msg_container = Vec::new(); - msg_container.push((DataTypes::send_time, DataValue::Number(message_time))); - msg_container.push((DataTypes::content, DataValue::Str(content.clone()))); - msg_container.push((DataTypes::message_state, DataValue::Str(message_state))); - msg_container.push((DataTypes::height, DataValue::Number(height))); - msg_container.push((DataTypes::sent_by_self, DataValue::Bool(sent_by_self))); - msg_array.push(DataValue::Container(msg_container)); + msg_container.push(( + DataType::SendTime, + DataValue::SignedNumber(message_time as i128), + )); + msg_container.push((DataType::Content, DataValue::Str(content.clone()))); + msg_container.push((DataType::MessageState, DataValue::Str(message_state))); + msg_container.push((DataType::Height, DataValue::SignedNumber(height as i128))); + msg_container.push((DataType::SentBySelf, DataValue::Bool(sent_by_self))); + msg_array.push(typed_container(msg_container)); if msg_array.len() == 1 { let sender_id = if sent_by_self { @@ -716,25 +739,27 @@ impl OmikronConnection { contact.user_id }; let mut last_msg = Vec::new(); - last_msg.push((DataTypes::content, DataValue::Str(content))); - last_msg.push((DataTypes::sender_id, DataValue::Number(sender_id))); - contact_container - .push((DataTypes::last_message, DataValue::Container(last_msg))); + last_msg.push((DataType::Content, DataValue::Str(content))); + last_msg.push(( + DataType::SenderId, + DataValue::SignedNumber(sender_id as i128), + )); + contact_container.push((DataType::LastMessage, typed_container(last_msg))); } } - contact_container.push((DataTypes::messages, DataValue::Array(msg_array))); - contacts_array.push(DataValue::Container(contact_container)); + contact_container.push((DataType::Messages, DataValue::Array(msg_array))); + contacts_array.push(typed_container(contact_container)); } - let resp = CommunicationValue::new(CommunicationType::client_connected) + let resp = CommunicationValue::new(CommunicationType::ClientConnected) .with_id(cv.get_id()) - .add_data(DataTypes::contacts, DataValue::Array(contacts_array)); + .add_typed_default(DataType::Contacts, DataValue::Array(contacts_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::identification_response) { - match cv.get_data(DataTypes::accepted).as_bool() { + if cv.is_type(CommunicationType::IdentificationResponse) { + match cv.get_data(DataType::Accepted).as_bool() { Some(true) => { let mut state = self.state.write().await; if let ConnectionState::Connected { identified: _ } = *state { @@ -757,15 +782,15 @@ impl OmikronConnection { // Direct messages // // ************************************************ // - if cv.is_type(CommunicationType::message_state) { + if cv.is_type(CommunicationType::MessageState) { let sender_id = &cv.get_sender(); - let receiver_id = match cv.get_data(DataTypes::chat_partner_id).as_number() { + let receiver_id = match cv.get_data(DataType::ChatPartnerId).as_number() { Some(id) => id, _ => return, }; // Parse send_time robustly: accept numeric or string, fallback to current time - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -782,28 +807,25 @@ impl OmikronConnection { timestamp_i64, receiver_id as i64, *sender_id as i64, - MessageState::from_str( - cv.get_data(DataTypes::message_state).as_str().unwrap_or(""), - ), + MessageState::from_str(cv.get_data(DataType::MessageState).as_str().unwrap_or("")), ); } // Incoming storsed message: store for the recipient, attempt local delivery, notify sender. - if cv.is_type(CommunicationType::message_send) { + if cv.is_type(CommunicationType::MessageSend) { let sender_id: u64 = cv.get_sender(); // parse receiver_id (the storage owner for this incoming message) - let receiver_id: i64 = if let Some(n) = cv.get_data(DataTypes::receiver_id).as_number() - { + let receiver_id: i64 = if let Some(n) = cv.get_data(DataType::ReceiverId).as_number() { n as i64 - } else if let Some(s) = cv.get_data(DataTypes::receiver_id).as_str() { + } else if let Some(s) = cv.get_data(DataType::ReceiverId).as_str() { s.parse::().unwrap_or(0) } else { 0 }; // parse send_time robustly (number or string), fallback to now - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -819,12 +841,12 @@ impl OmikronConnection { // content may be missing; default to empty string let content = cv - .get_data(DataTypes::content) + .get_data(DataType::Content) .as_str() .unwrap_or("") .to_string(); - let height = cv.get_data(DataTypes::height).as_number().unwrap_or(0) as i64; + let height = cv.get_data(DataType::Height).as_number().unwrap_or(0) as i64; let is_local = iota_storage::users::user_manager::get_user(receiver_id).is_some(); @@ -851,19 +873,22 @@ impl OmikronConnection { ); // send confirmation back to sender - let conf_msg = CommunicationValue::new(CommunicationType::message_send) + let conf_msg = CommunicationValue::new(CommunicationType::MessageSend) .with_id(cv.get_id()) .with_receiver(sender_id as u64); self.send_message(&conf_msg).await; if !is_local { - let fw_msg = CommunicationValue::new(CommunicationType::message_other_iota) + let fw_msg = CommunicationValue::new(CommunicationType::MessageOtherIota) .with_id(cv.get_id()) .with_receiver(receiver_id as u64) .with_sender(sender_id as u64) - .add_data(DataTypes::height, DataValue::Number(height)) - .add_data(DataTypes::content, DataValue::Str(content)) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)); + .add_typed_default(DataType::Height, DataValue::SignedNumber(height as i128)) + .add_typed_default(DataType::Content, DataValue::Str(content)) + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), + ); let other_iota_resp = self .clone() @@ -872,7 +897,7 @@ impl OmikronConnection { if let Ok(resp) = other_iota_resp { let ms_raw = resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -885,17 +910,20 @@ impl OmikronConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -909,17 +937,20 @@ impl OmikronConnection { ); self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -928,16 +959,22 @@ impl OmikronConnection { return; } else { // Build a live-delivery message for the local client (recipient) - let user_forward = CommunicationValue::new(CommunicationType::message_live) + let user_forward = CommunicationValue::new(CommunicationType::MessageLive) .with_id(cv.get_id()) .with_receiver(receiver_id as u64) - .add_data(DataTypes::sender_id, DataValue::Number(sender_id as i64)) - .add_data( - DataTypes::message, - DataValue::Container(vec![ - (DataTypes::content, DataValue::Str(content.clone())), - (DataTypes::send_time, DataValue::Number(timestamp_i64)), - (DataTypes::height, DataValue::Number(height)), + .add_typed_default( + DataType::SenderId, + DataValue::SignedNumber(sender_id as i128), + ) + .add_typed_default( + DataType::Message, + typed_container(vec![ + (DataType::Content, DataValue::Str(content.clone())), + ( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), + ), + (DataType::Height, DataValue::SignedNumber(height as i128)), ]), ); @@ -949,7 +986,7 @@ impl OmikronConnection { if let Ok(user_resp) = user_resp { let ms_raw = user_resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -973,17 +1010,20 @@ impl OmikronConnection { // notify original sender about the delivered/read state (if read receipts are enabled) if is_read_receipts_enabled().await { self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), ) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -1006,24 +1046,30 @@ impl OmikronConnection { ); // Send push notification to Omega since user is offline - let push_msg = CommunicationValue::new(CommunicationType::push_notification) + let push_msg = CommunicationValue::new(CommunicationType::PushNotification) .with_receiver(receiver_id as u64) - .add_data(DataTypes::sender_id, DataValue::Number(sender_id as i64)); + .add_typed_default( + DataType::SenderId, + DataValue::SignedNumber(sender_id as i128), + ); self.send_message(&push_msg).await; // notify sender self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(sender_id as u64) .with_sender(receiver_id as u64) - .add_data(DataTypes::send_time, DataValue::Number(timestamp_i64)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(receiver_id as i64), + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp_i64 as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(receiver_id as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -1033,12 +1079,12 @@ impl OmikronConnection { } } - if cv.is_type(CommunicationType::message_other_iota) { + if cv.is_type(CommunicationType::MessageOtherIota) { let sender_id = &cv.get_sender(); let receiver_id = &cv.get_receiver(); // parse send_time safely (number or string), fallback to now - let send_time_val = cv.get_data(DataTypes::send_time); + let send_time_val = cv.get_data(DataType::SendTime); let now_i64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default() @@ -1053,12 +1099,12 @@ impl OmikronConnection { // content may be missing or non-string; default to empty string let content = cv - .get_data(DataTypes::content) + .get_data(DataType::Content) .as_str() .unwrap_or("") .to_string(); - let height = cv.get_data(DataTypes::height).as_number().unwrap_or(0) as i64; + let height = cv.get_data(DataType::Height).as_number().unwrap_or(0) as i64; chat_files::add_message( timestamp as u128, @@ -1070,16 +1116,22 @@ impl OmikronConnection { ); // Build user_forward using the parsed numeric timestamp and safe content string - let user_forward = CommunicationValue::new(CommunicationType::message_live) + let user_forward = CommunicationValue::new(CommunicationType::MessageLive) .with_id(cv.get_id()) .with_receiver(*receiver_id) - .add_data(DataTypes::sender_id, DataValue::Number(*sender_id as i64)) - .add_data( - DataTypes::message, - DataValue::Container(vec![ - (DataTypes::content, DataValue::Str(content.clone())), - (DataTypes::send_time, DataValue::Number(timestamp)), - (DataTypes::height, DataValue::Number(height)), + .add_typed_default( + DataType::SenderId, + DataValue::SignedNumber(*sender_id as i128), + ) + .add_typed_default( + DataType::Message, + typed_container(vec![ + (DataType::Content, DataValue::Str(content.clone())), + ( + DataType::SendTime, + DataValue::SignedNumber(timestamp as i128), + ), + (DataType::Height, DataValue::SignedNumber(height as i128)), ]), ); @@ -1090,7 +1142,7 @@ impl OmikronConnection { if let Ok(user_resp) = user_resp { let ms_raw = user_resp - .get_data(DataTypes::message_state) + .get_data(DataType::MessageState) .as_string() .unwrap_or_else(|| "".to_string()); let ms = MessageState::from_str(&ms_raw).upgrade(MessageState::Received); @@ -1105,17 +1157,20 @@ impl OmikronConnection { // notify original sender about the delivered/read state (if read receipts are enabled) if is_read_receipts_enabled().await { self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(*sender_id) .with_sender(*receiver_id) - .add_data(DataTypes::send_time, DataValue::Number(timestamp)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(*sender_id as i64), + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(*sender_id as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(ms.as_str().to_string()), ), ) @@ -1131,23 +1186,29 @@ impl OmikronConnection { ); // Send push notification to Omega since user is offline - let push_msg = CommunicationValue::new(CommunicationType::push_notification) + let push_msg = CommunicationValue::new(CommunicationType::PushNotification) .with_receiver(*receiver_id) - .add_data(DataTypes::sender_id, DataValue::Number(*sender_id as i64)); + .add_typed_default( + DataType::SenderId, + DataValue::SignedNumber(*sender_id as i128), + ); self.send_message(&push_msg).await; self.send_message( - &CommunicationValue::new(CommunicationType::message_state) + &CommunicationValue::new(CommunicationType::MessageState) .with_id(cv.get_id()) .with_receiver(*sender_id) .with_sender(*receiver_id) - .add_data(DataTypes::send_time, DataValue::Number(timestamp)) - .add_data( - DataTypes::chat_partner_id, - DataValue::Number(*receiver_id as i64), + .add_typed_default( + DataType::SendTime, + DataValue::SignedNumber(timestamp as i128), ) - .add_data( - DataTypes::message_state, + .add_typed_default( + DataType::ChatPartnerId, + DataValue::SignedNumber(*receiver_id as i128), + ) + .add_typed_default( + DataType::MessageState, DataValue::Str(MessageState::Sent.as_str().to_string()), ), ) @@ -1156,12 +1217,17 @@ impl OmikronConnection { return; } - if cv.is_type(CommunicationType::messages_get) { + if cv.is_type(CommunicationType::MessagesGet) { let my_id = cv.get_sender(); - let partner_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0); - let offset = cv.get_data(DataTypes::offset).as_number().unwrap_or(0); - let amount = cv.get_data(DataTypes::amount).as_number().unwrap_or(0); - let messages = chat_files::get_messages(my_id as i64, partner_id, offset, amount); + let partner_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0); + let offset = cv.get_data(DataType::Offset).as_number().unwrap_or(0); + let amount = cv.get_data(DataType::Amount).as_number().unwrap_or(0); + let messages = chat_files::get_messages( + my_id as i64, + partner_id as i64, + offset as i64, + amount as i64, + ); let mut msg_array: Vec = Vec::new(); for m in messages.members() { let message_time: i64 = m["message_time"].as_i64().unwrap_or(0); @@ -1171,9 +1237,9 @@ impl OmikronConnection { let sender_id: i64 = if sent_by_self { my_id as i64 } else { - if let Some(n) = cv.get_data(DataTypes::chat_partner_id).as_number() { + if let Some(n) = cv.get_data(DataType::ChatPartnerId).as_number() { n as i64 - } else if let Some(s) = cv.get_data(DataTypes::chat_partner_id).as_str() { + } else if let Some(s) = cv.get_data(DataType::ChatPartnerId).as_str() { s.parse::().unwrap_or(partner_id as i64) } else { partner_id as i64 @@ -1182,53 +1248,62 @@ impl OmikronConnection { let message_state: String = m["message_state"].as_str().unwrap_or("").to_string(); let mut container = Vec::new(); - container.push((DataTypes::send_time, DataValue::Number(message_time))); - container.push((DataTypes::content, DataValue::Str(content))); - container.push((DataTypes::sender_id, DataValue::Number(sender_id))); - container.push((DataTypes::message_state, DataValue::Str(message_state))); - container.push((DataTypes::height, DataValue::Number(height))); - container.push((DataTypes::sent_by_self, DataValue::Bool(sent_by_self))); - msg_array.push(DataValue::Container(container)); + container.push(( + DataType::SendTime, + DataValue::SignedNumber(message_time as i128), + )); + container.push((DataType::Content, DataValue::Str(content))); + container.push(( + DataType::SenderId, + DataValue::SignedNumber(sender_id as i128), + )); + container.push((DataType::MessageState, DataValue::Str(message_state))); + container.push((DataType::Height, DataValue::SignedNumber(height as i128))); + container.push((DataType::SentBySelf, DataValue::Bool(sent_by_self))); + msg_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::messages_get) + let resp = CommunicationValue::new(CommunicationType::MessagesGet) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::messages, DataValue::Array(msg_array)); + .add_typed_default(DataType::Messages, DataValue::Array(msg_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::get_chats) { + if cv.is_type(CommunicationType::GetChats) { let user_id = cv.get_sender(); let users = chats_util::get_users(user_id as i64); let mut user_array = Vec::new(); for user in users { let mut container = Vec::new(); - container.push((DataTypes::user_id, DataValue::Number(user.user_id))); + container.push(( + DataType::UserId, + DataValue::SignedNumber(user.user_id as i128), + )); if let Some(name) = user.user_name { - container.push((DataTypes::username, DataValue::Str(name))); + container.push((DataType::Username, DataValue::Str(name))); } if let Some(ts) = user.last_message_at { - container.push((DataTypes::last_message_at, DataValue::Number(ts))); + container.push((DataType::LastMessageAt, DataValue::SignedNumber(ts as i128))); } - user_array.push(DataValue::Container(container)); + user_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::get_chats) + let resp = CommunicationValue::new(CommunicationType::GetChats) .with_id(cv.get_id()) .with_receiver(user_id) - .add_data(DataTypes::user_ids, DataValue::Array(user_array)); + .add_typed_default(DataType::UserIds, DataValue::Array(user_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::add_conversation) { + if cv.is_type(CommunicationType::AddConversation) { let user_id = cv.get_sender(); - let other_id = match cv.get_data(DataTypes::chat_partner_id).as_number() { + let other_id = match cv.get_data(DataType::ChatPartnerId).as_number() { Some(n) => n as i64, None => cv - .get_data(DataTypes::chat_partner_id) + .get_data(DataType::ChatPartnerId) .as_str() .unwrap_or("0") .parse() @@ -1236,7 +1311,7 @@ impl OmikronConnection { }; let mut contact = get_user(user_id as i64, other_id).unwrap_or(Contact::new(other_id)); - if let Some(name) = cv.get_data(DataTypes::chat_partner_name).as_str() { + if let Some(name) = cv.get_data(DataType::ChatPartnerName).as_str() { contact.user_name = Some(name.to_string()); } @@ -1247,89 +1322,86 @@ impl OmikronConnection { .as_millis() as i64, ); mod_user(user_id as i64, &contact); - let resp = CommunicationValue::new(CommunicationType::add_conversation) + let resp = CommunicationValue::new(CommunicationType::AddConversation) .with_id(cv.get_id()) .with_receiver(user_id); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::add_community) { + if cv.is_type(CommunicationType::AddCommunity) { CommunitiesUtil::add_community( cv.get_sender() as i64, - cv.get_data(DataTypes::community_address) + cv.get_data(DataType::CommunityAddress) .as_str() .unwrap() .to_string(), - cv.get_data(DataTypes::community_title) + cv.get_data(DataType::CommunityTitle) .as_str() .unwrap() .to_string(), - cv.get_data(DataTypes::position) + cv.get_data(DataType::Position) .as_str() .unwrap() .to_string(), ); - let resp = CommunicationValue::new(CommunicationType::add_community) + let resp = CommunicationValue::new(CommunicationType::AddCommunity) .with_id(cv.get_id()) .with_receiver(cv.get_sender()); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::get_communities) { + if cv.is_type(CommunicationType::GetCommunities) { let mut comm_array = Vec::new(); for c in CommunitiesUtil::get_communities(cv.get_sender() as i64) { - let mut container: Vec<(DataTypes, DataValue)> = Vec::new(); + let mut container: Vec<(DataType, DataValue)> = Vec::new(); if let Some(address) = c["address"].as_str() { container.push(( - DataTypes::community_address, + DataType::CommunityAddress, DataValue::Str(address.to_string()), )); } if let Some(title) = c["title"].as_str() { - container.push(( - DataTypes::community_title, - DataValue::Str(title.to_string()), - )); + container.push((DataType::CommunityTitle, DataValue::Str(title.to_string()))); } if let Some(position) = c["position"].as_str() { - container.push((DataTypes::position, DataValue::Str(position.to_string()))); + container.push((DataType::Position, DataValue::Str(position.to_string()))); } - comm_array.push(DataValue::Container(container)); + comm_array.push(typed_container(container)); } - let resp = CommunicationValue::new(CommunicationType::get_communities) + let resp = CommunicationValue::new(CommunicationType::GetCommunities) .with_id(cv.get_id()) .with_receiver(cv.get_sender()) - .add_data(DataTypes::communities, DataValue::Array(comm_array)); + .add_typed_default(DataType::Communities, DataValue::Array(comm_array)); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::remove_community) { + if cv.is_type(CommunicationType::RemoveCommunity) { CommunitiesUtil::remove_community( cv.get_sender() as i64, - cv.get_data(DataTypes::community_address) + cv.get_data(DataType::CommunityAddress) .as_str() .unwrap() .to_string(), ); - let resp = CommunicationValue::new(CommunicationType::remove_community) + let resp = CommunicationValue::new(CommunicationType::RemoveCommunity) .with_id(cv.get_id()) .with_receiver(cv.get_sender()); self.send_message(&resp).await; return; } - if cv.is_type(CommunicationType::global_settings_save) { + if cv.is_type(CommunicationType::GlobalSettingsSave) { let my_id = cv.get_sender(); - let Some(settings_value) = cv.get_data(DataTypes::payload).as_str() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(settings_value) = cv.get_data(DataType::Payload).as_str() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing settings payload".to_string()), ); self.send_message(&response).await; @@ -1342,32 +1414,37 @@ impl OmikronConnection { settings_value, ); - let mut response = CommunicationValue::new(CommunicationType::global_settings_save) + let mut response = CommunicationValue::new(CommunicationType::GlobalSettingsSave) .with_receiver(my_id) .with_id(cv.get_id()); - if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() { - response = response.add_data(DataTypes::session_id, DataValue::Number(session_id)); + if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() { + response = response.add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); } self.send_message(&response).await; return; } - if cv.is_type(CommunicationType::global_settings_load) { + if cv.is_type(CommunicationType::GlobalSettingsLoad) { let my_id = cv.get_sender(); let path = format!("users/{}", my_id); let name = "global.settings"; if !has_file(&path, name) { - let mut response = CommunicationValue::new(CommunicationType::error_not_found) + let mut response = CommunicationValue::new(CommunicationType::ErrorNotFound) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::path, DataValue::Str(name.to_string())); + .add_typed_default(DataType::Path, DataValue::Str(name.to_string())); - if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() { - response = - response.add_data(DataTypes::session_id, DataValue::Number(session_id)); + if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() { + response = response.add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); } self.send_message(&response).await; @@ -1375,53 +1452,62 @@ impl OmikronConnection { } let settings_value_str = load_file(&path, name); - let mut response = CommunicationValue::new(CommunicationType::global_settings_load) + let mut response = CommunicationValue::new(CommunicationType::GlobalSettingsLoad) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::payload, DataValue::Str(settings_value_str)); + .add_typed_default(DataType::Payload, DataValue::Str(settings_value_str)); - if let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() { - response = response.add_data(DataTypes::session_id, DataValue::Number(session_id)); + if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() { + response = response.add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); } self.send_message(&response).await; return; } - if cv.is_type(CommunicationType::settings_save) { + if cv.is_type(CommunicationType::SettingsSave) { let my_id = cv.get_sender(); - let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(session_id) = cv.get_data(DataType::SessionId).as_number() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing session_id".to_string()), ); self.send_message(&response).await; return; }; - let Some(settings_name) = cv.get_data(DataTypes::settings_name).as_str() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(settings_name) = cv.get_data(DataType::SettingsName).as_str() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing settings_name".to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; }; - let Some(settings_value) = cv.get_data(DataTypes::payload).as_str() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(settings_value) = cv.get_data(DataType::Payload).as_str() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing settings payload".to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; }; @@ -1431,18 +1517,21 @@ impl OmikronConnection { .all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '.') || settings_name.contains("..") { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Invalid settings_name".to_string()), ) - .add_data( - DataTypes::settings_name, + .add_typed_default( + DataType::SettingsName, DataValue::Str(settings_name.to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; } @@ -1453,41 +1542,47 @@ impl OmikronConnection { settings_value, ); - let response = CommunicationValue::new(CommunicationType::settings_save) + let response = CommunicationValue::new(CommunicationType::SettingsSave) .with_receiver(my_id) .with_id(cv.get_id()) - .add_data( - DataTypes::settings_name, + .add_typed_default( + DataType::SettingsName, DataValue::Str(settings_name.to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; } - if cv.is_type(CommunicationType::settings_load) { + if cv.is_type(CommunicationType::SettingsLoad) { let my_id = cv.get_sender(); - let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(session_id) = cv.get_data(DataType::SessionId).as_number() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing session_id".to_string()), ); self.send_message(&response).await; return; }; - let Some(settings_name) = cv.get_data(DataTypes::settings_name).as_str() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(settings_name) = cv.get_data(DataType::SettingsName).as_str() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing settings_name".to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; }; @@ -1497,18 +1592,21 @@ impl OmikronConnection { .all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '.') || settings_name.contains("..") { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Invalid settings_name".to_string()), ) - .add_data( - DataTypes::settings_name, + .add_typed_default( + DataType::SettingsName, DataValue::Str(settings_name.to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; } @@ -1516,41 +1614,47 @@ impl OmikronConnection { let settings_file = format!("{}.settings", settings_name); let settings_path = format!("users/{}/settings/{}/", my_id, session_id); if !has_file(&settings_path, &settings_file) { - let response = CommunicationValue::new(CommunicationType::error_not_found) + let response = CommunicationValue::new(CommunicationType::ErrorNotFound) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::settings_name, + .add_typed_default( + DataType::SettingsName, DataValue::Str(settings_name.to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; } let settings_value_str = load_file(&settings_path, &settings_file); - let response = CommunicationValue::new(CommunicationType::settings_load) + let response = CommunicationValue::new(CommunicationType::SettingsLoad) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::payload, DataValue::Str(settings_value_str)) - .add_data( - DataTypes::settings_name, + .add_typed_default(DataType::Payload, DataValue::Str(settings_value_str)) + .add_typed_default( + DataType::SettingsName, DataValue::Str(settings_name.to_string()), ) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; } - if cv.is_type(CommunicationType::settings_list) { + if cv.is_type(CommunicationType::SettingsList) { let my_id = cv.get_sender(); - let Some(session_id) = cv.get_data(DataTypes::session_id).as_number() else { - let response = CommunicationValue::new(CommunicationType::error_invalid_data) + let Some(session_id) = cv.get_data(DataType::SessionId).as_number() else { + let response = CommunicationValue::new(CommunicationType::ErrorInvalidData) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data( - DataTypes::message, + .add_typed_default( + DataType::Message, DataValue::Str("Missing session_id".to_string()), ); self.send_message(&response).await; @@ -1566,11 +1670,14 @@ impl OmikronConnection { } let _ = settings_json.push(DataValue::Str(s)); } - let response = CommunicationValue::new(CommunicationType::settings_list) + let response = CommunicationValue::new(CommunicationType::SettingsList) .with_id(cv.get_id()) .with_receiver(my_id) - .add_data(DataTypes::settings, DataValue::Array(settings_json)) - .add_data(DataTypes::session_id, DataValue::Number(session_id)); + .add_typed_default(DataType::Settings, DataValue::Array(settings_json)) + .add_typed_default( + DataType::SessionId, + DataValue::SignedNumber(session_id as i128), + ); self.send_message(&response).await; return; @@ -1589,11 +1696,11 @@ impl OmikronConnection { }; drop(conf); - let Some(omikron_public_key) = cv.get_data(DataTypes::public_key).as_str() else { + let Some(omikron_public_key) = cv.get_data(DataType::PublicKey).as_str() else { log_t!("omikron_challenge_decryption_failed"); return; }; - let Some(encrypted_challenge) = cv.get_data(DataTypes::challenge).as_str() else { + let Some(encrypted_challenge) = cv.get_data(DataType::Challenge).as_str() else { log_t!("omikron_challenge_decryption_failed"); return; }; @@ -1615,9 +1722,9 @@ impl OmikronConnection { if let Some(decrypted) = solved_challenge { let solved = decrypted.export(DataFormat::Raw); - let response = CommunicationValue::new(CommunicationType::challenge_response) + let response = CommunicationValue::new(CommunicationType::ChallengeResponse) .with_id(cv.get_id()) - .add_data(DataTypes::challenge, DataValue::Str(solved)); + .add_typed_default(DataType::Challenge, DataValue::Str(solved)); self.send_message(&response).await; } else { @@ -1674,7 +1781,7 @@ impl OmikronConnection { let sender_clone = Arc::clone(sender); drop(sender_guard); - if !cv.is_type(CommunicationType::ping) && !cv.is_type(CommunicationType::pong) { + if !cv.is_type(CommunicationType::Ping) && !cv.is_type(CommunicationType::Pong) { log_cv_out!(&cv); } @@ -1698,9 +1805,9 @@ impl OmikronConnection { for key in keys { if let Some((_, waiting_task)) = WAITING_TASKS.remove(&key) { - let response = CommunicationValue::new(CommunicationType::error_internal) + let response = CommunicationValue::new(CommunicationType::ErrorInternal) .with_id(key) - .add_data(DataTypes::message, DataValue::Str(reason.clone())); + .add_typed_default(DataType::Message, DataValue::Str(reason.clone())); let _ = (waiting_task.task)(OMIKRON_CONNECTION.clone(), response); } } @@ -1748,16 +1855,15 @@ impl OmikronConnection { match tokio::time::timeout(timeout, rx.recv()).await { Ok(Some(response_cv)) => { - let resp_type = response_cv.get_type(); - let is_error = resp_type == CommunicationType::error - || resp_type == CommunicationType::error_internal - || resp_type == CommunicationType::error_not_found - || resp_type == CommunicationType::error_invalid_data - || resp_type == CommunicationType::error_invalid_challenge - || resp_type == CommunicationType::error_not_authenticated; + let is_error = response_cv.is_type(CommunicationType::Error) + || response_cv.is_type(CommunicationType::ErrorInternal) + || response_cv.is_type(CommunicationType::ErrorNotFound) + || response_cv.is_type(CommunicationType::ErrorInvalidData) + || response_cv.is_type(CommunicationType::ErrorInvalidChallenge) + || response_cv.is_type(CommunicationType::ErrorNotAuthenticated); if is_error { let reason = response_cv - .get_data(DataTypes::message) + .get_data(DataType::Message) .as_str() .unwrap_or("connection error") .to_string(); diff --git a/omikron-connector/src/ping_pong_task.rs b/omikron-connector/src/ping_pong_task.rs index 18e651f..9c81c60 100644 --- a/omikron-connector/src/ping_pong_task.rs +++ b/omikron-connector/src/ping_pong_task.rs @@ -1,26 +1,26 @@ use crate::omikron_connection::OmikronConnection; use dashmap::DashMap; use iota_state::APP_STATE; +use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue}; use std::sync::LazyLock; use std::time::Instant; use tokio::time::Duration; -use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue, rand_u32}; static PING_TIMES: LazyLock> = LazyLock::new(|| DashMap::new()); impl OmikronConnection { pub async fn send_ping(&self) { - let id = rand_u32(); + let id = rand::random(); PING_TIMES.insert(id, Instant::now()); PING_TIMES.retain(|_, v| v.elapsed() < Duration::from_secs(30)); - let ping_message = CommunicationValue::new(CommunicationType::ping) + let ping_message = CommunicationValue::new(CommunicationType::Ping) .with_id(id) - .add_data( - DataTypes::last_ping, - DataValue::Array(vec![DataValue::Number(*self.last_ping.lock().await)]), + .add_typed_default( + DataType::LastPing, + DataValue::Array(vec![DataValue::SignedNumber(*self.last_ping.lock().await as i128)]), ); self.send_message(&ping_message).await; diff --git a/omikron-connector/src/user_ops.rs b/omikron-connector/src/user_ops.rs index eb14bcc..978e742 100644 --- a/omikron-connector/src/user_ops.rs +++ b/omikron-connector/src/user_ops.rs @@ -6,16 +6,16 @@ use iota_storage::users::user_manager::{add_user, save_users}; use iota_storage::users::user_profile::UserProfile; use iota_util::crypto_helper::public_key_to_base64; use iota_util::file_util::save_file; +use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue}; use rand_core::{OsRng, RngCore}; use sha2::{Digest, Sha256}; use std::time::Duration; -use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue}; use x448::{PublicKey, Secret}; use crate::omikron_connection::OMIKRON_CONNECTION; pub async fn create_user(username: &str) -> (Option, Option) { - let register_communication_value = CommunicationValue::new(CommunicationType::get_register); + let register_communication_value = CommunicationValue::new(CommunicationType::GetRegister); let connection = OMIKRON_CONNECTION.clone(); @@ -32,7 +32,7 @@ pub async fn create_user(username: &str) -> (Option, Option log_cv!(PrintType::Omega, response_communication_value); let user_id = match response_communication_value - .get_data(DataTypes::user_id) + .get_data(DataType::UserId) .as_number() { Some(id) => id, @@ -57,7 +57,7 @@ pub async fn create_user(username: &str) -> (Option, Option let reset_token = STANDARD.encode(&bytes); let user_profile = UserProfile::new( - user_id, + user_id as i64, username.to_string(), None, STANDARD.encode(&public_key.as_bytes()), @@ -65,15 +65,15 @@ pub async fn create_user(username: &str) -> (Option, Option reset_token.clone(), ); - let communication_value = CommunicationValue::new(CommunicationType::complete_register_user) - .add_data(DataTypes::user_id, DataValue::Number(user_id)) - .add_data(DataTypes::username, DataValue::Str(username.to_string())) - .add_data( - DataTypes::public_key, + let communication_value = CommunicationValue::new(CommunicationType::CompleteRegisterUser) + .add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id as i128)) + .add_typed_default(DataType::Username, DataValue::Str(username.to_string())) + .add_typed_default( + DataType::PublicKey, DataValue::Str(public_key_to_base64(&public_key)), ) - .add_data(DataTypes::iota_id, DataValue::Number(user_id)) - .add_data(DataTypes::reset_token, DataValue::Str(reset_token)); + .add_typed_default(DataType::IotaId, DataValue::SignedNumber(user_id as i128)) + .add_typed_default(DataType::ResetToken, DataValue::Str(reset_token)); let response_communication_value = connection .await_response(&communication_value, Some(Duration::from_secs(20))) @@ -81,7 +81,7 @@ pub async fn create_user(username: &str) -> (Option, Option if let Ok(response) = response_communication_value { log_cv!(PrintType::Omega, response); - if !response.is_type(CommunicationType::success) { + if !response.is_type(CommunicationType::Success) { return (None, None); } } else { diff --git a/other-iota/Cargo.toml b/other-iota/Cargo.toml index a1d34f7..641de58 100644 --- a/other-iota/Cargo.toml +++ b/other-iota/Cargo.toml @@ -4,8 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } iota-logger = { path = "../iota-logger" } iota-util = { path = "../iota-util" } iota-storage = { path = "../iota-storage" } diff --git a/type-maps.yaml b/type-maps.yaml new file mode 100644 index 0000000..5cd196f --- /dev/null +++ b/type-maps.yaml @@ -0,0 +1,241 @@ +# The version a Client should use +protocol_version: "1.0" + +# Note that markers 0 to 31 are reserved for default use, manually working with them is not recommended +# Fixed CommunicationType markers are: +# Error: 0 +# ErrorParsing: 1 +# ErrorBadVersion: 2 +# Disconnect: 3 +# Redirect: 4 +# Shutdown: 5 +# BadRequest: 6 +# Unauthorized: 7 +# Forbidden: 8 +# NotFound: 9 +# TooManyRequests: 10 +# InternalServerError: 11 +# BadGateway: 12 +# ServiceUnavailable: 13 +# GatewayTimeout: 14 +# Identification: 15 +# IdentificationResponse: 16 +# Register: 17 +# RegisterResponse: 18 +# Ping: 19 +# Pong: 20 +# +# Fixed Data Type markers are: +# Error: 0 +# ErrorParsing: 1 +# ErrorMessage: 2 +# Version: 3 +# Description: 4 +# Timestamp: 5 +# Id: 6 +# ClientNonce: 7 +# ServerNonce: 8 +# PublicKeys: 9 +# Signature: 10 +# Connected: 11 +# +# If a Type can't be used it will be mapped to 0 + +type_maps: + "1.0": # Protocol version 1.0 + CommunicationTypes: + ErrorProtocol: 33 + ErrorAnonymous: 34 + ErrorInternal: 35 + ErrorInvalidData: 36 + ErrorInvalidUserId: 37 + ErrorInvalidOmikronId: 38 + ErrorNotFound: 39 + ErrorNotAuthenticated: 40 + ErrorNoIota: 41 + ErrorInvalidChallenge: 42 + ErrorInvalidSecret: 43 + ErrorInvalidPrivateKey: 44 + ErrorInvalidPublicKey: 45 + ErrorNoUserId: 46 + ErrorNoCallId: 47 + ErrorInvalidCallId: 48 + Success: 49 + ShortenLink: 50 + SettingsSave: 51 + SettingsLoad: 52 + SettingsList: 53 + GlobalSettingsSave: 54 + GlobalSettingsLoad: 55 + Message: 56 + MessageState: 57 + MessageSend: 58 + MessageLive: 59 + MessageOtherIota: 60 + MessageChunk: 61 + MessagesGet: 62 + PushNotification: 63 + ReadNotification: 64 + GetNotifications: 65 + TauriIdentification: 66 + ChangeConfirm: 67 + ConfirmReceive: 68 + ConfirmRead: 69 + GetChats: 70 + GetStates: 71 + AddCommunity: 72 + RemoveCommunity: 73 + GetCommunities: 74 + RegisterIota: 81 + RegisterIotaSuccess: 82 + AddConversation: 85 + SendChat: 86 + ClientChanged: 87 + ClientConnected: 88 + ClientDisconnected: 89 + ClientClosed: 90 + PublicKey: 91 + PrivateKey: 92 + WebrtcSdp: 93 + WebrtcIce: 94 + StartStream: 95 + EndStream: 96 + WatchStream: 97 + CallToken: 98 + CallInvite: 99 + CallDisconnectUser: 100 + CallTimeoutUser: 101 + CallSetAnonymousJoining: 102 + CallData: 103 + EndCall: 104 + Function: 105 + Update: 106 + CreateUser: 107 + RhoUpdate: 108 + UserConnected: 109 + UserDisconnected: 110 + IotaConnected: 111 + IotaDisconnected: 112 + SyncClientIotaStatus: 113 + GetUserData: 114 + GetIotaData: 115 + IotaUserData: 116 + ChangeUserData: 117 + ChangeIotaData: 118 + GetRegister: 119 + CompleteRegisterUser: 120 + CompleteRegisterIota: 121 + DeleteUser: 122 + DeleteIota: 123 + StartRegister: 124 + CompleteRegister: 125 + GetApp: 126 + CreateApp: 127 + DeleteApp: 128 + SaveAppData: 129 + LoadAppData: 130 + AppIdentification: 131 + AppChallenge: 132 + AppChallengeResponse: 133 + AppIdentificationResponse: 134 + LoadTxtRecord: 135 + DataTypes: + ErrorType: 32 + ErrorProtocol: 33 + AcceptedIds: 34 + Uuid: 35 + RegisterId: 36 + Link: 37 + Settings: 38 + SettingsName: 39 + ChatPartnerId: 40 + ChatPartnerName: 41 + IotaId: 42 + UserId: 43 + UserIds: 44 + IotaIds: 45 + UserState: 46 + UserStates: 47 + UserPings: 48 + CallState: 49 + ScreenShare: 50 + PrivateKeyHash: 51 + Accepted: 52 + AcceptedProfiles: 53 + DeniedProfiles: 54 + Content: 55 + Messages: 56 + Notifications: 57 + SendTime: 58 + GetTime: 59 + GetVariant: 60 + SharedSecretOwn: 61 + SharedSecretOther: 62 + SharedSecretSign: 63 + SharedSecret: 64 + CallId: 65 + CallToken: 66 + CallSecret: 67 + Untill: 68 + Enabled: 69 + StartDate: 70 + EndDate: 71 + ReceiverId: 72 + SenderId: 73 + Signed: 75 + Message: 76 + MessageState: 77 + LastPing: 78 + PingIota: 79 + PingClients: 80 + Matches: 81 + Omikron: 82 + Offset: 83 + Amount: 84 + Position: 85 + Name: 86 + Path: 87 + Codec: 88 + Function: 89 + Payload: 90 + Result: 91 + Interactables: 92 + WantToWatch: 93 + Watcher: 94 + CreatedAt: 95 + Username: 96 + Display: 97 + Avatar: 98 + About: 99 + Status: 100 + PublicKey: 101 + SubLevel: 102 + SubEnd: 103 + CommunityAddress: 104 + CommunityTitle: 106 + Communities: 107 + RhoConnections: 108 + User: 109 + OnlineStatus: 110 + OmikronId: 111 + OmikronConnections: 112 + ResetToken: 113 + NewToken: 114 + CallInvited: 115 + CallMembers: 116 + Calls: 117 + Timeout: 118 + HasAdmin: 119 + LastMessageAt: 120 + Height: 121 + SentBySelf: 122 + SessionId: 123 + Contacts: 124 + LastMessage: 125 + AppIdentifier: 127 + AppPrivateKey: 128 + AppPublicKey: 129 + AppSession: 130 + AppData: 131 + TauriToken: 132 + Challenge: 133 diff --git a/web-server/Cargo.toml b/web-server/Cargo.toml index b214806..74de956 100644 --- a/web-server/Cargo.toml +++ b/web-server/Cargo.toml @@ -5,5 +5,4 @@ version = "0.1.0" edition = "2024" [dependencies] -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } diff --git a/web-ui/Cargo.toml b/web-ui/Cargo.toml index e0debbd..a6fbba1 100644 --- a/web-ui/Cargo.toml +++ b/web-ui/Cargo.toml @@ -9,8 +9,7 @@ iota-storage = { path = "../iota-storage" } iota-state = { path = "../iota-state" } iota-util = { path = "../iota-util" } iota-logger = { path = "../iota-logger" } -ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } -ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" } +mtp = { git = "https://git.methanium.net/Methanium/mtp.git" } actix-web = { version = "4", features = ["rustls-0_23"] } actix-web-actors = "4" @@ -24,7 +23,15 @@ futures = "*" futures-util = "*" hex = "*" hkdf = "0.12.4" -hyper = { version = "1.8.1", features = ["capi", "client", "full", "http1", "http2", "nightly", "server"] } +hyper = { version = "1.8.1", features = [ + "capi", + "client", + "full", + "http1", + "http2", + "nightly", + "server", +] } hyper-util = { version = "*" } json = "*" lazy_static = "1.5.0"