From 8037fb2d66e52fa65333e4b176c430118f59e89c Mon Sep 17 00:00:00 2001 From: AsamK Date: Fri, 11 Aug 2023 00:21:38 +0200 Subject: [PATCH] Switch to jsonrpsee Fixes #1275 --- client/Cargo.lock | 887 ++++++++++++++++---------- client/Cargo.toml | 22 +- client/src/cli.rs | 8 +- client/src/jsonrpc.rs | 219 ++++--- client/src/main.rs | 79 ++- client/src/tcp.rs | 29 - client/src/transports/ipc.rs | 23 + client/src/transports/mod.rs | 64 ++ client/src/transports/stream_codec.rs | 61 ++ client/src/transports/tcp.rs | 21 + 10 files changed, 910 insertions(+), 503 deletions(-) delete mode 100644 client/src/tcp.rs create mode 100644 client/src/transports/ipc.rs create mode 100644 client/src/transports/mod.rs create mode 100644 client/src/transports/stream_codec.rs create mode 100644 client/src/transports/tcp.rs diff --git a/client/Cargo.lock b/client/Cargo.lock index aed17e7f..45764a22 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -17,15 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aho-corasick" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" -dependencies = [ - "memchr", -] - [[package]] name = "anstream" version = "0.3.2" @@ -81,6 +72,26 @@ version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-trait" +version = "0.1.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -102,6 +113,21 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -115,14 +141,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] -name = "bstr" -version = "1.6.0" +name = "bumpalo" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" -dependencies = [ - "memchr", - "serde", -] +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytes" @@ -195,23 +217,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] -name = "convert_case" -version = "0.4.0" +name = "core-foundation" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] -name = "derive_more" -version = "0.99.17" +name = "core-foundation-sys" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" @@ -235,31 +260,16 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures" -version = "0.1.31" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] -name = "futures" -version = "0.3.28" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures-channel" @@ -268,7 +278,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -277,24 +286,6 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - [[package]] name = "futures-macro" version = "0.3.28" @@ -318,36 +309,27 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ - "futures 0.1.31", - "futures-channel", "futures-core", - "futures-io", "futures-macro", "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "gimli" version = "0.27.3" @@ -355,18 +337,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] -name = "globset" -version = "0.4.13" +name = "h2" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ - "aho-corasick", - "bstr", + "bytes", "fnv", - "log", - "regex", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -380,12 +380,97 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] -name = "instant" -version = "0.1.12" +name = "http" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "cfg-if", + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", ] [[package]] @@ -406,7 +491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.7", + "rustix 0.38.8", "windows-sys", ] @@ -417,66 +502,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] -name = "jsonrpc-client-transports" -version = "18.0.0" -source = "git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params#8a68f95e202943fd338fd0c14da08c2dc8f6e6a6" +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ - "derive_more", - "futures 0.3.28", - "jsonrpc-core 18.0.0 (git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params)", - "jsonrpc-pubsub", - "jsonrpc-server-utils 18.0.0 (git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params)", - "log", - "parity-tokio-ipc", - "serde", - "serde_json", - "tokio", + "wasm-bindgen", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" +name = "jsonrpsee" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +checksum = "e5f3783308bddc49d0218307f66a09330c106fbd792c58bac5c8dc294fdd0f98" dependencies = [ - "futures 0.3.28", - "futures-executor", - "futures-util", - "log", - "serde", - "serde_derive", - "serde_json", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-proc-macros", + "jsonrpsee-types", + "tracing", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" -source = "git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params#8a68f95e202943fd338fd0c14da08c2dc8f6e6a6" +name = "jsonrpsee-core" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa4c4d5fb801dcc316d81f76422db259809037a86b3194ae538dd026b05ed7" dependencies = [ - "futures 0.3.28", - "futures-executor", + "anyhow", + "async-lock", + "async-trait", + "beef", + "futures-timer", "futures-util", - "log", + "hyper", + "jsonrpsee-types", + "rustc-hash", "serde", - "serde_derive", "serde_json", + "thiserror", + "tokio", + "tokio-stream", + "tracing", ] [[package]] -name = "jsonrpc-core-client" -version = "18.0.0" +name = "jsonrpsee-http-client" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" +checksum = "aa7165efcbfbc951d180162ff28fe91b657ed81925e37a35e4a396ce12109f96" dependencies = [ - "futures 0.3.28", - "jsonrpc-client-transports", + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", ] [[package]] -name = "jsonrpc-derive" -version = "18.0.0" -source = "git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params#8a68f95e202943fd338fd0c14da08c2dc8f6e6a6" +name = "jsonrpsee-proc-macros" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dc12b1d4f16a86e8c522823c4fab219c88c03eb7c924ec0501a64bf12e058b" dependencies = [ + "heck", "proc-macro-crate", "proc-macro2", "quote", @@ -484,60 +579,19 @@ dependencies = [ ] [[package]] -name = "jsonrpc-pubsub" -version = "18.0.0" -source = "git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params#8a68f95e202943fd338fd0c14da08c2dc8f6e6a6" -dependencies = [ - "futures 0.3.28", - "jsonrpc-core 18.0.0 (git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params)", - "lazy_static", - "log", - "parking_lot", - "rand", - "serde", -] - -[[package]] -name = "jsonrpc-server-utils" -version = "18.0.0" +name = "jsonrpsee-types" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" +checksum = "00aa7cc87bc42e04e26c8ac3e7186142f7fd2949c763d9b6a7e64a69672d8fb2" dependencies = [ - "bytes", - "futures 0.3.28", - "globset", - "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static", - "log", - "tokio", - "tokio-stream", - "tokio-util", - "unicase", -] - -[[package]] -name = "jsonrpc-server-utils" -version = "18.0.0" -source = "git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params#8a68f95e202943fd338fd0c14da08c2dc8f6e6a6" -dependencies = [ - "bytes", - "futures 0.3.28", - "globset", - "jsonrpc-core 18.0.0 (git+https://github.com/AsamK/jsonrpc?branch=client_subscribe_named_params)", - "lazy_static", - "log", - "tokio", - "tokio-stream", - "tokio-util", - "unicase", + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.147" @@ -556,16 +610,6 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.19" @@ -594,7 +638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -624,42 +668,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] -name = "parity-tokio-ipc" -version = "0.9.0" +name = "openssl-probe" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" -dependencies = [ - "futures 0.3.28", - "libc", - "log", - "rand", - "tokio", - "winapi", -] +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] -name = "parking_lot" -version = "0.11.2" +name = "pin-project" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ - "instant", - "lock_api", - "parking_lot_core", + "pin-project-internal", ] [[package]] -name = "parking_lot_core" -version = "0.8.6" +name = "pin-project-internal" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "proc-macro2", + "quote", + "syn 2.0.28", ] [[package]] @@ -674,19 +705,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "toml", + "once_cell", + "toml_edit", ] [[package]] @@ -708,144 +734,150 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.7.3" +name = "ring" +version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ - "getrandom", + "cc", "libc", - "rand_chacha", - "rand_core", - "rand_hc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", ] [[package]] -name = "rand_chacha" -version = "0.2.2" +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "ppv-lite86", - "rand_core", + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "rustix" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "getrandom", + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.5", + "windows-sys", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "rustls" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ - "rand_core", + "log", + "ring", + "rustls-webpki", + "sct", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rustls-native-certs" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "bitflags 1.3.2", + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", ] [[package]] -name = "regex" -version = "1.9.3" +name = "rustls-pemfile" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "base64", ] [[package]] -name = "regex-automata" -version = "0.3.6" +name = "rustls-webpki" +version = "0.101.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "ring", + "untrusted", ] [[package]] -name = "regex-syntax" -version = "0.7.4" +name = "ryu" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "schannel" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "semver", + "ring", + "untrusted", ] [[package]] -name = "rustix" -version = "0.37.23" +name = "security-framework" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", - "errno", - "io-lifetimes", + "core-foundation", + "core-foundation-sys", "libc", - "linux-raw-sys 0.3.8", - "windows-sys", + "security-framework-sys", ] [[package]] -name = "rustix" -version = "0.38.7" +name = "security-framework-sys" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ - "bitflags 2.3.3", - "errno", + "core-foundation-sys", "libc", - "linux-raw-sys 0.4.5", - "windows-sys", ] -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - [[package]] name = "serde" version = "1.0.183" @@ -882,16 +914,16 @@ name = "signal-cli-client" version = "0.0.1" dependencies = [ "anyhow", + "bytes", "clap", - "jsonrpc-client-transports", - "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client", - "jsonrpc-derive", - "jsonrpc-server-utils 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util", + "jsonrpsee", "log", "serde", "serde_json", + "thiserror", "tokio", + "tokio-util", ] [[package]] @@ -904,10 +936,14 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.0" +name = "socket2" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] [[package]] name = "socket2" @@ -919,6 +955,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "strsim" version = "0.10.0" @@ -957,6 +999,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "tokio" version = "1.30.0" @@ -969,7 +1031,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "tokio-macros", "windows-sys", ] @@ -985,6 +1047,16 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -998,42 +1070,113 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.10" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] -name = "toml" -version = "0.5.11" +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "serde", + "indexmap 2.0.0", + "toml_datetime", + "winnow", ] [[package]] -name = "unicase" -version = "2.6.0" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "version_check", + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", ] +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "utf8parse" version = "0.2.1" @@ -1041,22 +1184,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] -name = "version_check" -version = "0.9.4" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasm-bindgen" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi" @@ -1145,3 +1349,12 @@ name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f495880723d0999eb3500a9064d8dbcf836460b24c17df80ea7b5794053aac" +dependencies = [ + "memchr", +] diff --git a/client/Cargo.toml b/client/Cargo.toml index 9e3cd4df..fb77b86c 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -8,18 +8,16 @@ edition = "2021" [dependencies] anyhow = "1" clap = { version = "4", features = ["cargo", "derive", "wrap_help"] } -jsonrpc-core = "18" -jsonrpc-core-client = "18" -jsonrpc-client-transports = { version = "18", default-features = false, features = [ - "ipc", -] } -jsonrpc-derive = "18" -jsonrpc-server-utils = "18" log = "0.4" serde = "1" serde_json = "1" -tokio = { version = "1", features = ["rt", "macros", "net"] } - -[patch.crates-io] -jsonrpc-client-transports = { git = "https://github.com/AsamK/jsonrpc", branch = "client_subscribe_named_params" } -jsonrpc-derive = { git = "https://github.com/AsamK/jsonrpc", branch = "client_subscribe_named_params" } +tokio = { version = "1", features = ["rt", "macros", "net", "rt-multi-thread"] } +jsonrpsee = { version = "0.19.0", features = [ + "macros", + "async-client", + "http-client", +] } +bytes = "1" +tokio-util = "0.7" +futures-util = "0.3" +thiserror = "1" diff --git a/client/src/cli.rs b/client/src/cli.rs index ca809290..6a8dd361 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -10,13 +10,17 @@ pub struct Cli { pub account: Option, /// TCP host and port of signal-cli daemon - #[arg(long)] + #[arg(long, conflicts_with = "json_rpc_http")] pub json_rpc_tcp: Option>, /// UNIX socket address and port of signal-cli daemon - #[arg(long)] + #[arg(long, conflicts_with = "json_rpc_tcp")] pub json_rpc_socket: Option>, + /// HTTP URL of signal-cli daemon + #[arg(long, conflicts_with = "json_rpc_socket")] + pub json_rpc_http: Option>, + #[arg(value_enum, long, default_value_t = OutputTypes::Json)] pub output: OutputTypes, diff --git a/client/src/jsonrpc.rs b/client/src/jsonrpc.rs index 51e41c19..cd257305 100644 --- a/client/src/jsonrpc.rs +++ b/client/src/jsonrpc.rs @@ -1,49 +1,59 @@ use std::path::Path; -use jsonrpc_client_transports::{transports::ipc, RpcError}; -use jsonrpc_core::serde::Deserialize; -use jsonrpc_derive::rpc; +use jsonrpsee::async_client::ClientBuilder; +use jsonrpsee::core::client::SubscriptionClientT; +use jsonrpsee::core::Error; +use jsonrpsee::http_client::HttpClientBuilder; +use jsonrpsee::proc_macros::rpc; +use serde::Deserialize; +use serde_json::Value; use tokio::net::ToSocketAddrs; -pub type SignalCliClient = gen_client::Client; - -#[rpc(client, params = "named")] +#[rpc(client)] pub trait Rpc { - #[rpc(name = "addDevice", params = "named")] - fn add_device(&self, account: Option, uri: String) -> Result; + #[method(name = "addDevice", param_kind = map)] + async fn add_device( + &self, + account: Option, + uri: String, + ) -> Result; - #[rpc(name = "block", params = "named")] + #[method(name = "block", param_kind = map)] fn block( &self, account: Option, recipients: Vec, #[allow(non_snake_case)] groupIds: Vec, - ) -> Result; + ) -> Result; - #[rpc(name = "deleteLocalAccountData", params = "named")] + #[method(name = "deleteLocalAccountData", param_kind = map)] fn delete_local_account_data( &self, account: Option, #[allow(non_snake_case)] ignoreRegistered: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "getUserStatus", params = "named")] - fn get_user_status(&self, account: Option, recipients: Vec) -> Result; + #[method(name = "getUserStatus", param_kind = map)] + fn get_user_status( + &self, + account: Option, + recipients: Vec, + ) -> Result; - #[rpc(name = "joinGroup", params = "named")] - fn join_group(&self, account: Option, uri: String) -> Result; + #[method(name = "joinGroup", param_kind = map)] + fn join_group(&self, account: Option, uri: String) -> Result; - #[rpc(name = "finishLink", params = "named")] + #[method(name = "finishLink", param_kind = map)] fn finish_link( &self, #[allow(non_snake_case)] deviceLinkUri: String, #[allow(non_snake_case)] deviceName: String, - ) -> Result; + ) -> Result; - #[rpc(name = "listAccounts", params = "named")] - fn list_accounts(&self) -> Result; + #[method(name = "listAccounts", param_kind = map)] + fn list_accounts(&self) -> Result; - #[rpc(name = "listContacts", params = "named")] + #[method(name = "listContacts", param_kind = map)] fn list_contacts( &self, account: Option, @@ -51,60 +61,64 @@ pub trait Rpc { #[allow(non_snake_case)] allRecipients: bool, blocked: Option, name: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "listDevices", params = "named")] - fn list_devices(&self, account: Option) -> Result; + #[method(name = "listDevices", param_kind = map)] + fn list_devices(&self, account: Option) -> Result; - #[rpc(name = "listGroups", params = "named")] + #[method(name = "listGroups", param_kind = map)] fn list_groups( &self, account: Option, #[allow(non_snake_case)] groupIds: Vec, - ) -> Result; + ) -> Result; - #[rpc(name = "listIdentities", params = "named")] - fn list_identities(&self, account: Option, number: Option) -> Result; + #[method(name = "listIdentities", param_kind = map)] + fn list_identities( + &self, + account: Option, + number: Option, + ) -> Result; - #[rpc(name = "listStickerPacks", params = "named")] - fn list_sticker_packs(&self, account: Option) -> Result; + #[method(name = "listStickerPacks", param_kind = map)] + fn list_sticker_packs(&self, account: Option) -> Result; - #[rpc(name = "quitGroup", params = "named")] + #[method(name = "quitGroup", param_kind = map)] fn quit_group( &self, account: Option, #[allow(non_snake_case)] groupId: String, delete: bool, admins: Vec, - ) -> Result; + ) -> Result; - #[rpc(name = "register", params = "named")] + #[method(name = "register", param_kind = map)] fn register( &self, account: Option, voice: bool, captcha: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "removeContact", params = "named")] + #[method(name = "removeContact", param_kind = map)] fn remove_contact( &self, account: Option, recipient: String, forget: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "removeDevice", params = "named")] + #[method(name = "removeDevice", param_kind = map)] fn remove_device( &self, account: Option, #[allow(non_snake_case)] deviceId: u32, - ) -> Result; + ) -> Result; - #[rpc(name = "removePin", params = "named")] - fn remove_pin(&self, account: Option) -> Result; + #[method(name = "removePin", param_kind = map)] + fn remove_pin(&self, account: Option) -> Result; - #[rpc(name = "remoteDelete", params = "named")] + #[method(name = "remoteDelete", param_kind = map)] fn remote_delete( &self, account: Option, @@ -112,9 +126,9 @@ pub trait Rpc { recipients: Vec, #[allow(non_snake_case)] groupIds: Vec, #[allow(non_snake_case)] noteToSelf: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "send", params = "named")] + #[method(name = "send", param_kind = map)] fn send( &self, account: Option, @@ -132,21 +146,21 @@ pub trait Rpc { sticker: Option, #[allow(non_snake_case)] storyTimestamp: Option, #[allow(non_snake_case)] storyAuthor: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "sendContacts", params = "named")] - fn send_contacts(&self, account: Option) -> Result; + #[method(name = "sendContacts", param_kind = map)] + fn send_contacts(&self, account: Option) -> Result; - #[rpc(name = "sendPaymentNotification", params = "named")] + #[method(name = "sendPaymentNotification", param_kind = map)] fn send_payment_notification( &self, account: Option, recipient: String, receipt: String, note: String, - ) -> Result; + ) -> Result; - #[rpc(name = "sendReaction", params = "named")] + #[method(name = "sendReaction", param_kind = map)] fn send_reaction( &self, account: Option, @@ -158,75 +172,75 @@ pub trait Rpc { #[allow(non_snake_case)] targetTimestamp: u64, remove: bool, story: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "sendReceipt", params = "named")] + #[method(name = "sendReceipt", param_kind = map)] fn send_receipt( &self, account: Option, recipient: String, #[allow(non_snake_case)] targetTimestamps: Vec, r#type: String, - ) -> Result; + ) -> Result; - #[rpc(name = "sendSyncRequest", params = "named")] - fn send_sync_request(&self, account: Option) -> Result; + #[method(name = "sendSyncRequest", param_kind = map)] + fn send_sync_request(&self, account: Option) -> Result; - #[rpc(name = "sendTyping", params = "named")] + #[method(name = "sendTyping", param_kind = map)] fn send_typing( &self, account: Option, recipients: Vec, #[allow(non_snake_case)] groupIds: Vec, stop: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "setPin", params = "named")] - fn set_pin(&self, account: Option, pin: String) -> Result; + #[method(name = "setPin", param_kind = map)] + fn set_pin(&self, account: Option, pin: String) -> Result; - #[rpc(name = "submitRateLimitChallenge", params = "named")] + #[method(name = "submitRateLimitChallenge", param_kind = map)] fn submit_rate_limit_challenge( &self, account: Option, challenge: String, captcha: String, - ) -> Result; + ) -> Result; - #[rpc(name = "startLink", params = "named")] - fn start_link(&self, account: Option) -> Result; + #[method(name = "startLink", param_kind = map)] + fn start_link(&self, account: Option) -> Result; - #[rpc(name = "trust", params = "named")] + #[method(name = "trust", param_kind = map)] fn trust( &self, account: Option, recipient: String, #[allow(non_snake_case)] trustAllKnownKeys: bool, #[allow(non_snake_case)] verifiedSafetyNumber: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "unblock", params = "named")] + #[method(name = "unblock", param_kind = map)] fn unblock( &self, account: Option, recipients: Vec, #[allow(non_snake_case)] groupIds: Vec, - ) -> Result; + ) -> Result; - #[rpc(name = "unregister", params = "named")] + #[method(name = "unregister", param_kind = map)] fn unregister( &self, account: Option, #[allow(non_snake_case)] deleteAccount: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "updateAccount", params = "named")] + #[method(name = "updateAccount", param_kind = map)] fn update_account( &self, account: Option, #[allow(non_snake_case)] deviceName: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "updateConfiguration", params = "named")] + #[method(name = "updateConfiguration", param_kind = map)] fn update_configuration( &self, account: Option, @@ -234,18 +248,18 @@ pub trait Rpc { #[allow(non_snake_case)] unidentifiedDeliveryIndicators: Option, #[allow(non_snake_case)] typingIndicators: Option, #[allow(non_snake_case)] linkPreviews: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "updateContact", params = "named")] + #[method(name = "updateContact", param_kind = map)] fn update_contact( &self, account: Option, recipient: String, name: Option, expiration: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "updateGroup", params = "named")] + #[method(name = "updateGroup", param_kind = map)] fn update_group( &self, account: Option, @@ -265,9 +279,9 @@ pub trait Rpc { #[allow(non_snake_case)] setPermissionEditDetails: Option, #[allow(non_snake_case)] setPermissionSendMessages: Option, expiration: Option, - ) -> Result; + ) -> Result; - #[rpc(name = "updateProfile", params = "named")] + #[method(name = "updateProfile", param_kind = map)] fn update_profile( &self, account: Option, @@ -278,32 +292,33 @@ pub trait Rpc { #[allow(non_snake_case)] mobileCoinAddress: Option, avatar: Option, #[allow(non_snake_case)] removeAvatar: bool, - ) -> Result; + ) -> Result; - #[rpc(name = "uploadStickerPack", params = "named")] - fn upload_sticker_pack(&self, account: Option, path: String) -> Result; + #[method(name = "uploadStickerPack", param_kind = map)] + fn upload_sticker_pack( + &self, + account: Option, + path: String, + ) -> Result; - #[rpc(name = "verify", params = "named")] + #[method(name = "verify", param_kind = map)] fn verify( &self, account: Option, #[allow(non_snake_case)] verificationCode: String, pin: Option, - ) -> Result; + ) -> Result; - #[pubsub( - subscription = "receive", - subscribe, - name = "subscribeReceive", - params = "named" + #[subscription( + name = "subscribeReceive" => "receive", + unsubscribe = "unsubscribeReceive", + item = Value, + param_kind = map )] - fn subscribe_receive(&self, _: Self::Metadata, _: Subscriber, account: Option); + async fn subscribe_receive(&self, account: Option) -> SubscriptionResult; - #[pubsub(subscription = "receive", unsubscribe, name = "unsubscribeReceive")] - fn unsubscribe_receive(&self, _: Option, _: SubscriptionId) -> Result; - - #[rpc(name = "version")] - fn version(&self) -> Result; + #[method(name = "version")] + fn version(&self) -> Result; } #[derive(Deserialize)] @@ -312,10 +327,20 @@ pub struct JsonLink { pub device_link_uri: String, } -pub async fn connect_tcp(tcp: impl ToSocketAddrs) -> Result { - super::tcp::connect::<_, SignalCliClient>(tcp).await +pub async fn connect_tcp(tcp: impl ToSocketAddrs) -> Result { + let (sender, receiver) = super::transports::tcp::connect(tcp).await?; + + Ok(ClientBuilder::default().build_with_tokio(sender, receiver)) +} + +pub async fn connect_unix( + socket_path: impl AsRef, +) -> Result { + let (sender, receiver) = super::transports::ipc::connect(socket_path).await?; + + Ok(ClientBuilder::default().build_with_tokio(sender, receiver)) } -pub async fn connect_unix(socket_path: impl AsRef) -> Result { - ipc::connect::<_, SignalCliClient>(socket_path).await +pub async fn connect_http(uri: &str) -> Result { + HttpClientBuilder::default().build(uri) } diff --git a/client/src/main.rs b/client/src/main.rs index ea9cb9c8..f4ab67f9 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,40 +1,53 @@ -use clap::Parser; -use jsonrpc_client_transports::{RpcError, TypedSubscriptionStream}; -use jsonrpc_core::{futures_util::StreamExt, Value}; use std::{path::PathBuf, time::Duration}; + +use clap::Parser; +use cli::Cli; +use jsonrpsee::core::client::{Subscription, SubscriptionClientT}; +use jsonrpsee::core::Error as RpcError; +use serde_json::Value; use tokio::{select, time::sleep}; use crate::cli::{GroupPermission, LinkState}; +use crate::jsonrpc::RpcClient; mod cli; -#[allow(clippy::too_many_arguments)] +#[allow(non_snake_case, clippy::too_many_arguments)] mod jsonrpc; -mod tcp; +mod transports; const DEFAULT_TCP: &str = "127.0.0.1:7583"; const DEFAULT_SOCKET_SUFFIX: &str = "signal-cli/socket"; +const DEFAULT_HTTP: &str = "http://localhost:8080/api/v1/rpc"; #[tokio::main] async fn main() -> Result<(), anyhow::Error> { let cli = cli::Cli::parse(); - let client = connect(&cli) - .await - .map_err(|e| anyhow::anyhow!("Failed to connect to socket: {e}"))?; + let result = connect(cli).await; + + match result { + Ok(Value::Null) => {} + Ok(v) => println!("{v}"), + Err(e) => return Err(anyhow::anyhow!("JSON-RPC command failed: {e:?}")), + } + Ok(()) +} - let result = match cli.command { +async fn handle_command( + cli: Cli, + client: impl SubscriptionClientT + Sync, +) -> Result { + match cli.command { cli::CliCommands::Receive { timeout } => { - let mut stream = client - .subscribe_receive(cli.account) - .map_err(|e| anyhow::anyhow!("JSON-RPC command failed: {:?}", e))?; + let mut stream = client.subscribe_receive(cli.account).await?; { while let Some(v) = stream_next(timeout, &mut stream).await { - let v = v.map_err(|e| anyhow::anyhow!("JSON-RPC command failed: {:?}", e))?; + let v = v?; println!("{v}"); } } - return Ok(()); + Ok(Value::Null) } cli::CliCommands::AddDevice { uri } => client.add_device(cli.account, uri).await, cli::CliCommands::Block { @@ -54,7 +67,7 @@ async fn main() -> Result<(), anyhow::Error> { let url = client .start_link(cli.account) .await - .map_err(|e| anyhow::anyhow!("JSON-RPC command startLink failed: {e:?}",))? + .map_err(|e| RpcError::Custom(format!("JSON-RPC command startLink failed: {e:?}")))? .device_link_uri; println!("{}", url); client.finish_link(url, name).await @@ -349,18 +362,28 @@ async fn main() -> Result<(), anyhow::Error> { pin, } => client.verify(cli.account, verification_code, pin).await, cli::CliCommands::Version => client.version().await, - }; - - result - .map(|v| println!("{v}")) - .map_err(|e| anyhow::anyhow!("JSON-RPC command failed: {e:?}",))?; - Ok(()) + } } -async fn connect(cli: &cli::Cli) -> Result { - if let Some(tcp) = cli.json_rpc_tcp { +async fn connect(cli: Cli) -> Result { + if let Some(http) = &cli.json_rpc_http { + let uri = if let Some(uri) = http { + uri + } else { + DEFAULT_HTTP + }; + let client = jsonrpc::connect_http(uri) + .await + .map_err(|e| RpcError::Custom(format!("Failed to connect to socket: {e}")))?; + + handle_command(cli, client).await + } else if let Some(tcp) = cli.json_rpc_tcp { let socket_addr = tcp.unwrap_or_else(|| DEFAULT_TCP.parse().unwrap()); - jsonrpc::connect_tcp(socket_addr).await + let client = jsonrpc::connect_tcp(socket_addr) + .await + .map_err(|e| RpcError::Custom(format!("Failed to connect to socket: {e}")))?; + + handle_command(cli, client).await } else { let socket_path = cli .json_rpc_socket @@ -374,13 +397,17 @@ async fn connect(cli: &cli::Cli) -> Result { }) }) .unwrap_or_else(|| ("/run".to_owned() + DEFAULT_SOCKET_SUFFIX).into()); - jsonrpc::connect_unix(socket_path).await + let client = jsonrpc::connect_unix(socket_path) + .await + .map_err(|e| RpcError::Custom(format!("Failed to connect to socket: {e}")))?; + + handle_command(cli, client).await } } async fn stream_next( timeout: f64, - stream: &mut TypedSubscriptionStream, + stream: &mut Subscription, ) -> Option> { if timeout < 0.0 { stream.next().await diff --git a/client/src/tcp.rs b/client/src/tcp.rs deleted file mode 100644 index 53650381..00000000 --- a/client/src/tcp.rs +++ /dev/null @@ -1,29 +0,0 @@ -use jsonrpc_client_transports::{transports::duplex, RpcChannel, RpcError}; -use jsonrpc_core::futures_util::{SinkExt, StreamExt, TryStreamExt}; -use jsonrpc_server_utils::{codecs::StreamCodec, tokio_util::codec::Decoder}; -use tokio::net::{TcpStream, ToSocketAddrs}; - -/// Connect to a JSON-RPC TCP server. -pub async fn connect>( - socket: S, -) -> Result { - let connection = TcpStream::connect(socket) - .await - .map_err(|e| RpcError::Other(Box::new(e)))?; - let (sink, stream) = StreamCodec::stream_incoming().framed(connection).split(); - let sink = sink.sink_map_err(|e| RpcError::Other(Box::new(e))); - let stream = stream.map_err(|e| log::error!("TCP stream error: {}", e)); - - let (client, sender) = duplex( - Box::pin(sink), - Box::pin( - stream - .take_while(|x| std::future::ready(x.is_ok())) - .map(|x| x.expect("Stream is closed upon first error.")), - ), - ); - - tokio::spawn(client); - - Ok(sender.into()) -} diff --git a/client/src/transports/ipc.rs b/client/src/transports/ipc.rs new file mode 100644 index 00000000..497955e3 --- /dev/null +++ b/client/src/transports/ipc.rs @@ -0,0 +1,23 @@ +use std::path::Path; + +use futures_util::stream::StreamExt; +use jsonrpsee::core::client::{TransportReceiverT, TransportSenderT}; +use jsonrpsee::core::Error; +use tokio::net::UnixStream; +use tokio_util::codec::Decoder; + +use super::stream_codec::StreamCodec; +use super::{Receiver, Sender}; + +/// Connect to a JSON-RPC Unix Socket server. +pub async fn connect( + socket: impl AsRef, +) -> Result<(impl TransportSenderT + Send, impl TransportReceiverT + Send), Error> { + let connection = UnixStream::connect(socket).await?; + let (sink, stream) = StreamCodec::stream_incoming().framed(connection).split(); + + let sender = Sender { inner: sink }; + let receiver = Receiver { inner: stream }; + + Ok((sender, receiver)) +} diff --git a/client/src/transports/mod.rs b/client/src/transports/mod.rs new file mode 100644 index 00000000..04f4390f --- /dev/null +++ b/client/src/transports/mod.rs @@ -0,0 +1,64 @@ +use futures_util::{stream::StreamExt, Sink, SinkExt, Stream}; +use jsonrpsee::core::{ + async_trait, + client::{ReceivedMessage, TransportReceiverT, TransportSenderT}, +}; +use thiserror::Error; + +pub mod ipc; +mod stream_codec; +pub mod tcp; + +#[derive(Debug, Error)] +enum Errors { + #[error("Other: {0}")] + Other(String), + #[error("Closed")] + Closed, +} + +struct Sender> { + inner: T, +} + +#[async_trait] +impl + Unpin + 'static> TransportSenderT + for Sender +{ + type Error = Errors; + + async fn send(&mut self, body: String) -> Result<(), Self::Error> { + self.inner + .send(body) + .await + .map_err(|e| Errors::Other(format!("{:?}", e)))?; + Ok(()) + } + + async fn close(&mut self) -> Result<(), Self::Error> { + self.inner + .close() + .await + .map_err(|e| Errors::Other(format!("{:?}", e)))?; + Ok(()) + } +} + +struct Receiver { + inner: T, +} + +#[async_trait] +impl> + Unpin + 'static> TransportReceiverT + for Receiver +{ + type Error = Errors; + + async fn receive(&mut self) -> Result { + match self.inner.next().await { + None => Err(Errors::Closed), + Some(Ok(msg)) => Ok(ReceivedMessage::Text(msg)), + Some(Err(e)) => Err(Errors::Other(format!("{:?}", e))), + } + } +} diff --git a/client/src/transports/stream_codec.rs b/client/src/transports/stream_codec.rs new file mode 100644 index 00000000..6f77306f --- /dev/null +++ b/client/src/transports/stream_codec.rs @@ -0,0 +1,61 @@ +use bytes::BytesMut; +use std::{io, str}; +use tokio_util::codec::{Decoder, Encoder}; + +type Separator = u8; + +/// Stream codec for streaming protocols (ipc, tcp) +#[derive(Debug, Default)] +pub struct StreamCodec { + incoming_separator: Separator, + outgoing_separator: Separator, +} + +impl StreamCodec { + /// Default codec with streaming input data. Input can be both enveloped and not. + pub fn stream_incoming() -> Self { + StreamCodec::new(b'\n', b'\n') + } + + /// New custom stream codec + pub fn new(incoming_separator: Separator, outgoing_separator: Separator) -> Self { + StreamCodec { + incoming_separator, + outgoing_separator, + } + } +} + +impl Decoder for StreamCodec { + type Item = String; + type Error = io::Error; + + fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { + if let Some(i) = buf + .as_ref() + .iter() + .position(|&b| b == self.incoming_separator) + { + let line = buf.split_to(i); + let _ = buf.split_to(1); + + match str::from_utf8(line.as_ref()) { + Ok(s) => Ok(Some(s.to_string())), + Err(_) => Err(io::Error::new(io::ErrorKind::Other, "invalid UTF-8")), + } + } else { + Ok(None) + } + } +} + +impl Encoder for StreamCodec { + type Error = io::Error; + + fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> { + let mut payload = msg.into_bytes(); + payload.push(self.outgoing_separator); + buf.extend_from_slice(&payload); + Ok(()) + } +} diff --git a/client/src/transports/tcp.rs b/client/src/transports/tcp.rs new file mode 100644 index 00000000..8d7a27dc --- /dev/null +++ b/client/src/transports/tcp.rs @@ -0,0 +1,21 @@ +use futures_util::stream::StreamExt; +use jsonrpsee::core::client::{TransportReceiverT, TransportSenderT}; +use jsonrpsee::core::Error; +use tokio::net::{TcpStream, ToSocketAddrs}; +use tokio_util::codec::Decoder; + +use super::stream_codec::StreamCodec; +use super::{Receiver, Sender}; + +/// Connect to a JSON-RPC TCP server. +pub async fn connect( + socket: impl ToSocketAddrs, +) -> Result<(impl TransportSenderT + Send, impl TransportReceiverT + Send), Error> { + let connection = TcpStream::connect(socket).await?; + let (sink, stream) = StreamCodec::stream_incoming().framed(connection).split(); + + let sender = Sender { inner: sink }; + let receiver = Receiver { inner: stream }; + + Ok((sender, receiver)) +} -- 2.50.1