Merge branch 'dht-testing' into 'main'
Many bug fixes, colors update for CLI See merge request veilid/veilid!31
This commit is contained in:
commit
231099fa9e
307
Cargo.lock
generated
307
Cargo.lock
generated
@ -193,6 +193,26 @@ version = "1.0.71"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arboard"
|
||||||
|
version = "3.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854"
|
||||||
|
dependencies = [
|
||||||
|
"clipboard-win",
|
||||||
|
"core-graphics",
|
||||||
|
"image",
|
||||||
|
"log",
|
||||||
|
"objc",
|
||||||
|
"objc-foundation",
|
||||||
|
"objc_id",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
|
"thiserror",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
"x11rb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argon2"
|
name = "argon2"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -727,6 +747,12 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -827,6 +853,12 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@ -1081,6 +1113,17 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clipboard-win"
|
||||||
|
version = "4.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362"
|
||||||
|
dependencies = [
|
||||||
|
"error-code",
|
||||||
|
"str-buf",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
version = "0.1.50"
|
version = "0.1.50"
|
||||||
@ -1103,6 +1146,12 @@ dependencies = [
|
|||||||
"owo-colors",
|
"owo-colors",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.6"
|
version = "4.6.6"
|
||||||
@ -1241,6 +1290,30 @@ version = "0.8.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-graphics"
|
||||||
|
version = "0.22.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation 0.9.3",
|
||||||
|
"core-graphics-types",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-graphics-types"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation 0.9.3",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -1413,8 +1486,6 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"maplit",
|
|
||||||
"ncurses",
|
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"tokio 1.28.2",
|
"tokio 1.28.2",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
@ -1431,7 +1502,7 @@ dependencies = [
|
|||||||
"flexi_logger",
|
"flexi_logger",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"time 0.3.22",
|
"time 0.3.9",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1473,7 +1544,7 @@ dependencies = [
|
|||||||
"owning_ref",
|
"owning_ref",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"time 0.3.22",
|
"time 0.3.9",
|
||||||
"tokio 1.28.2",
|
"tokio 1.28.2",
|
||||||
"toml 0.7.4",
|
"toml 0.7.4",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
@ -1826,6 +1897,16 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "error-code"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"str-buf",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethbloom"
|
name = "ethbloom"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@ -1912,6 +1993,15 @@ dependencies = [
|
|||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffi-support"
|
name = "ffi-support"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -1965,7 +2055,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time 0.3.22",
|
"time 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1987,6 +2077,21 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -2176,6 +2281,16 @@ dependencies = [
|
|||||||
"version_check 0.9.4",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -2593,6 +2708,21 @@ dependencies = [
|
|||||||
"xmltree",
|
"xmltree",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.24.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "impl-codec"
|
name = "impl-codec"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -2778,6 +2908,12 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.64"
|
||||||
@ -3029,6 +3165,15 @@ dependencies = [
|
|||||||
"linked-hash-map",
|
"linked-hash-map",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "malloc_buf"
|
||||||
|
version = "0.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maplit"
|
name = "maplit"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -3129,6 +3274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3232,17 +3378,6 @@ dependencies = [
|
|||||||
"socket2 0.4.9",
|
"socket2 0.4.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ncurses"
|
|
||||||
version = "5.101.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -3402,6 +3537,18 @@ dependencies = [
|
|||||||
"memoffset 0.6.5",
|
"memoffset 0.6.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.24.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"memoffset 0.6.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@ -3590,6 +3737,35 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||||
|
dependencies = [
|
||||||
|
"malloc_buf",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc-foundation"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||||
|
dependencies = [
|
||||||
|
"block",
|
||||||
|
"objc",
|
||||||
|
"objc_id",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc_id"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||||
|
dependencies = [
|
||||||
|
"objc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.30.4"
|
version = "0.30.4"
|
||||||
@ -4044,6 +4220,19 @@ dependencies = [
|
|||||||
"plotters-backend",
|
"plotters-backend",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide 0.7.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@ -5091,6 +5280,12 @@ version = "1.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simdutf8"
|
name = "simdutf8"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@ -5116,7 +5311,7 @@ checksum = "acee08041c5de3d5048c8b3f6f13fafb3026b24ba43c6a695a0c76179b844369"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"time 0.3.22",
|
"time 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5261,6 +5456,12 @@ dependencies = [
|
|||||||
"pin-project-lite 0.2.9",
|
"pin-project-lite 0.2.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "str-buf"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -5422,6 +5623,17 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -5450,24 +5662,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.22"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
|
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"libc",
|
"libc",
|
||||||
"num_threads",
|
"num_threads",
|
||||||
"serde",
|
"time-macros 0.2.4",
|
||||||
"time-core",
|
|
||||||
"time-macros 0.2.9",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-core"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros"
|
name = "time-macros"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -5480,12 +5684,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros"
|
name = "time-macros"
|
||||||
version = "0.2.9"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
|
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||||
dependencies = [
|
|
||||||
"time-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros-impl"
|
name = "time-macros-impl"
|
||||||
@ -5797,7 +5998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"time 0.3.22",
|
"time 0.3.9",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -6164,6 +6365,7 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|||||||
name = "veilid-cli"
|
name = "veilid-cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arboard",
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-tungstenite 0.8.0",
|
"async-tungstenite 0.8.0",
|
||||||
"bugsalot",
|
"bugsalot",
|
||||||
@ -6683,6 +6885,12 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wg"
|
name = "wg"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -6754,6 +6962,15 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-wsapoll"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -7022,6 +7239,28 @@ dependencies = [
|
|||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507"
|
||||||
|
dependencies = [
|
||||||
|
"gethostname",
|
||||||
|
"nix 0.24.3",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
"winapi-wsapoll",
|
||||||
|
"x11rb-protocol",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb-protocol"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67"
|
||||||
|
dependencies = [
|
||||||
|
"nix 0.24.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x25519-dalek"
|
name = "x25519-dalek"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
2
external/cursive-flexi-logger-view
vendored
2
external/cursive-flexi-logger-view
vendored
@ -1 +1 @@
|
|||||||
Subproject commit effa60cea24e99f294865ed325ffc57612d72785
|
Subproject commit 1eaa0814e0dd7e585b50c5d4e6e7cb9474d7a758
|
@ -11,7 +11,6 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "rt-tokio" ]
|
default = [ "rt-tokio" ]
|
||||||
macos = [ "cursive/ncurses-backend" ]
|
|
||||||
rt-async-std = [ "async-std", "veilid-tools/rt-async-std", "cursive/rt-async-std" ]
|
rt-async-std = [ "async-std", "veilid-tools/rt-async-std", "cursive/rt-async-std" ]
|
||||||
rt-tokio = [ "tokio", "tokio-util", "veilid-tools/rt-tokio", "cursive/rt-tokio" ]
|
rt-tokio = [ "tokio", "tokio-util", "veilid-tools/rt-tokio", "cursive/rt-tokio" ]
|
||||||
|
|
||||||
@ -26,6 +25,7 @@ cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
|
|||||||
# cursive-multiplex = "0.6.0"
|
# cursive-multiplex = "0.6.0"
|
||||||
# cursive_tree_view = "0.6.0"
|
# cursive_tree_view = "0.6.0"
|
||||||
cursive_table_view = "0.14.0"
|
cursive_table_view = "0.14.0"
|
||||||
|
arboard = "3.2.0"
|
||||||
# cursive-tabs = "0.5.0"
|
# cursive-tabs = "0.5.0"
|
||||||
clap = "^3"
|
clap = "^3"
|
||||||
directories = "^4"
|
directories = "^4"
|
||||||
|
@ -83,7 +83,7 @@ impl ClientApiConnection {
|
|||||||
async fn process_veilid_update(&self, update: json::JsonValue) {
|
async fn process_veilid_update(&self, update: json::JsonValue) {
|
||||||
let comproc = self.inner.lock().comproc.clone();
|
let comproc = self.inner.lock().comproc.clone();
|
||||||
let Some(kind) = update["kind"].as_str() else {
|
let Some(kind) = update["kind"].as_str() else {
|
||||||
comproc.log_message(format!("missing update kind: {}", update));
|
comproc.log_message(Level::Error, format!("missing update kind: {}", update));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match kind {
|
match kind {
|
||||||
@ -113,7 +113,7 @@ impl ClientApiConnection {
|
|||||||
comproc.update_value_change(&update);
|
comproc.update_value_change(&update);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
comproc.log_message(format!("unknown update kind: {}", update));
|
comproc.log_message(Level::Error, format!("unknown update kind: {}", update));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ impl CommandProcessor {
|
|||||||
pub fn cmd_help(&self, _rest: Option<String>, callback: UICallback) -> Result<(), String> {
|
pub fn cmd_help(&self, _rest: Option<String>, callback: UICallback) -> Result<(), String> {
|
||||||
trace!("CommandProcessor::cmd_help");
|
trace!("CommandProcessor::cmd_help");
|
||||||
self.ui_sender().add_node_event(
|
self.ui_sender().add_node_event(
|
||||||
|
Level::Info,
|
||||||
r#"Commands:
|
r#"Commands:
|
||||||
exit/quit - exit the client
|
exit/quit - exit the client
|
||||||
disconnect - disconnect the client from the Veilid node
|
disconnect - disconnect the client from the Veilid node
|
||||||
@ -186,8 +187,14 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let ui = self.ui_sender();
|
let ui = self.ui_sender();
|
||||||
spawn_detached_local(async move {
|
spawn_detached_local(async move {
|
||||||
match capi.server_debug(rest.unwrap_or_default()).await {
|
match capi.server_debug(rest.unwrap_or_default()).await {
|
||||||
Ok(output) => ui.display_string_dialog("Debug Output", output, callback),
|
Ok(output) => {
|
||||||
Err(e) => ui.display_string_dialog("Debug Error", e.to_string(), callback),
|
ui.add_node_event(Level::Debug, output);
|
||||||
|
ui.send_callback(callback);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
ui.add_node_event(Level::Error, e.to_string());
|
||||||
|
ui.send_callback(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -206,7 +213,7 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let log_level = match convert_loglevel(&rest.unwrap_or_default()) {
|
let log_level = match convert_loglevel(&rest.unwrap_or_default()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
ui.add_node_event(format!("Failed to change log level: {}", e));
|
ui.add_node_event(Level::Error, format!("Failed to change log level: {}", e));
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -239,7 +246,7 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let (id, msg) = if let Some(second) = second {
|
let (id, msg) = if let Some(second) = second {
|
||||||
let id = match u64::from_str(&first) {
|
let id = match u64::from_str(&first) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
ui.add_node_event(format!("invalid appcall id: {}", e));
|
ui.add_node_event(Level::Error, format!("invalid appcall id: {}", e));
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -249,7 +256,7 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
} else {
|
} else {
|
||||||
let id = match some_last_id {
|
let id = match some_last_id {
|
||||||
None => {
|
None => {
|
||||||
ui.add_node_event("must specify last call id".to_owned());
|
ui.add_node_event(Level::Error, "must specify last call id".to_owned());
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,7 +267,7 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let msg = if msg[0..1] == "#".to_owned() {
|
let msg = if msg[0..1] == "#".to_owned() {
|
||||||
match hex::decode(msg[1..].as_bytes().to_vec()) {
|
match hex::decode(msg[1..].as_bytes().to_vec()) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
ui.add_node_event(format!("invalid hex message: {}", e));
|
ui.add_node_event(Level::Error, format!("invalid hex message: {}", e));
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -272,7 +279,10 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let msglen = msg.len();
|
let msglen = msg.len();
|
||||||
match capi.server_appcall_reply(id, msg).await {
|
match capi.server_appcall_reply(id, msg).await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
ui.add_node_event(format!("reply sent to {} : {} bytes", id, msglen));
|
ui.add_node_event(
|
||||||
|
Level::Info,
|
||||||
|
format!("reply sent to {} : {} bytes", id, msglen),
|
||||||
|
);
|
||||||
ui.send_callback(callback);
|
ui.send_callback(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -383,8 +393,8 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
// calls into ui
|
// calls into ui
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
pub fn log_message(&self, message: String) {
|
pub fn log_message(&self, log_level: Level, message: String) {
|
||||||
self.inner().ui_sender.add_node_event(message);
|
self.inner().ui_sender.add_node_event(log_level, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_attachment(&self, attachment: &json::JsonValue) {
|
pub fn update_attachment(&self, attachment: &json::JsonValue) {
|
||||||
@ -428,25 +438,30 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !out.is_empty() {
|
if !out.is_empty() {
|
||||||
self.inner().ui_sender.add_node_event(out);
|
self.inner().ui_sender.add_node_event(Level::Info, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn update_value_change(&self, value_change: &json::JsonValue) {
|
pub fn update_value_change(&self, value_change: &json::JsonValue) {
|
||||||
let out = format!("Value change: {:?}", value_change.as_str().unwrap_or("???"));
|
let out = format!("Value change: {:?}", value_change.as_str().unwrap_or("???"));
|
||||||
self.inner().ui_sender.add_node_event(out);
|
self.inner().ui_sender.add_node_event(Level::Info, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_log(&self, log: &json::JsonValue) {
|
pub fn update_log(&self, log: &json::JsonValue) {
|
||||||
self.inner().ui_sender.add_node_event(format!(
|
let log_level =
|
||||||
"{}: {}{}",
|
Level::from_str(log["log_level"].as_str().unwrap_or("error")).unwrap_or(Level::Error);
|
||||||
log["log_level"].as_str().unwrap_or("???"),
|
self.inner().ui_sender.add_node_event(
|
||||||
log["message"].as_str().unwrap_or("???"),
|
log_level,
|
||||||
if let Some(bt) = log["backtrace"].as_str() {
|
format!(
|
||||||
format!("\nBacktrace:\n{}", bt)
|
"{}: {}{}",
|
||||||
} else {
|
log["log_level"].as_str().unwrap_or("???"),
|
||||||
"".to_owned()
|
log["message"].as_str().unwrap_or("???"),
|
||||||
}
|
if let Some(bt) = log["backtrace"].as_str() {
|
||||||
));
|
format!("\nBacktrace:\n{}", bt)
|
||||||
|
} else {
|
||||||
|
"".to_owned()
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_app_message(&self, msg: &json::JsonValue) {
|
pub fn update_app_message(&self, msg: &json::JsonValue) {
|
||||||
@ -466,9 +481,10 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
hex::encode(message)
|
hex::encode(message)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.inner()
|
self.inner().ui_sender.add_node_event(
|
||||||
.ui_sender
|
Level::Info,
|
||||||
.add_node_event(format!("AppMessage ({:?}): {}", msg["sender"], strmsg));
|
format!("AppMessage ({:?}): {}", msg["sender"], strmsg),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_app_call(&self, call: &json::JsonValue) {
|
pub fn update_app_call(&self, call: &json::JsonValue) {
|
||||||
@ -490,10 +506,13 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
|
|
||||||
let id = json_str_u64(&call["call_id"]);
|
let id = json_str_u64(&call["call_id"]);
|
||||||
|
|
||||||
self.inner().ui_sender.add_node_event(format!(
|
self.inner().ui_sender.add_node_event(
|
||||||
"AppCall ({:?}) id = {:016x} : {}",
|
Level::Info,
|
||||||
call["sender"], id, strmsg
|
format!(
|
||||||
));
|
"AppCall ({:?}) id = {:016x} : {}",
|
||||||
|
call["sender"], id, strmsg
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
self.inner_mut().last_call_id = Some(id);
|
self.inner_mut().last_call_id = Some(id);
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,14 @@ impl TableViewItem<PeerTableColumn> for json::JsonValue {
|
|||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
match column {
|
match column {
|
||||||
PeerTableColumn::NodeId => self.to_column(column).cmp(&other.to_column(column)),
|
PeerTableColumn::NodeId => self
|
||||||
PeerTableColumn::Address => self.to_column(column).cmp(&other.to_column(column)),
|
.to_column(column)
|
||||||
|
.to_ascii_lowercase()
|
||||||
|
.cmp(&other.to_column(column).to_ascii_lowercase()),
|
||||||
|
PeerTableColumn::Address => self
|
||||||
|
.to_column(column)
|
||||||
|
.to_ascii_lowercase()
|
||||||
|
.cmp(&other.to_column(column).to_ascii_lowercase()),
|
||||||
PeerTableColumn::LatencyAvg => json_str_u64(&self["peer_stats"]["latency"]["average"])
|
PeerTableColumn::LatencyAvg => json_str_u64(&self["peer_stats"]["latency"]["average"])
|
||||||
.cmp(&json_str_u64(&other["peer_stats"]["latency"]["average"])),
|
.cmp(&json_str_u64(&other["peer_stats"]["latency"]["average"])),
|
||||||
PeerTableColumn::TransferDownAvg => {
|
PeerTableColumn::TransferDownAvg => {
|
||||||
|
@ -27,23 +27,23 @@ interface:
|
|||||||
shadow: false
|
shadow: false
|
||||||
borders: "simple"
|
borders: "simple"
|
||||||
colors:
|
colors:
|
||||||
background : "#333D3D"
|
background : "black"
|
||||||
shadow : "#000000"
|
shadow : "black"
|
||||||
view : "#1c2323"
|
view : "black"
|
||||||
primary : "#a6d8d3"
|
primary : "light cyan"
|
||||||
secondary : "#8cb4b7"
|
secondary : "cyan"
|
||||||
tertiary : "#eeeeee"
|
tertiary : "green"
|
||||||
title_primary : "#f93fbd"
|
title_primary : "light magenta"
|
||||||
title_secondary : "#ff0000"
|
title_secondary : "magenta"
|
||||||
highlight : "#f93fbd"
|
highlight : "light white"
|
||||||
highlight_inactive : "#a6d8d3"
|
highlight_inactive : "white"
|
||||||
highlight_text : "#333333"
|
highlight_text : "black"
|
||||||
log_colors:
|
log_colors:
|
||||||
trace : "#707070"
|
trace : "light blue"
|
||||||
debug : "#a0a0a0"
|
debug : "light green"
|
||||||
info : "#5cd3c6"
|
info : "white"
|
||||||
warn : "#fedc50"
|
warn : "light yellow"
|
||||||
error : "#ff4a15"
|
error : "light red"
|
||||||
"###
|
"###
|
||||||
.replace(
|
.replace(
|
||||||
"%LOGGING_FILE_DIRECTORY%",
|
"%LOGGING_FILE_DIRECTORY%",
|
||||||
|
@ -12,10 +12,10 @@ use cursive::views::*;
|
|||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
use cursive::CursiveRunnable;
|
use cursive::CursiveRunnable;
|
||||||
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
||||||
//use cursive_multiplex::*;
|
// use cursive_multiplex::*;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::io::Write;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
///
|
///
|
||||||
struct Dirty<T> {
|
struct Dirty<T> {
|
||||||
@ -311,8 +311,7 @@ impl UI {
|
|||||||
.button("Close", move |s| {
|
.button("Close", move |s| {
|
||||||
s.pop_layer();
|
s.pop_layer();
|
||||||
close_cb(s);
|
close_cb(s);
|
||||||
}), //.wrap_with(CircularFocus::new)
|
}),
|
||||||
//.wrap_tab(),
|
|
||||||
);
|
);
|
||||||
s.set_global_callback(cursive::event::Event::Key(Key::Esc), move |s| {
|
s.set_global_callback(cursive::event::Event::Key(Key::Esc), move |s| {
|
||||||
s.set_global_callback(cursive::event::Event::Key(Key::Esc), UI::quit_handler);
|
s.set_global_callback(cursive::event::Event::Key(Key::Esc), UI::quit_handler);
|
||||||
@ -346,18 +345,19 @@ impl UI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// run command
|
// run command
|
||||||
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
|
||||||
|
cursive_flexi_logger_view::parse_lines_to_log(
|
||||||
|
ColorStyle::primary().into(),
|
||||||
format!("> {}", text),
|
format!("> {}", text),
|
||||||
ColorStyle::primary(),
|
);
|
||||||
));
|
|
||||||
match Self::run_command(s, text) {
|
match Self::run_command(s, text) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let color = *Self::inner_mut(s).log_colors.get(&Level::Error).unwrap();
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Error).unwrap();
|
||||||
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
cursive_flexi_logger_view::parse_lines_to_log(
|
||||||
|
color.into(),
|
||||||
format!(" Error: {}", e),
|
format!(" Error: {}", e),
|
||||||
color,
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// save to history unless it's a duplicate
|
// save to history unless it's a duplicate
|
||||||
@ -455,6 +455,55 @@ impl UI {
|
|||||||
Self::command_processor(s).start_connection();
|
Self::command_processor(s).start_connection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_to_clipboard<S: AsRef<str>>(s: &mut Cursive, text: S) {
|
||||||
|
if let Ok(mut clipboard) = arboard::Clipboard::new() {
|
||||||
|
// X11/Wayland/other system copy
|
||||||
|
if clipboard.set_text(text.as_ref()).is_ok() {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
|
||||||
|
cursive_flexi_logger_view::parse_lines_to_log(
|
||||||
|
color.into(),
|
||||||
|
format!(">> Copied: {}", text.as_ref()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Warn).unwrap();
|
||||||
|
cursive_flexi_logger_view::parse_lines_to_log(
|
||||||
|
color.into(),
|
||||||
|
format!(">> Could not copy to clipboard"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OSC52 clipboard copy for terminals
|
||||||
|
if std::io::stdout()
|
||||||
|
.write_all(
|
||||||
|
format!(
|
||||||
|
"\x1B]52;c;{}\x07",
|
||||||
|
data_encoding::BASE64.encode(text.as_ref().as_bytes()),
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
if std::io::stdout().flush().is_ok() {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
|
||||||
|
cursive_flexi_logger_view::parse_lines_to_log(
|
||||||
|
color.into(),
|
||||||
|
format!(">> Copied: {}", text.as_ref()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_submit_peers_table_view(s: &mut Cursive, _row: usize, index: usize) {
|
||||||
|
let peers_table_view = UI::peers(s);
|
||||||
|
let node_id = peers_table_view
|
||||||
|
.borrow_item(index)
|
||||||
|
.map(|j| j["node_ids"][0].to_string());
|
||||||
|
if let Some(node_id) = node_id {
|
||||||
|
Self::copy_to_clipboard(s, node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn show_connection_dialog(s: &mut Cursive, state: ConnectionState) -> bool {
|
fn show_connection_dialog(s: &mut Cursive, state: ConnectionState) -> bool {
|
||||||
let mut inner = Self::inner_mut(s);
|
let mut inner = Self::inner_mut(s);
|
||||||
|
|
||||||
@ -644,7 +693,28 @@ impl UI {
|
|||||||
fn refresh_peers(s: &mut Cursive) {
|
fn refresh_peers(s: &mut Cursive) {
|
||||||
let mut peers = UI::peers(s);
|
let mut peers = UI::peers(s);
|
||||||
let inner = Self::inner_mut(s);
|
let inner = Self::inner_mut(s);
|
||||||
|
let sel_item = peers.item();
|
||||||
|
let sel_item_text = peers
|
||||||
|
.item()
|
||||||
|
.map(|x| peers.borrow_items()[x]["node_ids"][0].clone());
|
||||||
|
|
||||||
peers.set_items_stable(inner.ui_state.peers_state.get().clone());
|
peers.set_items_stable(inner.ui_state.peers_state.get().clone());
|
||||||
|
|
||||||
|
let mut selected = false;
|
||||||
|
if let Some(sel_item_text) = sel_item_text {
|
||||||
|
// First select by name
|
||||||
|
for n in 0..peers.borrow_items().len() {
|
||||||
|
if peers.borrow_items()[n]["node_ids"][0] == sel_item_text {
|
||||||
|
peers.set_selected_item(n);
|
||||||
|
selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !selected {
|
||||||
|
if let Some(sel_item) = sel_item {
|
||||||
|
peers.set_selected_item(sel_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_cb(s: &mut Cursive) {
|
fn update_cb(s: &mut Cursive) {
|
||||||
@ -707,9 +777,6 @@ impl UI {
|
|||||||
// Instantiate the cursive runnable
|
// Instantiate the cursive runnable
|
||||||
let runnable = CursiveRunnable::new(
|
let runnable = CursiveRunnable::new(
|
||||||
|| -> Result<Box<dyn cursive::backend::Backend>, Box<DumbError>> {
|
|| -> Result<Box<dyn cursive::backend::Backend>, Box<DumbError>> {
|
||||||
#[cfg(feature = "macos")]
|
|
||||||
let backend = cursive::backends::curses::n::Backend::init().unwrap();
|
|
||||||
#[cfg(not(feature = "macos"))]
|
|
||||||
let backend = cursive::backends::crossterm::Backend::init().unwrap();
|
let backend = cursive::backends::crossterm::Backend::init().unwrap();
|
||||||
let buffered_backend = cursive_buffered_backend::BufferedBackend::new(backend);
|
let buffered_backend = cursive_buffered_backend::BufferedBackend::new(backend);
|
||||||
Ok(Box::new(buffered_backend))
|
Ok(Box::new(buffered_backend))
|
||||||
@ -737,6 +804,11 @@ impl UI {
|
|||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ui_sender = UISender {
|
||||||
|
inner: this.inner.clone(),
|
||||||
|
cb_sink,
|
||||||
|
};
|
||||||
|
|
||||||
let mut inner = this.inner.lock();
|
let mut inner = this.inner.lock();
|
||||||
|
|
||||||
// Make the inner object accessible in callbacks easily
|
// Make the inner object accessible in callbacks easily
|
||||||
@ -750,12 +822,14 @@ impl UI {
|
|||||||
.with_name("node-events-panel")
|
.with_name("node-events-panel")
|
||||||
.full_screen();
|
.full_screen();
|
||||||
|
|
||||||
let peers_table_view = PeersTableView::new()
|
let mut peers_table_view = PeersTableView::new()
|
||||||
.column(PeerTableColumn::NodeId, "Node Id", |c| c.width(48))
|
.column(PeerTableColumn::NodeId, "Node Id", |c| c.width(48))
|
||||||
.column(PeerTableColumn::Address, "Address", |c| c)
|
.column(PeerTableColumn::Address, "Address", |c| c)
|
||||||
.column(PeerTableColumn::LatencyAvg, "Ping", |c| c.width(8))
|
.column(PeerTableColumn::LatencyAvg, "Ping", |c| c.width(8))
|
||||||
.column(PeerTableColumn::TransferDownAvg, "Down", |c| c.width(8))
|
.column(PeerTableColumn::TransferDownAvg, "Down", |c| c.width(8))
|
||||||
.column(PeerTableColumn::TransferUpAvg, "Up", |c| c.width(8))
|
.column(PeerTableColumn::TransferUpAvg, "Up", |c| c.width(8));
|
||||||
|
peers_table_view.set_on_submit(UI::on_submit_peers_table_view);
|
||||||
|
let peers_table_view = peers_table_view
|
||||||
.with_name("peers")
|
.with_name("peers")
|
||||||
.full_width()
|
.full_width()
|
||||||
.min_height(8);
|
.min_height(8);
|
||||||
@ -832,8 +906,7 @@ impl UI {
|
|||||||
|
|
||||||
drop(inner);
|
drop(inner);
|
||||||
|
|
||||||
let inner = this.inner.clone();
|
(this, ui_sender)
|
||||||
(this, UISender { inner, cb_sink })
|
|
||||||
}
|
}
|
||||||
pub fn cursive_flexi_logger(&self) -> Box<CursiveLogWriter> {
|
pub fn cursive_flexi_logger(&self) -> Box<CursiveLogWriter> {
|
||||||
let mut flv = cursive_flexi_logger_view::cursive_flexi_logger(self.siv.cb_sink().clone());
|
let mut flv = cursive_flexi_logger_view::cursive_flexi_logger(self.siv.cb_sink().clone());
|
||||||
@ -906,7 +979,7 @@ impl UISender {
|
|||||||
started: bool,
|
started: bool,
|
||||||
bps_down: u64,
|
bps_down: u64,
|
||||||
bps_up: u64,
|
bps_up: u64,
|
||||||
peers: Vec<json::JsonValue>,
|
mut peers: Vec<json::JsonValue>,
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
@ -915,6 +988,11 @@ impl UISender {
|
|||||||
((bps_down as f64) / 1000.0f64) as f32,
|
((bps_down as f64) / 1000.0f64) as f32,
|
||||||
((bps_up as f64) / 1000.0f64) as f32,
|
((bps_up as f64) / 1000.0f64) as f32,
|
||||||
));
|
));
|
||||||
|
peers.sort_by(|a, b| {
|
||||||
|
a["node_ids"][0]
|
||||||
|
.to_string()
|
||||||
|
.cmp(&b["node_ids"][0].to_string())
|
||||||
|
});
|
||||||
inner.ui_state.peers_state.set(peers);
|
inner.ui_state.peers_state.set(peers);
|
||||||
}
|
}
|
||||||
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
||||||
@ -922,10 +1000,18 @@ impl UISender {
|
|||||||
pub fn set_config(&mut self, config: &json::JsonValue) {
|
pub fn set_config(&mut self, config: &json::JsonValue) {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
inner
|
let node_ids = &config["network"]["routing_table"]["node_id"];
|
||||||
.ui_state
|
|
||||||
.node_id
|
let mut node_id_str = String::new();
|
||||||
.set(config["network"]["routing_table"]["node_id"].to_string());
|
for l in 0..node_ids.len() {
|
||||||
|
let nid = &node_ids[l];
|
||||||
|
if !node_id_str.is_empty() {
|
||||||
|
node_id_str.push_str(" ");
|
||||||
|
}
|
||||||
|
node_id_str.push_str(nid.to_string().as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
inner.ui_state.node_id.set(node_id_str);
|
||||||
}
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
{
|
{
|
||||||
@ -935,17 +1021,11 @@ impl UISender {
|
|||||||
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_node_event(&self, event: String) {
|
pub fn add_node_event(&self, log_color: Level, event: String) {
|
||||||
{
|
{
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
let color = *inner.log_colors.get(&Level::Info).unwrap();
|
let color = *inner.log_colors.get(&log_color).unwrap();
|
||||||
let mut starting_style: Style = color.into();
|
cursive_flexi_logger_view::parse_lines_to_log(color.into(), event);
|
||||||
for line in event.lines() {
|
|
||||||
let (spanned_string, end_style) =
|
|
||||||
cursive::utils::markup::ansi::parse_with_starting_style(starting_style, line);
|
|
||||||
cursive_flexi_logger_view::push_to_log(spanned_string);
|
|
||||||
starting_style = end_style;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
let _ = self.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ macro_rules! byte_array_type {
|
|||||||
Self { bytes }
|
Self { bytes }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Big endian bit ordering
|
||||||
pub fn bit(&self, index: usize) -> bool {
|
pub fn bit(&self, index: usize) -> bool {
|
||||||
assert!(index < ($size * 8));
|
assert!(index < ($size * 8));
|
||||||
let bi = index / 8;
|
let bi = index / 8;
|
||||||
@ -152,6 +153,7 @@ macro_rules! byte_array_type {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Big endian nibble ordering
|
||||||
pub fn nibble(&self, index: usize) -> u8 {
|
pub fn nibble(&self, index: usize) -> u8 {
|
||||||
assert!(index < ($size * 2));
|
assert!(index < ($size * 2));
|
||||||
let bi = index / 2;
|
let bi = index / 2;
|
||||||
|
@ -353,10 +353,40 @@ async fn test_operations(vcrypto: CryptoSystemVersion) {
|
|||||||
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn test_crypto_key_ordering() {
|
||||||
|
let k1 = CryptoKey::new([
|
||||||
|
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
let k2 = CryptoKey::new([
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
let k3 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 128,
|
||||||
|
]);
|
||||||
|
let k4 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1,
|
||||||
|
]);
|
||||||
|
let k5 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(k2 < k1);
|
||||||
|
assert!(k3 < k2);
|
||||||
|
assert!(k4 < k3);
|
||||||
|
assert!(k5 < k4);
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let api = crypto_tests_startup().await;
|
let api = crypto_tests_startup().await;
|
||||||
let crypto = api.crypto().unwrap();
|
let crypto = api.crypto().unwrap();
|
||||||
|
|
||||||
|
test_crypto_key_ordering().await;
|
||||||
|
|
||||||
// Test versions
|
// Test versions
|
||||||
for v in VALID_CRYPTO_KINDS {
|
for v in VALID_CRYPTO_KINDS {
|
||||||
let vcrypto = crypto.get(v).unwrap();
|
let vcrypto = crypto.get(v).unwrap();
|
||||||
|
@ -51,6 +51,7 @@ impl RoutingTable {
|
|||||||
return NetworkResult::invalid_message("unsupported cryptosystem");
|
return NetworkResult::invalid_message("unsupported cryptosystem");
|
||||||
};
|
};
|
||||||
let own_distance = vcrypto.distance(&own_node_id.value, &key.value);
|
let own_distance = vcrypto.distance(&own_node_id.value, &key.value);
|
||||||
|
let vcrypto2 = vcrypto.clone();
|
||||||
|
|
||||||
let filter = Box::new(
|
let filter = Box::new(
|
||||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||||
@ -98,6 +99,46 @@ impl RoutingTable {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// xxx test
|
||||||
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
|
let valid = match Self::verify_peers_closer(vcrypto2, own_node_id, key, &closest_nodes) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
panic!("missing cryptosystem in peers node ids: {}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !valid {
|
||||||
|
panic!("non-closer peers returned");
|
||||||
|
}
|
||||||
|
|
||||||
NetworkResult::value(closest_nodes)
|
NetworkResult::value(closest_nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if set of peers is closer to key_near than key_far
|
||||||
|
pub(crate) fn verify_peers_closer(
|
||||||
|
vcrypto: CryptoSystemVersion,
|
||||||
|
key_far: TypedKey,
|
||||||
|
key_near: TypedKey,
|
||||||
|
peers: &[PeerInfo],
|
||||||
|
) -> EyreResult<bool> {
|
||||||
|
let kind = vcrypto.kind();
|
||||||
|
|
||||||
|
if key_far.kind != kind || key_near.kind != kind {
|
||||||
|
bail!("keys all need the same cryptosystem");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut closer = true;
|
||||||
|
for peer in peers {
|
||||||
|
let Some(key_peer) = peer.node_ids().get(kind) else {
|
||||||
|
bail!("peers need to have a key with the same cryptosystem");
|
||||||
|
};
|
||||||
|
let d_near = vcrypto.distance(&key_near.value, &key_peer.value);
|
||||||
|
let d_far = vcrypto.distance(&key_far.value, &key_peer.value);
|
||||||
|
if d_far < d_near {
|
||||||
|
closer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(closer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,13 @@ pub enum Destination {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Destination {
|
impl Destination {
|
||||||
|
pub fn target(&self) -> Option<NodeRef> {
|
||||||
|
match self {
|
||||||
|
Destination::Direct { target, safety_selection: _ } => Some(target.clone()),
|
||||||
|
Destination::Relay { relay:_, target, safety_selection: _ } => Some(target.clone()),
|
||||||
|
Destination::PrivateRoute { private_route:_, safety_selection:_ } => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn direct(target: NodeRef) -> Self {
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
let sequencing = target.sequencing();
|
let sequencing = target.sequencing();
|
||||||
Self::Direct {
|
Self::Direct {
|
||||||
|
@ -88,6 +88,7 @@ where
|
|||||||
for cn in &ctx.closest_nodes {
|
for cn in &ctx.closest_nodes {
|
||||||
if cn.same_entry(&nn) {
|
if cn.same_entry(&nn) {
|
||||||
dup = true;
|
dup = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !dup {
|
if !dup {
|
||||||
@ -125,6 +126,7 @@ where
|
|||||||
// New fanout call candidate found
|
// New fanout call candidate found
|
||||||
next_node = Some(cn.clone());
|
next_node = Some(cn.clone());
|
||||||
ctx.called_nodes.add(key);
|
ctx.called_nodes.add(key);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ impl RPCProcessor {
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// Determine if a SignedNodeInfo can be placed into the specified routing domain
|
/// Determine if a SignedNodeInfo can be placed into the specified routing domain
|
||||||
fn filter_node_info(
|
fn verify_node_info(
|
||||||
&self,
|
&self,
|
||||||
routing_domain: RoutingDomain,
|
routing_domain: RoutingDomain,
|
||||||
signed_node_info: &SignedNodeInfo,
|
signed_node_info: &SignedNodeInfo,
|
||||||
@ -1348,7 +1348,7 @@ impl RPCProcessor {
|
|||||||
// Ensure the sender peer info is for the actual sender specified in the envelope
|
// Ensure the sender peer info is for the actual sender specified in the envelope
|
||||||
|
|
||||||
// Sender PeerInfo was specified, update our routing table with it
|
// Sender PeerInfo was specified, update our routing table with it
|
||||||
if !self.filter_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
if !self.verify_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"sender peerinfo has invalid peer scope",
|
"sender peerinfo has invalid peer scope",
|
||||||
));
|
));
|
||||||
|
@ -29,9 +29,9 @@ impl RPCProcessor {
|
|||||||
let app_call_a = match kind {
|
let app_call_a = match kind {
|
||||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||||
RPCAnswerDetail::AppCallA(a) => a,
|
RPCAnswerDetail::AppCallA(a) => a,
|
||||||
_ => return Err(RPCError::invalid_format("not an appcall answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an appcall answer")),
|
||||||
},
|
},
|
||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let a_message = app_call_a.destructure();
|
let a_message = app_call_a.destructure();
|
||||||
|
@ -46,17 +46,17 @@ impl RPCProcessor {
|
|||||||
let find_node_a = match kind {
|
let find_node_a = match kind {
|
||||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||||
RPCAnswerDetail::FindNodeA(a) => a,
|
RPCAnswerDetail::FindNodeA(a) => a,
|
||||||
_ => return Err(RPCError::invalid_format("not a find_node answer")),
|
_ => return Ok(NetworkResult::invalid_message("not a find_node answer")),
|
||||||
},
|
},
|
||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify peers are in the correct peer scope
|
// Verify peers are in the correct peer scope
|
||||||
let peers = find_node_a.destructure();
|
let peers = find_node_a.destructure();
|
||||||
|
|
||||||
for peer_info in &peers {
|
for peer_info in &peers {
|
||||||
if !self.filter_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
if !self.verify_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
||||||
return Err(RPCError::invalid_format(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"find_node response has invalid peer scope",
|
"find_node response has invalid peer scope",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -24,32 +24,32 @@ impl RPCProcessor {
|
|||||||
last_descriptor: Option<SignedValueDescriptor>,
|
last_descriptor: Option<SignedValueDescriptor>,
|
||||||
) -> Result<NetworkResult<Answer<GetValueAnswer>>, RPCError> {
|
) -> Result<NetworkResult<Answer<GetValueAnswer>>, RPCError> {
|
||||||
// Ensure destination never has a private route
|
// Ensure destination never has a private route
|
||||||
if matches!(
|
// and get the target noderef so we can validate the response
|
||||||
dest,
|
let Some(target) = dest.target() else {
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route: _,
|
|
||||||
safety_selection: _
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return Err(RPCError::internal(
|
return Err(RPCError::internal(
|
||||||
"Never send get value requests over private routes",
|
"Never send set value requests over private routes",
|
||||||
));
|
));
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Get the target node id
|
||||||
|
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||||
|
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||||
|
};
|
||||||
|
let Some(target_node_id) = target.node_ids().get(key.kind) else {
|
||||||
|
return Err(RPCError::internal("No node id for crypto kind"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the getvalue question
|
||||||
let get_value_q = RPCOperationGetValueQ::new(key, subkey, last_descriptor.is_none());
|
let get_value_q = RPCOperationGetValueQ::new(key, subkey, last_descriptor.is_none());
|
||||||
let question = RPCQuestion::new(
|
let question = RPCQuestion::new(
|
||||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||||
RPCQuestionDetail::GetValueQ(get_value_q),
|
RPCQuestionDetail::GetValueQ(get_value_q),
|
||||||
);
|
);
|
||||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
|
||||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send the getvalue question
|
|
||||||
let question_context = QuestionContext::GetValue(ValidateGetValueContext {
|
let question_context = QuestionContext::GetValue(ValidateGetValueContext {
|
||||||
last_descriptor,
|
last_descriptor,
|
||||||
subkey,
|
subkey,
|
||||||
vcrypto,
|
vcrypto: vcrypto.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let waitable_reply = network_result_try!(
|
let waitable_reply = network_result_try!(
|
||||||
@ -68,13 +68,27 @@ impl RPCProcessor {
|
|||||||
let get_value_a = match kind {
|
let get_value_a = match kind {
|
||||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||||
RPCAnswerDetail::GetValueA(a) => a,
|
RPCAnswerDetail::GetValueA(a) => a,
|
||||||
_ => return Err(RPCError::invalid_format("not a getvalue answer")),
|
_ => return Ok(NetworkResult::invalid_message("not a getvalue answer")),
|
||||||
},
|
},
|
||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (value, peers, descriptor) = get_value_a.destructure();
|
let (value, peers, descriptor) = get_value_a.destructure();
|
||||||
|
|
||||||
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
|
let valid = match RoutingTable::verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
|
"missing cryptosystem in peers node ids: {}",
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !valid {
|
||||||
|
return Ok(NetworkResult::invalid_message("non-closer peers returned"));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(NetworkResult::value(Answer::new(
|
Ok(NetworkResult::value(Answer::new(
|
||||||
latency,
|
latency,
|
||||||
GetValueAnswer {
|
GetValueAnswer {
|
||||||
|
@ -62,7 +62,7 @@ impl RPCProcessor {
|
|||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
// Make sure hop count makes sense
|
// Make sure hop count makes sense
|
||||||
if next_private_route.hop_count as usize > self.unlocked_inner.max_route_hop_count {
|
if next_private_route.hop_count as usize > self.unlocked_inner.max_route_hop_count {
|
||||||
return Err(RPCError::protocol(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"Private route hop count too high to process",
|
"Private route hop count too high to process",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -110,9 +110,9 @@ impl RPCProcessor {
|
|||||||
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
||||||
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
||||||
let node_id_secret = self.routing_table.node_id_secret_key(remote_sr_pubkey.kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(remote_sr_pubkey.kind);
|
||||||
let dh_secret = vcrypto
|
let Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &node_id_secret) else {
|
||||||
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
return Ok(NetworkResult::invalid_message("dh failed for remote safety route for safety routed operation"));
|
||||||
.map_err(RPCError::protocol)?;
|
};
|
||||||
let body = match vcrypto.decrypt_aead(
|
let body = match vcrypto.decrypt_aead(
|
||||||
routed_operation.data(),
|
routed_operation.data(),
|
||||||
routed_operation.nonce(),
|
routed_operation.nonce(),
|
||||||
@ -183,19 +183,18 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
||||||
// xxx: punish nodes that send messages that fail to decrypt eventually. How to do this for private routes?
|
// xxx: punish nodes that send messages that fail to decrypt eventually. How to do this for private routes?
|
||||||
let dh_secret = vcrypto
|
let Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &secret_key) else {
|
||||||
.cached_dh(&remote_sr_pubkey.value, &secret_key)
|
return Ok(NetworkResult::invalid_message("dh failed for remote safety route for private routed operation"));
|
||||||
.map_err(RPCError::protocol)?;
|
};
|
||||||
let body = vcrypto
|
let Ok(body) = vcrypto
|
||||||
.decrypt_aead(
|
.decrypt_aead(
|
||||||
routed_operation.data(),
|
routed_operation.data(),
|
||||||
routed_operation.nonce(),
|
routed_operation.nonce(),
|
||||||
&dh_secret,
|
&dh_secret,
|
||||||
None,
|
None,
|
||||||
)
|
) else {
|
||||||
.map_err(RPCError::map_internal(
|
return Ok(NetworkResult::invalid_message("decryption of routed operation failed"));
|
||||||
"decryption of routed operation failed",
|
};
|
||||||
))?;
|
|
||||||
|
|
||||||
// Pass message to RPC system
|
// Pass message to RPC system
|
||||||
self.enqueue_private_routed_message(
|
self.enqueue_private_routed_message(
|
||||||
@ -401,37 +400,48 @@ impl RPCProcessor {
|
|||||||
SafetyRouteHops::Data(ref route_hop_data) => {
|
SafetyRouteHops::Data(ref route_hop_data) => {
|
||||||
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
||||||
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||||
let dh_secret = vcrypto
|
let Ok(dh_secret) = vcrypto
|
||||||
.cached_dh(&safety_route.public_key.value, &node_id_secret)
|
.cached_dh(&safety_route.public_key.value, &node_id_secret) else {
|
||||||
.map_err(RPCError::protocol)?;
|
return Ok(NetworkResult::invalid_message("dh failed for safety route hop"));
|
||||||
let mut dec_blob_data = vcrypto
|
};
|
||||||
|
let Ok(mut dec_blob_data) = vcrypto
|
||||||
.decrypt_aead(
|
.decrypt_aead(
|
||||||
&route_hop_data.blob,
|
&route_hop_data.blob,
|
||||||
&route_hop_data.nonce,
|
&route_hop_data.nonce,
|
||||||
&dh_secret,
|
&dh_secret,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.map_err(RPCError::protocol)?;
|
else {
|
||||||
|
return Ok(NetworkResult::invalid_message("failed to decrypt route hop data for safety route hop"));
|
||||||
|
};
|
||||||
|
|
||||||
// See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop
|
// See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop
|
||||||
let Some(dec_blob_tag) = dec_blob_data.pop() else {
|
let Some(dec_blob_tag) = dec_blob_data.pop() else {
|
||||||
return Ok(NetworkResult::invalid_message("no bytes in blob"));
|
return Ok(NetworkResult::invalid_message("no bytes in blob"));
|
||||||
};
|
};
|
||||||
|
|
||||||
let dec_blob_reader = RPCMessageData::new(dec_blob_data).get_reader()?;
|
let Ok(dec_blob_reader) = RPCMessageData::new(dec_blob_data).get_reader() else {
|
||||||
|
return Ok(NetworkResult::invalid_message("Failed to decode RPCMessageData from blob"));
|
||||||
|
};
|
||||||
|
|
||||||
// Decode the blob appropriately
|
// Decode the blob appropriately
|
||||||
if dec_blob_tag == 1 {
|
if dec_blob_tag == 1 {
|
||||||
// PrivateRoute
|
// PrivateRoute
|
||||||
let private_route = {
|
let private_route = {
|
||||||
let pr_reader = dec_blob_reader
|
let Ok(pr_reader) = dec_blob_reader
|
||||||
.get_root::<veilid_capnp::private_route::Reader>()
|
.get_root::<veilid_capnp::private_route::Reader>() else {
|
||||||
.map_err(RPCError::protocol)?;
|
return Ok(NetworkResult::invalid_message("failed to get private route reader for blob"));
|
||||||
decode_private_route(&pr_reader)?
|
};
|
||||||
|
let Ok(private_route) = decode_private_route(&pr_reader) else {
|
||||||
|
return Ok(NetworkResult::invalid_message("failed to decode private route"));
|
||||||
|
};
|
||||||
|
private_route
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validate the private route
|
// Validate the private route
|
||||||
private_route.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
if let Err(_) = private_route.validate(self.crypto.clone()) {
|
||||||
|
return Ok(NetworkResult::invalid_message("failed to validate private route"));
|
||||||
|
}
|
||||||
|
|
||||||
// Switching from full safety route to private route first hop
|
// Switching from full safety route to private route first hop
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
@ -445,14 +455,20 @@ impl RPCProcessor {
|
|||||||
} else if dec_blob_tag == 0 {
|
} else if dec_blob_tag == 0 {
|
||||||
// RouteHop
|
// RouteHop
|
||||||
let route_hop = {
|
let route_hop = {
|
||||||
let rh_reader = dec_blob_reader
|
let Ok(rh_reader) = dec_blob_reader
|
||||||
.get_root::<veilid_capnp::route_hop::Reader>()
|
.get_root::<veilid_capnp::route_hop::Reader>() else {
|
||||||
.map_err(RPCError::protocol)?;
|
return Ok(NetworkResult::invalid_message("failed to get route hop reader for blob"));
|
||||||
decode_route_hop(&rh_reader)?
|
};
|
||||||
|
let Ok(route_hop) = decode_route_hop(&rh_reader) else {
|
||||||
|
return Ok(NetworkResult::invalid_message("failed to decode route hop"));
|
||||||
|
};
|
||||||
|
route_hop
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validate the route hop
|
// Validate the route hop
|
||||||
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
if let Err(_) = route_hop.validate(self.crypto.clone()) {
|
||||||
|
return Ok(NetworkResult::invalid_message("failed to validate route hop"));
|
||||||
|
}
|
||||||
|
|
||||||
// Continue the full safety route with another hop
|
// Continue the full safety route with another hop
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
|
@ -14,7 +14,6 @@ impl RPCProcessor {
|
|||||||
/// Because this leaks information about the identity of the node itself,
|
/// Because this leaks information about the identity of the node itself,
|
||||||
/// replying to this request received over a private route will leak
|
/// replying to this request received over a private route will leak
|
||||||
/// the identity of the node and defeat the private route.
|
/// the identity of the node and defeat the private route.
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
|
||||||
pub async fn rpc_call_set_value(
|
pub async fn rpc_call_set_value(
|
||||||
self,
|
self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
@ -25,18 +24,22 @@ impl RPCProcessor {
|
|||||||
send_descriptor: bool,
|
send_descriptor: bool,
|
||||||
) -> Result<NetworkResult<Answer<SetValueAnswer>>, RPCError> {
|
) -> Result<NetworkResult<Answer<SetValueAnswer>>, RPCError> {
|
||||||
// Ensure destination never has a private route
|
// Ensure destination never has a private route
|
||||||
if matches!(
|
// and get the target noderef so we can validate the response
|
||||||
dest,
|
let Some(target) = dest.target() else {
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route: _,
|
|
||||||
safety_selection: _
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return Err(RPCError::internal(
|
return Err(RPCError::internal(
|
||||||
"Never send set value requests over private routes",
|
"Never send set value requests over private routes",
|
||||||
));
|
));
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Get the target node id
|
||||||
|
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||||
|
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||||
|
};
|
||||||
|
let Some(target_node_id) = target.node_ids().get(key.kind) else {
|
||||||
|
return Err(RPCError::internal("No node id for crypto kind"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the setvalue question
|
||||||
let set_value_q = RPCOperationSetValueQ::new(
|
let set_value_q = RPCOperationSetValueQ::new(
|
||||||
key,
|
key,
|
||||||
subkey,
|
subkey,
|
||||||
@ -51,17 +54,11 @@ impl RPCProcessor {
|
|||||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||||
RPCQuestionDetail::SetValueQ(set_value_q),
|
RPCQuestionDetail::SetValueQ(set_value_q),
|
||||||
);
|
);
|
||||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
|
||||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send the setvalue question
|
|
||||||
let question_context = QuestionContext::SetValue(ValidateSetValueContext {
|
let question_context = QuestionContext::SetValue(ValidateSetValueContext {
|
||||||
descriptor,
|
descriptor,
|
||||||
subkey,
|
subkey,
|
||||||
vcrypto,
|
vcrypto: vcrypto.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let waitable_reply = network_result_try!(
|
let waitable_reply = network_result_try!(
|
||||||
self.question(dest, question, Some(question_context))
|
self.question(dest, question, Some(question_context))
|
||||||
.await?
|
.await?
|
||||||
@ -78,13 +75,27 @@ impl RPCProcessor {
|
|||||||
let set_value_a = match kind {
|
let set_value_a = match kind {
|
||||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||||
RPCAnswerDetail::SetValueA(a) => a,
|
RPCAnswerDetail::SetValueA(a) => a,
|
||||||
_ => return Err(RPCError::invalid_format("not a setvalue answer")),
|
_ => return Ok(NetworkResult::invalid_message("not a setvalue answer")),
|
||||||
},
|
},
|
||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (set, value, peers) = set_value_a.destructure();
|
let (set, value, peers) = set_value_a.destructure();
|
||||||
|
|
||||||
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
|
let valid = match RoutingTable::verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
|
"missing cryptosystem in peers node ids: {}",
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !valid {
|
||||||
|
return Ok(NetworkResult::invalid_message("non-closer peers returned"));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(NetworkResult::value(Answer::new(
|
Ok(NetworkResult::value(Answer::new(
|
||||||
latency,
|
latency,
|
||||||
SetValueAnswer { set, value, peers },
|
SetValueAnswer { set, value, peers },
|
||||||
|
@ -119,9 +119,9 @@ impl RPCProcessor {
|
|||||||
let status_a = match kind {
|
let status_a = match kind {
|
||||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||||
RPCAnswerDetail::StatusA(a) => a,
|
RPCAnswerDetail::StatusA(a) => a,
|
||||||
_ => return Err(RPCError::invalid_format("not a status answer")),
|
_ => return Ok(NetworkResult::invalid_message("not a status answer")),
|
||||||
},
|
},
|
||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||||
};
|
};
|
||||||
let (a_node_status, sender_info) = status_a.destructure();
|
let (a_node_status, sender_info) = status_a.destructure();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// The context of the do_get_value operation
|
/// The context of the outbound_get_value operation
|
||||||
struct DoGetValueContext {
|
struct OutboundGetValueContext {
|
||||||
/// The latest value of the subkey, may be the value passed in
|
/// The latest value of the subkey, may be the value passed in
|
||||||
pub value: Option<SignedValueData>,
|
pub value: Option<SignedValueData>,
|
||||||
/// The consensus count for the value we have received
|
/// The consensus count for the value we have received
|
||||||
@ -42,7 +42,7 @@ impl StorageManager {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let context = Arc::new(Mutex::new(DoGetValueContext {
|
let context = Arc::new(Mutex::new(OutboundGetValueContext {
|
||||||
value: last_subkey_result.value,
|
value: last_subkey_result.value,
|
||||||
value_count: 0,
|
value_count: 0,
|
||||||
descriptor: last_subkey_result.descriptor.clone(),
|
descriptor: last_subkey_result.descriptor.clone(),
|
||||||
|
@ -341,7 +341,6 @@ impl StorageManager {
|
|||||||
} else {
|
} else {
|
||||||
ValueData::new(data, writer.key)
|
ValueData::new(data, writer.key)
|
||||||
};
|
};
|
||||||
let seq = value_data.seq();
|
|
||||||
|
|
||||||
// Validate with schema
|
// Validate with schema
|
||||||
if !schema.check_subkey_value_data(descriptor.owner(), subkey, &value_data) {
|
if !schema.check_subkey_value_data(descriptor.owner(), subkey, &value_data) {
|
||||||
@ -374,7 +373,6 @@ impl StorageManager {
|
|||||||
drop(inner);
|
drop(inner);
|
||||||
|
|
||||||
// Use the safety selection we opened the record with
|
// Use the safety selection we opened the record with
|
||||||
|
|
||||||
let final_signed_value_data = self
|
let final_signed_value_data = self
|
||||||
.outbound_set_value(
|
.outbound_set_value(
|
||||||
rpc_processor,
|
rpc_processor,
|
||||||
@ -386,13 +384,12 @@ impl StorageManager {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// If we got a new value back then write it to the opened record
|
// Whatever record we got back, store it locally, might be newer than the one we asked to save
|
||||||
if final_signed_value_data.value_data().seq() != seq {
|
let mut inner = self.lock().await?;
|
||||||
let mut inner = self.lock().await?;
|
inner
|
||||||
inner
|
.handle_set_local_value(key, subkey, final_signed_value_data.clone())
|
||||||
.handle_set_local_value(key, subkey, final_signed_value_data.clone())
|
.await?;
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(Some(final_signed_value_data.into_value_data()))
|
Ok(Some(final_signed_value_data.into_value_data()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// The context of the do_get_value operation
|
/// The context of the outbound_set_value operation
|
||||||
struct DoSetValueContext {
|
struct OutboundSetValueContext {
|
||||||
/// The latest value of the subkey, may be the value passed in
|
/// The latest value of the subkey, may be the value passed in
|
||||||
pub value: SignedValueData,
|
pub value: SignedValueData,
|
||||||
/// The consensus count for the value we have received
|
/// The consensus count for the value we have received
|
||||||
@ -37,7 +37,7 @@ impl StorageManager {
|
|||||||
|
|
||||||
// Make do-set-value answer context
|
// Make do-set-value answer context
|
||||||
let schema = descriptor.schema()?;
|
let schema = descriptor.schema()?;
|
||||||
let context = Arc::new(Mutex::new(DoSetValueContext {
|
let context = Arc::new(Mutex::new(OutboundSetValueContext {
|
||||||
value,
|
value,
|
||||||
value_count: 0,
|
value_count: 0,
|
||||||
schema,
|
schema,
|
||||||
|
@ -1,74 +1,77 @@
|
|||||||
# # Routing context veilid tests
|
# Routing context veilid tests
|
||||||
|
|
||||||
# import veilid
|
import veilid
|
||||||
# import pytest
|
import pytest
|
||||||
# import asyncio
|
import asyncio
|
||||||
# import json
|
import json
|
||||||
# from . import *
|
from . import *
|
||||||
|
|
||||||
# ##################################################################
|
##################################################################
|
||||||
# BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
|
BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_get_dht_value_unopened(api_connection: veilid.VeilidAPI):
|
async def test_get_dht_value_unopened(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# with pytest.raises(veilid.VeilidAPIError):
|
with pytest.raises(veilid.VeilidAPIError):
|
||||||
# out = await rc.get_dht_value(BOGUS_KEY, veilid.ValueSubkey(0), False)
|
out = await rc.get_dht_value(BOGUS_KEY, veilid.ValueSubkey(0), False)
|
||||||
|
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_open_dht_record_nonexistent_no_writer(api_connection: veilid.VeilidAPI):
|
async def test_open_dht_record_nonexistent_no_writer(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# with pytest.raises(veilid.VeilidAPIError):
|
with pytest.raises(veilid.VeilidAPIError):
|
||||||
# out = await rc.open_dht_record(BOGUS_KEY, None)
|
out = await rc.open_dht_record(BOGUS_KEY, None)
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_close_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
async def test_close_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# with pytest.raises(veilid.VeilidAPIError):
|
with pytest.raises(veilid.VeilidAPIError):
|
||||||
# await rc.close_dht_record(BOGUS_KEY)
|
await rc.close_dht_record(BOGUS_KEY)
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_delete_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
async def test_delete_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# with pytest.raises(veilid.VeilidAPIError):
|
with pytest.raises(veilid.VeilidAPIError):
|
||||||
# await rc.delete_dht_record(BOGUS_KEY)
|
await rc.delete_dht_record(BOGUS_KEY)
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_create_delete_dht_record_simple(api_connection: veilid.VeilidAPI):
|
async def test_create_delete_dht_record_simple(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||||
# await rc.close_dht_record(rec.key)
|
await rc.close_dht_record(rec.key)
|
||||||
# await rc.delete_dht_record(rec.key)
|
await rc.delete_dht_record(rec.key)
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_get_dht_value_nonexistent(api_connection: veilid.VeilidAPI):
|
async def test_get_dht_value_nonexistent(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||||
# assert await rc.get_dht_value(rec.key, 0, False) == None
|
assert await rc.get_dht_value(rec.key, 0, False) == None
|
||||||
# await rc.close_dht_record(rec.key)
|
await rc.close_dht_record(rec.key)
|
||||||
# await rc.delete_dht_record(rec.key)
|
await rc.delete_dht_record(rec.key)
|
||||||
|
|
||||||
# @pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
# async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
|
async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
|
||||||
# rc = await api_connection.new_routing_context()
|
rc = await api_connection.new_routing_context()
|
||||||
# async with rc:
|
async with rc:
|
||||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||||
|
|
||||||
# vd = await rc.set_dht_value(rec.key, 0, b"BLAH BLAH BLAH")
|
vd = await rc.set_dht_value(rec.key, 0, b"BLAH BLAH BLAH")
|
||||||
# assert vd != None
|
assert vd != None
|
||||||
|
|
||||||
# vd2 = await rc.get_dht_value(rec.key, 0, False)
|
vd2 = await rc.get_dht_value(rec.key, 0, False)
|
||||||
# assert vd2 != None
|
assert vd2 != None
|
||||||
|
|
||||||
# assert vd == vd2
|
print("vd: {}", vd.__dict__)
|
||||||
|
print("vd2: {}", vd2.__dict__)
|
||||||
|
|
||||||
# await rc.close_dht_record(rec.key)
|
assert vd == vd2
|
||||||
# await rc.delete_dht_record(rec.key)
|
|
||||||
|
await rc.close_dht_record(rec.key)
|
||||||
|
await rc.delete_dht_record(rec.key)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import base64
|
|||||||
import json
|
import json
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from typing import Any, Optional, Self, Tuple
|
from typing import Any, Optional, Self, Tuple
|
||||||
|
from functools import total_ordering
|
||||||
|
|
||||||
####################################################################
|
####################################################################
|
||||||
|
|
||||||
@ -206,6 +207,7 @@ class ValueSeqNum(int):
|
|||||||
####################################################################
|
####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
class VeilidVersion:
|
class VeilidVersion:
|
||||||
_major: int
|
_major: int
|
||||||
_minor: int
|
_minor: int
|
||||||
@ -216,6 +218,25 @@ class VeilidVersion:
|
|||||||
self._minor = minor
|
self._minor = minor
|
||||||
self._patch = patch
|
self._patch = patch
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if other is None:
|
||||||
|
return False
|
||||||
|
if self._major < other._major:
|
||||||
|
return True
|
||||||
|
if self._major > other._major:
|
||||||
|
return False
|
||||||
|
if self._minor < other._minor:
|
||||||
|
return True
|
||||||
|
if self._minor > other._minor:
|
||||||
|
return False
|
||||||
|
if self._patch < other._patch:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, VeilidVersion) and self.data == other.data and self.seq == other.seq and self.writer == other.writer
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def major(self):
|
def major(self):
|
||||||
return self._major
|
return self._major
|
||||||
@ -323,6 +344,7 @@ class DHTRecordDescriptor:
|
|||||||
return self.__dict__
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
class ValueData:
|
class ValueData:
|
||||||
seq: ValueSeqNum
|
seq: ValueSeqNum
|
||||||
data: bytes
|
data: bytes
|
||||||
@ -333,6 +355,24 @@ class ValueData:
|
|||||||
self.data = data
|
self.data = data
|
||||||
self.writer = writer
|
self.writer = writer
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if other is None:
|
||||||
|
return true
|
||||||
|
if self.data < other.data:
|
||||||
|
return True
|
||||||
|
if self.data > other.data:
|
||||||
|
return False
|
||||||
|
if self.seq < other.seq:
|
||||||
|
return True
|
||||||
|
if self.seq > other.seq:
|
||||||
|
return False
|
||||||
|
if self.writer < other.writer:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, ValueData) and self.data == other.data and self.seq == other.seq and self.writer == other.writer
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls, j: dict) -> Self:
|
def from_json(cls, j: dict) -> Self:
|
||||||
return cls(
|
return cls(
|
||||||
|
Loading…
Reference in New Issue
Block a user