mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-13 01:51:23 +00:00
feat: migrate to quick-protobuf
Instead of relying on `protoc` and buildscripts, we generate the bindings using `pb-rs` and version them within our codebase. This makes for a better IDE integration, a faster build and an easier use of `rust-libp2p` because we don't force the `protoc` dependency onto them. Resolves #3024. Pull-Request: #3312.
This commit is contained in:
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@ -293,3 +293,30 @@ jobs:
|
|||||||
echo "PR title is too long (greater than 72 characters)"
|
echo "PR title is too long (greater than 72 characters)"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
check-proto-files:
|
||||||
|
name: Check for changes in proto files
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
|
- run: cargo install --version 0.10.0 pb-rs --locked
|
||||||
|
|
||||||
|
- name: Glob match
|
||||||
|
uses: tj-actions/glob@v16
|
||||||
|
id: glob
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
**/generated/*.proto
|
||||||
|
|
||||||
|
- name: Generate proto files
|
||||||
|
run: pb-rs --dont_use_cow ${{ steps.glob.outputs.paths }}
|
||||||
|
|
||||||
|
- name: Ensure generated files are unmodified # https://stackoverflow.com/a/5737794
|
||||||
|
run: |
|
||||||
|
git_status=$(git status --porcelain)
|
||||||
|
|
||||||
|
echo $git_status
|
||||||
|
test -z "$git_status"
|
||||||
|
179
Cargo.lock
generated
179
Cargo.lock
generated
@ -1407,12 +1407,6 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.25"
|
version = "1.0.25"
|
||||||
@ -2177,8 +2171,7 @@ dependencies = [
|
|||||||
"libp2p-tcp",
|
"libp2p-tcp",
|
||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2208,8 +2201,7 @@ dependencies = [
|
|||||||
"p256 0.12.0",
|
"p256 0.12.0",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"ring",
|
"ring",
|
||||||
@ -2248,9 +2240,8 @@ dependencies = [
|
|||||||
"libp2p-tcp",
|
"libp2p-tcp",
|
||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"void",
|
"void",
|
||||||
@ -2296,9 +2287,8 @@ dependencies = [
|
|||||||
"libp2p-core",
|
"libp2p-core",
|
||||||
"libp2p-swarm",
|
"libp2p-swarm",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@ -2327,9 +2317,8 @@ dependencies = [
|
|||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prometheus-client",
|
"prometheus-client",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"regex",
|
"regex",
|
||||||
@ -2359,9 +2348,8 @@ dependencies = [
|
|||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"lru",
|
"lru",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"void",
|
"void",
|
||||||
@ -2385,8 +2373,7 @@ dependencies = [
|
|||||||
"libp2p-swarm",
|
"libp2p-swarm",
|
||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
@ -2493,8 +2480,7 @@ dependencies = [
|
|||||||
"libsodium-sys-stable",
|
"libsodium-sys-stable",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"sha2 0.10.6",
|
"sha2 0.10.6",
|
||||||
@ -2536,8 +2522,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"libp2p-core",
|
"libp2p-core",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"unsigned-varint",
|
"unsigned-varint",
|
||||||
@ -2611,9 +2596,8 @@ dependencies = [
|
|||||||
"libp2p-tcp",
|
"libp2p-tcp",
|
||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"quickcheck-ext",
|
"quickcheck-ext",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
@ -2641,9 +2625,8 @@ dependencies = [
|
|||||||
"libp2p-tcp",
|
"libp2p-tcp",
|
||||||
"libp2p-yamux",
|
"libp2p-yamux",
|
||||||
"log",
|
"log",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -2787,9 +2770,8 @@ dependencies = [
|
|||||||
"libp2p-swarm",
|
"libp2p-swarm",
|
||||||
"log",
|
"log",
|
||||||
"multihash",
|
"multihash",
|
||||||
"prost",
|
"quick-protobuf",
|
||||||
"prost-build",
|
"quick-protobuf-codec",
|
||||||
"prost-codec",
|
|
||||||
"quickcheck",
|
"quickcheck",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rcgen 0.9.3",
|
"rcgen 0.9.3",
|
||||||
@ -3103,12 +3085,6 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "multimap"
|
|
||||||
version = "0.8.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multistream-select"
|
name = "multistream-select"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -3441,16 +3417,6 @@ version = "2.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "petgraph"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
|
|
||||||
dependencies = [
|
|
||||||
"fixedbitset",
|
|
||||||
"indexmap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
@ -3593,16 +3559,6 @@ version = "0.2.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prettyplease"
|
|
||||||
version = "0.1.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "primeorder"
|
name = "primeorder"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -3678,78 +3634,32 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prost"
|
|
||||||
version = "0.11.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"prost-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prost-build"
|
|
||||||
version = "0.11.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"heck",
|
|
||||||
"itertools",
|
|
||||||
"lazy_static",
|
|
||||||
"log",
|
|
||||||
"multimap",
|
|
||||||
"petgraph",
|
|
||||||
"prettyplease",
|
|
||||||
"prost",
|
|
||||||
"prost-types",
|
|
||||||
"regex",
|
|
||||||
"syn",
|
|
||||||
"tempfile",
|
|
||||||
"which",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prost-codec"
|
|
||||||
version = "0.3.0"
|
|
||||||
dependencies = [
|
|
||||||
"asynchronous-codec",
|
|
||||||
"bytes",
|
|
||||||
"prost",
|
|
||||||
"prost-build",
|
|
||||||
"thiserror",
|
|
||||||
"unsigned-varint",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prost-derive"
|
|
||||||
version = "0.11.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"itertools",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prost-types"
|
|
||||||
version = "0.11.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
|
|
||||||
dependencies = [
|
|
||||||
"prost",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.3"
|
version = "1.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-protobuf"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-protobuf-codec"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"asynchronous-codec",
|
||||||
|
"bytes",
|
||||||
|
"quick-protobuf",
|
||||||
|
"thiserror",
|
||||||
|
"unsigned-varint",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quickcheck"
|
name = "quickcheck"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@ -5374,17 +5284,6 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "which"
|
|
||||||
version = "4.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -146,7 +146,7 @@ members = [
|
|||||||
"misc/multistream-select",
|
"misc/multistream-select",
|
||||||
"misc/rw-stream-sink",
|
"misc/rw-stream-sink",
|
||||||
"misc/keygen",
|
"misc/keygen",
|
||||||
"misc/prost-codec",
|
"misc/quick-protobuf-codec",
|
||||||
"misc/quickcheck-ext",
|
"misc/quickcheck-ext",
|
||||||
"muxers/mplex",
|
"muxers/mplex",
|
||||||
"muxers/yamux",
|
"muxers/yamux",
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
- Move `ConnectionId` to `libp2p-swarm`. See [PR 3221].
|
- Move `ConnectionId` to `libp2p-swarm`. See [PR 3221].
|
||||||
- Move `PendingPoint` to `libp2p-swarm` and make it crate-private. See [PR 3221].
|
- Move `PendingPoint` to `libp2p-swarm` and make it crate-private. See [PR 3221].
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
[PR 3221]: https://github.com/libp2p/rust-libp2p/pull/3221
|
[PR 3221]: https://github.com/libp2p/rust-libp2p/pull/3221
|
||||||
|
|
||||||
# 0.38.0
|
# 0.38.0
|
||||||
|
@ -27,7 +27,7 @@ multistream-select = { version = "0.12.1", path = "../misc/multistream-select" }
|
|||||||
p256 = { version = "0.12.0", default-features = false, features = ["ecdsa", "std"], optional = true }
|
p256 = { version = "0.12.0", default-features = false, features = ["ecdsa", "std"], optional = true }
|
||||||
parking_lot = "0.12.0"
|
parking_lot = "0.12.0"
|
||||||
pin-project = "1.0.0"
|
pin-project = "1.0.0"
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.17.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
rw-stream-sink = { version = "0.3.0", path = "../misc/rw-stream-sink" }
|
rw-stream-sink = { version = "0.3.0", path = "../misc/rw-stream-sink" }
|
||||||
@ -54,9 +54,6 @@ quickcheck = { package = "quickcheck-ext", path = "../misc/quickcheck-ext" }
|
|||||||
rmp-serde = "1.0"
|
rmp-serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
secp256k1 = [ "libsecp256k1" ]
|
secp256k1 = [ "libsecp256k1" ]
|
||||||
ecdsa = [ "p256" ]
|
ecdsa = [ "p256" ]
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(
|
|
||||||
&[
|
|
||||||
"src/keys.proto",
|
|
||||||
"src/envelope.proto",
|
|
||||||
"src/peer_record.proto",
|
|
||||||
],
|
|
||||||
&["src"],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
59
core/src/generated/envelope_proto.rs
Normal file
59
core/src/generated/envelope_proto.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Automatically generated rust module for 'envelope.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Envelope {
|
||||||
|
pub public_key: Option<keys_proto::PublicKey>,
|
||||||
|
pub payload_type: Vec<u8>,
|
||||||
|
pub payload: Vec<u8>,
|
||||||
|
pub signature: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Envelope {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.public_key = Some(r.read_message::<keys_proto::PublicKey>(bytes)?),
|
||||||
|
Ok(18) => msg.payload_type = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(26) => msg.payload = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(42) => msg.signature = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Envelope {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.public_key.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ if self.payload_type.is_empty() { 0 } else { 1 + sizeof_len((&self.payload_type).len()) }
|
||||||
|
+ if self.payload.is_empty() { 0 } else { 1 + sizeof_len((&self.payload).len()) }
|
||||||
|
+ if self.signature.is_empty() { 0 } else { 1 + sizeof_len((&self.signature).len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.public_key { w.write_with_tag(10, |w| w.write_message(s))?; }
|
||||||
|
if !self.payload_type.is_empty() { w.write_with_tag(18, |w| w.write_bytes(&**&self.payload_type))?; }
|
||||||
|
if !self.payload.is_empty() { w.write_with_tag(26, |w| w.write_bytes(&**&self.payload))?; }
|
||||||
|
if !self.signature.is_empty() { w.write_with_tag(42, |w| w.write_bytes(&**&self.signature))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
125
core/src/generated/keys_proto.rs
Normal file
125
core/src/generated/keys_proto.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// Automatically generated rust module for 'keys.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum KeyType {
|
||||||
|
RSA = 0,
|
||||||
|
Ed25519 = 1,
|
||||||
|
Secp256k1 = 2,
|
||||||
|
ECDSA = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for KeyType {
|
||||||
|
fn default() -> Self {
|
||||||
|
KeyType::RSA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for KeyType {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => KeyType::RSA,
|
||||||
|
1 => KeyType::Ed25519,
|
||||||
|
2 => KeyType::Secp256k1,
|
||||||
|
3 => KeyType::ECDSA,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for KeyType {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"RSA" => KeyType::RSA,
|
||||||
|
"Ed25519" => KeyType::Ed25519,
|
||||||
|
"Secp256k1" => KeyType::Secp256k1,
|
||||||
|
"ECDSA" => KeyType::ECDSA,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct PublicKey {
|
||||||
|
pub Type: keys_proto::KeyType,
|
||||||
|
pub Data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for PublicKey {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.Type = r.read_enum(bytes)?,
|
||||||
|
Ok(18) => msg.Data = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for PublicKey {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.Type) as u64)
|
||||||
|
+ 1 + sizeof_len((&self.Data).len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_enum(*&self.Type as i32))?;
|
||||||
|
w.write_with_tag(18, |w| w.write_bytes(&**&self.Data))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct PrivateKey {
|
||||||
|
pub Type: keys_proto::KeyType,
|
||||||
|
pub Data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for PrivateKey {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.Type = r.read_enum(bytes)?,
|
||||||
|
Ok(18) => msg.Data = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for PrivateKey {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.Type) as u64)
|
||||||
|
+ 1 + sizeof_len((&self.Data).len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_enum(*&self.Type as i32))?;
|
||||||
|
w.write_with_tag(18, |w| w.write_bytes(&**&self.Data))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
core/src/generated/mod.rs
Normal file
4
core/src/generated/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod envelope_proto;
|
||||||
|
pub mod keys_proto;
|
||||||
|
pub mod peer_record_proto;
|
93
core/src/generated/peer_record_proto.rs
Normal file
93
core/src/generated/peer_record_proto.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Automatically generated rust module for 'peer_record.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct PeerRecord {
|
||||||
|
pub peer_id: Vec<u8>,
|
||||||
|
pub seq: u64,
|
||||||
|
pub addresses: Vec<peer_record_proto::mod_PeerRecord::AddressInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for PeerRecord {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.peer_id = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(16) => msg.seq = r.read_uint64(bytes)?,
|
||||||
|
Ok(26) => msg.addresses.push(r.read_message::<peer_record_proto::mod_PeerRecord::AddressInfo>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for PeerRecord {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ if self.peer_id.is_empty() { 0 } else { 1 + sizeof_len((&self.peer_id).len()) }
|
||||||
|
+ if self.seq == 0u64 { 0 } else { 1 + sizeof_varint(*(&self.seq) as u64) }
|
||||||
|
+ self.addresses.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if !self.peer_id.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.peer_id))?; }
|
||||||
|
if self.seq != 0u64 { w.write_with_tag(16, |w| w.write_uint64(*&self.seq))?; }
|
||||||
|
for s in &self.addresses { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_PeerRecord {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct AddressInfo {
|
||||||
|
pub multiaddr: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for AddressInfo {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.multiaddr = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for AddressInfo {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ if self.multiaddr.is_empty() { 0 } else { 1 + sizeof_len((&self.multiaddr).len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if !self.multiaddr.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.multiaddr))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -43,7 +43,8 @@ pub mod secp256k1;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
use self::error::*;
|
use self::error::*;
|
||||||
use crate::{keys_proto, PeerId};
|
use crate::{proto, PeerId};
|
||||||
|
use quick_protobuf::{BytesReader, Writer};
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
/// Identity keypair of a node.
|
/// Identity keypair of a node.
|
||||||
@ -147,12 +148,12 @@ impl Keypair {
|
|||||||
|
|
||||||
/// Encode a private key as protobuf structure.
|
/// Encode a private key as protobuf structure.
|
||||||
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
|
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let pk = match self {
|
let pk = match self {
|
||||||
Self::Ed25519(data) => keys_proto::PrivateKey {
|
Self::Ed25519(data) => proto::PrivateKey {
|
||||||
r#type: keys_proto::KeyType::Ed25519.into(),
|
Type: proto::KeyType::Ed25519,
|
||||||
data: data.encode().into(),
|
Data: data.encode().to_vec(),
|
||||||
},
|
},
|
||||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||||
Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
|
Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
|
||||||
@ -162,35 +163,38 @@ impl Keypair {
|
|||||||
Self::Ecdsa(_) => return Err(DecodingError::encoding_unsupported("ECDSA")),
|
Self::Ecdsa(_) => return Err(DecodingError::encoding_unsupported("ECDSA")),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pk.encode_to_vec())
|
let mut buf = Vec::with_capacity(pk.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
|
pk.write_message(&mut writer).expect("Encoding to succeed");
|
||||||
|
|
||||||
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
|
/// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
|
||||||
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
let mut private_key = keys_proto::PrivateKey::decode(bytes)
|
let mut reader = BytesReader::from_bytes(bytes);
|
||||||
|
let mut private_key = proto::PrivateKey::from_reader(&mut reader, bytes)
|
||||||
.map_err(|e| DecodingError::bad_protobuf("private key bytes", e))
|
.map_err(|e| DecodingError::bad_protobuf("private key bytes", e))
|
||||||
.map(zeroize::Zeroizing::new)?;
|
.map(zeroize::Zeroizing::new)?;
|
||||||
|
|
||||||
let key_type = keys_proto::KeyType::from_i32(private_key.r#type)
|
match private_key.Type {
|
||||||
.ok_or_else(|| DecodingError::unknown_key_type(private_key.r#type))?;
|
proto::KeyType::Ed25519 => {
|
||||||
|
ed25519::Keypair::decode(&mut private_key.Data).map(Keypair::Ed25519)
|
||||||
match key_type {
|
|
||||||
keys_proto::KeyType::Ed25519 => {
|
|
||||||
ed25519::Keypair::decode(&mut private_key.data).map(Keypair::Ed25519)
|
|
||||||
}
|
}
|
||||||
keys_proto::KeyType::Rsa => Err(DecodingError::decoding_unsupported("RSA")),
|
proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")),
|
||||||
keys_proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
|
proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
|
||||||
keys_proto::KeyType::Ecdsa => Err(DecodingError::decoding_unsupported("ECDSA")),
|
proto::KeyType::ECDSA => Err(DecodingError::decoding_unsupported("ECDSA")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl zeroize::Zeroize for keys_proto::PrivateKey {
|
impl zeroize::Zeroize for proto::PrivateKey {
|
||||||
fn zeroize(&mut self) {
|
fn zeroize(&mut self) {
|
||||||
self.r#type.zeroize();
|
// KeyType cannot be zeroized.
|
||||||
self.data.zeroize();
|
self.Type = proto::KeyType::default();
|
||||||
|
self.Data.zeroize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,23 +236,27 @@ impl PublicKey {
|
|||||||
/// Encode the public key into a protobuf structure for storage or
|
/// Encode the public key into a protobuf structure for storage or
|
||||||
/// exchange with other nodes.
|
/// exchange with other nodes.
|
||||||
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
|
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let public_key = keys_proto::PublicKey::from(self);
|
let public_key = proto::PublicKey::from(self);
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity(public_key.encoded_len());
|
let mut buf = Vec::with_capacity(public_key.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
public_key
|
public_key
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
|
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a public key from a protobuf structure, e.g. read from storage
|
/// Decode a public key from a protobuf structure, e.g. read from storage
|
||||||
/// or received from another node.
|
/// or received from another node.
|
||||||
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
let pubkey = keys_proto::PublicKey::decode(bytes)
|
let mut reader = BytesReader::from_bytes(bytes);
|
||||||
|
|
||||||
|
let pubkey = proto::PublicKey::from_reader(&mut reader, bytes)
|
||||||
.map_err(|e| DecodingError::bad_protobuf("public key bytes", e))?;
|
.map_err(|e| DecodingError::bad_protobuf("public key bytes", e))?;
|
||||||
|
|
||||||
pubkey.try_into()
|
pubkey.try_into()
|
||||||
@ -260,67 +268,62 @@ impl PublicKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&PublicKey> for keys_proto::PublicKey {
|
impl From<&PublicKey> for proto::PublicKey {
|
||||||
fn from(key: &PublicKey) -> Self {
|
fn from(key: &PublicKey) -> Self {
|
||||||
match key {
|
match key {
|
||||||
PublicKey::Ed25519(key) => keys_proto::PublicKey {
|
PublicKey::Ed25519(key) => proto::PublicKey {
|
||||||
r#type: keys_proto::KeyType::Ed25519 as i32,
|
Type: proto::KeyType::Ed25519,
|
||||||
data: key.encode().to_vec(),
|
Data: key.encode().to_vec(),
|
||||||
},
|
},
|
||||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||||
PublicKey::Rsa(key) => keys_proto::PublicKey {
|
PublicKey::Rsa(key) => proto::PublicKey {
|
||||||
r#type: keys_proto::KeyType::Rsa as i32,
|
Type: proto::KeyType::RSA,
|
||||||
data: key.encode_x509(),
|
Data: key.encode_x509(),
|
||||||
},
|
},
|
||||||
#[cfg(feature = "secp256k1")]
|
#[cfg(feature = "secp256k1")]
|
||||||
PublicKey::Secp256k1(key) => keys_proto::PublicKey {
|
PublicKey::Secp256k1(key) => proto::PublicKey {
|
||||||
r#type: keys_proto::KeyType::Secp256k1 as i32,
|
Type: proto::KeyType::Secp256k1,
|
||||||
data: key.encode().to_vec(),
|
Data: key.encode().to_vec(),
|
||||||
},
|
},
|
||||||
#[cfg(feature = "ecdsa")]
|
#[cfg(feature = "ecdsa")]
|
||||||
PublicKey::Ecdsa(key) => keys_proto::PublicKey {
|
PublicKey::Ecdsa(key) => proto::PublicKey {
|
||||||
r#type: keys_proto::KeyType::Ecdsa as i32,
|
Type: proto::KeyType::ECDSA,
|
||||||
data: key.encode_der(),
|
Data: key.encode_der(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<keys_proto::PublicKey> for PublicKey {
|
impl TryFrom<proto::PublicKey> for PublicKey {
|
||||||
type Error = DecodingError;
|
type Error = DecodingError;
|
||||||
|
|
||||||
fn try_from(pubkey: keys_proto::PublicKey) -> Result<Self, Self::Error> {
|
fn try_from(pubkey: proto::PublicKey) -> Result<Self, Self::Error> {
|
||||||
let key_type = keys_proto::KeyType::from_i32(pubkey.r#type)
|
match pubkey.Type {
|
||||||
.ok_or_else(|| DecodingError::unknown_key_type(pubkey.r#type))?;
|
proto::KeyType::Ed25519 => {
|
||||||
|
ed25519::PublicKey::decode(&pubkey.Data).map(PublicKey::Ed25519)
|
||||||
match key_type {
|
|
||||||
keys_proto::KeyType::Ed25519 => {
|
|
||||||
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::Ed25519)
|
|
||||||
}
|
}
|
||||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||||
keys_proto::KeyType::Rsa => {
|
proto::KeyType::RSA => rsa::PublicKey::decode_x509(&pubkey.Data).map(PublicKey::Rsa),
|
||||||
rsa::PublicKey::decode_x509(&pubkey.data).map(PublicKey::Rsa)
|
|
||||||
}
|
|
||||||
#[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))]
|
#[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))]
|
||||||
keys_proto::KeyType::Rsa => {
|
proto::KeyType::RSA => {
|
||||||
log::debug!("support for RSA was disabled at compile-time");
|
log::debug!("support for RSA was disabled at compile-time");
|
||||||
Err(DecodingError::missing_feature("rsa"))
|
Err(DecodingError::missing_feature("rsa"))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "secp256k1")]
|
#[cfg(feature = "secp256k1")]
|
||||||
keys_proto::KeyType::Secp256k1 => {
|
proto::KeyType::Secp256k1 => {
|
||||||
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1)
|
secp256k1::PublicKey::decode(&pubkey.Data).map(PublicKey::Secp256k1)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "secp256k1"))]
|
#[cfg(not(feature = "secp256k1"))]
|
||||||
keys_proto::KeyType::Secp256k1 => {
|
proto::KeyType::Secp256k1 => {
|
||||||
log::debug!("support for secp256k1 was disabled at compile-time");
|
log::debug!("support for secp256k1 was disabled at compile-time");
|
||||||
Err(DecodingError::missing_feature("secp256k1"))
|
Err(DecodingError::missing_feature("secp256k1"))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "ecdsa")]
|
#[cfg(feature = "ecdsa")]
|
||||||
keys_proto::KeyType::Ecdsa => {
|
proto::KeyType::ECDSA => {
|
||||||
ecdsa::PublicKey::decode_der(&pubkey.data).map(PublicKey::Ecdsa)
|
ecdsa::PublicKey::decode_der(&pubkey.Data).map(PublicKey::Ecdsa)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "ecdsa"))]
|
#[cfg(not(feature = "ecdsa"))]
|
||||||
keys_proto::KeyType::Ecdsa => {
|
proto::KeyType::ECDSA => {
|
||||||
log::debug!("support for ECDSA was disabled at compile-time");
|
log::debug!("support for ECDSA was disabled at compile-time");
|
||||||
Err(DecodingError::missing_feature("ecdsa"))
|
Err(DecodingError::missing_feature("ecdsa"))
|
||||||
}
|
}
|
||||||
|
@ -68,13 +68,6 @@ impl DecodingError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn unknown_key_type(key_type: i32) -> Self {
|
|
||||||
Self {
|
|
||||||
msg: format!("unknown key-type {key_type}"),
|
|
||||||
source: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn decoding_unsupported(key_type: &'static str) -> Self {
|
pub(crate) fn decoding_unsupported(key_type: &'static str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
msg: format!("decoding {key_type} key from Protobuf is unsupported"),
|
msg: format!("decoding {key_type} key from Protobuf is unsupported"),
|
||||||
|
@ -37,22 +37,18 @@
|
|||||||
|
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod keys_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/keys_proto.rs"));
|
pub use self::{
|
||||||
}
|
envelope_proto::*, keys_proto::*, peer_record_proto::mod_PeerRecord::*,
|
||||||
|
peer_record_proto::PeerRecord,
|
||||||
mod envelope_proto {
|
};
|
||||||
include!(concat!(env!("OUT_DIR"), "/envelope_proto.rs"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
||||||
mod peer_record_proto {
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/peer_record_proto.rs"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multi-address re-export.
|
/// Multi-address re-export.
|
||||||
pub use multiaddr;
|
pub use multiaddr;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Formatter;
|
||||||
pub type Negotiated<T> = multistream_select::Negotiated<T>;
|
pub type Negotiated<T> = multistream_select::Negotiated<T>;
|
||||||
|
|
||||||
mod peer_id;
|
mod peer_id;
|
||||||
@ -80,6 +76,17 @@ pub use translation::address_translation;
|
|||||||
pub use transport::Transport;
|
pub use transport::Transport;
|
||||||
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};
|
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error(transparent)]
|
pub struct DecodeError(String);
|
||||||
pub struct DecodeError(prost::DecodeError);
|
|
||||||
|
impl From<quick_protobuf::Error> for DecodeError {
|
||||||
|
fn from(e: quick_protobuf::Error) -> Self {
|
||||||
|
Self(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DecodeError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::identity::error::SigningError;
|
use crate::identity::error::SigningError;
|
||||||
use crate::identity::Keypair;
|
use crate::identity::Keypair;
|
||||||
|
use crate::proto;
|
||||||
use crate::signed_envelope::SignedEnvelope;
|
use crate::signed_envelope::SignedEnvelope;
|
||||||
use crate::{peer_record_proto, signed_envelope, DecodeError, Multiaddr, PeerId};
|
use crate::{signed_envelope, DecodeError, Multiaddr, PeerId};
|
||||||
use instant::SystemTime;
|
use instant::SystemTime;
|
||||||
|
use quick_protobuf::{BytesReader, Writer};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
const PAYLOAD_TYPE: &str = "/libp2p/routing-state-record";
|
const PAYLOAD_TYPE: &str = "/libp2p/routing-state-record";
|
||||||
@ -29,11 +31,13 @@ impl PeerRecord {
|
|||||||
///
|
///
|
||||||
/// If this function succeeds, the [`SignedEnvelope`] contained a peer record with a valid signature and can hence be considered authenticated.
|
/// If this function succeeds, the [`SignedEnvelope`] contained a peer record with a valid signature and can hence be considered authenticated.
|
||||||
pub fn from_signed_envelope(envelope: SignedEnvelope) -> Result<Self, FromEnvelopeError> {
|
pub fn from_signed_envelope(envelope: SignedEnvelope) -> Result<Self, FromEnvelopeError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
let (payload, signing_key) =
|
let (payload, signing_key) =
|
||||||
envelope.payload_and_signing_key(String::from(DOMAIN_SEP), PAYLOAD_TYPE.as_bytes())?;
|
envelope.payload_and_signing_key(String::from(DOMAIN_SEP), PAYLOAD_TYPE.as_bytes())?;
|
||||||
let record = peer_record_proto::PeerRecord::decode(payload).map_err(DecodeError)?;
|
let mut reader = BytesReader::from_bytes(payload);
|
||||||
|
let record =
|
||||||
|
proto::PeerRecord::from_reader(&mut reader, payload).map_err(DecodeError::from)?;
|
||||||
|
|
||||||
let peer_id = PeerId::from_bytes(&record.peer_id)?;
|
let peer_id = PeerId::from_bytes(&record.peer_id)?;
|
||||||
|
|
||||||
@ -45,7 +49,7 @@ impl PeerRecord {
|
|||||||
let addresses = record
|
let addresses = record
|
||||||
.addresses
|
.addresses
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|a| a.multiaddr.try_into())
|
.map(|a| a.multiaddr.to_vec().try_into())
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -60,7 +64,7 @@ impl PeerRecord {
|
|||||||
///
|
///
|
||||||
/// This is the same key that is used for authenticating every libp2p connection of your application, i.e. what you use when setting up your [`crate::transport::Transport`].
|
/// This is the same key that is used for authenticating every libp2p connection of your application, i.e. what you use when setting up your [`crate::transport::Transport`].
|
||||||
pub fn new(key: &Keypair, addresses: Vec<Multiaddr>) -> Result<Self, SigningError> {
|
pub fn new(key: &Keypair, addresses: Vec<Multiaddr>) -> Result<Self, SigningError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let seq = SystemTime::now()
|
let seq = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
@ -69,21 +73,23 @@ impl PeerRecord {
|
|||||||
let peer_id = key.public().to_peer_id();
|
let peer_id = key.public().to_peer_id();
|
||||||
|
|
||||||
let payload = {
|
let payload = {
|
||||||
let record = peer_record_proto::PeerRecord {
|
let record = proto::PeerRecord {
|
||||||
peer_id: peer_id.to_bytes(),
|
peer_id: peer_id.to_bytes(),
|
||||||
seq,
|
seq,
|
||||||
addresses: addresses
|
addresses: addresses
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| peer_record_proto::peer_record::AddressInfo {
|
.map(|m| proto::AddressInfo {
|
||||||
multiaddr: m.to_vec(),
|
multiaddr: m.to_vec(),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity(record.encoded_len());
|
let mut buf = Vec::with_capacity(record.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
record
|
record
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
|
|
||||||
buf
|
buf
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,7 +168,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mismatched_signature() {
|
fn mismatched_signature() {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let addr: Multiaddr = HOME.parse().unwrap();
|
let addr: Multiaddr = HOME.parse().unwrap();
|
||||||
|
|
||||||
@ -171,18 +177,20 @@ mod tests {
|
|||||||
let identity_b = Keypair::generate_ed25519();
|
let identity_b = Keypair::generate_ed25519();
|
||||||
|
|
||||||
let payload = {
|
let payload = {
|
||||||
let record = peer_record_proto::PeerRecord {
|
let record = proto::PeerRecord {
|
||||||
peer_id: identity_a.public().to_peer_id().to_bytes(),
|
peer_id: identity_a.public().to_peer_id().to_bytes(),
|
||||||
seq: 0,
|
seq: 0,
|
||||||
addresses: vec![peer_record_proto::peer_record::AddressInfo {
|
addresses: vec![proto::AddressInfo {
|
||||||
multiaddr: addr.to_vec(),
|
multiaddr: addr.to_vec(),
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity(record.encoded_len());
|
let mut buf = Vec::with_capacity(record.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
record
|
record
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
|
|
||||||
buf
|
buf
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::identity::error::SigningError;
|
use crate::identity::error::SigningError;
|
||||||
use crate::identity::Keypair;
|
use crate::identity::Keypair;
|
||||||
use crate::{identity, DecodeError, PublicKey};
|
use crate::{identity, proto, DecodeError, PublicKey};
|
||||||
|
use quick_protobuf::{BytesReader, Writer};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use unsigned_varint::encode::usize_buffer;
|
use unsigned_varint::encode::usize_buffer;
|
||||||
@ -73,37 +74,41 @@ impl SignedEnvelope {
|
|||||||
|
|
||||||
/// Encode this [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
/// Encode this [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
||||||
pub fn into_protobuf_encoding(self) -> Vec<u8> {
|
pub fn into_protobuf_encoding(self) -> Vec<u8> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let envelope = crate::envelope_proto::Envelope {
|
let envelope = proto::Envelope {
|
||||||
public_key: Some((&self.key).into()),
|
public_key: Some((&self.key).into()),
|
||||||
payload_type: self.payload_type,
|
payload_type: self.payload_type,
|
||||||
payload: self.payload,
|
payload: self.payload,
|
||||||
signature: self.signature,
|
signature: self.signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity(envelope.encoded_len());
|
let mut buf = Vec::with_capacity(envelope.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
|
|
||||||
envelope
|
envelope
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
|
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
/// Decode a [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
||||||
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Self, DecodingError> {
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Self, DecodingError> {
|
||||||
use prost::Message;
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
let envelope = crate::envelope_proto::Envelope::decode(bytes).map_err(DecodeError)?;
|
let mut reader = BytesReader::from_bytes(bytes);
|
||||||
|
let envelope =
|
||||||
|
proto::Envelope::from_reader(&mut reader, bytes).map_err(DecodeError::from)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
key: envelope
|
key: envelope
|
||||||
.public_key
|
.public_key
|
||||||
.ok_or(DecodingError::MissingPublicKey)?
|
.ok_or(DecodingError::MissingPublicKey)?
|
||||||
.try_into()?,
|
.try_into()?,
|
||||||
payload_type: envelope.payload_type,
|
payload_type: envelope.payload_type.to_vec(),
|
||||||
payload: envelope.payload,
|
payload: envelope.payload.to_vec(),
|
||||||
signature: envelope.signature,
|
signature: envelope.signature.to_vec(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ FROM rust:1.67.0
|
|||||||
# Setup protoc. TODO this breaks reproducibility and uses an old version of protoc.
|
# Setup protoc. TODO this breaks reproducibility and uses an old version of protoc.
|
||||||
# In the future protobuf generated files will be checked in, so we can remove this
|
# In the future protobuf generated files will be checked in, so we can remove this
|
||||||
WORKDIR /protoc-setup
|
WORKDIR /protoc-setup
|
||||||
RUN apt-get update && apt-get install -y cmake protobuf-compiler
|
RUN apt-get update && apt-get install -y cmake
|
||||||
|
|
||||||
# Run with access to the target cache to speed up builds
|
# Run with access to the target cache to speed up builds
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
# 0.3.0
|
|
||||||
|
|
||||||
- Implement `From` trait for `std::io::Error`. See [PR 2622].
|
|
||||||
- Don't leak `prost` dependency in `Error` type. See [PR 3058].
|
|
||||||
|
|
||||||
- Update `rust-version` to reflect the actual MSRV: 1.60.0. See [PR 3090].
|
|
||||||
|
|
||||||
[PR 2622]: https://github.com/libp2p/rust-libp2p/pull/2622/
|
|
||||||
[PR 3058]: https://github.com/libp2p/rust-libp2p/pull/3058/
|
|
||||||
[PR 3090]: https://github.com/libp2p/rust-libp2p/pull/3090
|
|
||||||
|
|
||||||
# 0.2.0
|
|
||||||
|
|
||||||
- Update to prost(-build) `v0.11`. See [PR 2788].
|
|
||||||
|
|
||||||
[PR 2788]: https://github.com/libp2p/rust-libp2p/pull/2788/
|
|
5
misc/quick-protobuf-codec/CHANGELOG.md
Normal file
5
misc/quick-protobuf-codec/CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# 0.1.0 [unreleased]
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
@ -1,9 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "prost-codec"
|
name = "quick-protobuf-codec"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.60.0"
|
rust-version = "1.60.0"
|
||||||
description = "Asynchronous de-/encoding of Protobuf structs using asynchronous-codec, unsigned-varint and prost."
|
description = "Asynchronous de-/encoding of Protobuf structs using asynchronous-codec, unsigned-varint and quick-protobuf."
|
||||||
version = "0.3.0"
|
version = "0.1.0"
|
||||||
authors = ["Max Inden <mail@max-inden.de>"]
|
authors = ["Max Inden <mail@max-inden.de>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/libp2p/rust-libp2p"
|
repository = "https://github.com/libp2p/rust-libp2p"
|
||||||
@ -13,12 +13,9 @@ categories = ["asynchronous"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
asynchronous-codec = { version = "0.6" }
|
asynchronous-codec = { version = "0.6" }
|
||||||
bytes = { version = "1" }
|
bytes = { version = "1" }
|
||||||
prost = "0.11"
|
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }
|
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }
|
||||||
|
quick-protobuf = "0.8"
|
||||||
[dev-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||||
# More information: https://docs.rs/about/builds#cross-compiling
|
# More information: https://docs.rs/about/builds#cross-compiling
|
@ -1,15 +1,14 @@
|
|||||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||||
|
|
||||||
use asynchronous_codec::{Decoder, Encoder};
|
use asynchronous_codec::{Decoder, Encoder};
|
||||||
use bytes::BytesMut;
|
use bytes::{Bytes, BytesMut};
|
||||||
use prost::Message;
|
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||||
use std::io::Cursor;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use unsigned_varint::codec::UviBytes;
|
use unsigned_varint::codec::UviBytes;
|
||||||
|
|
||||||
/// [`Codec`] implements [`Encoder`] and [`Decoder`], uses [`unsigned_varint`]
|
/// [`Codec`] implements [`Encoder`] and [`Decoder`], uses [`unsigned_varint`]
|
||||||
/// to prefix messages with their length and uses [`prost`] and a provided
|
/// to prefix messages with their length and uses [`quick_protobuf`] and a provided
|
||||||
/// `struct` implementing [`Message`] to do the encoding.
|
/// `struct` implementing [`MessageRead`] and [`MessageWrite`] to do the encoding.
|
||||||
pub struct Codec<In, Out = In> {
|
pub struct Codec<In, Out = In> {
|
||||||
uvi: UviBytes,
|
uvi: UviBytes,
|
||||||
phantom: PhantomData<(In, Out)>,
|
phantom: PhantomData<(In, Out)>,
|
||||||
@ -31,21 +30,25 @@ impl<In, Out> Codec<In, Out> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<In: Message, Out> Encoder for Codec<In, Out> {
|
impl<In: MessageWrite, Out> Encoder for Codec<In, Out> {
|
||||||
type Item = In;
|
type Item = In;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||||
let mut encoded_msg = BytesMut::new();
|
let mut encoded_msg = Vec::new();
|
||||||
item.encode(&mut encoded_msg)
|
let mut writer = Writer::new(&mut encoded_msg);
|
||||||
.expect("BytesMut to have sufficient capacity.");
|
item.write_message(&mut writer)
|
||||||
self.uvi.encode(encoded_msg.freeze(), dst)?;
|
.expect("Encoding to succeed");
|
||||||
|
self.uvi.encode(Bytes::from(encoded_msg), dst)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<In, Out: Message + Default> Decoder for Codec<In, Out> {
|
impl<In, Out> Decoder for Codec<In, Out>
|
||||||
|
where
|
||||||
|
Out: for<'a> MessageRead<'a>,
|
||||||
|
{
|
||||||
type Item = Out;
|
type Item = Out;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -55,9 +58,9 @@ impl<In, Out: Message + Default> Decoder for Codec<In, Out> {
|
|||||||
Some(msg) => msg,
|
Some(msg) => msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = Message::decode(Cursor::new(msg))
|
let mut reader = BytesReader::from_bytes(&msg);
|
||||||
|
let message = Self::Item::from_reader(&mut reader, &msg)
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
Ok(Some(message))
|
Ok(Some(message))
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
- Update to `libp2p-swarm` `v0.42.0`.
|
- Update to `libp2p-swarm` `v0.42.0`.
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
||||||
|
|
||||||
# 0.9.1
|
# 0.9.1
|
||||||
|
@ -10,9 +10,6 @@ repository = "https://github.com/libp2p/rust-libp2p"
|
|||||||
keywords = ["peer-to-peer", "libp2p", "networking"]
|
keywords = ["peer-to-peer", "libp2p", "networking"]
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
@ -23,7 +20,7 @@ libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
|||||||
libp2p-request-response = { version = "0.24.0", path = "../request-response" }
|
libp2p-request-response = { version = "0.24.0", path = "../request-response" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
async-std = { version = "1.10", features = ["attributes"] }
|
async-std = { version = "1.10", features = ["attributes"] }
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2021 Protocol Labs.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/structs.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
2
protocols/autonat/src/generated/mod.rs
Normal file
2
protocols/autonat/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod structs;
|
242
protocols/autonat/src/generated/structs.rs
Normal file
242
protocols/autonat/src/generated/structs.rs
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// Automatically generated rust module for 'structs.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub type_pb: Option<structs::mod_Message::MessageType>,
|
||||||
|
pub dial: Option<structs::mod_Message::Dial>,
|
||||||
|
pub dialResponse: Option<structs::mod_Message::DialResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Message {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.type_pb = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(18) => msg.dial = Some(r.read_message::<structs::mod_Message::Dial>(bytes)?),
|
||||||
|
Ok(26) => msg.dialResponse = Some(r.read_message::<structs::mod_Message::DialResponse>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Message {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.type_pb.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.dial.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.dialResponse.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.type_pb { w.write_with_tag(8, |w| w.write_enum(*s as i32))?; }
|
||||||
|
if let Some(ref s) = self.dial { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.dialResponse { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_Message {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct PeerInfo {
|
||||||
|
pub id: Option<Vec<u8>>,
|
||||||
|
pub addrs: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for PeerInfo {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.id = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.addrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for PeerInfo {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.addrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.id { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.addrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Dial {
|
||||||
|
pub peer: Option<structs::mod_Message::PeerInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Dial {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.peer = Some(r.read_message::<structs::mod_Message::PeerInfo>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Dial {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.peer.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.peer { w.write_with_tag(10, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct DialResponse {
|
||||||
|
pub status: Option<structs::mod_Message::ResponseStatus>,
|
||||||
|
pub statusText: Option<String>,
|
||||||
|
pub addr: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for DialResponse {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.status = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(18) => msg.statusText = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.addr = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for DialResponse {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.status.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.statusText.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.addr.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.status { w.write_with_tag(8, |w| w.write_enum(*s as i32))?; }
|
||||||
|
if let Some(ref s) = self.statusText { w.write_with_tag(18, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.addr { w.write_with_tag(26, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum MessageType {
|
||||||
|
DIAL = 0,
|
||||||
|
DIAL_RESPONSE = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MessageType {
|
||||||
|
fn default() -> Self {
|
||||||
|
MessageType::DIAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for MessageType {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => MessageType::DIAL,
|
||||||
|
1 => MessageType::DIAL_RESPONSE,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for MessageType {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"DIAL" => MessageType::DIAL,
|
||||||
|
"DIAL_RESPONSE" => MessageType::DIAL_RESPONSE,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum ResponseStatus {
|
||||||
|
OK = 0,
|
||||||
|
E_DIAL_ERROR = 100,
|
||||||
|
E_DIAL_REFUSED = 101,
|
||||||
|
E_BAD_REQUEST = 200,
|
||||||
|
E_INTERNAL_ERROR = 300,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ResponseStatus {
|
||||||
|
fn default() -> Self {
|
||||||
|
ResponseStatus::OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for ResponseStatus {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => ResponseStatus::OK,
|
||||||
|
100 => ResponseStatus::E_DIAL_ERROR,
|
||||||
|
101 => ResponseStatus::E_DIAL_REFUSED,
|
||||||
|
200 => ResponseStatus::E_BAD_REQUEST,
|
||||||
|
300 => ResponseStatus::E_INTERNAL_ERROR,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for ResponseStatus {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"OK" => ResponseStatus::OK,
|
||||||
|
"E_DIAL_ERROR" => ResponseStatus::E_DIAL_ERROR,
|
||||||
|
"E_DIAL_REFUSED" => ResponseStatus::E_DIAL_REFUSED,
|
||||||
|
"E_BAD_REQUEST" => ResponseStatus::E_BAD_REQUEST,
|
||||||
|
"E_INTERNAL_ERROR" => ResponseStatus::E_INTERNAL_ERROR,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -34,7 +34,7 @@ pub use self::{
|
|||||||
};
|
};
|
||||||
pub use libp2p_request_response::{InboundFailure, OutboundFailure};
|
pub use libp2p_request_response::{InboundFailure, OutboundFailure};
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod structs_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/structs.rs"));
|
pub use self::structs::{mod_Message::*, Message};
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,12 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::structs_proto;
|
use crate::proto;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use futures::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
use futures::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||||
use libp2p_core::{upgrade, Multiaddr, PeerId};
|
use libp2p_core::{upgrade, Multiaddr, PeerId};
|
||||||
use libp2p_request_response::{self as request_response, ProtocolName};
|
use libp2p_request_response::{self as request_response, ProtocolName};
|
||||||
use prost::Message;
|
use quick_protobuf::{BytesReader, Writer};
|
||||||
use std::{convert::TryFrom, io};
|
use std::{convert::TryFrom, io};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -108,14 +108,17 @@ pub struct DialRequest {
|
|||||||
|
|
||||||
impl DialRequest {
|
impl DialRequest {
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, io::Error> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<Self, io::Error> {
|
||||||
let msg = structs_proto::Message::decode(bytes)
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
|
let mut reader = BytesReader::from_bytes(bytes);
|
||||||
|
let msg = proto::Message::from_reader(&mut reader, bytes)
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||||
if msg.r#type != Some(structs_proto::message::MessageType::Dial as _) {
|
if msg.type_pb != Some(proto::MessageType::DIAL) {
|
||||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid type"));
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid type"));
|
||||||
}
|
}
|
||||||
let (peer_id, addrs) = if let Some(structs_proto::message::Dial {
|
let (peer_id, addrs) = if let Some(proto::Dial {
|
||||||
peer:
|
peer:
|
||||||
Some(structs_proto::message::PeerInfo {
|
Some(proto::PeerInfo {
|
||||||
id: Some(peer_id),
|
id: Some(peer_id),
|
||||||
addrs,
|
addrs,
|
||||||
}),
|
}),
|
||||||
@ -131,12 +134,13 @@ impl DialRequest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let peer_id = {
|
let peer_id = {
|
||||||
PeerId::try_from(peer_id)
|
PeerId::try_from(peer_id.to_vec())
|
||||||
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid peer id"))?
|
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "invalid peer id"))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let addrs = addrs
|
let addrs = addrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||||
Ok(a) => Some(a),
|
Ok(a) => Some(a),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("Unable to parse multiaddr: {e}");
|
log::debug!("Unable to parse multiaddr: {e}");
|
||||||
@ -151,6 +155,8 @@ impl DialRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_bytes(self) -> Vec<u8> {
|
pub fn into_bytes(self) -> Vec<u8> {
|
||||||
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let peer_id = self.peer_id.to_bytes();
|
let peer_id = self.peer_id.to_bytes();
|
||||||
let addrs = self
|
let addrs = self
|
||||||
.addresses
|
.addresses
|
||||||
@ -158,21 +164,21 @@ impl DialRequest {
|
|||||||
.map(|addr| addr.to_vec())
|
.map(|addr| addr.to_vec())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let msg = structs_proto::Message {
|
let msg = proto::Message {
|
||||||
r#type: Some(structs_proto::message::MessageType::Dial as _),
|
type_pb: Some(proto::MessageType::DIAL),
|
||||||
dial: Some(structs_proto::message::Dial {
|
dial: Some(proto::Dial {
|
||||||
peer: Some(structs_proto::message::PeerInfo {
|
peer: Some(proto::PeerInfo {
|
||||||
id: Some(peer_id),
|
id: Some(peer_id.to_vec()),
|
||||||
addrs,
|
addrs,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
dial_response: None,
|
dialResponse: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
let mut buf = Vec::with_capacity(msg.get_size());
|
||||||
msg.encode(&mut bytes)
|
let mut writer = Writer::new(&mut buf);
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||||
bytes
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,29 +190,27 @@ pub enum ResponseError {
|
|||||||
InternalError,
|
InternalError,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ResponseError> for i32 {
|
impl From<ResponseError> for proto::ResponseStatus {
|
||||||
fn from(t: ResponseError) -> Self {
|
fn from(t: ResponseError) -> Self {
|
||||||
match t {
|
match t {
|
||||||
ResponseError::DialError => 100,
|
ResponseError::DialError => proto::ResponseStatus::E_DIAL_ERROR,
|
||||||
ResponseError::DialRefused => 101,
|
ResponseError::DialRefused => proto::ResponseStatus::E_DIAL_REFUSED,
|
||||||
ResponseError::BadRequest => 200,
|
ResponseError::BadRequest => proto::ResponseStatus::E_BAD_REQUEST,
|
||||||
ResponseError::InternalError => 300,
|
ResponseError::InternalError => proto::ResponseStatus::E_INTERNAL_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<structs_proto::message::ResponseStatus> for ResponseError {
|
impl TryFrom<proto::ResponseStatus> for ResponseError {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn try_from(value: structs_proto::message::ResponseStatus) -> Result<Self, Self::Error> {
|
fn try_from(value: proto::ResponseStatus) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
structs_proto::message::ResponseStatus::EDialError => Ok(ResponseError::DialError),
|
proto::ResponseStatus::E_DIAL_ERROR => Ok(ResponseError::DialError),
|
||||||
structs_proto::message::ResponseStatus::EDialRefused => Ok(ResponseError::DialRefused),
|
proto::ResponseStatus::E_DIAL_REFUSED => Ok(ResponseError::DialRefused),
|
||||||
structs_proto::message::ResponseStatus::EBadRequest => Ok(ResponseError::BadRequest),
|
proto::ResponseStatus::E_BAD_REQUEST => Ok(ResponseError::BadRequest),
|
||||||
structs_proto::message::ResponseStatus::EInternalError => {
|
proto::ResponseStatus::E_INTERNAL_ERROR => Ok(ResponseError::InternalError),
|
||||||
Ok(ResponseError::InternalError)
|
proto::ResponseStatus::OK => {
|
||||||
}
|
|
||||||
structs_proto::message::ResponseStatus::Ok => {
|
|
||||||
log::debug!("Received response with status code OK but expected error.");
|
log::debug!("Received response with status code OK but expected error.");
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidData,
|
io::ErrorKind::InvalidData,
|
||||||
@ -225,38 +229,35 @@ pub struct DialResponse {
|
|||||||
|
|
||||||
impl DialResponse {
|
impl DialResponse {
|
||||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, io::Error> {
|
pub fn from_bytes(bytes: &[u8]) -> Result<Self, io::Error> {
|
||||||
let msg = structs_proto::Message::decode(bytes)
|
use quick_protobuf::MessageRead;
|
||||||
|
|
||||||
|
let mut reader = BytesReader::from_bytes(bytes);
|
||||||
|
let msg = proto::Message::from_reader(&mut reader, bytes)
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||||
if msg.r#type != Some(structs_proto::message::MessageType::DialResponse as _) {
|
if msg.type_pb != Some(proto::MessageType::DIAL_RESPONSE) {
|
||||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid type"));
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match msg.dial_response {
|
Ok(match msg.dialResponse {
|
||||||
Some(structs_proto::message::DialResponse {
|
Some(proto::DialResponse {
|
||||||
status: Some(status),
|
status: Some(proto::ResponseStatus::OK),
|
||||||
status_text,
|
statusText,
|
||||||
addr: Some(addr),
|
addr: Some(addr),
|
||||||
}) if structs_proto::message::ResponseStatus::from_i32(status)
|
}) => {
|
||||||
== Some(structs_proto::message::ResponseStatus::Ok) =>
|
let addr = Multiaddr::try_from(addr.to_vec())
|
||||||
{
|
|
||||||
let addr = Multiaddr::try_from(addr)
|
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||||
Self {
|
Self {
|
||||||
status_text,
|
status_text: statusText,
|
||||||
result: Ok(addr),
|
result: Ok(addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(structs_proto::message::DialResponse {
|
Some(proto::DialResponse {
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
status_text,
|
statusText,
|
||||||
addr: None,
|
addr: None,
|
||||||
}) => Self {
|
}) => Self {
|
||||||
status_text,
|
status_text: statusText,
|
||||||
result: Err(ResponseError::try_from(
|
result: Err(ResponseError::try_from(status)?),
|
||||||
structs_proto::message::ResponseStatus::from_i32(status).ok_or_else(|| {
|
|
||||||
io::Error::new(io::ErrorKind::InvalidData, "invalid response status code")
|
|
||||||
})?,
|
|
||||||
)?),
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
log::debug!("Received malformed response message.");
|
log::debug!("Received malformed response message.");
|
||||||
@ -269,35 +270,38 @@ impl DialResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_bytes(self) -> Vec<u8> {
|
pub fn into_bytes(self) -> Vec<u8> {
|
||||||
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let dial_response = match self.result {
|
let dial_response = match self.result {
|
||||||
Ok(addr) => structs_proto::message::DialResponse {
|
Ok(addr) => proto::DialResponse {
|
||||||
status: Some(0),
|
status: Some(proto::ResponseStatus::OK),
|
||||||
status_text: self.status_text,
|
statusText: self.status_text,
|
||||||
addr: Some(addr.to_vec()),
|
addr: Some(addr.to_vec()),
|
||||||
},
|
},
|
||||||
Err(error) => structs_proto::message::DialResponse {
|
Err(error) => proto::DialResponse {
|
||||||
status: Some(error.into()),
|
status: Some(error.into()),
|
||||||
status_text: self.status_text,
|
statusText: self.status_text,
|
||||||
addr: None,
|
addr: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = structs_proto::Message {
|
let msg = proto::Message {
|
||||||
r#type: Some(structs_proto::message::MessageType::DialResponse as _),
|
type_pb: Some(proto::MessageType::DIAL_RESPONSE),
|
||||||
dial: None,
|
dial: None,
|
||||||
dial_response: Some(dial_response),
|
dialResponse: Some(dial_response),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
let mut buf = Vec::with_capacity(msg.get_size());
|
||||||
msg.encode(&mut bytes)
|
let mut writer = Writer::new(&mut buf);
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||||
bytes
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_request_encode_decode() {
|
fn test_request_encode_decode() {
|
||||||
@ -346,20 +350,20 @@ mod tests {
|
|||||||
a
|
a
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = structs_proto::Message {
|
let msg = proto::Message {
|
||||||
r#type: Some(structs_proto::message::MessageType::Dial.into()),
|
type_pb: Some(proto::MessageType::DIAL),
|
||||||
dial: Some(structs_proto::message::Dial {
|
dial: Some(proto::Dial {
|
||||||
peer: Some(structs_proto::message::PeerInfo {
|
peer: Some(proto::PeerInfo {
|
||||||
id: Some(PeerId::random().to_bytes()),
|
id: Some(PeerId::random().to_bytes()),
|
||||||
addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
dial_response: None,
|
dialResponse: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
let mut bytes = Vec::with_capacity(msg.get_size());
|
||||||
msg.encode(&mut bytes)
|
let mut writer = Writer::new(&mut bytes);
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||||
|
|
||||||
let request = DialRequest::from_bytes(&bytes).expect("not to fail");
|
let request = DialRequest::from_bytes(&bytes).expect("not to fail");
|
||||||
|
|
||||||
|
@ -11,10 +11,13 @@
|
|||||||
|
|
||||||
- Rename types in public API to follow naming conventions defined in [issue 2217]. See [PR 3214].
|
- Rename types in public API to follow naming conventions defined in [issue 2217]. See [PR 3214].
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[PR 3213]: https://github.com/libp2p/rust-libp2p/pull/3213
|
[PR 3213]: https://github.com/libp2p/rust-libp2p/pull/3213
|
||||||
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
||||||
[issue 2217]: https://github.com/libp2p/rust-libp2p/issues/2217
|
[issue 2217]: https://github.com/libp2p/rust-libp2p/issues/2217
|
||||||
[PR 3214]: https://github.com/libp2p/rust-libp2p/pull/3214
|
[PR 3214]: https://github.com/libp2p/rust-libp2p/pull/3214
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.8.1
|
# 0.8.1
|
||||||
|
|
||||||
|
@ -19,14 +19,11 @@ instant = "0.1.11"
|
|||||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
quick-protobuf = "0.8"
|
||||||
prost = "0.11"
|
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
void = "1"
|
void = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
clap = { version = "4.1.6", features = ["derive"] }
|
clap = { version = "4.1.6", features = ["derive"] }
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2021 Protocol Labs.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/message.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
2
protocols/dcutr/src/generated/holepunch/mod.rs
Normal file
2
protocols/dcutr/src/generated/holepunch/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
88
protocols/dcutr/src/generated/holepunch/pb.rs
Normal file
88
protocols/dcutr/src/generated/holepunch/pb.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Automatically generated rust module for 'message.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct HolePunch {
|
||||||
|
pub type_pb: holepunch::pb::mod_HolePunch::Type,
|
||||||
|
pub ObsAddrs: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for HolePunch {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.type_pb = r.read_enum(bytes)?,
|
||||||
|
Ok(18) => msg.ObsAddrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for HolePunch {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.type_pb) as u64)
|
||||||
|
+ self.ObsAddrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_enum(*&self.type_pb as i32))?;
|
||||||
|
for s in &self.ObsAddrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_HolePunch {
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Type {
|
||||||
|
CONNECT = 100,
|
||||||
|
SYNC = 300,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Type {
|
||||||
|
fn default() -> Self {
|
||||||
|
Type::CONNECT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Type {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
100 => Type::CONNECT,
|
||||||
|
300 => Type::SYNC,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for Type {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"CONNECT" => Type::CONNECT,
|
||||||
|
"SYNC" => Type::SYNC,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
2
protocols/dcutr/src/generated/mod.rs
Normal file
2
protocols/dcutr/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod holepunch;
|
@ -26,9 +26,10 @@
|
|||||||
mod behaviour_impl; // TODO: Rename back `behaviour` once deprecation symbols are removed.
|
mod behaviour_impl; // TODO: Rename back `behaviour` once deprecation symbols are removed.
|
||||||
mod handler;
|
mod handler;
|
||||||
mod protocol;
|
mod protocol;
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
||||||
mod message_proto {
|
mod proto {
|
||||||
include!(concat!(env!("OUT_DIR"), "/holepunch.pb.rs"));
|
include!("generated/mod.rs");
|
||||||
|
pub use self::holepunch::pb::{mod_HolePunch::*, HolePunch};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use behaviour_impl::Behaviour;
|
pub use behaviour_impl::Behaviour;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::message_proto::{hole_punch, HolePunch};
|
use crate::proto;
|
||||||
use asynchronous_codec::Framed;
|
use asynchronous_codec::Framed;
|
||||||
use futures::{future::BoxFuture, prelude::*};
|
use futures::{future::BoxFuture, prelude::*};
|
||||||
use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr};
|
use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr};
|
||||||
@ -46,19 +46,19 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
||||||
let mut substream = Framed::new(
|
let mut substream = Framed::new(
|
||||||
substream,
|
substream,
|
||||||
prost_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||||
);
|
);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let HolePunch { r#type, obs_addrs } =
|
let proto::HolePunch { type_pb, ObsAddrs } =
|
||||||
substream.next().await.ok_or(UpgradeError::StreamClosed)??;
|
substream.next().await.ok_or(UpgradeError::StreamClosed)??;
|
||||||
|
|
||||||
let obs_addrs = if obs_addrs.is_empty() {
|
let obs_addrs = if ObsAddrs.is_empty() {
|
||||||
return Err(UpgradeError::NoAddresses);
|
return Err(UpgradeError::NoAddresses);
|
||||||
} else {
|
} else {
|
||||||
obs_addrs
|
ObsAddrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||||
Ok(a) => Some(a),
|
Ok(a) => Some(a),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("Unable to parse multiaddr: {e}");
|
log::debug!("Unable to parse multiaddr: {e}");
|
||||||
@ -77,11 +77,9 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
.collect::<Vec<Multiaddr>>()
|
.collect::<Vec<Multiaddr>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
match type_pb {
|
||||||
|
proto::Type::CONNECT => {}
|
||||||
match r#type {
|
proto::Type::SYNC => return Err(UpgradeError::UnexpectedTypeSync),
|
||||||
hole_punch::Type::Connect => {}
|
|
||||||
hole_punch::Type::Sync => return Err(UpgradeError::UnexpectedTypeSync),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PendingConnect {
|
Ok(PendingConnect {
|
||||||
@ -94,7 +92,7 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct PendingConnect {
|
pub struct PendingConnect {
|
||||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HolePunch>>,
|
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HolePunch>>,
|
||||||
remote_obs_addrs: Vec<Multiaddr>,
|
remote_obs_addrs: Vec<Multiaddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,22 +101,21 @@ impl PendingConnect {
|
|||||||
mut self,
|
mut self,
|
||||||
local_obs_addrs: Vec<Multiaddr>,
|
local_obs_addrs: Vec<Multiaddr>,
|
||||||
) -> Result<Vec<Multiaddr>, UpgradeError> {
|
) -> Result<Vec<Multiaddr>, UpgradeError> {
|
||||||
let msg = HolePunch {
|
let msg = proto::HolePunch {
|
||||||
r#type: hole_punch::Type::Connect.into(),
|
type_pb: proto::Type::CONNECT,
|
||||||
obs_addrs: local_obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
ObsAddrs: local_obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.substream.send(msg).await?;
|
self.substream.send(msg).await?;
|
||||||
let HolePunch { r#type, .. } = self
|
let proto::HolePunch { type_pb, .. } = self
|
||||||
.substream
|
.substream
|
||||||
.next()
|
.next()
|
||||||
.await
|
.await
|
||||||
.ok_or(UpgradeError::StreamClosed)??;
|
.ok_or(UpgradeError::StreamClosed)??;
|
||||||
|
|
||||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
match type_pb {
|
||||||
match r#type {
|
proto::Type::CONNECT => return Err(UpgradeError::UnexpectedTypeConnect),
|
||||||
hole_punch::Type::Connect => return Err(UpgradeError::UnexpectedTypeConnect),
|
proto::Type::SYNC => {}
|
||||||
hole_punch::Type::Sync => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.remote_obs_addrs)
|
Ok(self.remote_obs_addrs)
|
||||||
@ -128,7 +125,7 @@ impl PendingConnect {
|
|||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum UpgradeError {
|
pub enum UpgradeError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Codec(#[from] prost_codec::Error),
|
Codec(#[from] quick_protobuf_codec::Error),
|
||||||
#[error("Stream closed")]
|
#[error("Stream closed")]
|
||||||
StreamClosed,
|
StreamClosed,
|
||||||
#[error("Expected at least one address in reservation.")]
|
#[error("Expected at least one address in reservation.")]
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::message_proto::{hole_punch, HolePunch};
|
use crate::proto;
|
||||||
use asynchronous_codec::Framed;
|
use asynchronous_codec::Framed;
|
||||||
use futures::{future::BoxFuture, prelude::*};
|
use futures::{future::BoxFuture, prelude::*};
|
||||||
use futures_timer::Delay;
|
use futures_timer::Delay;
|
||||||
@ -56,12 +56,12 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
||||||
let mut substream = Framed::new(
|
let mut substream = Framed::new(
|
||||||
substream,
|
substream,
|
||||||
prost_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||||
);
|
);
|
||||||
|
|
||||||
let msg = HolePunch {
|
let msg = proto::HolePunch {
|
||||||
r#type: hole_punch::Type::Connect.into(),
|
type_pb: proto::Type::CONNECT,
|
||||||
obs_addrs: self.obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
ObsAddrs: self.obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
@ -69,23 +69,22 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
|
|
||||||
let sent_time = Instant::now();
|
let sent_time = Instant::now();
|
||||||
|
|
||||||
let HolePunch { r#type, obs_addrs } =
|
let proto::HolePunch { type_pb, ObsAddrs } =
|
||||||
substream.next().await.ok_or(UpgradeError::StreamClosed)??;
|
substream.next().await.ok_or(UpgradeError::StreamClosed)??;
|
||||||
|
|
||||||
let rtt = sent_time.elapsed();
|
let rtt = sent_time.elapsed();
|
||||||
|
|
||||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
match type_pb {
|
||||||
match r#type {
|
proto::Type::CONNECT => {}
|
||||||
hole_punch::Type::Connect => {}
|
proto::Type::SYNC => return Err(UpgradeError::UnexpectedTypeSync),
|
||||||
hole_punch::Type::Sync => return Err(UpgradeError::UnexpectedTypeSync),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let obs_addrs = if obs_addrs.is_empty() {
|
let obs_addrs = if ObsAddrs.is_empty() {
|
||||||
return Err(UpgradeError::NoAddresses);
|
return Err(UpgradeError::NoAddresses);
|
||||||
} else {
|
} else {
|
||||||
obs_addrs
|
ObsAddrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||||
Ok(a) => Some(a),
|
Ok(a) => Some(a),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("Unable to parse multiaddr: {e}");
|
log::debug!("Unable to parse multiaddr: {e}");
|
||||||
@ -104,9 +103,9 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
.collect::<Vec<Multiaddr>>()
|
.collect::<Vec<Multiaddr>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = HolePunch {
|
let msg = proto::HolePunch {
|
||||||
r#type: hole_punch::Type::Sync.into(),
|
type_pb: proto::Type::SYNC,
|
||||||
obs_addrs: vec![],
|
ObsAddrs: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
substream.send(msg).await?;
|
substream.send(msg).await?;
|
||||||
@ -126,7 +125,7 @@ pub struct Connect {
|
|||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum UpgradeError {
|
pub enum UpgradeError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Codec(#[from] prost_codec::Error),
|
Codec(#[from] quick_protobuf_codec::Error),
|
||||||
#[error("Stream closed")]
|
#[error("Stream closed")]
|
||||||
StreamClosed,
|
StreamClosed,
|
||||||
#[error("Expected 'status' field to be set.")]
|
#[error("Expected 'status' field to be set.")]
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
- Update to `libp2p-swarm` `v0.42.0`.
|
- Update to `libp2p-swarm` `v0.42.0`.
|
||||||
|
|
||||||
- Read and write protocols messages via `prost-codec`. See [PR 3224].
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[pr 3224]: https://github.com/libp2p/rust-libp2p/pull/3224
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.41.0
|
# 0.41.0
|
||||||
|
|
||||||
|
@ -18,15 +18,12 @@ futures = "0.3.26"
|
|||||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||||
# More information: https://docs.rs/about/builds#cross-compiling
|
# More information: https://docs.rs/about/builds#cross-compiling
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/rpc.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
2
protocols/floodsub/src/generated/floodsub/mod.rs
Normal file
2
protocols/floodsub/src/generated/floodsub/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
137
protocols/floodsub/src/generated/floodsub/pb.rs
Normal file
137
protocols/floodsub/src/generated/floodsub/pb.rs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Automatically generated rust module for 'rpc.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct RPC {
|
||||||
|
pub subscriptions: Vec<floodsub::pb::mod_RPC::SubOpts>,
|
||||||
|
pub publish: Vec<floodsub::pb::Message>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for RPC {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.subscriptions.push(r.read_message::<floodsub::pb::mod_RPC::SubOpts>(bytes)?),
|
||||||
|
Ok(18) => msg.publish.push(r.read_message::<floodsub::pb::Message>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for RPC {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.subscriptions.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.publish.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
for s in &self.subscriptions { w.write_with_tag(10, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.publish { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_RPC {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct SubOpts {
|
||||||
|
pub subscribe: Option<bool>,
|
||||||
|
pub topic_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for SubOpts {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.subscribe = Some(r.read_bool(bytes)?),
|
||||||
|
Ok(18) => msg.topic_id = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for SubOpts {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.subscribe.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.topic_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.subscribe { w.write_with_tag(8, |w| w.write_bool(*s))?; }
|
||||||
|
if let Some(ref s) = self.topic_id { w.write_with_tag(18, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub from: Option<Vec<u8>>,
|
||||||
|
pub data: Option<Vec<u8>>,
|
||||||
|
pub seqno: Option<Vec<u8>>,
|
||||||
|
pub topic_ids: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Message {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.from = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.data = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.seqno = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(34) => msg.topic_ids.push(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Message {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.from.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.data.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.seqno.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.topic_ids.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.from { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.data { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.seqno { w.write_with_tag(26, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.topic_ids { w.write_with_tag(34, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
protocols/floodsub/src/generated/mod.rs
Normal file
2
protocols/floodsub/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod floodsub;
|
@ -29,9 +29,9 @@ pub mod protocol;
|
|||||||
mod layer;
|
mod layer;
|
||||||
mod topic;
|
mod topic;
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod rpc_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/floodsub.pb.rs"));
|
pub use self::floodsub::pb::{mod_RPC::SubOpts, Message, RPC};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::layer::{Floodsub, FloodsubEvent};
|
pub use self::layer::{Floodsub, FloodsubEvent};
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::rpc_proto;
|
use crate::proto;
|
||||||
use crate::topic::Topic;
|
use crate::topic::Topic;
|
||||||
use asynchronous_codec::Framed;
|
use asynchronous_codec::Framed;
|
||||||
use futures::{
|
use futures::{
|
||||||
@ -65,7 +65,7 @@ where
|
|||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let mut framed = Framed::new(
|
let mut framed = Framed::new(
|
||||||
socket,
|
socket,
|
||||||
prost_codec::Codec::<rpc_proto::Rpc>::new(MAX_MESSAGE_LEN_BYTES),
|
quick_protobuf_codec::Codec::<proto::RPC>::new(MAX_MESSAGE_LEN_BYTES),
|
||||||
);
|
);
|
||||||
|
|
||||||
let rpc = framed
|
let rpc = framed
|
||||||
@ -120,7 +120,7 @@ pub enum FloodsubError {
|
|||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
pub struct CodecError(#[from] prost_codec::Error);
|
pub struct CodecError(#[from] quick_protobuf_codec::Error);
|
||||||
|
|
||||||
/// An RPC received by the floodsub system.
|
/// An RPC received by the floodsub system.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -152,7 +152,7 @@ where
|
|||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let mut framed = Framed::new(
|
let mut framed = Framed::new(
|
||||||
socket,
|
socket,
|
||||||
prost_codec::Codec::<rpc_proto::Rpc>::new(MAX_MESSAGE_LEN_BYTES),
|
quick_protobuf_codec::Codec::<proto::RPC>::new(MAX_MESSAGE_LEN_BYTES),
|
||||||
);
|
);
|
||||||
framed.send(self.into_rpc()).await?;
|
framed.send(self.into_rpc()).await?;
|
||||||
framed.close().await?;
|
framed.close().await?;
|
||||||
@ -163,12 +163,12 @@ where
|
|||||||
|
|
||||||
impl FloodsubRpc {
|
impl FloodsubRpc {
|
||||||
/// Turns this `FloodsubRpc` into a message that can be sent to a substream.
|
/// Turns this `FloodsubRpc` into a message that can be sent to a substream.
|
||||||
fn into_rpc(self) -> rpc_proto::Rpc {
|
fn into_rpc(self) -> proto::RPC {
|
||||||
rpc_proto::Rpc {
|
proto::RPC {
|
||||||
publish: self
|
publish: self
|
||||||
.messages
|
.messages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|msg| rpc_proto::Message {
|
.map(|msg| proto::Message {
|
||||||
from: Some(msg.source.to_bytes()),
|
from: Some(msg.source.to_bytes()),
|
||||||
data: Some(msg.data),
|
data: Some(msg.data),
|
||||||
seqno: Some(msg.sequence_number),
|
seqno: Some(msg.sequence_number),
|
||||||
@ -179,7 +179,7 @@ impl FloodsubRpc {
|
|||||||
subscriptions: self
|
subscriptions: self
|
||||||
.subscriptions
|
.subscriptions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|topic| rpc_proto::rpc::SubOpts {
|
.map(|topic| proto::SubOpts {
|
||||||
subscribe: Some(topic.action == FloodsubSubscriptionAction::Subscribe),
|
subscribe: Some(topic.action == FloodsubSubscriptionAction::Subscribe),
|
||||||
topic_id: Some(topic.topic.into()),
|
topic_id: Some(topic.topic.into()),
|
||||||
})
|
})
|
||||||
|
@ -14,10 +14,13 @@
|
|||||||
It is preferred to import the gossipsub protocol as a module (`use libp2p::gossipsub;`), and refer to its types via `gossipsub::`.
|
It is preferred to import the gossipsub protocol as a module (`use libp2p::gossipsub;`), and refer to its types via `gossipsub::`.
|
||||||
For example: `gossipsub::Behaviour` or `gossipsub::RawMessage`. See [PR 3303].
|
For example: `gossipsub::Behaviour` or `gossipsub::RawMessage`. See [PR 3303].
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[PR 3207]: https://github.com/libp2p/rust-libp2p/pull/3207/
|
[PR 3207]: https://github.com/libp2p/rust-libp2p/pull/3207/
|
||||||
[PR 3303]: https://github.com/libp2p/rust-libp2p/pull/3303/
|
[PR 3303]: https://github.com/libp2p/rust-libp2p/pull/3303/
|
||||||
[PR 3381]: https://github.com/libp2p/rust-libp2p/pull/3381/
|
[PR 3381]: https://github.com/libp2p/rust-libp2p/pull/3381/
|
||||||
[discussion 2174]: https://github.com/libp2p/rust-libp2p/discussions/2174
|
[discussion 2174]: https://github.com/libp2p/rust-libp2p/discussions/2174
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.43.0
|
# 0.43.0
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ log = "0.4.11"
|
|||||||
sha2 = "0.10.0"
|
sha2 = "0.10.0"
|
||||||
base64 = "0.21.0"
|
base64 = "0.21.0"
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||||
hex_fmt = "0.3.0"
|
hex_fmt = "0.3.0"
|
||||||
regex = "1.5.5"
|
regex = "1.5.5"
|
||||||
serde = { version = "1", optional = true, features = ["derive"] }
|
serde = { version = "1", optional = true, features = ["derive"] }
|
||||||
@ -46,9 +46,6 @@ libp2p-swarm = { path = "../../swarm" }
|
|||||||
libp2p-yamux = { path = "../../muxers/yamux" }
|
libp2p-yamux = { path = "../../muxers/yamux" }
|
||||||
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
|
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||||
# More information: https://docs.rs/about/builds#cross-compiling
|
# More information: https://docs.rs/about/builds#cross-compiling
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/rpc.proto", "src/compat.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
@ -32,7 +32,6 @@ use std::{
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use log::{debug, error, trace, warn};
|
use log::{debug, error, trace, warn};
|
||||||
use prometheus_client::registry::Registry;
|
use prometheus_client::registry::Registry;
|
||||||
use prost::Message as _;
|
|
||||||
use rand::{seq::SliceRandom, thread_rng};
|
use rand::{seq::SliceRandom, thread_rng};
|
||||||
|
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
@ -64,8 +63,9 @@ use crate::types::{
|
|||||||
Subscription, SubscriptionAction,
|
Subscription, SubscriptionAction,
|
||||||
};
|
};
|
||||||
use crate::types::{PeerConnections, PeerKind, Rpc};
|
use crate::types::{PeerConnections, PeerKind, Rpc};
|
||||||
use crate::{rpc_proto, TopicScoreParams};
|
use crate::{rpc_proto::proto, TopicScoreParams};
|
||||||
use crate::{PublishError, SubscriptionError, ValidationError};
|
use crate::{PublishError, SubscriptionError, ValidationError};
|
||||||
|
use quick_protobuf::{MessageWrite, Writer};
|
||||||
use std::{cmp::Ordering::Equal, fmt::Debug};
|
use std::{cmp::Ordering::Equal, fmt::Debug};
|
||||||
use wasm_timer::Interval;
|
use wasm_timer::Interval;
|
||||||
|
|
||||||
@ -179,8 +179,8 @@ impl From<MessageAuthenticity> for PublishConfig {
|
|||||||
let public_key = keypair.public();
|
let public_key = keypair.public();
|
||||||
let key_enc = public_key.to_protobuf_encoding();
|
let key_enc = public_key.to_protobuf_encoding();
|
||||||
let key = if key_enc.len() <= 42 {
|
let key = if key_enc.len() <= 42 {
|
||||||
// The public key can be inlined in [`rpc_proto::Message::from`], so we don't include it
|
// The public key can be inlined in [`rpc_proto::proto::::Message::from`], so we don't include it
|
||||||
// specifically in the [`rpc_proto::Message::key`] field.
|
// specifically in the [`rpc_proto::proto::Message::key`] field.
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// Include the protobuf encoding of the public key in the message.
|
// Include the protobuf encoding of the public key in the message.
|
||||||
@ -610,7 +610,7 @@ where
|
|||||||
.into_protobuf();
|
.into_protobuf();
|
||||||
|
|
||||||
// check that the size doesn't exceed the max transmission size
|
// check that the size doesn't exceed the max transmission size
|
||||||
if event.encoded_len() > self.config.max_transmit_size() {
|
if event.get_size() > self.config.max_transmit_size() {
|
||||||
return Err(PublishError::MessageTooLarge);
|
return Err(PublishError::MessageTooLarge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,7 +721,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send to peers we know are subscribed to the topic.
|
// Send to peers we know are subscribed to the topic.
|
||||||
let msg_bytes = event.encoded_len();
|
let msg_bytes = event.get_size();
|
||||||
for peer_id in recipient_peers.iter() {
|
for peer_id in recipient_peers.iter() {
|
||||||
trace!("Sending message to peer: {:?}", peer_id);
|
trace!("Sending message to peer: {:?}", peer_id);
|
||||||
self.send_message(*peer_id, event.clone())?;
|
self.send_message(*peer_id, event.clone())?;
|
||||||
@ -1338,7 +1338,7 @@ where
|
|||||||
}
|
}
|
||||||
.into_protobuf();
|
.into_protobuf();
|
||||||
|
|
||||||
let msg_bytes = message.encoded_len();
|
let msg_bytes = message.get_size();
|
||||||
|
|
||||||
if self.send_message(*peer_id, message).is_err() {
|
if self.send_message(*peer_id, message).is_err() {
|
||||||
error!("Failed to send cached messages. Messages too large");
|
error!("Failed to send cached messages. Messages too large");
|
||||||
@ -2733,7 +2733,7 @@ where
|
|||||||
}
|
}
|
||||||
.into_protobuf();
|
.into_protobuf();
|
||||||
|
|
||||||
let msg_bytes = event.encoded_len();
|
let msg_bytes = event.get_size();
|
||||||
for peer in recipient_peers.iter() {
|
for peer in recipient_peers.iter() {
|
||||||
debug!("Sending message: {:?} to peer {:?}", msg_id, peer);
|
debug!("Sending message: {:?} to peer {:?}", msg_id, peer);
|
||||||
self.send_message(*peer, event.clone())?;
|
self.send_message(*peer, event.clone())?;
|
||||||
@ -2764,7 +2764,7 @@ where
|
|||||||
let sequence_number: u64 = rand::random();
|
let sequence_number: u64 = rand::random();
|
||||||
|
|
||||||
let signature = {
|
let signature = {
|
||||||
let message = rpc_proto::Message {
|
let message = proto::Message {
|
||||||
from: Some(author.clone().to_bytes()),
|
from: Some(author.clone().to_bytes()),
|
||||||
data: Some(data.clone()),
|
data: Some(data.clone()),
|
||||||
seqno: Some(sequence_number.to_be_bytes().to_vec()),
|
seqno: Some(sequence_number.to_be_bytes().to_vec()),
|
||||||
@ -2773,10 +2773,12 @@ where
|
|||||||
key: None,
|
key: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity(message.encoded_len());
|
let mut buf = Vec::with_capacity(message.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
|
|
||||||
message
|
message
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Buffer has sufficient capacity");
|
.expect("Encoding to succeed");
|
||||||
|
|
||||||
// the signature is over the bytes "libp2p-pubsub:<protobuf-message>"
|
// the signature is over the bytes "libp2p-pubsub:<protobuf-message>"
|
||||||
let mut signature_bytes = SIGNING_PREFIX.to_vec();
|
let mut signature_bytes = SIGNING_PREFIX.to_vec();
|
||||||
@ -2875,11 +2877,7 @@ where
|
|||||||
|
|
||||||
/// Send a [`Rpc`] message to a peer. This will wrap the message in an arc if it
|
/// Send a [`Rpc`] message to a peer. This will wrap the message in an arc if it
|
||||||
/// is not already an arc.
|
/// is not already an arc.
|
||||||
fn send_message(
|
fn send_message(&mut self, peer_id: PeerId, message: proto::RPC) -> Result<(), PublishError> {
|
||||||
&mut self,
|
|
||||||
peer_id: PeerId,
|
|
||||||
message: rpc_proto::Rpc,
|
|
||||||
) -> Result<(), PublishError> {
|
|
||||||
// If the message is oversized, try and fragment it. If it cannot be fragmented, log an
|
// If the message is oversized, try and fragment it. If it cannot be fragmented, log an
|
||||||
// error and drop the message (all individual messages should be small enough to fit in the
|
// error and drop the message (all individual messages should be small enough to fit in the
|
||||||
// max_transmit_size)
|
// max_transmit_size)
|
||||||
@ -2899,12 +2897,12 @@ where
|
|||||||
|
|
||||||
// If a message is too large to be sent as-is, this attempts to fragment it into smaller RPC
|
// If a message is too large to be sent as-is, this attempts to fragment it into smaller RPC
|
||||||
// messages to be sent.
|
// messages to be sent.
|
||||||
fn fragment_message(&self, rpc: rpc_proto::Rpc) -> Result<Vec<rpc_proto::Rpc>, PublishError> {
|
fn fragment_message(&self, rpc: proto::RPC) -> Result<Vec<proto::RPC>, PublishError> {
|
||||||
if rpc.encoded_len() < self.config.max_transmit_size() {
|
if rpc.get_size() < self.config.max_transmit_size() {
|
||||||
return Ok(vec![rpc]);
|
return Ok(vec![rpc]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_rpc = rpc_proto::Rpc {
|
let new_rpc = proto::RPC {
|
||||||
subscriptions: Vec::new(),
|
subscriptions: Vec::new(),
|
||||||
publish: Vec::new(),
|
publish: Vec::new(),
|
||||||
control: None,
|
control: None,
|
||||||
@ -2920,7 +2918,7 @@ where
|
|||||||
|
|
||||||
// create a new RPC if the new object plus 5% of its size (for length prefix
|
// create a new RPC if the new object plus 5% of its size (for length prefix
|
||||||
// buffers) exceeds the max transmit size.
|
// buffers) exceeds the max transmit size.
|
||||||
if rpc_list[list_index].encoded_len() + (($object_size as f64) * 1.05) as usize
|
if rpc_list[list_index].get_size() + (($object_size as f64) * 1.05) as usize
|
||||||
> self.config.max_transmit_size()
|
> self.config.max_transmit_size()
|
||||||
&& rpc_list[list_index] != new_rpc
|
&& rpc_list[list_index] != new_rpc
|
||||||
{
|
{
|
||||||
@ -2932,7 +2930,7 @@ where
|
|||||||
|
|
||||||
macro_rules! add_item {
|
macro_rules! add_item {
|
||||||
($object: ident, $type: ident ) => {
|
($object: ident, $type: ident ) => {
|
||||||
let object_size = $object.encoded_len();
|
let object_size = $object.get_size();
|
||||||
|
|
||||||
if object_size + 2 > self.config.max_transmit_size() {
|
if object_size + 2 > self.config.max_transmit_size() {
|
||||||
// This should not be possible. All received and published messages have already
|
// This should not be possible. All received and published messages have already
|
||||||
@ -2960,12 +2958,12 @@ where
|
|||||||
|
|
||||||
// handle the control messages. If all are within the max_transmit_size, send them without
|
// handle the control messages. If all are within the max_transmit_size, send them without
|
||||||
// fragmenting, otherwise, fragment the control messages
|
// fragmenting, otherwise, fragment the control messages
|
||||||
let empty_control = rpc_proto::ControlMessage::default();
|
let empty_control = proto::ControlMessage::default();
|
||||||
if let Some(control) = rpc.control.as_ref() {
|
if let Some(control) = rpc.control.as_ref() {
|
||||||
if control.encoded_len() + 2 > self.config.max_transmit_size() {
|
if control.get_size() + 2 > self.config.max_transmit_size() {
|
||||||
// fragment the RPC
|
// fragment the RPC
|
||||||
for ihave in &control.ihave {
|
for ihave in &control.ihave {
|
||||||
let len = ihave.encoded_len();
|
let len = ihave.get_size();
|
||||||
create_or_add_rpc!(len);
|
create_or_add_rpc!(len);
|
||||||
rpc_list
|
rpc_list
|
||||||
.last_mut()
|
.last_mut()
|
||||||
@ -2976,7 +2974,7 @@ where
|
|||||||
.push(ihave.clone());
|
.push(ihave.clone());
|
||||||
}
|
}
|
||||||
for iwant in &control.iwant {
|
for iwant in &control.iwant {
|
||||||
let len = iwant.encoded_len();
|
let len = iwant.get_size();
|
||||||
create_or_add_rpc!(len);
|
create_or_add_rpc!(len);
|
||||||
rpc_list
|
rpc_list
|
||||||
.last_mut()
|
.last_mut()
|
||||||
@ -2987,7 +2985,7 @@ where
|
|||||||
.push(iwant.clone());
|
.push(iwant.clone());
|
||||||
}
|
}
|
||||||
for graft in &control.graft {
|
for graft in &control.graft {
|
||||||
let len = graft.encoded_len();
|
let len = graft.get_size();
|
||||||
create_or_add_rpc!(len);
|
create_or_add_rpc!(len);
|
||||||
rpc_list
|
rpc_list
|
||||||
.last_mut()
|
.last_mut()
|
||||||
@ -2998,7 +2996,7 @@ where
|
|||||||
.push(graft.clone());
|
.push(graft.clone());
|
||||||
}
|
}
|
||||||
for prune in &control.prune {
|
for prune in &control.prune {
|
||||||
let len = prune.encoded_len();
|
let len = prune.get_size();
|
||||||
create_or_add_rpc!(len);
|
create_or_add_rpc!(len);
|
||||||
rpc_list
|
rpc_list
|
||||||
.last_mut()
|
.last_mut()
|
||||||
@ -3009,7 +3007,7 @@ where
|
|||||||
.push(prune.clone());
|
.push(prune.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let len = control.encoded_len();
|
let len = control.get_size();
|
||||||
create_or_add_rpc!(len);
|
create_or_add_rpc!(len);
|
||||||
rpc_list.last_mut().expect("Always an element").control = Some(control.clone());
|
rpc_list.last_mut().expect("Always an element").control = Some(control.clone());
|
||||||
}
|
}
|
||||||
@ -3769,7 +3767,7 @@ mod local_test {
|
|||||||
|
|
||||||
// Messages over the limit should be split
|
// Messages over the limit should be split
|
||||||
|
|
||||||
while rpc_proto.encoded_len() < max_transmit_size {
|
while rpc_proto.get_size() < max_transmit_size {
|
||||||
rpc.messages.push(test_message());
|
rpc.messages.push(test_message());
|
||||||
rpc_proto = rpc.clone().into_protobuf();
|
rpc_proto = rpc.clone().into_protobuf();
|
||||||
}
|
}
|
||||||
@ -3786,7 +3784,7 @@ mod local_test {
|
|||||||
// all fragmented messages should be under the limit
|
// all fragmented messages should be under the limit
|
||||||
for message in fragmented_messages {
|
for message in fragmented_messages {
|
||||||
assert!(
|
assert!(
|
||||||
message.encoded_len() < max_transmit_size,
|
message.get_size() < max_transmit_size,
|
||||||
"all messages should be less than the transmission size"
|
"all messages should be less than the transmission size"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -3813,7 +3811,7 @@ mod local_test {
|
|||||||
.fragment_message(rpc_proto.clone())
|
.fragment_message(rpc_proto.clone())
|
||||||
.expect("Messages must be valid");
|
.expect("Messages must be valid");
|
||||||
|
|
||||||
if rpc_proto.encoded_len() < max_transmit_size {
|
if rpc_proto.get_size() < max_transmit_size {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
fragmented_messages.len(),
|
fragmented_messages.len(),
|
||||||
1,
|
1,
|
||||||
@ -3829,12 +3827,12 @@ mod local_test {
|
|||||||
// all fragmented messages should be under the limit
|
// all fragmented messages should be under the limit
|
||||||
for message in fragmented_messages {
|
for message in fragmented_messages {
|
||||||
assert!(
|
assert!(
|
||||||
message.encoded_len() < max_transmit_size,
|
message.get_size() < max_transmit_size,
|
||||||
"all messages should be less than the transmission size: list size {} max size{}", message.encoded_len(), max_transmit_size
|
"all messages should be less than the transmission size: list size {} max size{}", message.get_size(), max_transmit_size
|
||||||
);
|
);
|
||||||
|
|
||||||
// ensure they can all be encoded
|
// ensure they can all be encoded
|
||||||
let mut buf = bytes::BytesMut::with_capacity(message.encoded_len());
|
let mut buf = bytes::BytesMut::with_capacity(message.get_size());
|
||||||
codec.encode(message, &mut buf).unwrap()
|
codec.encode(message, &mut buf).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Converts a protobuf message into a gossipsub message for reading the Gossipsub event queue.
|
// Converts a protobuf message into a gossipsub message for reading the Gossipsub event queue.
|
||||||
fn proto_to_message(rpc: &crate::rpc_proto::Rpc) -> Rpc {
|
fn proto_to_message(rpc: &proto::RPC) -> Rpc {
|
||||||
// Store valid messages.
|
// Store valid messages.
|
||||||
let mut messages = Vec::with_capacity(rpc.publish.len());
|
let mut messages = Vec::with_capacity(rpc.publish.len());
|
||||||
let rpc = rpc.clone();
|
let rpc = rpc.clone();
|
||||||
|
@ -100,7 +100,7 @@ pub enum HandlerError {
|
|||||||
#[error("Protocol negotiation failed.")]
|
#[error("Protocol negotiation failed.")]
|
||||||
NegotiationProtocolError(ProtocolError),
|
NegotiationProtocolError(ProtocolError),
|
||||||
#[error("Failed to encode or decode")]
|
#[error("Failed to encode or decode")]
|
||||||
Codec(#[from] prost_codec::Error),
|
Codec(#[from] quick_protobuf_codec::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@ -136,7 +136,7 @@ impl std::error::Error for ValidationError {}
|
|||||||
|
|
||||||
impl From<std::io::Error> for HandlerError {
|
impl From<std::io::Error> for HandlerError {
|
||||||
fn from(error: std::io::Error) -> HandlerError {
|
fn from(error: std::io::Error) -> HandlerError {
|
||||||
HandlerError::Codec(prost_codec::Error::from(error))
|
HandlerError::Codec(quick_protobuf_codec::Error::from(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
protocols/gossipsub/src/generated/compat/mod.rs
Normal file
2
protocols/gossipsub/src/generated/compat/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
67
protocols/gossipsub/src/generated/compat/pb.rs
Normal file
67
protocols/gossipsub/src/generated/compat/pb.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Automatically generated rust module for 'compat.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub from: Option<Vec<u8>>,
|
||||||
|
pub data: Option<Vec<u8>>,
|
||||||
|
pub seqno: Option<Vec<u8>>,
|
||||||
|
pub topic_ids: Vec<String>,
|
||||||
|
pub signature: Option<Vec<u8>>,
|
||||||
|
pub key: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Message {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.from = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.data = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.seqno = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(34) => msg.topic_ids.push(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(42) => msg.signature = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(50) => msg.key = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Message {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.from.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.data.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.seqno.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.topic_ids.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
+ self.signature.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.key.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.from { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.data { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.seqno { w.write_with_tag(26, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.topic_ids { w.write_with_tag(34, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.signature { w.write_with_tag(42, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.key { w.write_with_tag(50, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
protocols/gossipsub/src/generated/gossipsub/mod.rs
Normal file
2
protocols/gossipsub/src/generated/gossipsub/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
567
protocols/gossipsub/src/generated/gossipsub/pb.rs
Normal file
567
protocols/gossipsub/src/generated/gossipsub/pb.rs
Normal file
@ -0,0 +1,567 @@
|
|||||||
|
// Automatically generated rust module for 'rpc.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct RPC {
|
||||||
|
pub subscriptions: Vec<gossipsub::pb::mod_RPC::SubOpts>,
|
||||||
|
pub publish: Vec<gossipsub::pb::Message>,
|
||||||
|
pub control: Option<gossipsub::pb::ControlMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for RPC {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.subscriptions.push(r.read_message::<gossipsub::pb::mod_RPC::SubOpts>(bytes)?),
|
||||||
|
Ok(18) => msg.publish.push(r.read_message::<gossipsub::pb::Message>(bytes)?),
|
||||||
|
Ok(26) => msg.control = Some(r.read_message::<gossipsub::pb::ControlMessage>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for RPC {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.subscriptions.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.publish.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.control.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
for s in &self.subscriptions { w.write_with_tag(10, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.publish { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.control { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_RPC {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct SubOpts {
|
||||||
|
pub subscribe: Option<bool>,
|
||||||
|
pub topic_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for SubOpts {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.subscribe = Some(r.read_bool(bytes)?),
|
||||||
|
Ok(18) => msg.topic_id = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for SubOpts {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.subscribe.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.topic_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.subscribe { w.write_with_tag(8, |w| w.write_bool(*s))?; }
|
||||||
|
if let Some(ref s) = self.topic_id { w.write_with_tag(18, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub from: Option<Vec<u8>>,
|
||||||
|
pub data: Option<Vec<u8>>,
|
||||||
|
pub seqno: Option<Vec<u8>>,
|
||||||
|
pub topic: String,
|
||||||
|
pub signature: Option<Vec<u8>>,
|
||||||
|
pub key: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Message {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.from = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.data = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.seqno = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(34) => msg.topic = r.read_string(bytes)?.to_owned(),
|
||||||
|
Ok(42) => msg.signature = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(50) => msg.key = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Message {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.from.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.data.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.seqno.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ 1 + sizeof_len((&self.topic).len())
|
||||||
|
+ self.signature.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.key.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.from { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.data { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.seqno { w.write_with_tag(26, |w| w.write_bytes(&**s))?; }
|
||||||
|
w.write_with_tag(34, |w| w.write_string(&**&self.topic))?;
|
||||||
|
if let Some(ref s) = self.signature { w.write_with_tag(42, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.key { w.write_with_tag(50, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct ControlMessage {
|
||||||
|
pub ihave: Vec<gossipsub::pb::ControlIHave>,
|
||||||
|
pub iwant: Vec<gossipsub::pb::ControlIWant>,
|
||||||
|
pub graft: Vec<gossipsub::pb::ControlGraft>,
|
||||||
|
pub prune: Vec<gossipsub::pb::ControlPrune>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for ControlMessage {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.ihave.push(r.read_message::<gossipsub::pb::ControlIHave>(bytes)?),
|
||||||
|
Ok(18) => msg.iwant.push(r.read_message::<gossipsub::pb::ControlIWant>(bytes)?),
|
||||||
|
Ok(26) => msg.graft.push(r.read_message::<gossipsub::pb::ControlGraft>(bytes)?),
|
||||||
|
Ok(34) => msg.prune.push(r.read_message::<gossipsub::pb::ControlPrune>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for ControlMessage {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.ihave.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.iwant.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.graft.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.prune.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
for s in &self.ihave { w.write_with_tag(10, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.iwant { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.graft { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.prune { w.write_with_tag(34, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct ControlIHave {
|
||||||
|
pub topic_id: Option<String>,
|
||||||
|
pub message_ids: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for ControlIHave {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.topic_id = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.message_ids.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for ControlIHave {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.topic_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.message_ids.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.topic_id { w.write_with_tag(10, |w| w.write_string(&**s))?; }
|
||||||
|
for s in &self.message_ids { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct ControlIWant {
|
||||||
|
pub message_ids: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for ControlIWant {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.message_ids.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for ControlIWant {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.message_ids.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
for s in &self.message_ids { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct ControlGraft {
|
||||||
|
pub topic_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for ControlGraft {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.topic_id = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for ControlGraft {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.topic_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.topic_id { w.write_with_tag(10, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct ControlPrune {
|
||||||
|
pub topic_id: Option<String>,
|
||||||
|
pub peers: Vec<gossipsub::pb::PeerInfo>,
|
||||||
|
pub backoff: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for ControlPrune {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.topic_id = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.peers.push(r.read_message::<gossipsub::pb::PeerInfo>(bytes)?),
|
||||||
|
Ok(24) => msg.backoff = Some(r.read_uint64(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for ControlPrune {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.topic_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.peers.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.backoff.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.topic_id { w.write_with_tag(10, |w| w.write_string(&**s))?; }
|
||||||
|
for s in &self.peers { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.backoff { w.write_with_tag(24, |w| w.write_uint64(*s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct PeerInfo {
|
||||||
|
pub peer_id: Option<Vec<u8>>,
|
||||||
|
pub signed_peer_record: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for PeerInfo {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.peer_id = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.signed_peer_record = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for PeerInfo {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.peer_id.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.signed_peer_record.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.peer_id { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.signed_peer_record { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct TopicDescriptor {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub auth: Option<gossipsub::pb::mod_TopicDescriptor::AuthOpts>,
|
||||||
|
pub enc: Option<gossipsub::pb::mod_TopicDescriptor::EncOpts>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for TopicDescriptor {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.name = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.auth = Some(r.read_message::<gossipsub::pb::mod_TopicDescriptor::AuthOpts>(bytes)?),
|
||||||
|
Ok(26) => msg.enc = Some(r.read_message::<gossipsub::pb::mod_TopicDescriptor::EncOpts>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for TopicDescriptor {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.name.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.auth.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.enc.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.name { w.write_with_tag(10, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.auth { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.enc { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_TopicDescriptor {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct AuthOpts {
|
||||||
|
pub mode: Option<gossipsub::pb::mod_TopicDescriptor::mod_AuthOpts::AuthMode>,
|
||||||
|
pub keys: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for AuthOpts {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.mode = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(18) => msg.keys.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for AuthOpts {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.mode.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.keys.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.mode { w.write_with_tag(8, |w| w.write_enum(*s as i32))?; }
|
||||||
|
for s in &self.keys { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_AuthOpts {
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum AuthMode {
|
||||||
|
NONE = 0,
|
||||||
|
KEY = 1,
|
||||||
|
WOT = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AuthMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
AuthMode::NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for AuthMode {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => AuthMode::NONE,
|
||||||
|
1 => AuthMode::KEY,
|
||||||
|
2 => AuthMode::WOT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for AuthMode {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"NONE" => AuthMode::NONE,
|
||||||
|
"KEY" => AuthMode::KEY,
|
||||||
|
"WOT" => AuthMode::WOT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct EncOpts {
|
||||||
|
pub mode: Option<gossipsub::pb::mod_TopicDescriptor::mod_EncOpts::EncMode>,
|
||||||
|
pub key_hashes: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for EncOpts {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.mode = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(18) => msg.key_hashes.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for EncOpts {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.mode.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.key_hashes.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.mode { w.write_with_tag(8, |w| w.write_enum(*s as i32))?; }
|
||||||
|
for s in &self.key_hashes { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_EncOpts {
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum EncMode {
|
||||||
|
NONE = 0,
|
||||||
|
SHAREDKEY = 1,
|
||||||
|
WOT = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EncMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
EncMode::NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for EncMode {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => EncMode::NONE,
|
||||||
|
1 => EncMode::SHAREDKEY,
|
||||||
|
2 => EncMode::WOT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for EncMode {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"NONE" => EncMode::NONE,
|
||||||
|
"SHAREDKEY" => EncMode::SHAREDKEY,
|
||||||
|
"WOT" => EncMode::WOT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
3
protocols/gossipsub/src/generated/mod.rs
Normal file
3
protocols/gossipsub/src/generated/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod compat;
|
||||||
|
pub mod gossipsub;
|
@ -19,6 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
||||||
|
use crate::rpc_proto::proto;
|
||||||
use crate::types::{PeerKind, RawMessage, Rpc};
|
use crate::types::{PeerKind, RawMessage, Rpc};
|
||||||
use crate::{HandlerError, ValidationError};
|
use crate::{HandlerError, ValidationError};
|
||||||
use asynchronous_codec::Framed;
|
use asynchronous_codec::Framed;
|
||||||
@ -67,7 +68,7 @@ pub enum HandlerEvent {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum HandlerIn {
|
pub enum HandlerIn {
|
||||||
/// A gossipsub message to send.
|
/// A gossipsub message to send.
|
||||||
Message(crate::rpc_proto::Rpc),
|
Message(proto::RPC),
|
||||||
/// The peer has joined the mesh.
|
/// The peer has joined the mesh.
|
||||||
JoinedMesh,
|
JoinedMesh,
|
||||||
/// The peer has left the mesh.
|
/// The peer has left the mesh.
|
||||||
@ -93,7 +94,7 @@ pub struct Handler {
|
|||||||
inbound_substream: Option<InboundSubstreamState>,
|
inbound_substream: Option<InboundSubstreamState>,
|
||||||
|
|
||||||
/// Queue of values that we want to send to the remote.
|
/// Queue of values that we want to send to the remote.
|
||||||
send_queue: SmallVec<[crate::rpc_proto::Rpc; 16]>,
|
send_queue: SmallVec<[proto::RPC; 16]>,
|
||||||
|
|
||||||
/// Flag indicating that an outbound substream is being established to prevent duplicate
|
/// Flag indicating that an outbound substream is being established to prevent duplicate
|
||||||
/// requests.
|
/// requests.
|
||||||
@ -149,10 +150,7 @@ enum OutboundSubstreamState {
|
|||||||
/// Waiting for the user to send a message. The idle state for an outbound substream.
|
/// Waiting for the user to send a message. The idle state for an outbound substream.
|
||||||
WaitingOutput(Framed<NegotiatedSubstream, GossipsubCodec>),
|
WaitingOutput(Framed<NegotiatedSubstream, GossipsubCodec>),
|
||||||
/// Waiting to send a message to the remote.
|
/// Waiting to send a message to the remote.
|
||||||
PendingSend(
|
PendingSend(Framed<NegotiatedSubstream, GossipsubCodec>, proto::RPC),
|
||||||
Framed<NegotiatedSubstream, GossipsubCodec>,
|
|
||||||
crate::rpc_proto::Rpc,
|
|
||||||
),
|
|
||||||
/// Waiting to flush the substream so that the data arrives to the remote.
|
/// Waiting to flush the substream so that the data arrives to the remote.
|
||||||
PendingFlush(Framed<NegotiatedSubstream, GossipsubCodec>),
|
PendingFlush(Framed<NegotiatedSubstream, GossipsubCodec>),
|
||||||
/// The substream is being closed. Used by either substream.
|
/// The substream is being closed. Used by either substream.
|
||||||
@ -251,7 +249,7 @@ impl ConnectionHandler for Handler {
|
|||||||
type Error = HandlerError;
|
type Error = HandlerError;
|
||||||
type InboundOpenInfo = ();
|
type InboundOpenInfo = ();
|
||||||
type InboundProtocol = ProtocolConfig;
|
type InboundProtocol = ProtocolConfig;
|
||||||
type OutboundOpenInfo = crate::rpc_proto::Rpc;
|
type OutboundOpenInfo = proto::RPC;
|
||||||
type OutboundProtocol = ProtocolConfig;
|
type OutboundProtocol = ProtocolConfig;
|
||||||
|
|
||||||
fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
|
fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
|
||||||
|
@ -24,7 +24,7 @@ use crate::topic::TopicHash;
|
|||||||
use crate::types::{
|
use crate::types::{
|
||||||
ControlAction, MessageId, PeerInfo, PeerKind, RawMessage, Rpc, Subscription, SubscriptionAction,
|
ControlAction, MessageId, PeerInfo, PeerKind, RawMessage, Rpc, Subscription, SubscriptionAction,
|
||||||
};
|
};
|
||||||
use crate::{rpc_proto, Config};
|
use crate::{rpc_proto::proto, Config};
|
||||||
use crate::{HandlerError, ValidationError};
|
use crate::{HandlerError, ValidationError};
|
||||||
use asynchronous_codec::{Decoder, Encoder, Framed};
|
use asynchronous_codec::{Decoder, Encoder, Framed};
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
@ -35,7 +35,7 @@ use libp2p_core::{
|
|||||||
identity::PublicKey, InboundUpgrade, OutboundUpgrade, PeerId, ProtocolName, UpgradeInfo,
|
identity::PublicKey, InboundUpgrade, OutboundUpgrade, PeerId, ProtocolName, UpgradeInfo,
|
||||||
};
|
};
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
use prost::Message as _;
|
use quick_protobuf::Writer;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use unsigned_varint::codec;
|
use unsigned_varint::codec;
|
||||||
|
|
||||||
@ -191,12 +191,12 @@ pub struct GossipsubCodec {
|
|||||||
/// Determines the level of validation performed on incoming messages.
|
/// Determines the level of validation performed on incoming messages.
|
||||||
validation_mode: ValidationMode,
|
validation_mode: ValidationMode,
|
||||||
/// The codec to handle common encoding/decoding of protobuf messages
|
/// The codec to handle common encoding/decoding of protobuf messages
|
||||||
codec: prost_codec::Codec<rpc_proto::Rpc>,
|
codec: quick_protobuf_codec::Codec<proto::RPC>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GossipsubCodec {
|
impl GossipsubCodec {
|
||||||
pub fn new(length_codec: codec::UviBytes, validation_mode: ValidationMode) -> GossipsubCodec {
|
pub fn new(length_codec: codec::UviBytes, validation_mode: ValidationMode) -> GossipsubCodec {
|
||||||
let codec = prost_codec::Codec::new(length_codec.max_len());
|
let codec = quick_protobuf_codec::Codec::new(length_codec.max_len());
|
||||||
GossipsubCodec {
|
GossipsubCodec {
|
||||||
validation_mode,
|
validation_mode,
|
||||||
codec,
|
codec,
|
||||||
@ -206,7 +206,9 @@ impl GossipsubCodec {
|
|||||||
/// Verifies a gossipsub message. This returns either a success or failure. All errors
|
/// Verifies a gossipsub message. This returns either a success or failure. All errors
|
||||||
/// are logged, which prevents error handling in the codec and handler. We simply drop invalid
|
/// are logged, which prevents error handling in the codec and handler. We simply drop invalid
|
||||||
/// messages and log warnings, rather than propagating errors through the codec.
|
/// messages and log warnings, rather than propagating errors through the codec.
|
||||||
fn verify_signature(message: &rpc_proto::Message) -> bool {
|
fn verify_signature(message: &proto::Message) -> bool {
|
||||||
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
let from = match message.from.as_ref() {
|
let from = match message.from.as_ref() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
@ -258,10 +260,11 @@ impl GossipsubCodec {
|
|||||||
let mut message_sig = message.clone();
|
let mut message_sig = message.clone();
|
||||||
message_sig.signature = None;
|
message_sig.signature = None;
|
||||||
message_sig.key = None;
|
message_sig.key = None;
|
||||||
let mut buf = Vec::with_capacity(message_sig.encoded_len());
|
let mut buf = Vec::with_capacity(message_sig.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
message_sig
|
message_sig
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Buffer has sufficient capacity");
|
.expect("Encoding to succeed");
|
||||||
let mut signature_bytes = SIGNING_PREFIX.to_vec();
|
let mut signature_bytes = SIGNING_PREFIX.to_vec();
|
||||||
signature_bytes.extend_from_slice(&buf);
|
signature_bytes.extend_from_slice(&buf);
|
||||||
public_key.verify(&signature_bytes, signature)
|
public_key.verify(&signature_bytes, signature)
|
||||||
@ -269,7 +272,7 @@ impl GossipsubCodec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Encoder for GossipsubCodec {
|
impl Encoder for GossipsubCodec {
|
||||||
type Item = rpc_proto::Rpc;
|
type Item = proto::RPC;
|
||||||
type Error = HandlerError;
|
type Error = HandlerError;
|
||||||
|
|
||||||
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), HandlerError> {
|
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), HandlerError> {
|
||||||
|
@ -17,27 +17,26 @@
|
|||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
#![allow(clippy::derive_partial_eq_without_eq)]
|
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/gossipsub.pb.rs"));
|
pub mod proto {
|
||||||
|
include!("generated/mod.rs");
|
||||||
|
pub use self::gossipsub::pb::{mod_RPC::SubOpts, *};
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::rpc_proto::proto::compat;
|
||||||
use crate::IdentTopic as Topic;
|
use crate::IdentTopic as Topic;
|
||||||
use libp2p_core::PeerId;
|
use libp2p_core::PeerId;
|
||||||
use prost::Message;
|
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
mod compat_proto {
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/compat.pb.rs"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multi_topic_message_compatibility() {
|
fn test_multi_topic_message_compatibility() {
|
||||||
let topic1 = Topic::new("t1").hash();
|
let topic1 = Topic::new("t1").hash();
|
||||||
let topic2 = Topic::new("t2").hash();
|
let topic2 = Topic::new("t2").hash();
|
||||||
|
|
||||||
let new_message1 = super::Message {
|
let new_message1 = super::proto::Message {
|
||||||
from: Some(PeerId::random().to_bytes()),
|
from: Some(PeerId::random().to_bytes()),
|
||||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
||||||
@ -45,7 +44,7 @@ mod test {
|
|||||||
signature: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
signature: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
};
|
};
|
||||||
let old_message1 = compat_proto::Message {
|
let old_message1 = compat::pb::Message {
|
||||||
from: Some(PeerId::random().to_bytes()),
|
from: Some(PeerId::random().to_bytes()),
|
||||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
||||||
@ -53,7 +52,7 @@ mod test {
|
|||||||
signature: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
signature: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
};
|
};
|
||||||
let old_message2 = compat_proto::Message {
|
let old_message2 = compat::pb::Message {
|
||||||
from: Some(PeerId::random().to_bytes()),
|
from: Some(PeerId::random().to_bytes()),
|
||||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
data: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
seqno: Some(rand::thread_rng().gen::<[u8; 8]>().to_vec()),
|
||||||
@ -62,22 +61,31 @@ mod test {
|
|||||||
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
key: Some(rand::thread_rng().gen::<[u8; 32]>().to_vec()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_message1b = Vec::with_capacity(new_message1.encoded_len());
|
let mut new_message1b = Vec::with_capacity(new_message1.get_size());
|
||||||
new_message1.encode(&mut new_message1b).unwrap();
|
let mut writer = Writer::new(&mut new_message1b);
|
||||||
|
new_message1.write_message(&mut writer).unwrap();
|
||||||
|
|
||||||
let mut old_message1b = Vec::with_capacity(old_message1.encoded_len());
|
let mut old_message1b = Vec::with_capacity(old_message1.get_size());
|
||||||
old_message1.encode(&mut old_message1b).unwrap();
|
let mut writer = Writer::new(&mut old_message1b);
|
||||||
|
old_message1.write_message(&mut writer).unwrap();
|
||||||
|
|
||||||
let mut old_message2b = Vec::with_capacity(old_message2.encoded_len());
|
let mut old_message2b = Vec::with_capacity(old_message2.get_size());
|
||||||
old_message2.encode(&mut old_message2b).unwrap();
|
let mut writer = Writer::new(&mut old_message2b);
|
||||||
|
old_message2.write_message(&mut writer).unwrap();
|
||||||
|
|
||||||
let new_message = super::Message::decode(&old_message1b[..]).unwrap();
|
let mut reader = BytesReader::from_bytes(&old_message1b[..]);
|
||||||
|
let new_message =
|
||||||
|
super::proto::Message::from_reader(&mut reader, &old_message1b[..]).unwrap();
|
||||||
assert_eq!(new_message.topic, topic1.clone().into_string());
|
assert_eq!(new_message.topic, topic1.clone().into_string());
|
||||||
|
|
||||||
let new_message = super::Message::decode(&old_message2b[..]).unwrap();
|
let mut reader = BytesReader::from_bytes(&old_message2b[..]);
|
||||||
|
let new_message =
|
||||||
|
super::proto::Message::from_reader(&mut reader, &old_message2b[..]).unwrap();
|
||||||
assert_eq!(new_message.topic, topic2.into_string());
|
assert_eq!(new_message.topic, topic2.into_string());
|
||||||
|
|
||||||
let old_message = compat_proto::Message::decode(&new_message1b[..]).unwrap();
|
let mut reader = BytesReader::from_bytes(&new_message1b[..]);
|
||||||
|
let old_message =
|
||||||
|
compat::pb::Message::from_reader(&mut reader, &new_message1b[..]).unwrap();
|
||||||
assert_eq!(old_message.topic_ids, vec![topic1.into_string()]);
|
assert_eq!(old_message.topic_ids, vec![topic1.into_string()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::rpc_proto;
|
use crate::rpc_proto::proto;
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use prometheus_client::encoding::EncodeLabelSet;
|
use prometheus_client::encoding::EncodeLabelSet;
|
||||||
use prost::Message;
|
use quick_protobuf::Writer;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@ -47,15 +47,18 @@ impl Hasher for Sha256Hash {
|
|||||||
/// Creates a [`TopicHash`] by SHA256 hashing the topic then base64 encoding the
|
/// Creates a [`TopicHash`] by SHA256 hashing the topic then base64 encoding the
|
||||||
/// hash.
|
/// hash.
|
||||||
fn hash(topic_string: String) -> TopicHash {
|
fn hash(topic_string: String) -> TopicHash {
|
||||||
let topic_descripter = rpc_proto::TopicDescriptor {
|
use quick_protobuf::MessageWrite;
|
||||||
|
|
||||||
|
let topic_descripter = proto::TopicDescriptor {
|
||||||
name: Some(topic_string),
|
name: Some(topic_string),
|
||||||
auth: None,
|
auth: None,
|
||||||
enc: None,
|
enc: None,
|
||||||
};
|
};
|
||||||
let mut bytes = Vec::with_capacity(topic_descripter.encoded_len());
|
let mut bytes = Vec::with_capacity(topic_descripter.get_size());
|
||||||
|
let mut writer = Writer::new(&mut bytes);
|
||||||
topic_descripter
|
topic_descripter
|
||||||
.encode(&mut bytes)
|
.write_message(&mut writer)
|
||||||
.expect("buffer is large enough");
|
.expect("Encoding to succeed");
|
||||||
let hash = BASE64_STANDARD.encode(Sha256::digest(&bytes));
|
let hash = BASE64_STANDARD.encode(Sha256::digest(&bytes));
|
||||||
TopicHash { hash }
|
TopicHash { hash }
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,15 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
//! A collection of types using the Gossipsub system.
|
//! A collection of types using the Gossipsub system.
|
||||||
use crate::rpc_proto;
|
|
||||||
use crate::TopicHash;
|
use crate::TopicHash;
|
||||||
use libp2p_core::PeerId;
|
use libp2p_core::PeerId;
|
||||||
use libp2p_swarm::ConnectionId;
|
use libp2p_swarm::ConnectionId;
|
||||||
use prometheus_client::encoding::EncodeLabelValue;
|
use prometheus_client::encoding::EncodeLabelValue;
|
||||||
use prost::Message as _;
|
use quick_protobuf::MessageWrite;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::rpc_proto::proto;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ pub struct RawMessage {
|
|||||||
impl RawMessage {
|
impl RawMessage {
|
||||||
/// Calculates the encoded length of this message (used for calculating metrics).
|
/// Calculates the encoded length of this message (used for calculating metrics).
|
||||||
pub fn raw_protobuf_len(&self) -> usize {
|
pub fn raw_protobuf_len(&self) -> usize {
|
||||||
let message = rpc_proto::Message {
|
let message = proto::Message {
|
||||||
from: self.source.map(|m| m.to_bytes()),
|
from: self.source.map(|m| m.to_bytes()),
|
||||||
data: Some(self.data.clone()),
|
data: Some(self.data.clone()),
|
||||||
seqno: self.sequence_number.map(|s| s.to_be_bytes().to_vec()),
|
seqno: self.sequence_number.map(|s| s.to_be_bytes().to_vec()),
|
||||||
@ -144,7 +144,7 @@ impl RawMessage {
|
|||||||
signature: self.signature.clone(),
|
signature: self.signature.clone(),
|
||||||
key: self.key.clone(),
|
key: self.key.clone(),
|
||||||
};
|
};
|
||||||
message.encoded_len()
|
message.get_size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,19 +250,19 @@ pub struct Rpc {
|
|||||||
impl Rpc {
|
impl Rpc {
|
||||||
/// Converts the GossipsubRPC into its protobuf format.
|
/// Converts the GossipsubRPC into its protobuf format.
|
||||||
// A convenience function to avoid explicitly specifying types.
|
// A convenience function to avoid explicitly specifying types.
|
||||||
pub fn into_protobuf(self) -> rpc_proto::Rpc {
|
pub fn into_protobuf(self) -> proto::RPC {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rpc> for rpc_proto::Rpc {
|
impl From<Rpc> for proto::RPC {
|
||||||
/// Converts the RPC into protobuf format.
|
/// Converts the RPC into protobuf format.
|
||||||
fn from(rpc: Rpc) -> Self {
|
fn from(rpc: Rpc) -> Self {
|
||||||
// Messages
|
// Messages
|
||||||
let mut publish = Vec::new();
|
let mut publish = Vec::new();
|
||||||
|
|
||||||
for message in rpc.messages.into_iter() {
|
for message in rpc.messages.into_iter() {
|
||||||
let message = rpc_proto::Message {
|
let message = proto::Message {
|
||||||
from: message.source.map(|m| m.to_bytes()),
|
from: message.source.map(|m| m.to_bytes()),
|
||||||
data: Some(message.data),
|
data: Some(message.data),
|
||||||
seqno: message.sequence_number.map(|s| s.to_be_bytes().to_vec()),
|
seqno: message.sequence_number.map(|s| s.to_be_bytes().to_vec()),
|
||||||
@ -278,14 +278,14 @@ impl From<Rpc> for rpc_proto::Rpc {
|
|||||||
let subscriptions = rpc
|
let subscriptions = rpc
|
||||||
.subscriptions
|
.subscriptions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|sub| rpc_proto::rpc::SubOpts {
|
.map(|sub| proto::SubOpts {
|
||||||
subscribe: Some(sub.action == SubscriptionAction::Subscribe),
|
subscribe: Some(sub.action == SubscriptionAction::Subscribe),
|
||||||
topic_id: Some(sub.topic_hash.into_string()),
|
topic_id: Some(sub.topic_hash.into_string()),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// control messages
|
// control messages
|
||||||
let mut control = rpc_proto::ControlMessage {
|
let mut control = proto::ControlMessage {
|
||||||
ihave: Vec::new(),
|
ihave: Vec::new(),
|
||||||
iwant: Vec::new(),
|
iwant: Vec::new(),
|
||||||
graft: Vec::new(),
|
graft: Vec::new(),
|
||||||
@ -301,20 +301,20 @@ impl From<Rpc> for rpc_proto::Rpc {
|
|||||||
topic_hash,
|
topic_hash,
|
||||||
message_ids,
|
message_ids,
|
||||||
} => {
|
} => {
|
||||||
let rpc_ihave = rpc_proto::ControlIHave {
|
let rpc_ihave = proto::ControlIHave {
|
||||||
topic_id: Some(topic_hash.into_string()),
|
topic_id: Some(topic_hash.into_string()),
|
||||||
message_ids: message_ids.into_iter().map(|msg_id| msg_id.0).collect(),
|
message_ids: message_ids.into_iter().map(|msg_id| msg_id.0).collect(),
|
||||||
};
|
};
|
||||||
control.ihave.push(rpc_ihave);
|
control.ihave.push(rpc_ihave);
|
||||||
}
|
}
|
||||||
ControlAction::IWant { message_ids } => {
|
ControlAction::IWant { message_ids } => {
|
||||||
let rpc_iwant = rpc_proto::ControlIWant {
|
let rpc_iwant = proto::ControlIWant {
|
||||||
message_ids: message_ids.into_iter().map(|msg_id| msg_id.0).collect(),
|
message_ids: message_ids.into_iter().map(|msg_id| msg_id.0).collect(),
|
||||||
};
|
};
|
||||||
control.iwant.push(rpc_iwant);
|
control.iwant.push(rpc_iwant);
|
||||||
}
|
}
|
||||||
ControlAction::Graft { topic_hash } => {
|
ControlAction::Graft { topic_hash } => {
|
||||||
let rpc_graft = rpc_proto::ControlGraft {
|
let rpc_graft = proto::ControlGraft {
|
||||||
topic_id: Some(topic_hash.into_string()),
|
topic_id: Some(topic_hash.into_string()),
|
||||||
};
|
};
|
||||||
control.graft.push(rpc_graft);
|
control.graft.push(rpc_graft);
|
||||||
@ -324,11 +324,11 @@ impl From<Rpc> for rpc_proto::Rpc {
|
|||||||
peers,
|
peers,
|
||||||
backoff,
|
backoff,
|
||||||
} => {
|
} => {
|
||||||
let rpc_prune = rpc_proto::ControlPrune {
|
let rpc_prune = proto::ControlPrune {
|
||||||
topic_id: Some(topic_hash.into_string()),
|
topic_id: Some(topic_hash.into_string()),
|
||||||
peers: peers
|
peers: peers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|info| rpc_proto::PeerInfo {
|
.map(|info| proto::PeerInfo {
|
||||||
peer_id: info.peer_id.map(|id| id.to_bytes()),
|
peer_id: info.peer_id.map(|id| id.to_bytes()),
|
||||||
/// TODO, see https://github.com/libp2p/specs/pull/217
|
/// TODO, see https://github.com/libp2p/specs/pull/217
|
||||||
signed_peer_record: None,
|
signed_peer_record: None,
|
||||||
@ -341,7 +341,7 @@ impl From<Rpc> for rpc_proto::Rpc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_proto::Rpc {
|
proto::RPC {
|
||||||
subscriptions,
|
subscriptions,
|
||||||
publish,
|
publish,
|
||||||
control: if empty_control_msg {
|
control: if empty_control_msg {
|
||||||
|
@ -9,8 +9,11 @@
|
|||||||
|
|
||||||
- Don't close the stream when reading the identify info in `protocol::recv`. See [PR 3344].
|
- Don't close the stream when reading the identify info in `protocol::recv`. See [PR 3344].
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[PR 3208]: https://github.com/libp2p/rust-libp2p/pull/3208
|
[PR 3208]: https://github.com/libp2p/rust-libp2p/pull/3208
|
||||||
[PR 3344]: https://github.com/libp2p/rust-libp2p/pull/3344
|
[PR 3344]: https://github.com/libp2p/rust-libp2p/pull/3344
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.41.1
|
# 0.41.1
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ libp2p-core = { version = "0.39.0", path = "../../core" }
|
|||||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
lru = "0.9.0"
|
lru = "0.9.0"
|
||||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
void = "1.0"
|
void = "1.0"
|
||||||
@ -34,9 +34,6 @@ libp2p-noise = { path = "../../transports/noise" }
|
|||||||
libp2p-swarm = { path = "../../swarm", features = ["async-std"] }
|
libp2p-swarm = { path = "../../swarm", features = ["async-std"] }
|
||||||
libp2p-tcp = { path = "../../transports/tcp", features = ["async-io"] }
|
libp2p-tcp = { path = "../../transports/tcp", features = ["async-io"] }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||||
# More information: https://docs.rs/about/builds#cross-compiling
|
# More information: https://docs.rs/about/builds#cross-compiling
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/structs.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
2
protocols/identify/src/generated/mod.rs
Normal file
2
protocols/identify/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod structs;
|
67
protocols/identify/src/generated/structs.rs
Normal file
67
protocols/identify/src/generated/structs.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Automatically generated rust module for 'structs.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Identify {
|
||||||
|
pub protocolVersion: Option<String>,
|
||||||
|
pub agentVersion: Option<String>,
|
||||||
|
pub publicKey: Option<Vec<u8>>,
|
||||||
|
pub listenAddrs: Vec<Vec<u8>>,
|
||||||
|
pub observedAddr: Option<Vec<u8>>,
|
||||||
|
pub protocols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Identify {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(42) => msg.protocolVersion = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(50) => msg.agentVersion = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(10) => msg.publicKey = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.listenAddrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(34) => msg.observedAddr = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.protocols.push(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Identify {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.protocolVersion.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.agentVersion.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.publicKey.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.listenAddrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
+ self.observedAddr.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.protocols.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.protocolVersion { w.write_with_tag(42, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.agentVersion { w.write_with_tag(50, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.publicKey { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.listenAddrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.observedAddr { w.write_with_tag(34, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.protocols { w.write_with_tag(26, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ mod behaviour;
|
|||||||
mod handler;
|
mod handler;
|
||||||
mod protocol;
|
mod protocol;
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod structs_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/structs.rs"));
|
pub use self::structs::Identify;
|
||||||
}
|
}
|
||||||
|
2
protocols/identify/src/mod.rs
Normal file
2
protocols/identify/src/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod structs;
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::structs_proto;
|
use crate::proto;
|
||||||
use asynchronous_codec::{FramedRead, FramedWrite};
|
use asynchronous_codec::{FramedRead, FramedWrite};
|
||||||
use futures::{future::BoxFuture, prelude::*};
|
use futures::{future::BoxFuture, prelude::*};
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
@ -169,18 +169,18 @@ where
|
|||||||
|
|
||||||
let pubkey_bytes = info.public_key.to_protobuf_encoding();
|
let pubkey_bytes = info.public_key.to_protobuf_encoding();
|
||||||
|
|
||||||
let message = structs_proto::Identify {
|
let message = proto::Identify {
|
||||||
agent_version: Some(info.agent_version),
|
agentVersion: Some(info.agent_version),
|
||||||
protocol_version: Some(info.protocol_version),
|
protocolVersion: Some(info.protocol_version),
|
||||||
public_key: Some(pubkey_bytes),
|
publicKey: Some(pubkey_bytes),
|
||||||
listen_addrs,
|
listenAddrs: listen_addrs,
|
||||||
observed_addr: Some(info.observed_addr.to_vec()),
|
observedAddr: Some(info.observed_addr.to_vec()),
|
||||||
protocols: info.protocols,
|
protocols: info.protocols,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut framed_io = FramedWrite::new(
|
let mut framed_io = FramedWrite::new(
|
||||||
io,
|
io,
|
||||||
prost_codec::Codec::<structs_proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
quick_protobuf_codec::Codec::<proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
||||||
);
|
);
|
||||||
|
|
||||||
framed_io.send(message).await?;
|
framed_io.send(message).await?;
|
||||||
@ -200,7 +200,7 @@ where
|
|||||||
|
|
||||||
let info = FramedRead::new(
|
let info = FramedRead::new(
|
||||||
socket,
|
socket,
|
||||||
prost_codec::Codec::<structs_proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
quick_protobuf_codec::Codec::<proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
||||||
)
|
)
|
||||||
.next()
|
.next()
|
||||||
.await
|
.await
|
||||||
@ -212,17 +212,17 @@ where
|
|||||||
Ok(info)
|
Ok(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<structs_proto::Identify> for Info {
|
impl TryFrom<proto::Identify> for Info {
|
||||||
type Error = UpgradeError;
|
type Error = UpgradeError;
|
||||||
|
|
||||||
fn try_from(msg: structs_proto::Identify) -> Result<Self, Self::Error> {
|
fn try_from(msg: proto::Identify) -> Result<Self, Self::Error> {
|
||||||
fn parse_multiaddr(bytes: Vec<u8>) -> Result<Multiaddr, multiaddr::Error> {
|
fn parse_multiaddr(bytes: Vec<u8>) -> Result<Multiaddr, multiaddr::Error> {
|
||||||
Multiaddr::try_from(bytes)
|
Multiaddr::try_from(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
let listen_addrs = {
|
let listen_addrs = {
|
||||||
let mut addrs = Vec::new();
|
let mut addrs = Vec::new();
|
||||||
for addr in msg.listen_addrs.into_iter() {
|
for addr in msg.listenAddrs.into_iter() {
|
||||||
match parse_multiaddr(addr) {
|
match parse_multiaddr(addr) {
|
||||||
Ok(a) => addrs.push(a),
|
Ok(a) => addrs.push(a),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -233,9 +233,9 @@ impl TryFrom<structs_proto::Identify> for Info {
|
|||||||
addrs
|
addrs
|
||||||
};
|
};
|
||||||
|
|
||||||
let public_key = PublicKey::from_protobuf_encoding(&msg.public_key.unwrap_or_default())?;
|
let public_key = PublicKey::from_protobuf_encoding(&msg.publicKey.unwrap_or_default())?;
|
||||||
|
|
||||||
let observed_addr = match parse_multiaddr(msg.observed_addr.unwrap_or_default()) {
|
let observed_addr = match parse_multiaddr(msg.observedAddr.unwrap_or_default()) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Unable to parse multiaddr: {e:?}");
|
debug!("Unable to parse multiaddr: {e:?}");
|
||||||
@ -244,8 +244,8 @@ impl TryFrom<structs_proto::Identify> for Info {
|
|||||||
};
|
};
|
||||||
let info = Info {
|
let info = Info {
|
||||||
public_key,
|
public_key,
|
||||||
protocol_version: msg.protocol_version.unwrap_or_default(),
|
protocol_version: msg.protocolVersion.unwrap_or_default(),
|
||||||
agent_version: msg.agent_version.unwrap_or_default(),
|
agent_version: msg.agentVersion.unwrap_or_default(),
|
||||||
listen_addrs,
|
listen_addrs,
|
||||||
protocols: msg.protocols,
|
protocols: msg.protocols,
|
||||||
observed_addr,
|
observed_addr,
|
||||||
@ -258,7 +258,7 @@ impl TryFrom<structs_proto::Identify> for Info {
|
|||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum UpgradeError {
|
pub enum UpgradeError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Codec(#[from] prost_codec::Error),
|
Codec(#[from] quick_protobuf_codec::Error),
|
||||||
#[error("I/O interaction failed")]
|
#[error("I/O interaction failed")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
#[error("Stream closed")]
|
#[error("Stream closed")]
|
||||||
@ -375,13 +375,13 @@ mod tests {
|
|||||||
a
|
a
|
||||||
};
|
};
|
||||||
|
|
||||||
let payload = structs_proto::Identify {
|
let payload = proto::Identify {
|
||||||
agent_version: None,
|
agentVersion: None,
|
||||||
listen_addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
listenAddrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||||
observed_addr: None,
|
observedAddr: None,
|
||||||
protocol_version: None,
|
protocolVersion: None,
|
||||||
protocols: vec![],
|
protocols: vec![],
|
||||||
public_key: Some(
|
publicKey: Some(
|
||||||
identity::Keypair::generate_ed25519()
|
identity::Keypair::generate_ed25519()
|
||||||
.public()
|
.public()
|
||||||
.to_protobuf_encoding(),
|
.to_protobuf_encoding(),
|
||||||
|
67
protocols/identify/src/structs.rs
Normal file
67
protocols/identify/src/structs.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Automatically generated rust module for 'structs.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Identify {
|
||||||
|
pub protocolVersion: Option<String>,
|
||||||
|
pub agentVersion: Option<String>,
|
||||||
|
pub publicKey: Option<Vec<u8>>,
|
||||||
|
pub listenAddrs: Vec<Vec<u8>>,
|
||||||
|
pub observedAddr: Option<Vec<u8>>,
|
||||||
|
pub protocols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Identify {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(42) => msg.protocolVersion = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(50) => msg.agentVersion = Some(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(10) => msg.publicKey = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(18) => msg.listenAddrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(34) => msg.observedAddr = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.protocols.push(r.read_string(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Identify {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.protocolVersion.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.agentVersion.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.publicKey.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.listenAddrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
+ self.observedAddr.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
+ self.protocols.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.protocolVersion { w.write_with_tag(42, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.agentVersion { w.write_with_tag(50, |w| w.write_string(&**s))?; }
|
||||||
|
if let Some(ref s) = self.publicKey { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.listenAddrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.observedAddr { w.write_with_tag(34, |w| w.write_bytes(&**s))?; }
|
||||||
|
for s in &self.protocols { w.write_with_tag(26, |w| w.write_string(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,8 +10,11 @@
|
|||||||
|
|
||||||
- Bump MSRV to 1.65.0.
|
- Bump MSRV to 1.65.0.
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[PR 3239]: https://github.com/libp2p/rust-libp2p/pull/3239
|
[PR 3239]: https://github.com/libp2p/rust-libp2p/pull/3239
|
||||||
[PR 3287]: https://github.com/libp2p/rust-libp2p/pull/3287
|
[PR 3287]: https://github.com/libp2p/rust-libp2p/pull/3287
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.42.1
|
# 0.42.1
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ futures = "0.3.26"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||||
prost = "0.11"
|
quick-protobuf = "0.8"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
sha2 = "0.10.0"
|
sha2 = "0.10.0"
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
@ -39,9 +39,6 @@ libp2p-noise = { path = "../../transports/noise" }
|
|||||||
libp2p-yamux = { path = "../../muxers/yamux" }
|
libp2p-yamux = { path = "../../muxers/yamux" }
|
||||||
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
|
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
serde = ["dep:serde", "bytes/serde"]
|
serde = ["dep:serde", "bytes/serde"]
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/dht.proto"], &["src"]).unwrap();
|
|
||||||
}
|
|
2
protocols/kad/src/generated/dht/mod.rs
Normal file
2
protocols/kad/src/generated/dht/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
243
protocols/kad/src/generated/dht/pb.rs
Normal file
243
protocols/kad/src/generated/dht/pb.rs
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
// Automatically generated rust module for 'dht.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Record {
|
||||||
|
pub key: Vec<u8>,
|
||||||
|
pub value: Vec<u8>,
|
||||||
|
pub timeReceived: String,
|
||||||
|
pub publisher: Vec<u8>,
|
||||||
|
pub ttl: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Record {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.key = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(18) => msg.value = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(42) => msg.timeReceived = r.read_string(bytes)?.to_owned(),
|
||||||
|
Ok(5330) => msg.publisher = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(6216) => msg.ttl = r.read_uint32(bytes)?,
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Record {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ if self.key.is_empty() { 0 } else { 1 + sizeof_len((&self.key).len()) }
|
||||||
|
+ if self.value.is_empty() { 0 } else { 1 + sizeof_len((&self.value).len()) }
|
||||||
|
+ if self.timeReceived == String::default() { 0 } else { 1 + sizeof_len((&self.timeReceived).len()) }
|
||||||
|
+ if self.publisher.is_empty() { 0 } else { 2 + sizeof_len((&self.publisher).len()) }
|
||||||
|
+ if self.ttl == 0u32 { 0 } else { 2 + sizeof_varint(*(&self.ttl) as u64) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if !self.key.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.key))?; }
|
||||||
|
if !self.value.is_empty() { w.write_with_tag(18, |w| w.write_bytes(&**&self.value))?; }
|
||||||
|
if self.timeReceived != String::default() { w.write_with_tag(42, |w| w.write_string(&**&self.timeReceived))?; }
|
||||||
|
if !self.publisher.is_empty() { w.write_with_tag(5330, |w| w.write_bytes(&**&self.publisher))?; }
|
||||||
|
if self.ttl != 0u32 { w.write_with_tag(6216, |w| w.write_uint32(*&self.ttl))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Message {
|
||||||
|
pub type_pb: dht::pb::mod_Message::MessageType,
|
||||||
|
pub clusterLevelRaw: i32,
|
||||||
|
pub key: Vec<u8>,
|
||||||
|
pub record: Option<dht::pb::Record>,
|
||||||
|
pub closerPeers: Vec<dht::pb::mod_Message::Peer>,
|
||||||
|
pub providerPeers: Vec<dht::pb::mod_Message::Peer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Message {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.type_pb = r.read_enum(bytes)?,
|
||||||
|
Ok(80) => msg.clusterLevelRaw = r.read_int32(bytes)?,
|
||||||
|
Ok(18) => msg.key = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(26) => msg.record = Some(r.read_message::<dht::pb::Record>(bytes)?),
|
||||||
|
Ok(66) => msg.closerPeers.push(r.read_message::<dht::pb::mod_Message::Peer>(bytes)?),
|
||||||
|
Ok(74) => msg.providerPeers.push(r.read_message::<dht::pb::mod_Message::Peer>(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Message {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ if self.type_pb == dht::pb::mod_Message::MessageType::PUT_VALUE { 0 } else { 1 + sizeof_varint(*(&self.type_pb) as u64) }
|
||||||
|
+ if self.clusterLevelRaw == 0i32 { 0 } else { 1 + sizeof_varint(*(&self.clusterLevelRaw) as u64) }
|
||||||
|
+ if self.key.is_empty() { 0 } else { 1 + sizeof_len((&self.key).len()) }
|
||||||
|
+ self.record.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.closerPeers.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
+ self.providerPeers.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if self.type_pb != dht::pb::mod_Message::MessageType::PUT_VALUE { w.write_with_tag(8, |w| w.write_enum(*&self.type_pb as i32))?; }
|
||||||
|
if self.clusterLevelRaw != 0i32 { w.write_with_tag(80, |w| w.write_int32(*&self.clusterLevelRaw))?; }
|
||||||
|
if !self.key.is_empty() { w.write_with_tag(18, |w| w.write_bytes(&**&self.key))?; }
|
||||||
|
if let Some(ref s) = self.record { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.closerPeers { w.write_with_tag(66, |w| w.write_message(s))?; }
|
||||||
|
for s in &self.providerPeers { w.write_with_tag(74, |w| w.write_message(s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_Message {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Peer {
|
||||||
|
pub id: Vec<u8>,
|
||||||
|
pub addrs: Vec<Vec<u8>>,
|
||||||
|
pub connection: dht::pb::mod_Message::ConnectionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Peer {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.id = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(18) => msg.addrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(24) => msg.connection = r.read_enum(bytes)?,
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Peer {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ if self.id.is_empty() { 0 } else { 1 + sizeof_len((&self.id).len()) }
|
||||||
|
+ self.addrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
+ if self.connection == dht::pb::mod_Message::ConnectionType::NOT_CONNECTED { 0 } else { 1 + sizeof_varint(*(&self.connection) as u64) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if !self.id.is_empty() { w.write_with_tag(10, |w| w.write_bytes(&**&self.id))?; }
|
||||||
|
for s in &self.addrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if self.connection != dht::pb::mod_Message::ConnectionType::NOT_CONNECTED { w.write_with_tag(24, |w| w.write_enum(*&self.connection as i32))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum MessageType {
|
||||||
|
PUT_VALUE = 0,
|
||||||
|
GET_VALUE = 1,
|
||||||
|
ADD_PROVIDER = 2,
|
||||||
|
GET_PROVIDERS = 3,
|
||||||
|
FIND_NODE = 4,
|
||||||
|
PING = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MessageType {
|
||||||
|
fn default() -> Self {
|
||||||
|
MessageType::PUT_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for MessageType {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => MessageType::PUT_VALUE,
|
||||||
|
1 => MessageType::GET_VALUE,
|
||||||
|
2 => MessageType::ADD_PROVIDER,
|
||||||
|
3 => MessageType::GET_PROVIDERS,
|
||||||
|
4 => MessageType::FIND_NODE,
|
||||||
|
5 => MessageType::PING,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for MessageType {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"PUT_VALUE" => MessageType::PUT_VALUE,
|
||||||
|
"GET_VALUE" => MessageType::GET_VALUE,
|
||||||
|
"ADD_PROVIDER" => MessageType::ADD_PROVIDER,
|
||||||
|
"GET_PROVIDERS" => MessageType::GET_PROVIDERS,
|
||||||
|
"FIND_NODE" => MessageType::FIND_NODE,
|
||||||
|
"PING" => MessageType::PING,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum ConnectionType {
|
||||||
|
NOT_CONNECTED = 0,
|
||||||
|
CONNECTED = 1,
|
||||||
|
CAN_CONNECT = 2,
|
||||||
|
CANNOT_CONNECT = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ConnectionType {
|
||||||
|
fn default() -> Self {
|
||||||
|
ConnectionType::NOT_CONNECTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for ConnectionType {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => ConnectionType::NOT_CONNECTED,
|
||||||
|
1 => ConnectionType::CONNECTED,
|
||||||
|
2 => ConnectionType::CAN_CONNECT,
|
||||||
|
3 => ConnectionType::CANNOT_CONNECT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for ConnectionType {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"NOT_CONNECTED" => ConnectionType::NOT_CONNECTED,
|
||||||
|
"CONNECTED" => ConnectionType::CONNECTED,
|
||||||
|
"CAN_CONNECT" => ConnectionType::CAN_CONNECT,
|
||||||
|
"CANNOT_CONNECT" => ConnectionType::CANNOT_CONNECT,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
2
protocols/kad/src/generated/mod.rs
Normal file
2
protocols/kad/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod dht;
|
@ -48,9 +48,12 @@ mod behaviour;
|
|||||||
mod jobs;
|
mod jobs;
|
||||||
mod query;
|
mod query;
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod dht_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/dht.pb.rs"));
|
pub use self::dht::pb::{
|
||||||
|
mod_Message::{ConnectionType, MessageType, Peer},
|
||||||
|
Message, Record,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use addresses::Addresses;
|
pub use addresses::Addresses;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
//! to poll the underlying transport for incoming messages, and the `Sink` component
|
//! to poll the underlying transport for incoming messages, and the `Sink` component
|
||||||
//! is used to send messages to remote peers.
|
//! is used to send messages to remote peers.
|
||||||
|
|
||||||
use crate::dht_proto as proto;
|
use crate::proto;
|
||||||
use crate::record::{self, Record};
|
use crate::record::{self, Record};
|
||||||
use asynchronous_codec::Framed;
|
use asynchronous_codec::Framed;
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
@ -35,7 +35,7 @@ use futures::prelude::*;
|
|||||||
use instant::Instant;
|
use instant::Instant;
|
||||||
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
||||||
use libp2p_core::{Multiaddr, PeerId};
|
use libp2p_core::{Multiaddr, PeerId};
|
||||||
use prost::Message;
|
use quick_protobuf::{BytesReader, Writer};
|
||||||
use std::{borrow::Cow, convert::TryFrom, time::Duration};
|
use std::{borrow::Cow, convert::TryFrom, time::Duration};
|
||||||
use std::{io, iter};
|
use std::{io, iter};
|
||||||
use unsigned_varint::codec;
|
use unsigned_varint::codec;
|
||||||
@ -59,26 +59,26 @@ pub enum KadConnectionType {
|
|||||||
CannotConnect = 3,
|
CannotConnect = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<proto::message::ConnectionType> for KadConnectionType {
|
impl From<proto::ConnectionType> for KadConnectionType {
|
||||||
fn from(raw: proto::message::ConnectionType) -> KadConnectionType {
|
fn from(raw: proto::ConnectionType) -> KadConnectionType {
|
||||||
use proto::message::ConnectionType::*;
|
use proto::ConnectionType::*;
|
||||||
match raw {
|
match raw {
|
||||||
NotConnected => KadConnectionType::NotConnected,
|
NOT_CONNECTED => KadConnectionType::NotConnected,
|
||||||
Connected => KadConnectionType::Connected,
|
CONNECTED => KadConnectionType::Connected,
|
||||||
CanConnect => KadConnectionType::CanConnect,
|
CAN_CONNECT => KadConnectionType::CanConnect,
|
||||||
CannotConnect => KadConnectionType::CannotConnect,
|
CANNOT_CONNECT => KadConnectionType::CannotConnect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<KadConnectionType> for proto::message::ConnectionType {
|
impl From<KadConnectionType> for proto::ConnectionType {
|
||||||
fn from(val: KadConnectionType) -> Self {
|
fn from(val: KadConnectionType) -> Self {
|
||||||
use proto::message::ConnectionType::*;
|
use proto::ConnectionType::*;
|
||||||
match val {
|
match val {
|
||||||
KadConnectionType::NotConnected => NotConnected,
|
KadConnectionType::NotConnected => NOT_CONNECTED,
|
||||||
KadConnectionType::Connected => Connected,
|
KadConnectionType::Connected => CONNECTED,
|
||||||
KadConnectionType::CanConnect => CanConnect,
|
KadConnectionType::CanConnect => CAN_CONNECT,
|
||||||
KadConnectionType::CannotConnect => CannotConnect,
|
KadConnectionType::CannotConnect => CANNOT_CONNECT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,10 +95,10 @@ pub struct KadPeer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Builds a `KadPeer` from a corresponding protobuf message.
|
// Builds a `KadPeer` from a corresponding protobuf message.
|
||||||
impl TryFrom<proto::message::Peer> for KadPeer {
|
impl TryFrom<proto::Peer> for KadPeer {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn try_from(peer: proto::message::Peer) -> Result<KadPeer, Self::Error> {
|
fn try_from(peer: proto::Peer) -> Result<KadPeer, Self::Error> {
|
||||||
// TODO: this is in fact a CID; not sure if this should be handled in `from_bytes` or
|
// TODO: this is in fact a CID; not sure if this should be handled in `from_bytes` or
|
||||||
// as a special case here
|
// as a special case here
|
||||||
let node_id = PeerId::from_bytes(&peer.id).map_err(|_| invalid_data("invalid peer id"))?;
|
let node_id = PeerId::from_bytes(&peer.id).map_err(|_| invalid_data("invalid peer id"))?;
|
||||||
@ -113,27 +113,20 @@ impl TryFrom<proto::message::Peer> for KadPeer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let connection_ty = proto::message::ConnectionType::from_i32(peer.connection)
|
|
||||||
.ok_or_else(|| invalid_data("unknown connection type"))?
|
|
||||||
.into();
|
|
||||||
|
|
||||||
Ok(KadPeer {
|
Ok(KadPeer {
|
||||||
node_id,
|
node_id,
|
||||||
multiaddrs: addrs,
|
multiaddrs: addrs,
|
||||||
connection_ty,
|
connection_ty: peer.connection.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<KadPeer> for proto::message::Peer {
|
impl From<KadPeer> for proto::Peer {
|
||||||
fn from(peer: KadPeer) -> Self {
|
fn from(peer: KadPeer) -> Self {
|
||||||
proto::message::Peer {
|
proto::Peer {
|
||||||
id: peer.node_id.to_bytes(),
|
id: peer.node_id.to_bytes(),
|
||||||
addrs: peer.multiaddrs.into_iter().map(|a| a.to_vec()).collect(),
|
addrs: peer.multiaddrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||||
connection: {
|
connection: peer.connection_ty.into(),
|
||||||
let ct: proto::message::ConnectionType = peer.connection_ty.into();
|
|
||||||
ct as i32
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,6 +188,8 @@ where
|
|||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn upgrade_inbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
fn upgrade_inbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
||||||
|
use quick_protobuf::{MessageRead, MessageWrite};
|
||||||
|
|
||||||
let mut codec = UviBytes::default();
|
let mut codec = UviBytes::default();
|
||||||
codec.set_max_len(self.max_packet_size);
|
codec.set_max_len(self.max_packet_size);
|
||||||
|
|
||||||
@ -203,14 +198,16 @@ where
|
|||||||
.err_into()
|
.err_into()
|
||||||
.with::<_, _, fn(_) -> _, _>(|response| {
|
.with::<_, _, fn(_) -> _, _>(|response| {
|
||||||
let proto_struct = resp_msg_to_proto(response);
|
let proto_struct = resp_msg_to_proto(response);
|
||||||
let mut buf = Vec::with_capacity(proto_struct.encoded_len());
|
let mut buf = Vec::with_capacity(proto_struct.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
proto_struct
|
proto_struct
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
future::ready(Ok(io::Cursor::new(buf)))
|
future::ready(Ok(io::Cursor::new(buf)))
|
||||||
})
|
})
|
||||||
.and_then::<_, fn(_) -> _>(|bytes| {
|
.and_then::<_, fn(_) -> _>(|bytes| {
|
||||||
let request = match proto::Message::decode(bytes) {
|
let mut reader = BytesReader::from_bytes(&bytes);
|
||||||
|
let request = match proto::Message::from_reader(&mut reader, &bytes) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(err) => return future::ready(Err(err.into())),
|
Err(err) => return future::ready(Err(err.into())),
|
||||||
};
|
};
|
||||||
@ -229,6 +226,8 @@ where
|
|||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn upgrade_outbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
fn upgrade_outbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
||||||
|
use quick_protobuf::{MessageRead, MessageWrite};
|
||||||
|
|
||||||
let mut codec = UviBytes::default();
|
let mut codec = UviBytes::default();
|
||||||
codec.set_max_len(self.max_packet_size);
|
codec.set_max_len(self.max_packet_size);
|
||||||
|
|
||||||
@ -237,14 +236,16 @@ where
|
|||||||
.err_into()
|
.err_into()
|
||||||
.with::<_, _, fn(_) -> _, _>(|request| {
|
.with::<_, _, fn(_) -> _, _>(|request| {
|
||||||
let proto_struct = req_msg_to_proto(request);
|
let proto_struct = req_msg_to_proto(request);
|
||||||
let mut buf = Vec::with_capacity(proto_struct.encoded_len());
|
let mut buf = Vec::with_capacity(proto_struct.get_size());
|
||||||
|
let mut writer = Writer::new(&mut buf);
|
||||||
proto_struct
|
proto_struct
|
||||||
.encode(&mut buf)
|
.write_message(&mut writer)
|
||||||
.expect("Vec<u8> provides capacity as needed");
|
.expect("Encoding to succeed");
|
||||||
future::ready(Ok(io::Cursor::new(buf)))
|
future::ready(Ok(io::Cursor::new(buf)))
|
||||||
})
|
})
|
||||||
.and_then::<_, fn(_) -> _>(|bytes| {
|
.and_then::<_, fn(_) -> _>(|bytes| {
|
||||||
let response = match proto::Message::decode(bytes) {
|
let mut reader = BytesReader::from_bytes(&bytes);
|
||||||
|
let response = match proto::Message::from_reader(&mut reader, &bytes) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(err) => return future::ready(Err(err.into())),
|
Err(err) => return future::ready(Err(err.into())),
|
||||||
};
|
};
|
||||||
@ -351,36 +352,36 @@ pub enum KadResponseMsg {
|
|||||||
fn req_msg_to_proto(kad_msg: KadRequestMsg) -> proto::Message {
|
fn req_msg_to_proto(kad_msg: KadRequestMsg) -> proto::Message {
|
||||||
match kad_msg {
|
match kad_msg {
|
||||||
KadRequestMsg::Ping => proto::Message {
|
KadRequestMsg::Ping => proto::Message {
|
||||||
r#type: proto::message::MessageType::Ping as i32,
|
type_pb: proto::MessageType::PING,
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadRequestMsg::FindNode { key } => proto::Message {
|
KadRequestMsg::FindNode { key } => proto::Message {
|
||||||
r#type: proto::message::MessageType::FindNode as i32,
|
type_pb: proto::MessageType::FIND_NODE,
|
||||||
key,
|
key,
|
||||||
cluster_level_raw: 10,
|
clusterLevelRaw: 10,
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadRequestMsg::GetProviders { key } => proto::Message {
|
KadRequestMsg::GetProviders { key } => proto::Message {
|
||||||
r#type: proto::message::MessageType::GetProviders as i32,
|
type_pb: proto::MessageType::GET_PROVIDERS,
|
||||||
key: key.to_vec(),
|
key: key.to_vec(),
|
||||||
cluster_level_raw: 10,
|
clusterLevelRaw: 10,
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadRequestMsg::AddProvider { key, provider } => proto::Message {
|
KadRequestMsg::AddProvider { key, provider } => proto::Message {
|
||||||
r#type: proto::message::MessageType::AddProvider as i32,
|
type_pb: proto::MessageType::ADD_PROVIDER,
|
||||||
cluster_level_raw: 10,
|
clusterLevelRaw: 10,
|
||||||
key: key.to_vec(),
|
key: key.to_vec(),
|
||||||
provider_peers: vec![provider.into()],
|
providerPeers: vec![provider.into()],
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadRequestMsg::GetValue { key } => proto::Message {
|
KadRequestMsg::GetValue { key } => proto::Message {
|
||||||
r#type: proto::message::MessageType::GetValue as i32,
|
type_pb: proto::MessageType::GET_VALUE,
|
||||||
cluster_level_raw: 10,
|
clusterLevelRaw: 10,
|
||||||
key: key.to_vec(),
|
key: key.to_vec(),
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadRequestMsg::PutValue { record } => proto::Message {
|
KadRequestMsg::PutValue { record } => proto::Message {
|
||||||
r#type: proto::message::MessageType::PutValue as i32,
|
type_pb: proto::MessageType::PUT_VALUE,
|
||||||
key: record.key.to_vec(),
|
key: record.key.to_vec(),
|
||||||
record: Some(record_to_proto(record)),
|
record: Some(record_to_proto(record)),
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
@ -392,37 +393,37 @@ fn req_msg_to_proto(kad_msg: KadRequestMsg) -> proto::Message {
|
|||||||
fn resp_msg_to_proto(kad_msg: KadResponseMsg) -> proto::Message {
|
fn resp_msg_to_proto(kad_msg: KadResponseMsg) -> proto::Message {
|
||||||
match kad_msg {
|
match kad_msg {
|
||||||
KadResponseMsg::Pong => proto::Message {
|
KadResponseMsg::Pong => proto::Message {
|
||||||
r#type: proto::message::MessageType::Ping as i32,
|
type_pb: proto::MessageType::PING,
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadResponseMsg::FindNode { closer_peers } => proto::Message {
|
KadResponseMsg::FindNode { closer_peers } => proto::Message {
|
||||||
r#type: proto::message::MessageType::FindNode as i32,
|
type_pb: proto::MessageType::FIND_NODE,
|
||||||
cluster_level_raw: 9,
|
clusterLevelRaw: 9,
|
||||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadResponseMsg::GetProviders {
|
KadResponseMsg::GetProviders {
|
||||||
closer_peers,
|
closer_peers,
|
||||||
provider_peers,
|
provider_peers,
|
||||||
} => proto::Message {
|
} => proto::Message {
|
||||||
r#type: proto::message::MessageType::GetProviders as i32,
|
type_pb: proto::MessageType::GET_PROVIDERS,
|
||||||
cluster_level_raw: 9,
|
clusterLevelRaw: 9,
|
||||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||||
provider_peers: provider_peers.into_iter().map(KadPeer::into).collect(),
|
providerPeers: provider_peers.into_iter().map(KadPeer::into).collect(),
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadResponseMsg::GetValue {
|
KadResponseMsg::GetValue {
|
||||||
record,
|
record,
|
||||||
closer_peers,
|
closer_peers,
|
||||||
} => proto::Message {
|
} => proto::Message {
|
||||||
r#type: proto::message::MessageType::GetValue as i32,
|
type_pb: proto::MessageType::GET_VALUE,
|
||||||
cluster_level_raw: 9,
|
clusterLevelRaw: 9,
|
||||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||||
record: record.map(record_to_proto),
|
record: record.map(record_to_proto),
|
||||||
..proto::Message::default()
|
..proto::Message::default()
|
||||||
},
|
},
|
||||||
KadResponseMsg::PutValue { key, value } => proto::Message {
|
KadResponseMsg::PutValue { key, value } => proto::Message {
|
||||||
r#type: proto::message::MessageType::PutValue as i32,
|
type_pb: proto::MessageType::PUT_VALUE,
|
||||||
key: key.to_vec(),
|
key: key.to_vec(),
|
||||||
record: Some(proto::Record {
|
record: Some(proto::Record {
|
||||||
key: key.to_vec(),
|
key: key.to_vec(),
|
||||||
@ -438,28 +439,25 @@ fn resp_msg_to_proto(kad_msg: KadResponseMsg) -> proto::Message {
|
|||||||
///
|
///
|
||||||
/// Fails if the protobuf message is not a valid and supported Kademlia request message.
|
/// Fails if the protobuf message is not a valid and supported Kademlia request message.
|
||||||
fn proto_to_req_msg(message: proto::Message) -> Result<KadRequestMsg, io::Error> {
|
fn proto_to_req_msg(message: proto::Message) -> Result<KadRequestMsg, io::Error> {
|
||||||
let msg_type = proto::message::MessageType::from_i32(message.r#type)
|
match message.type_pb {
|
||||||
.ok_or_else(|| invalid_data(format!("unknown message type: {}", message.r#type)))?;
|
proto::MessageType::PING => Ok(KadRequestMsg::Ping),
|
||||||
|
proto::MessageType::PUT_VALUE => {
|
||||||
match msg_type {
|
|
||||||
proto::message::MessageType::Ping => Ok(KadRequestMsg::Ping),
|
|
||||||
proto::message::MessageType::PutValue => {
|
|
||||||
let record = record_from_proto(message.record.unwrap_or_default())?;
|
let record = record_from_proto(message.record.unwrap_or_default())?;
|
||||||
Ok(KadRequestMsg::PutValue { record })
|
Ok(KadRequestMsg::PutValue { record })
|
||||||
}
|
}
|
||||||
proto::message::MessageType::GetValue => Ok(KadRequestMsg::GetValue {
|
proto::MessageType::GET_VALUE => Ok(KadRequestMsg::GetValue {
|
||||||
key: record::Key::from(message.key),
|
key: record::Key::from(message.key),
|
||||||
}),
|
}),
|
||||||
proto::message::MessageType::FindNode => Ok(KadRequestMsg::FindNode { key: message.key }),
|
proto::MessageType::FIND_NODE => Ok(KadRequestMsg::FindNode { key: message.key }),
|
||||||
proto::message::MessageType::GetProviders => Ok(KadRequestMsg::GetProviders {
|
proto::MessageType::GET_PROVIDERS => Ok(KadRequestMsg::GetProviders {
|
||||||
key: record::Key::from(message.key),
|
key: record::Key::from(message.key),
|
||||||
}),
|
}),
|
||||||
proto::message::MessageType::AddProvider => {
|
proto::MessageType::ADD_PROVIDER => {
|
||||||
// TODO: for now we don't parse the peer properly, so it is possible that we get
|
// TODO: for now we don't parse the peer properly, so it is possible that we get
|
||||||
// parsing errors for peers even when they are valid; we ignore these
|
// parsing errors for peers even when they are valid; we ignore these
|
||||||
// errors for now, but ultimately we should just error altogether
|
// errors for now, but ultimately we should just error altogether
|
||||||
let provider = message
|
let provider = message
|
||||||
.provider_peers
|
.providerPeers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find_map(|peer| KadPeer::try_from(peer).ok());
|
.find_map(|peer| KadPeer::try_from(peer).ok());
|
||||||
|
|
||||||
@ -477,12 +475,9 @@ fn proto_to_req_msg(message: proto::Message) -> Result<KadRequestMsg, io::Error>
|
|||||||
///
|
///
|
||||||
/// Fails if the protobuf message is not a valid and supported Kademlia response message.
|
/// Fails if the protobuf message is not a valid and supported Kademlia response message.
|
||||||
fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Error> {
|
fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Error> {
|
||||||
let msg_type = proto::message::MessageType::from_i32(message.r#type)
|
match message.type_pb {
|
||||||
.ok_or_else(|| invalid_data(format!("unknown message type: {}", message.r#type)))?;
|
proto::MessageType::PING => Ok(KadResponseMsg::Pong),
|
||||||
|
proto::MessageType::GET_VALUE => {
|
||||||
match msg_type {
|
|
||||||
proto::message::MessageType::Ping => Ok(KadResponseMsg::Pong),
|
|
||||||
proto::message::MessageType::GetValue => {
|
|
||||||
let record = if let Some(r) = message.record {
|
let record = if let Some(r) = message.record {
|
||||||
Some(record_from_proto(r)?)
|
Some(record_from_proto(r)?)
|
||||||
} else {
|
} else {
|
||||||
@ -490,7 +485,7 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
|||||||
};
|
};
|
||||||
|
|
||||||
let closer_peers = message
|
let closer_peers = message
|
||||||
.closer_peers
|
.closerPeers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||||
.collect();
|
.collect();
|
||||||
@ -501,9 +496,9 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
proto::message::MessageType::FindNode => {
|
proto::MessageType::FIND_NODE => {
|
||||||
let closer_peers = message
|
let closer_peers = message
|
||||||
.closer_peers
|
.closerPeers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||||
.collect();
|
.collect();
|
||||||
@ -511,15 +506,15 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
|||||||
Ok(KadResponseMsg::FindNode { closer_peers })
|
Ok(KadResponseMsg::FindNode { closer_peers })
|
||||||
}
|
}
|
||||||
|
|
||||||
proto::message::MessageType::GetProviders => {
|
proto::MessageType::GET_PROVIDERS => {
|
||||||
let closer_peers = message
|
let closer_peers = message
|
||||||
.closer_peers
|
.closerPeers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let provider_peers = message
|
let provider_peers = message
|
||||||
.provider_peers
|
.providerPeers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||||
.collect();
|
.collect();
|
||||||
@ -530,7 +525,7 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
proto::message::MessageType::PutValue => {
|
proto::MessageType::PUT_VALUE => {
|
||||||
let key = record::Key::from(message.key);
|
let key = record::Key::from(message.key);
|
||||||
let rec = message
|
let rec = message
|
||||||
.record
|
.record
|
||||||
@ -542,7 +537,7 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
proto::message::MessageType::AddProvider => {
|
proto::MessageType::ADD_PROVIDER => {
|
||||||
Err(invalid_data("received an unexpected AddProvider message"))
|
Err(invalid_data("received an unexpected AddProvider message"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,7 +585,7 @@ fn record_to_proto(record: Record) -> proto::Record {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
time_received: String::new(),
|
timeReceived: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,10 +612,10 @@ mod tests {
|
|||||||
a
|
a
|
||||||
};
|
};
|
||||||
|
|
||||||
let payload = proto::message::Peer {
|
let payload = proto::Peer {
|
||||||
id: PeerId::random().to_bytes(),
|
id: PeerId::random().to_bytes(),
|
||||||
addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||||
connection: proto::message::ConnectionType::CanConnect.into(),
|
connection: proto::ConnectionType::CAN_CONNECT,
|
||||||
};
|
};
|
||||||
|
|
||||||
let peer = KadPeer::try_from(payload).expect("not to fail");
|
let peer = KadPeer::try_from(payload).expect("not to fail");
|
||||||
|
@ -11,8 +11,11 @@
|
|||||||
|
|
||||||
- Update to `libp2p-swarm` `v0.42.0`.
|
- Update to `libp2p-swarm` `v0.42.0`.
|
||||||
|
|
||||||
|
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||||
|
|
||||||
[PR 3238]: https://github.com/libp2p/rust-libp2p/pull/3238
|
[PR 3238]: https://github.com/libp2p/rust-libp2p/pull/3238
|
||||||
[discussion 2174]: https://github.com/libp2p/rust-libp2p/issues/2174
|
[discussion 2174]: https://github.com/libp2p/rust-libp2p/issues/2174
|
||||||
|
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||||
|
|
||||||
# 0.14.0
|
# 0.14.0
|
||||||
|
|
||||||
|
@ -20,16 +20,13 @@ instant = "0.1.11"
|
|||||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
quick-protobuf = "0.8"
|
||||||
prost = "0.11"
|
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
static_assertions = "1"
|
static_assertions = "1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
void = "1"
|
void = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
prost-build = "0.11"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
clap = { version = "4.1.6", features = ["derive"] }
|
clap = { version = "4.1.6", features = ["derive"] }
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
prost_build::compile_protos(&["src/message.proto"], &["src/"]).unwrap();
|
|
||||||
}
|
|
@ -24,8 +24,8 @@ mod handler;
|
|||||||
pub mod rate_limiter;
|
pub mod rate_limiter;
|
||||||
|
|
||||||
use crate::behaviour::handler::Handler;
|
use crate::behaviour::handler::Handler;
|
||||||
use crate::message_proto;
|
|
||||||
use crate::multiaddr_ext::MultiaddrExt;
|
use crate::multiaddr_ext::MultiaddrExt;
|
||||||
|
use crate::proto;
|
||||||
use crate::protocol::{inbound_hop, outbound_stop};
|
use crate::protocol::{inbound_hop, outbound_stop};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use instant::Instant;
|
use instant::Instant;
|
||||||
@ -381,7 +381,7 @@ impl NetworkBehaviour for Behaviour {
|
|||||||
peer_id: event_source,
|
peer_id: event_source,
|
||||||
event: Either::Left(handler::In::DenyReservationReq {
|
event: Either::Left(handler::In::DenyReservationReq {
|
||||||
inbound_reservation_req,
|
inbound_reservation_req,
|
||||||
status: message_proto::Status::ResourceLimitExceeded,
|
status: proto::Status::RESOURCE_LIMIT_EXCEEDED,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
@ -496,7 +496,7 @@ impl NetworkBehaviour for Behaviour {
|
|||||||
event: Either::Left(handler::In::DenyCircuitReq {
|
event: Either::Left(handler::In::DenyCircuitReq {
|
||||||
circuit_id: None,
|
circuit_id: None,
|
||||||
inbound_circuit_req,
|
inbound_circuit_req,
|
||||||
status: message_proto::Status::ResourceLimitExceeded,
|
status: proto::Status::RESOURCE_LIMIT_EXCEEDED,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
} else if let Some(dst_conn) = self
|
} else if let Some(dst_conn) = self
|
||||||
@ -532,7 +532,7 @@ impl NetworkBehaviour for Behaviour {
|
|||||||
event: Either::Left(handler::In::DenyCircuitReq {
|
event: Either::Left(handler::In::DenyCircuitReq {
|
||||||
circuit_id: None,
|
circuit_id: None,
|
||||||
inbound_circuit_req,
|
inbound_circuit_req,
|
||||||
status: message_proto::Status::NoReservation,
|
status: proto::Status::NO_RESERVATION,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
use crate::behaviour::CircuitId;
|
use crate::behaviour::CircuitId;
|
||||||
use crate::copy_future::CopyFuture;
|
use crate::copy_future::CopyFuture;
|
||||||
use crate::message_proto::Status;
|
use crate::proto;
|
||||||
use crate::protocol::{inbound_hop, outbound_stop};
|
use crate::protocol::{inbound_hop, outbound_stop};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
@ -58,12 +58,12 @@ pub enum In {
|
|||||||
},
|
},
|
||||||
DenyReservationReq {
|
DenyReservationReq {
|
||||||
inbound_reservation_req: inbound_hop::ReservationReq,
|
inbound_reservation_req: inbound_hop::ReservationReq,
|
||||||
status: Status,
|
status: proto::Status,
|
||||||
},
|
},
|
||||||
DenyCircuitReq {
|
DenyCircuitReq {
|
||||||
circuit_id: Option<CircuitId>,
|
circuit_id: Option<CircuitId>,
|
||||||
inbound_circuit_req: inbound_hop::CircuitReq,
|
inbound_circuit_req: inbound_hop::CircuitReq,
|
||||||
status: Status,
|
status: proto::Status,
|
||||||
},
|
},
|
||||||
NegotiateOutboundConnect {
|
NegotiateOutboundConnect {
|
||||||
circuit_id: CircuitId,
|
circuit_id: CircuitId,
|
||||||
@ -208,7 +208,7 @@ pub enum Event {
|
|||||||
src_peer_id: PeerId,
|
src_peer_id: PeerId,
|
||||||
src_connection_id: ConnectionId,
|
src_connection_id: ConnectionId,
|
||||||
inbound_circuit_req: inbound_hop::CircuitReq,
|
inbound_circuit_req: inbound_hop::CircuitReq,
|
||||||
status: Status,
|
status: proto::Status,
|
||||||
error: ConnectionHandlerUpgrErr<outbound_stop::CircuitFailedReason>,
|
error: ConnectionHandlerUpgrErr<outbound_stop::CircuitFailedReason>,
|
||||||
},
|
},
|
||||||
/// An inbound circuit has closed.
|
/// An inbound circuit has closed.
|
||||||
@ -522,12 +522,14 @@ impl Handler {
|
|||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let (non_fatal_error, status) = match error {
|
let (non_fatal_error, status) = match error {
|
||||||
ConnectionHandlerUpgrErr::Timeout => {
|
ConnectionHandlerUpgrErr::Timeout => (
|
||||||
(ConnectionHandlerUpgrErr::Timeout, Status::ConnectionFailed)
|
ConnectionHandlerUpgrErr::Timeout,
|
||||||
}
|
proto::Status::CONNECTION_FAILED,
|
||||||
ConnectionHandlerUpgrErr::Timer => {
|
),
|
||||||
(ConnectionHandlerUpgrErr::Timer, Status::ConnectionFailed)
|
ConnectionHandlerUpgrErr::Timer => (
|
||||||
}
|
ConnectionHandlerUpgrErr::Timer,
|
||||||
|
proto::Status::CONNECTION_FAILED,
|
||||||
|
),
|
||||||
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
|
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
|
||||||
upgrade::NegotiationError::Failed,
|
upgrade::NegotiationError::Failed,
|
||||||
)) => {
|
)) => {
|
||||||
@ -556,10 +558,10 @@ impl Handler {
|
|||||||
outbound_stop::UpgradeError::CircuitFailed(error) => {
|
outbound_stop::UpgradeError::CircuitFailed(error) => {
|
||||||
let status = match error {
|
let status = match error {
|
||||||
outbound_stop::CircuitFailedReason::ResourceLimitExceeded => {
|
outbound_stop::CircuitFailedReason::ResourceLimitExceeded => {
|
||||||
Status::ResourceLimitExceeded
|
proto::Status::RESOURCE_LIMIT_EXCEEDED
|
||||||
}
|
}
|
||||||
outbound_stop::CircuitFailedReason::PermissionDenied => {
|
outbound_stop::CircuitFailedReason::PermissionDenied => {
|
||||||
Status::PermissionDenied
|
proto::Status::PERMISSION_DENIED
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
|
2
protocols/relay/src/generated/message_v2/mod.rs
Normal file
2
protocols/relay/src/generated/message_v2/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod pb;
|
346
protocols/relay/src/generated/message_v2/pb.rs
Normal file
346
protocols/relay/src/generated/message_v2/pb.rs
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
// Automatically generated rust module for 'message.proto' file
|
||||||
|
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(unknown_lints)]
|
||||||
|
#![allow(clippy::all)]
|
||||||
|
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
||||||
|
|
||||||
|
use quick_protobuf::{MessageInfo, MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
|
||||||
|
use quick_protobuf::sizeofs::*;
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Status {
|
||||||
|
OK = 100,
|
||||||
|
RESERVATION_REFUSED = 200,
|
||||||
|
RESOURCE_LIMIT_EXCEEDED = 201,
|
||||||
|
PERMISSION_DENIED = 202,
|
||||||
|
CONNECTION_FAILED = 203,
|
||||||
|
NO_RESERVATION = 204,
|
||||||
|
MALFORMED_MESSAGE = 400,
|
||||||
|
UNEXPECTED_MESSAGE = 401,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Status {
|
||||||
|
fn default() -> Self {
|
||||||
|
Status::OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Status {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
100 => Status::OK,
|
||||||
|
200 => Status::RESERVATION_REFUSED,
|
||||||
|
201 => Status::RESOURCE_LIMIT_EXCEEDED,
|
||||||
|
202 => Status::PERMISSION_DENIED,
|
||||||
|
203 => Status::CONNECTION_FAILED,
|
||||||
|
204 => Status::NO_RESERVATION,
|
||||||
|
400 => Status::MALFORMED_MESSAGE,
|
||||||
|
401 => Status::UNEXPECTED_MESSAGE,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for Status {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"OK" => Status::OK,
|
||||||
|
"RESERVATION_REFUSED" => Status::RESERVATION_REFUSED,
|
||||||
|
"RESOURCE_LIMIT_EXCEEDED" => Status::RESOURCE_LIMIT_EXCEEDED,
|
||||||
|
"PERMISSION_DENIED" => Status::PERMISSION_DENIED,
|
||||||
|
"CONNECTION_FAILED" => Status::CONNECTION_FAILED,
|
||||||
|
"NO_RESERVATION" => Status::NO_RESERVATION,
|
||||||
|
"MALFORMED_MESSAGE" => Status::MALFORMED_MESSAGE,
|
||||||
|
"UNEXPECTED_MESSAGE" => Status::UNEXPECTED_MESSAGE,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct HopMessage {
|
||||||
|
pub type_pb: message_v2::pb::mod_HopMessage::Type,
|
||||||
|
pub peer: Option<message_v2::pb::Peer>,
|
||||||
|
pub reservation: Option<message_v2::pb::Reservation>,
|
||||||
|
pub limit: Option<message_v2::pb::Limit>,
|
||||||
|
pub status: Option<message_v2::pb::Status>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for HopMessage {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.type_pb = r.read_enum(bytes)?,
|
||||||
|
Ok(18) => msg.peer = Some(r.read_message::<message_v2::pb::Peer>(bytes)?),
|
||||||
|
Ok(26) => msg.reservation = Some(r.read_message::<message_v2::pb::Reservation>(bytes)?),
|
||||||
|
Ok(34) => msg.limit = Some(r.read_message::<message_v2::pb::Limit>(bytes)?),
|
||||||
|
Ok(40) => msg.status = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for HopMessage {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.type_pb) as u64)
|
||||||
|
+ self.peer.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.reservation.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.limit.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.status.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_enum(*&self.type_pb as i32))?;
|
||||||
|
if let Some(ref s) = self.peer { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.reservation { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.limit { w.write_with_tag(34, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.status { w.write_with_tag(40, |w| w.write_enum(*s as i32))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_HopMessage {
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Type {
|
||||||
|
RESERVE = 0,
|
||||||
|
CONNECT = 1,
|
||||||
|
STATUS = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Type {
|
||||||
|
fn default() -> Self {
|
||||||
|
Type::RESERVE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Type {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => Type::RESERVE,
|
||||||
|
1 => Type::CONNECT,
|
||||||
|
2 => Type::STATUS,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for Type {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"RESERVE" => Type::RESERVE,
|
||||||
|
"CONNECT" => Type::CONNECT,
|
||||||
|
"STATUS" => Type::STATUS,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct StopMessage {
|
||||||
|
pub type_pb: message_v2::pb::mod_StopMessage::Type,
|
||||||
|
pub peer: Option<message_v2::pb::Peer>,
|
||||||
|
pub limit: Option<message_v2::pb::Limit>,
|
||||||
|
pub status: Option<message_v2::pb::Status>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for StopMessage {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.type_pb = r.read_enum(bytes)?,
|
||||||
|
Ok(18) => msg.peer = Some(r.read_message::<message_v2::pb::Peer>(bytes)?),
|
||||||
|
Ok(26) => msg.limit = Some(r.read_message::<message_v2::pb::Limit>(bytes)?),
|
||||||
|
Ok(32) => msg.status = Some(r.read_enum(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for StopMessage {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.type_pb) as u64)
|
||||||
|
+ self.peer.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.limit.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
|
||||||
|
+ self.status.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_enum(*&self.type_pb as i32))?;
|
||||||
|
if let Some(ref s) = self.peer { w.write_with_tag(18, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.limit { w.write_with_tag(26, |w| w.write_message(s))?; }
|
||||||
|
if let Some(ref s) = self.status { w.write_with_tag(32, |w| w.write_enum(*s as i32))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod mod_StopMessage {
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Type {
|
||||||
|
CONNECT = 0,
|
||||||
|
STATUS = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Type {
|
||||||
|
fn default() -> Self {
|
||||||
|
Type::CONNECT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Type {
|
||||||
|
fn from(i: i32) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => Type::CONNECT,
|
||||||
|
1 => Type::STATUS,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for Type {
|
||||||
|
fn from(s: &'a str) -> Self {
|
||||||
|
match s {
|
||||||
|
"CONNECT" => Type::CONNECT,
|
||||||
|
"STATUS" => Type::STATUS,
|
||||||
|
_ => Self::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Peer {
|
||||||
|
pub id: Vec<u8>,
|
||||||
|
pub addrs: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Peer {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(10) => msg.id = r.read_bytes(bytes)?.to_owned(),
|
||||||
|
Ok(18) => msg.addrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Peer {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_len((&self.id).len())
|
||||||
|
+ self.addrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(10, |w| w.write_bytes(&**&self.id))?;
|
||||||
|
for s in &self.addrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Reservation {
|
||||||
|
pub expire: u64,
|
||||||
|
pub addrs: Vec<Vec<u8>>,
|
||||||
|
pub voucher: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Reservation {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.expire = r.read_uint64(bytes)?,
|
||||||
|
Ok(18) => msg.addrs.push(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(26) => msg.voucher = Some(r.read_bytes(bytes)?.to_owned()),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Reservation {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ 1 + sizeof_varint(*(&self.expire) as u64)
|
||||||
|
+ self.addrs.iter().map(|s| 1 + sizeof_len((s).len())).sum::<usize>()
|
||||||
|
+ self.voucher.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
w.write_with_tag(8, |w| w.write_uint64(*&self.expire))?;
|
||||||
|
for s in &self.addrs { w.write_with_tag(18, |w| w.write_bytes(&**s))?; }
|
||||||
|
if let Some(ref s) = self.voucher { w.write_with_tag(26, |w| w.write_bytes(&**s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct Limit {
|
||||||
|
pub duration: Option<u32>,
|
||||||
|
pub data: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MessageRead<'a> for Limit {
|
||||||
|
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
let mut msg = Self::default();
|
||||||
|
while !r.is_eof() {
|
||||||
|
match r.next_tag(bytes) {
|
||||||
|
Ok(8) => msg.duration = Some(r.read_uint32(bytes)?),
|
||||||
|
Ok(16) => msg.data = Some(r.read_uint64(bytes)?),
|
||||||
|
Ok(t) => { r.read_unknown(bytes, t)?; }
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageWrite for Limit {
|
||||||
|
fn get_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
+ self.duration.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
+ self.data.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
|
||||||
|
if let Some(ref s) = self.duration { w.write_with_tag(8, |w| w.write_uint32(*s))?; }
|
||||||
|
if let Some(ref s) = self.data { w.write_with_tag(16, |w| w.write_uint64(*s))?; }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
protocols/relay/src/generated/mod.rs
Normal file
2
protocols/relay/src/generated/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Automatically generated mod.rs
|
||||||
|
pub mod message_v2;
|
@ -30,9 +30,11 @@ mod priv_client;
|
|||||||
mod protocol;
|
mod protocol;
|
||||||
pub mod v2;
|
pub mod v2;
|
||||||
|
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
mod proto {
|
||||||
mod message_proto {
|
include!("generated/mod.rs");
|
||||||
include!(concat!(env!("OUT_DIR"), "/message_v2.pb.rs"));
|
pub use self::message_v2::pb::mod_HopMessage::Type as HopMessageType;
|
||||||
|
pub use self::message_v2::pb::mod_StopMessage::Type as StopMessageType;
|
||||||
|
pub use self::message_v2::pb::{HopMessage, Limit, Peer, Reservation, Status, StopMessage};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use behaviour::{Behaviour, CircuitId, Config, Event};
|
pub use behaviour::{Behaviour, CircuitId, Config, Event};
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::message_proto::Status;
|
|
||||||
use crate::priv_client::transport;
|
use crate::priv_client::transport;
|
||||||
|
use crate::proto;
|
||||||
use crate::protocol::{self, inbound_stop, outbound_hop};
|
use crate::protocol::{self, inbound_stop, outbound_hop};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use futures::channel::{mpsc, oneshot};
|
use futures::channel::{mpsc, oneshot};
|
||||||
@ -218,7 +218,7 @@ impl Handler {
|
|||||||
.circuit_deny_futs
|
.circuit_deny_futs
|
||||||
.insert(
|
.insert(
|
||||||
src_peer_id,
|
src_peer_id,
|
||||||
inbound_circuit.deny(Status::NoReservation).boxed(),
|
inbound_circuit.deny(proto::Status::NO_RESERVATION).boxed(),
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::message_proto;
|
use crate::proto;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub mod inbound_hop;
|
pub mod inbound_hop;
|
||||||
@ -37,8 +37,8 @@ pub struct Limit {
|
|||||||
data_in_bytes: Option<u64>,
|
data_in_bytes: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<message_proto::Limit> for Limit {
|
impl From<proto::Limit> for Limit {
|
||||||
fn from(limit: message_proto::Limit) -> Self {
|
fn from(limit: proto::Limit) -> Self {
|
||||||
Limit {
|
Limit {
|
||||||
duration: limit.duration.map(|d| Duration::from_secs(d.into())),
|
duration: limit.duration.map(|d| Duration::from_secs(d.into())),
|
||||||
data_in_bytes: limit.data,
|
data_in_bytes: limit.data,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::message_proto::{hop_message, HopMessage, Limit, Reservation, Status};
|
use crate::proto;
|
||||||
use crate::protocol::{HOP_PROTOCOL_NAME, MAX_MESSAGE_SIZE};
|
use crate::protocol::{HOP_PROTOCOL_NAME, MAX_MESSAGE_SIZE};
|
||||||
use asynchronous_codec::{Framed, FramedParts};
|
use asynchronous_codec::{Framed, FramedParts};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@ -51,11 +51,14 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||||
|
|
||||||
fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
||||||
let mut substream = Framed::new(substream, prost_codec::Codec::new(MAX_MESSAGE_SIZE));
|
let mut substream = Framed::new(
|
||||||
|
substream,
|
||||||
|
quick_protobuf_codec::Codec::new(MAX_MESSAGE_SIZE),
|
||||||
|
);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let HopMessage {
|
let proto::HopMessage {
|
||||||
r#type,
|
type_pb,
|
||||||
peer,
|
peer,
|
||||||
reservation: _,
|
reservation: _,
|
||||||
limit: _,
|
limit: _,
|
||||||
@ -65,21 +68,19 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
|||||||
.await
|
.await
|
||||||
.ok_or(FatalUpgradeError::StreamClosed)??;
|
.ok_or(FatalUpgradeError::StreamClosed)??;
|
||||||
|
|
||||||
let r#type =
|
let req = match type_pb {
|
||||||
hop_message::Type::from_i32(r#type).ok_or(FatalUpgradeError::ParseTypeField)?;
|
proto::HopMessageType::RESERVE => Req::Reserve(ReservationReq {
|
||||||
let req = match r#type {
|
|
||||||
hop_message::Type::Reserve => Req::Reserve(ReservationReq {
|
|
||||||
substream,
|
substream,
|
||||||
reservation_duration: self.reservation_duration,
|
reservation_duration: self.reservation_duration,
|
||||||
max_circuit_duration: self.max_circuit_duration,
|
max_circuit_duration: self.max_circuit_duration,
|
||||||
max_circuit_bytes: self.max_circuit_bytes,
|
max_circuit_bytes: self.max_circuit_bytes,
|
||||||
}),
|
}),
|
||||||
hop_message::Type::Connect => {
|
proto::HopMessageType::CONNECT => {
|
||||||
let dst = PeerId::from_bytes(&peer.ok_or(FatalUpgradeError::MissingPeer)?.id)
|
let dst = PeerId::from_bytes(&peer.ok_or(FatalUpgradeError::MissingPeer)?.id)
|
||||||
.map_err(|_| FatalUpgradeError::ParsePeerId)?;
|
.map_err(|_| FatalUpgradeError::ParsePeerId)?;
|
||||||
Req::Connect(CircuitReq { dst, substream })
|
Req::Connect(CircuitReq { dst, substream })
|
||||||
}
|
}
|
||||||
hop_message::Type::Status => {
|
proto::HopMessageType::STATUS => {
|
||||||
return Err(FatalUpgradeError::UnexpectedTypeStatus.into())
|
return Err(FatalUpgradeError::UnexpectedTypeStatus.into())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -96,8 +97,8 @@ pub enum UpgradeError {
|
|||||||
Fatal(#[from] FatalUpgradeError),
|
Fatal(#[from] FatalUpgradeError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<prost_codec::Error> for UpgradeError {
|
impl From<quick_protobuf_codec::Error> for UpgradeError {
|
||||||
fn from(error: prost_codec::Error) -> Self {
|
fn from(error: quick_protobuf_codec::Error) -> Self {
|
||||||
Self::Fatal(error.into())
|
Self::Fatal(error.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ impl From<prost_codec::Error> for UpgradeError {
|
|||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum FatalUpgradeError {
|
pub enum FatalUpgradeError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Codec(#[from] prost_codec::Error),
|
Codec(#[from] quick_protobuf_codec::Error),
|
||||||
#[error("Stream closed")]
|
#[error("Stream closed")]
|
||||||
StreamClosed,
|
StreamClosed,
|
||||||
#[error("Failed to parse response type field.")]
|
#[error("Failed to parse response type field.")]
|
||||||
@ -124,7 +125,7 @@ pub enum Req {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReservationReq {
|
pub struct ReservationReq {
|
||||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HopMessage>>,
|
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HopMessage>>,
|
||||||
reservation_duration: Duration,
|
reservation_duration: Duration,
|
||||||
max_circuit_duration: Duration,
|
max_circuit_duration: Duration,
|
||||||
max_circuit_bytes: u64,
|
max_circuit_bytes: u64,
|
||||||
@ -132,10 +133,10 @@ pub struct ReservationReq {
|
|||||||
|
|
||||||
impl ReservationReq {
|
impl ReservationReq {
|
||||||
pub async fn accept(self, addrs: Vec<Multiaddr>) -> Result<(), UpgradeError> {
|
pub async fn accept(self, addrs: Vec<Multiaddr>) -> Result<(), UpgradeError> {
|
||||||
let msg = HopMessage {
|
let msg = proto::HopMessage {
|
||||||
r#type: hop_message::Type::Status.into(),
|
type_pb: proto::HopMessageType::STATUS,
|
||||||
peer: None,
|
peer: None,
|
||||||
reservation: Some(Reservation {
|
reservation: Some(proto::Reservation {
|
||||||
addrs: addrs.into_iter().map(|a| a.to_vec()).collect(),
|
addrs: addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||||
expire: (SystemTime::now() + self.reservation_duration)
|
expire: (SystemTime::now() + self.reservation_duration)
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
@ -143,7 +144,7 @@ impl ReservationReq {
|
|||||||
.as_secs(),
|
.as_secs(),
|
||||||
voucher: None,
|
voucher: None,
|
||||||
}),
|
}),
|
||||||
limit: Some(Limit {
|
limit: Some(proto::Limit {
|
||||||
duration: Some(
|
duration: Some(
|
||||||
self.max_circuit_duration
|
self.max_circuit_duration
|
||||||
.as_secs()
|
.as_secs()
|
||||||
@ -152,25 +153,25 @@ impl ReservationReq {
|
|||||||
),
|
),
|
||||||
data: Some(self.max_circuit_bytes),
|
data: Some(self.max_circuit_bytes),
|
||||||
}),
|
}),
|
||||||
status: Some(Status::Ok.into()),
|
status: Some(proto::Status::OK),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.send(msg).await
|
self.send(msg).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn deny(self, status: Status) -> Result<(), UpgradeError> {
|
pub async fn deny(self, status: proto::Status) -> Result<(), UpgradeError> {
|
||||||
let msg = HopMessage {
|
let msg = proto::HopMessage {
|
||||||
r#type: hop_message::Type::Status.into(),
|
type_pb: proto::HopMessageType::STATUS,
|
||||||
peer: None,
|
peer: None,
|
||||||
reservation: None,
|
reservation: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
status: Some(status.into()),
|
status: Some(status),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.send(msg).await
|
self.send(msg).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send(mut self, msg: HopMessage) -> Result<(), UpgradeError> {
|
async fn send(mut self, msg: proto::HopMessage) -> Result<(), UpgradeError> {
|
||||||
self.substream.send(msg).await?;
|
self.substream.send(msg).await?;
|
||||||
self.substream.flush().await?;
|
self.substream.flush().await?;
|
||||||
self.substream.close().await?;
|
self.substream.close().await?;
|
||||||
@ -181,7 +182,7 @@ impl ReservationReq {
|
|||||||
|
|
||||||
pub struct CircuitReq {
|
pub struct CircuitReq {
|
||||||
dst: PeerId,
|
dst: PeerId,
|
||||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HopMessage>>,
|
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HopMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CircuitReq {
|
impl CircuitReq {
|
||||||
@ -190,12 +191,12 @@ impl CircuitReq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn accept(mut self) -> Result<(NegotiatedSubstream, Bytes), UpgradeError> {
|
pub async fn accept(mut self) -> Result<(NegotiatedSubstream, Bytes), UpgradeError> {
|
||||||
let msg = HopMessage {
|
let msg = proto::HopMessage {
|
||||||
r#type: hop_message::Type::Status.into(),
|
type_pb: proto::HopMessageType::STATUS,
|
||||||
peer: None,
|
peer: None,
|
||||||
reservation: None,
|
reservation: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
status: Some(Status::Ok.into()),
|
status: Some(proto::Status::OK),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.send(msg).await?;
|
self.send(msg).await?;
|
||||||
@ -214,19 +215,19 @@ impl CircuitReq {
|
|||||||
Ok((io, read_buffer.freeze()))
|
Ok((io, read_buffer.freeze()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn deny(mut self, status: Status) -> Result<(), UpgradeError> {
|
pub async fn deny(mut self, status: proto::Status) -> Result<(), UpgradeError> {
|
||||||
let msg = HopMessage {
|
let msg = proto::HopMessage {
|
||||||
r#type: hop_message::Type::Status.into(),
|
type_pb: proto::HopMessageType::STATUS,
|
||||||
peer: None,
|
peer: None,
|
||||||
reservation: None,
|
reservation: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
status: Some(status.into()),
|
status: Some(status),
|
||||||
};
|
};
|
||||||
self.send(msg).await?;
|
self.send(msg).await?;
|
||||||
self.substream.close().await.map_err(Into::into)
|
self.substream.close().await.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send(&mut self, msg: HopMessage) -> Result<(), prost_codec::Error> {
|
async fn send(&mut self, msg: proto::HopMessage) -> Result<(), quick_protobuf_codec::Error> {
|
||||||
self.substream.send(msg).await?;
|
self.substream.send(msg).await?;
|
||||||
self.substream.flush().await?;
|
self.substream.flush().await?;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user