mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-12 01:21:21 +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)"
|
||||
exit 1
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
@ -2177,8 +2171,7 @@ dependencies = [
|
||||
"libp2p-tcp",
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"quick-protobuf",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
@ -2208,8 +2201,7 @@ dependencies = [
|
||||
"p256 0.12.0",
|
||||
"parking_lot 0.12.1",
|
||||
"pin-project",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"quick-protobuf",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"ring",
|
||||
@ -2248,9 +2240,8 @@ dependencies = [
|
||||
"libp2p-tcp",
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"rand 0.8.5",
|
||||
"thiserror",
|
||||
"void",
|
||||
@ -2296,9 +2287,8 @@ dependencies = [
|
||||
"libp2p-core",
|
||||
"libp2p-swarm",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"rand 0.8.5",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
@ -2327,9 +2317,8 @@ dependencies = [
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prometheus-client",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
@ -2359,9 +2348,8 @@ dependencies = [
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"lru",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"void",
|
||||
@ -2385,8 +2373,7 @@ dependencies = [
|
||||
"libp2p-swarm",
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"quick-protobuf",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@ -2493,8 +2480,7 @@ dependencies = [
|
||||
"libsodium-sys-stable",
|
||||
"log",
|
||||
"once_cell",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"quick-protobuf",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.10.6",
|
||||
@ -2536,8 +2522,7 @@ dependencies = [
|
||||
"futures",
|
||||
"libp2p-core",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"quick-protobuf",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"unsigned-varint",
|
||||
@ -2611,9 +2596,8 @@ dependencies = [
|
||||
"libp2p-tcp",
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"quickcheck-ext",
|
||||
"rand 0.8.5",
|
||||
"static_assertions",
|
||||
@ -2641,9 +2625,8 @@ dependencies = [
|
||||
"libp2p-tcp",
|
||||
"libp2p-yamux",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"rand 0.8.5",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
@ -2787,9 +2770,8 @@ dependencies = [
|
||||
"libp2p-swarm",
|
||||
"log",
|
||||
"multihash",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-codec",
|
||||
"quick-protobuf",
|
||||
"quick-protobuf-codec",
|
||||
"quickcheck",
|
||||
"rand 0.8.5",
|
||||
"rcgen 0.9.3",
|
||||
@ -3103,12 +3085,6 @@ dependencies = [
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||
|
||||
[[package]]
|
||||
name = "multistream-select"
|
||||
version = "0.12.1"
|
||||
@ -3441,16 +3417,6 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "pin-project"
|
||||
version = "1.0.12"
|
||||
@ -3593,16 +3559,6 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "primeorder"
|
||||
version = "0.12.1"
|
||||
@ -3678,78 +3634,32 @@ dependencies = [
|
||||
"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]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "quickcheck"
|
||||
version = "1.0.3"
|
||||
@ -5374,17 +5284,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "widestring"
|
||||
version = "0.5.1"
|
||||
|
@ -146,7 +146,7 @@ members = [
|
||||
"misc/multistream-select",
|
||||
"misc/rw-stream-sink",
|
||||
"misc/keygen",
|
||||
"misc/prost-codec",
|
||||
"misc/quick-protobuf-codec",
|
||||
"misc/quickcheck-ext",
|
||||
"muxers/mplex",
|
||||
"muxers/yamux",
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
- Move `ConnectionId` to `libp2p-swarm`. 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
|
||||
|
||||
# 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 }
|
||||
parking_lot = "0.12.0"
|
||||
pin-project = "1.0.0"
|
||||
prost = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
once_cell = "1.17.1"
|
||||
rand = "0.8"
|
||||
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"
|
||||
serde_json = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
[features]
|
||||
secp256k1 = [ "libsecp256k1" ]
|
||||
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;
|
||||
|
||||
use self::error::*;
|
||||
use crate::{keys_proto, PeerId};
|
||||
use crate::{proto, PeerId};
|
||||
use quick_protobuf::{BytesReader, Writer};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
/// Identity keypair of a node.
|
||||
@ -147,12 +148,12 @@ impl Keypair {
|
||||
|
||||
/// Encode a private key as protobuf structure.
|
||||
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
|
||||
use prost::Message;
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
let pk = match self {
|
||||
Self::Ed25519(data) => keys_proto::PrivateKey {
|
||||
r#type: keys_proto::KeyType::Ed25519.into(),
|
||||
data: data.encode().into(),
|
||||
Self::Ed25519(data) => proto::PrivateKey {
|
||||
Type: proto::KeyType::Ed25519,
|
||||
Data: data.encode().to_vec(),
|
||||
},
|
||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||
Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
|
||||
@ -162,35 +163,38 @@ impl Keypair {
|
||||
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`].
|
||||
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(zeroize::Zeroizing::new)?;
|
||||
|
||||
let key_type = keys_proto::KeyType::from_i32(private_key.r#type)
|
||||
.ok_or_else(|| DecodingError::unknown_key_type(private_key.r#type))?;
|
||||
|
||||
match key_type {
|
||||
keys_proto::KeyType::Ed25519 => {
|
||||
ed25519::Keypair::decode(&mut private_key.data).map(Keypair::Ed25519)
|
||||
match private_key.Type {
|
||||
proto::KeyType::Ed25519 => {
|
||||
ed25519::Keypair::decode(&mut private_key.Data).map(Keypair::Ed25519)
|
||||
}
|
||||
keys_proto::KeyType::Rsa => Err(DecodingError::decoding_unsupported("RSA")),
|
||||
keys_proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
|
||||
keys_proto::KeyType::Ecdsa => Err(DecodingError::decoding_unsupported("ECDSA")),
|
||||
proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")),
|
||||
proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
|
||||
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) {
|
||||
self.r#type.zeroize();
|
||||
self.data.zeroize();
|
||||
// KeyType cannot be zeroized.
|
||||
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
|
||||
/// exchange with other nodes.
|
||||
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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
/// Decode a public key from a protobuf structure, e.g. read from storage
|
||||
/// or received from another node.
|
||||
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))?;
|
||||
|
||||
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 {
|
||||
match key {
|
||||
PublicKey::Ed25519(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Ed25519 as i32,
|
||||
data: key.encode().to_vec(),
|
||||
PublicKey::Ed25519(key) => proto::PublicKey {
|
||||
Type: proto::KeyType::Ed25519,
|
||||
Data: key.encode().to_vec(),
|
||||
},
|
||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||
PublicKey::Rsa(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Rsa as i32,
|
||||
data: key.encode_x509(),
|
||||
PublicKey::Rsa(key) => proto::PublicKey {
|
||||
Type: proto::KeyType::RSA,
|
||||
Data: key.encode_x509(),
|
||||
},
|
||||
#[cfg(feature = "secp256k1")]
|
||||
PublicKey::Secp256k1(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Secp256k1 as i32,
|
||||
data: key.encode().to_vec(),
|
||||
PublicKey::Secp256k1(key) => proto::PublicKey {
|
||||
Type: proto::KeyType::Secp256k1,
|
||||
Data: key.encode().to_vec(),
|
||||
},
|
||||
#[cfg(feature = "ecdsa")]
|
||||
PublicKey::Ecdsa(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Ecdsa as i32,
|
||||
data: key.encode_der(),
|
||||
PublicKey::Ecdsa(key) => proto::PublicKey {
|
||||
Type: proto::KeyType::ECDSA,
|
||||
Data: key.encode_der(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<keys_proto::PublicKey> for PublicKey {
|
||||
impl TryFrom<proto::PublicKey> for PublicKey {
|
||||
type Error = DecodingError;
|
||||
|
||||
fn try_from(pubkey: keys_proto::PublicKey) -> Result<Self, Self::Error> {
|
||||
let key_type = keys_proto::KeyType::from_i32(pubkey.r#type)
|
||||
.ok_or_else(|| DecodingError::unknown_key_type(pubkey.r#type))?;
|
||||
|
||||
match key_type {
|
||||
keys_proto::KeyType::Ed25519 => {
|
||||
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::Ed25519)
|
||||
fn try_from(pubkey: proto::PublicKey) -> Result<Self, Self::Error> {
|
||||
match pubkey.Type {
|
||||
proto::KeyType::Ed25519 => {
|
||||
ed25519::PublicKey::decode(&pubkey.Data).map(PublicKey::Ed25519)
|
||||
}
|
||||
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
||||
keys_proto::KeyType::Rsa => {
|
||||
rsa::PublicKey::decode_x509(&pubkey.data).map(PublicKey::Rsa)
|
||||
}
|
||||
proto::KeyType::RSA => rsa::PublicKey::decode_x509(&pubkey.Data).map(PublicKey::Rsa),
|
||||
#[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");
|
||||
Err(DecodingError::missing_feature("rsa"))
|
||||
}
|
||||
#[cfg(feature = "secp256k1")]
|
||||
keys_proto::KeyType::Secp256k1 => {
|
||||
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1)
|
||||
proto::KeyType::Secp256k1 => {
|
||||
secp256k1::PublicKey::decode(&pubkey.Data).map(PublicKey::Secp256k1)
|
||||
}
|
||||
#[cfg(not(feature = "secp256k1"))]
|
||||
keys_proto::KeyType::Secp256k1 => {
|
||||
proto::KeyType::Secp256k1 => {
|
||||
log::debug!("support for secp256k1 was disabled at compile-time");
|
||||
Err(DecodingError::missing_feature("secp256k1"))
|
||||
}
|
||||
#[cfg(feature = "ecdsa")]
|
||||
keys_proto::KeyType::Ecdsa => {
|
||||
ecdsa::PublicKey::decode_der(&pubkey.data).map(PublicKey::Ecdsa)
|
||||
proto::KeyType::ECDSA => {
|
||||
ecdsa::PublicKey::decode_der(&pubkey.Data).map(PublicKey::Ecdsa)
|
||||
}
|
||||
#[cfg(not(feature = "ecdsa"))]
|
||||
keys_proto::KeyType::Ecdsa => {
|
||||
proto::KeyType::ECDSA => {
|
||||
log::debug!("support for ECDSA was disabled at compile-time");
|
||||
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 {
|
||||
Self {
|
||||
msg: format!("decoding {key_type} key from Protobuf is unsupported"),
|
||||
|
@ -37,22 +37,18 @@
|
||||
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod keys_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/keys_proto.rs"));
|
||||
}
|
||||
|
||||
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"));
|
||||
mod proto {
|
||||
include!("generated/mod.rs");
|
||||
pub use self::{
|
||||
envelope_proto::*, keys_proto::*, peer_record_proto::mod_PeerRecord::*,
|
||||
peer_record_proto::PeerRecord,
|
||||
};
|
||||
}
|
||||
|
||||
/// Multi-address re-export.
|
||||
pub use multiaddr;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
pub type Negotiated<T> = multistream_select::Negotiated<T>;
|
||||
|
||||
mod peer_id;
|
||||
@ -80,6 +76,17 @@ pub use translation::address_translation;
|
||||
pub use transport::Transport;
|
||||
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct DecodeError(prost::DecodeError);
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub struct DecodeError(String);
|
||||
|
||||
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::Keypair;
|
||||
use crate::proto;
|
||||
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 quick_protobuf::{BytesReader, Writer};
|
||||
use std::convert::TryInto;
|
||||
|
||||
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.
|
||||
pub fn from_signed_envelope(envelope: SignedEnvelope) -> Result<Self, FromEnvelopeError> {
|
||||
use prost::Message;
|
||||
use quick_protobuf::MessageRead;
|
||||
|
||||
let (payload, signing_key) =
|
||||
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)?;
|
||||
|
||||
@ -45,7 +49,7 @@ impl PeerRecord {
|
||||
let addresses = record
|
||||
.addresses
|
||||
.into_iter()
|
||||
.map(|a| a.multiaddr.try_into())
|
||||
.map(|a| a.multiaddr.to_vec().try_into())
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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`].
|
||||
pub fn new(key: &Keypair, addresses: Vec<Multiaddr>) -> Result<Self, SigningError> {
|
||||
use prost::Message;
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
let seq = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
@ -69,21 +73,23 @@ impl PeerRecord {
|
||||
let peer_id = key.public().to_peer_id();
|
||||
|
||||
let payload = {
|
||||
let record = peer_record_proto::PeerRecord {
|
||||
let record = proto::PeerRecord {
|
||||
peer_id: peer_id.to_bytes(),
|
||||
seq,
|
||||
addresses: addresses
|
||||
.iter()
|
||||
.map(|m| peer_record_proto::peer_record::AddressInfo {
|
||||
.map(|m| proto::AddressInfo {
|
||||
multiaddr: m.to_vec(),
|
||||
})
|
||||
.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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
|
||||
buf
|
||||
};
|
||||
|
||||
@ -162,7 +168,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn mismatched_signature() {
|
||||
use prost::Message;
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
let addr: Multiaddr = HOME.parse().unwrap();
|
||||
|
||||
@ -171,18 +177,20 @@ mod tests {
|
||||
let identity_b = Keypair::generate_ed25519();
|
||||
|
||||
let payload = {
|
||||
let record = peer_record_proto::PeerRecord {
|
||||
let record = proto::PeerRecord {
|
||||
peer_id: identity_a.public().to_peer_id().to_bytes(),
|
||||
seq: 0,
|
||||
addresses: vec![peer_record_proto::peer_record::AddressInfo {
|
||||
addresses: vec![proto::AddressInfo {
|
||||
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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
|
||||
buf
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::identity::error::SigningError;
|
||||
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::fmt;
|
||||
use unsigned_varint::encode::usize_buffer;
|
||||
@ -73,37 +74,41 @@ impl SignedEnvelope {
|
||||
|
||||
/// Encode this [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
||||
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()),
|
||||
payload_type: self.payload_type,
|
||||
payload: self.payload,
|
||||
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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
/// Decode a [`SignedEnvelope`] using the protobuf encoding specified in the RFC.
|
||||
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 {
|
||||
key: envelope
|
||||
.public_key
|
||||
.ok_or(DecodingError::MissingPublicKey)?
|
||||
.try_into()?,
|
||||
payload_type: envelope.payload_type,
|
||||
payload: envelope.payload,
|
||||
signature: envelope.signature,
|
||||
payload_type: envelope.payload_type.to_vec(),
|
||||
payload: envelope.payload.to_vec(),
|
||||
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.
|
||||
# In the future protobuf generated files will be checked in, so we can remove this
|
||||
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
|
||||
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]
|
||||
name = "prost-codec"
|
||||
name = "quick-protobuf-codec"
|
||||
edition = "2021"
|
||||
rust-version = "1.60.0"
|
||||
description = "Asynchronous de-/encoding of Protobuf structs using asynchronous-codec, unsigned-varint and prost."
|
||||
version = "0.3.0"
|
||||
description = "Asynchronous de-/encoding of Protobuf structs using asynchronous-codec, unsigned-varint and quick-protobuf."
|
||||
version = "0.1.0"
|
||||
authors = ["Max Inden <mail@max-inden.de>"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/libp2p/rust-libp2p"
|
||||
@ -13,12 +13,9 @@ categories = ["asynchronous"]
|
||||
[dependencies]
|
||||
asynchronous-codec = { version = "0.6" }
|
||||
bytes = { version = "1" }
|
||||
prost = "0.11"
|
||||
thiserror = "1.0"
|
||||
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }
|
||||
|
||||
[dev-dependencies]
|
||||
prost-build = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
@ -1,15 +1,14 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
use asynchronous_codec::{Decoder, Encoder};
|
||||
use bytes::BytesMut;
|
||||
use prost::Message;
|
||||
use std::io::Cursor;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||
use std::marker::PhantomData;
|
||||
use unsigned_varint::codec::UviBytes;
|
||||
|
||||
/// [`Codec`] implements [`Encoder`] and [`Decoder`], uses [`unsigned_varint`]
|
||||
/// to prefix messages with their length and uses [`prost`] and a provided
|
||||
/// `struct` implementing [`Message`] to do the encoding.
|
||||
/// to prefix messages with their length and uses [`quick_protobuf`] and a provided
|
||||
/// `struct` implementing [`MessageRead`] and [`MessageWrite`] to do the encoding.
|
||||
pub struct Codec<In, Out = In> {
|
||||
uvi: UviBytes,
|
||||
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 Error = Error;
|
||||
|
||||
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
let mut encoded_msg = BytesMut::new();
|
||||
item.encode(&mut encoded_msg)
|
||||
.expect("BytesMut to have sufficient capacity.");
|
||||
self.uvi.encode(encoded_msg.freeze(), dst)?;
|
||||
let mut encoded_msg = Vec::new();
|
||||
let mut writer = Writer::new(&mut encoded_msg);
|
||||
item.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
self.uvi.encode(Bytes::from(encoded_msg), dst)?;
|
||||
|
||||
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 Error = Error;
|
||||
|
||||
@ -55,9 +58,9 @@ impl<In, Out: Message + Default> Decoder for Codec<In, Out> {
|
||||
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))?;
|
||||
|
||||
Ok(Some(message))
|
||||
}
|
||||
}
|
@ -8,6 +8,9 @@
|
||||
|
||||
- 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
|
||||
|
||||
# 0.9.1
|
||||
|
@ -10,9 +10,6 @@ repository = "https://github.com/libp2p/rust-libp2p"
|
||||
keywords = ["peer-to-peer", "libp2p", "networking"]
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1"
|
||||
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" }
|
||||
log = "0.4"
|
||||
rand = "0.8"
|
||||
prost = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
|
||||
[dev-dependencies]
|
||||
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};
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod structs_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/structs.rs"));
|
||||
mod proto {
|
||||
include!("generated/mod.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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::structs_proto;
|
||||
use crate::proto;
|
||||
use async_trait::async_trait;
|
||||
use futures::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||
use libp2p_core::{upgrade, Multiaddr, PeerId};
|
||||
use libp2p_request_response::{self as request_response, ProtocolName};
|
||||
use prost::Message;
|
||||
use quick_protobuf::{BytesReader, Writer};
|
||||
use std::{convert::TryFrom, io};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -108,14 +108,17 @@ pub struct DialRequest {
|
||||
|
||||
impl DialRequest {
|
||||
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))?;
|
||||
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"));
|
||||
}
|
||||
let (peer_id, addrs) = if let Some(structs_proto::message::Dial {
|
||||
let (peer_id, addrs) = if let Some(proto::Dial {
|
||||
peer:
|
||||
Some(structs_proto::message::PeerInfo {
|
||||
Some(proto::PeerInfo {
|
||||
id: Some(peer_id),
|
||||
addrs,
|
||||
}),
|
||||
@ -131,12 +134,13 @@ impl DialRequest {
|
||||
};
|
||||
|
||||
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"))?
|
||||
};
|
||||
|
||||
let addrs = addrs
|
||||
.into_iter()
|
||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
||||
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||
Ok(a) => Some(a),
|
||||
Err(e) => {
|
||||
log::debug!("Unable to parse multiaddr: {e}");
|
||||
@ -151,6 +155,8 @@ impl DialRequest {
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
let peer_id = self.peer_id.to_bytes();
|
||||
let addrs = self
|
||||
.addresses
|
||||
@ -158,21 +164,21 @@ impl DialRequest {
|
||||
.map(|addr| addr.to_vec())
|
||||
.collect();
|
||||
|
||||
let msg = structs_proto::Message {
|
||||
r#type: Some(structs_proto::message::MessageType::Dial as _),
|
||||
dial: Some(structs_proto::message::Dial {
|
||||
peer: Some(structs_proto::message::PeerInfo {
|
||||
id: Some(peer_id),
|
||||
let msg = proto::Message {
|
||||
type_pb: Some(proto::MessageType::DIAL),
|
||||
dial: Some(proto::Dial {
|
||||
peer: Some(proto::PeerInfo {
|
||||
id: Some(peer_id.to_vec()),
|
||||
addrs,
|
||||
}),
|
||||
}),
|
||||
dial_response: None,
|
||||
dialResponse: None,
|
||||
};
|
||||
|
||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
||||
msg.encode(&mut bytes)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
bytes
|
||||
let mut buf = Vec::with_capacity(msg.get_size());
|
||||
let mut writer = Writer::new(&mut buf);
|
||||
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,29 +190,27 @@ pub enum ResponseError {
|
||||
InternalError,
|
||||
}
|
||||
|
||||
impl From<ResponseError> for i32 {
|
||||
impl From<ResponseError> for proto::ResponseStatus {
|
||||
fn from(t: ResponseError) -> Self {
|
||||
match t {
|
||||
ResponseError::DialError => 100,
|
||||
ResponseError::DialRefused => 101,
|
||||
ResponseError::BadRequest => 200,
|
||||
ResponseError::InternalError => 300,
|
||||
ResponseError::DialError => proto::ResponseStatus::E_DIAL_ERROR,
|
||||
ResponseError::DialRefused => proto::ResponseStatus::E_DIAL_REFUSED,
|
||||
ResponseError::BadRequest => proto::ResponseStatus::E_BAD_REQUEST,
|
||||
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;
|
||||
|
||||
fn try_from(value: structs_proto::message::ResponseStatus) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: proto::ResponseStatus) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
structs_proto::message::ResponseStatus::EDialError => Ok(ResponseError::DialError),
|
||||
structs_proto::message::ResponseStatus::EDialRefused => Ok(ResponseError::DialRefused),
|
||||
structs_proto::message::ResponseStatus::EBadRequest => Ok(ResponseError::BadRequest),
|
||||
structs_proto::message::ResponseStatus::EInternalError => {
|
||||
Ok(ResponseError::InternalError)
|
||||
}
|
||||
structs_proto::message::ResponseStatus::Ok => {
|
||||
proto::ResponseStatus::E_DIAL_ERROR => Ok(ResponseError::DialError),
|
||||
proto::ResponseStatus::E_DIAL_REFUSED => Ok(ResponseError::DialRefused),
|
||||
proto::ResponseStatus::E_BAD_REQUEST => Ok(ResponseError::BadRequest),
|
||||
proto::ResponseStatus::E_INTERNAL_ERROR => Ok(ResponseError::InternalError),
|
||||
proto::ResponseStatus::OK => {
|
||||
log::debug!("Received response with status code OK but expected error.");
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
@ -225,38 +229,35 @@ pub struct DialResponse {
|
||||
|
||||
impl DialResponse {
|
||||
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))?;
|
||||
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"));
|
||||
}
|
||||
|
||||
Ok(match msg.dial_response {
|
||||
Some(structs_proto::message::DialResponse {
|
||||
status: Some(status),
|
||||
status_text,
|
||||
Ok(match msg.dialResponse {
|
||||
Some(proto::DialResponse {
|
||||
status: Some(proto::ResponseStatus::OK),
|
||||
statusText,
|
||||
addr: Some(addr),
|
||||
}) if structs_proto::message::ResponseStatus::from_i32(status)
|
||||
== Some(structs_proto::message::ResponseStatus::Ok) =>
|
||||
{
|
||||
let addr = Multiaddr::try_from(addr)
|
||||
}) => {
|
||||
let addr = Multiaddr::try_from(addr.to_vec())
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||
Self {
|
||||
status_text,
|
||||
status_text: statusText,
|
||||
result: Ok(addr),
|
||||
}
|
||||
}
|
||||
Some(structs_proto::message::DialResponse {
|
||||
Some(proto::DialResponse {
|
||||
status: Some(status),
|
||||
status_text,
|
||||
statusText,
|
||||
addr: None,
|
||||
}) => Self {
|
||||
status_text,
|
||||
result: Err(ResponseError::try_from(
|
||||
structs_proto::message::ResponseStatus::from_i32(status).ok_or_else(|| {
|
||||
io::Error::new(io::ErrorKind::InvalidData, "invalid response status code")
|
||||
})?,
|
||||
)?),
|
||||
status_text: statusText,
|
||||
result: Err(ResponseError::try_from(status)?),
|
||||
},
|
||||
_ => {
|
||||
log::debug!("Received malformed response message.");
|
||||
@ -269,35 +270,38 @@ impl DialResponse {
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
let dial_response = match self.result {
|
||||
Ok(addr) => structs_proto::message::DialResponse {
|
||||
status: Some(0),
|
||||
status_text: self.status_text,
|
||||
Ok(addr) => proto::DialResponse {
|
||||
status: Some(proto::ResponseStatus::OK),
|
||||
statusText: self.status_text,
|
||||
addr: Some(addr.to_vec()),
|
||||
},
|
||||
Err(error) => structs_proto::message::DialResponse {
|
||||
Err(error) => proto::DialResponse {
|
||||
status: Some(error.into()),
|
||||
status_text: self.status_text,
|
||||
statusText: self.status_text,
|
||||
addr: None,
|
||||
},
|
||||
};
|
||||
|
||||
let msg = structs_proto::Message {
|
||||
r#type: Some(structs_proto::message::MessageType::DialResponse as _),
|
||||
let msg = proto::Message {
|
||||
type_pb: Some(proto::MessageType::DIAL_RESPONSE),
|
||||
dial: None,
|
||||
dial_response: Some(dial_response),
|
||||
dialResponse: Some(dial_response),
|
||||
};
|
||||
|
||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
||||
msg.encode(&mut bytes)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
bytes
|
||||
let mut buf = Vec::with_capacity(msg.get_size());
|
||||
let mut writer = Writer::new(&mut buf);
|
||||
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use quick_protobuf::MessageWrite;
|
||||
|
||||
#[test]
|
||||
fn test_request_encode_decode() {
|
||||
@ -346,20 +350,20 @@ mod tests {
|
||||
a
|
||||
};
|
||||
|
||||
let msg = structs_proto::Message {
|
||||
r#type: Some(structs_proto::message::MessageType::Dial.into()),
|
||||
dial: Some(structs_proto::message::Dial {
|
||||
peer: Some(structs_proto::message::PeerInfo {
|
||||
let msg = proto::Message {
|
||||
type_pb: Some(proto::MessageType::DIAL),
|
||||
dial: Some(proto::Dial {
|
||||
peer: Some(proto::PeerInfo {
|
||||
id: Some(PeerId::random().to_bytes()),
|
||||
addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||
}),
|
||||
}),
|
||||
dial_response: None,
|
||||
dialResponse: None,
|
||||
};
|
||||
|
||||
let mut bytes = Vec::with_capacity(msg.encoded_len());
|
||||
msg.encode(&mut bytes)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
let mut bytes = Vec::with_capacity(msg.get_size());
|
||||
let mut writer = Writer::new(&mut bytes);
|
||||
msg.write_message(&mut writer).expect("Encoding to succeed");
|
||||
|
||||
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].
|
||||
|
||||
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||
|
||||
[PR 3213]: https://github.com/libp2p/rust-libp2p/pull/3213
|
||||
[PR 3153]: https://github.com/libp2p/rust-libp2p/pull/3153
|
||||
[issue 2217]: https://github.com/libp2p/rust-libp2p/issues/2217
|
||||
[PR 3214]: https://github.com/libp2p/rust-libp2p/pull/3214
|
||||
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||
|
||||
# 0.8.1
|
||||
|
||||
|
@ -19,14 +19,11 @@ instant = "0.1.11"
|
||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
log = "0.4"
|
||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
||||
prost = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||
thiserror = "1.0"
|
||||
void = "1"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
[dev-dependencies]
|
||||
clap = { version = "4.1.6", features = ["derive"] }
|
||||
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 handler;
|
||||
mod protocol;
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod message_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/holepunch.pb.rs"));
|
||||
|
||||
mod proto {
|
||||
include!("generated/mod.rs");
|
||||
pub use self::holepunch::pb::{mod_HolePunch::*, HolePunch};
|
||||
}
|
||||
|
||||
pub use behaviour_impl::Behaviour;
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::message_proto::{hole_punch, HolePunch};
|
||||
use crate::proto;
|
||||
use asynchronous_codec::Framed;
|
||||
use futures::{future::BoxFuture, prelude::*};
|
||||
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 {
|
||||
let mut substream = Framed::new(
|
||||
substream,
|
||||
prost_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||
quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||
);
|
||||
|
||||
async move {
|
||||
let HolePunch { r#type, obs_addrs } =
|
||||
let proto::HolePunch { type_pb, ObsAddrs } =
|
||||
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);
|
||||
} else {
|
||||
obs_addrs
|
||||
ObsAddrs
|
||||
.into_iter()
|
||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
||||
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||
Ok(a) => Some(a),
|
||||
Err(e) => {
|
||||
log::debug!("Unable to parse multiaddr: {e}");
|
||||
@ -77,11 +77,9 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
.collect::<Vec<Multiaddr>>()
|
||||
};
|
||||
|
||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
||||
|
||||
match r#type {
|
||||
hole_punch::Type::Connect => {}
|
||||
hole_punch::Type::Sync => return Err(UpgradeError::UnexpectedTypeSync),
|
||||
match type_pb {
|
||||
proto::Type::CONNECT => {}
|
||||
proto::Type::SYNC => return Err(UpgradeError::UnexpectedTypeSync),
|
||||
}
|
||||
|
||||
Ok(PendingConnect {
|
||||
@ -94,7 +92,7 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
}
|
||||
|
||||
pub struct PendingConnect {
|
||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HolePunch>>,
|
||||
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HolePunch>>,
|
||||
remote_obs_addrs: Vec<Multiaddr>,
|
||||
}
|
||||
|
||||
@ -103,22 +101,21 @@ impl PendingConnect {
|
||||
mut self,
|
||||
local_obs_addrs: Vec<Multiaddr>,
|
||||
) -> Result<Vec<Multiaddr>, UpgradeError> {
|
||||
let msg = HolePunch {
|
||||
r#type: hole_punch::Type::Connect.into(),
|
||||
obs_addrs: local_obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
let msg = proto::HolePunch {
|
||||
type_pb: proto::Type::CONNECT,
|
||||
ObsAddrs: local_obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
};
|
||||
|
||||
self.substream.send(msg).await?;
|
||||
let HolePunch { r#type, .. } = self
|
||||
let proto::HolePunch { type_pb, .. } = self
|
||||
.substream
|
||||
.next()
|
||||
.await
|
||||
.ok_or(UpgradeError::StreamClosed)??;
|
||||
|
||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
||||
match r#type {
|
||||
hole_punch::Type::Connect => return Err(UpgradeError::UnexpectedTypeConnect),
|
||||
hole_punch::Type::Sync => {}
|
||||
match type_pb {
|
||||
proto::Type::CONNECT => return Err(UpgradeError::UnexpectedTypeConnect),
|
||||
proto::Type::SYNC => {}
|
||||
}
|
||||
|
||||
Ok(self.remote_obs_addrs)
|
||||
@ -128,7 +125,7 @@ impl PendingConnect {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UpgradeError {
|
||||
#[error(transparent)]
|
||||
Codec(#[from] prost_codec::Error),
|
||||
Codec(#[from] quick_protobuf_codec::Error),
|
||||
#[error("Stream closed")]
|
||||
StreamClosed,
|
||||
#[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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::message_proto::{hole_punch, HolePunch};
|
||||
use crate::proto;
|
||||
use asynchronous_codec::Framed;
|
||||
use futures::{future::BoxFuture, prelude::*};
|
||||
use futures_timer::Delay;
|
||||
@ -56,12 +56,12 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future {
|
||||
let mut substream = Framed::new(
|
||||
substream,
|
||||
prost_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||
quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES),
|
||||
);
|
||||
|
||||
let msg = HolePunch {
|
||||
r#type: hole_punch::Type::Connect.into(),
|
||||
obs_addrs: self.obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
let msg = proto::HolePunch {
|
||||
type_pb: proto::Type::CONNECT,
|
||||
ObsAddrs: self.obs_addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
};
|
||||
|
||||
async move {
|
||||
@ -69,23 +69,22 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
|
||||
let sent_time = Instant::now();
|
||||
|
||||
let HolePunch { r#type, obs_addrs } =
|
||||
let proto::HolePunch { type_pb, ObsAddrs } =
|
||||
substream.next().await.ok_or(UpgradeError::StreamClosed)??;
|
||||
|
||||
let rtt = sent_time.elapsed();
|
||||
|
||||
let r#type = hole_punch::Type::from_i32(r#type).ok_or(UpgradeError::ParseTypeField)?;
|
||||
match r#type {
|
||||
hole_punch::Type::Connect => {}
|
||||
hole_punch::Type::Sync => return Err(UpgradeError::UnexpectedTypeSync),
|
||||
match type_pb {
|
||||
proto::Type::CONNECT => {}
|
||||
proto::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);
|
||||
} else {
|
||||
obs_addrs
|
||||
ObsAddrs
|
||||
.into_iter()
|
||||
.filter_map(|a| match Multiaddr::try_from(a) {
|
||||
.filter_map(|a| match Multiaddr::try_from(a.to_vec()) {
|
||||
Ok(a) => Some(a),
|
||||
Err(e) => {
|
||||
log::debug!("Unable to parse multiaddr: {e}");
|
||||
@ -104,9 +103,9 @@ impl upgrade::OutboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
.collect::<Vec<Multiaddr>>()
|
||||
};
|
||||
|
||||
let msg = HolePunch {
|
||||
r#type: hole_punch::Type::Sync.into(),
|
||||
obs_addrs: vec![],
|
||||
let msg = proto::HolePunch {
|
||||
type_pb: proto::Type::SYNC,
|
||||
ObsAddrs: vec![],
|
||||
};
|
||||
|
||||
substream.send(msg).await?;
|
||||
@ -126,7 +125,7 @@ pub struct Connect {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UpgradeError {
|
||||
#[error(transparent)]
|
||||
Codec(#[from] prost_codec::Error),
|
||||
Codec(#[from] quick_protobuf_codec::Error),
|
||||
#[error("Stream closed")]
|
||||
StreamClosed,
|
||||
#[error("Expected 'status' field to be set.")]
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
- 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
|
||||
|
||||
|
@ -18,15 +18,12 @@ futures = "0.3.26"
|
||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
log = "0.4"
|
||||
prost = "0.11"
|
||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
||||
quick-protobuf = "0.8"
|
||||
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||
rand = "0.8"
|
||||
smallvec = "1.6.1"
|
||||
thiserror = "1.0.37"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
||||
[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 topic;
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod rpc_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/floodsub.pb.rs"));
|
||||
mod proto {
|
||||
include!("generated/mod.rs");
|
||||
pub use self::floodsub::pb::{mod_RPC::SubOpts, Message, RPC};
|
||||
}
|
||||
|
||||
pub use self::layer::{Floodsub, FloodsubEvent};
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::rpc_proto;
|
||||
use crate::proto;
|
||||
use crate::topic::Topic;
|
||||
use asynchronous_codec::Framed;
|
||||
use futures::{
|
||||
@ -65,7 +65,7 @@ where
|
||||
Box::pin(async move {
|
||||
let mut framed = Framed::new(
|
||||
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
|
||||
@ -120,7 +120,7 @@ pub enum FloodsubError {
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct CodecError(#[from] prost_codec::Error);
|
||||
pub struct CodecError(#[from] quick_protobuf_codec::Error);
|
||||
|
||||
/// An RPC received by the floodsub system.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -152,7 +152,7 @@ where
|
||||
Box::pin(async move {
|
||||
let mut framed = Framed::new(
|
||||
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.close().await?;
|
||||
@ -163,12 +163,12 @@ where
|
||||
|
||||
impl FloodsubRpc {
|
||||
/// Turns this `FloodsubRpc` into a message that can be sent to a substream.
|
||||
fn into_rpc(self) -> rpc_proto::Rpc {
|
||||
rpc_proto::Rpc {
|
||||
fn into_rpc(self) -> proto::RPC {
|
||||
proto::RPC {
|
||||
publish: self
|
||||
.messages
|
||||
.into_iter()
|
||||
.map(|msg| rpc_proto::Message {
|
||||
.map(|msg| proto::Message {
|
||||
from: Some(msg.source.to_bytes()),
|
||||
data: Some(msg.data),
|
||||
seqno: Some(msg.sequence_number),
|
||||
@ -179,7 +179,7 @@ impl FloodsubRpc {
|
||||
subscriptions: self
|
||||
.subscriptions
|
||||
.into_iter()
|
||||
.map(|topic| rpc_proto::rpc::SubOpts {
|
||||
.map(|topic| proto::SubOpts {
|
||||
subscribe: Some(topic.action == FloodsubSubscriptionAction::Subscribe),
|
||||
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::`.
|
||||
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 3303]: https://github.com/libp2p/rust-libp2p/pull/3303/
|
||||
[PR 3381]: https://github.com/libp2p/rust-libp2p/pull/3381/
|
||||
[discussion 2174]: https://github.com/libp2p/rust-libp2p/discussions/2174
|
||||
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||
|
||||
# 0.43.0
|
||||
|
||||
|
@ -24,8 +24,8 @@ log = "0.4.11"
|
||||
sha2 = "0.10.0"
|
||||
base64 = "0.21.0"
|
||||
smallvec = "1.6.1"
|
||||
prost = "0.11"
|
||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
||||
quick-protobuf = "0.8"
|
||||
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||
hex_fmt = "0.3.0"
|
||||
regex = "1.5.5"
|
||||
serde = { version = "1", optional = true, features = ["derive"] }
|
||||
@ -46,9 +46,6 @@ libp2p-swarm = { path = "../../swarm" }
|
||||
libp2p-yamux = { path = "../../muxers/yamux" }
|
||||
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.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
||||
[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 log::{debug, error, trace, warn};
|
||||
use prometheus_client::registry::Registry;
|
||||
use prost::Message as _;
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
use libp2p_core::{
|
||||
@ -64,8 +63,9 @@ use crate::types::{
|
||||
Subscription, SubscriptionAction,
|
||||
};
|
||||
use crate::types::{PeerConnections, PeerKind, Rpc};
|
||||
use crate::{rpc_proto, TopicScoreParams};
|
||||
use crate::{rpc_proto::proto, TopicScoreParams};
|
||||
use crate::{PublishError, SubscriptionError, ValidationError};
|
||||
use quick_protobuf::{MessageWrite, Writer};
|
||||
use std::{cmp::Ordering::Equal, fmt::Debug};
|
||||
use wasm_timer::Interval;
|
||||
|
||||
@ -179,8 +179,8 @@ impl From<MessageAuthenticity> for PublishConfig {
|
||||
let public_key = keypair.public();
|
||||
let key_enc = public_key.to_protobuf_encoding();
|
||||
let key = if key_enc.len() <= 42 {
|
||||
// The public key can be inlined in [`rpc_proto::Message::from`], so we don't include it
|
||||
// specifically in the [`rpc_proto::Message::key`] field.
|
||||
// The public key can be inlined in [`rpc_proto::proto::::Message::from`], so we don't include it
|
||||
// specifically in the [`rpc_proto::proto::Message::key`] field.
|
||||
None
|
||||
} else {
|
||||
// Include the protobuf encoding of the public key in the message.
|
||||
@ -610,7 +610,7 @@ where
|
||||
.into_protobuf();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -721,7 +721,7 @@ where
|
||||
}
|
||||
|
||||
// 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() {
|
||||
trace!("Sending message to peer: {:?}", peer_id);
|
||||
self.send_message(*peer_id, event.clone())?;
|
||||
@ -1338,7 +1338,7 @@ where
|
||||
}
|
||||
.into_protobuf();
|
||||
|
||||
let msg_bytes = message.encoded_len();
|
||||
let msg_bytes = message.get_size();
|
||||
|
||||
if self.send_message(*peer_id, message).is_err() {
|
||||
error!("Failed to send cached messages. Messages too large");
|
||||
@ -2733,7 +2733,7 @@ where
|
||||
}
|
||||
.into_protobuf();
|
||||
|
||||
let msg_bytes = event.encoded_len();
|
||||
let msg_bytes = event.get_size();
|
||||
for peer in recipient_peers.iter() {
|
||||
debug!("Sending message: {:?} to peer {:?}", msg_id, peer);
|
||||
self.send_message(*peer, event.clone())?;
|
||||
@ -2764,7 +2764,7 @@ where
|
||||
let sequence_number: u64 = rand::random();
|
||||
|
||||
let signature = {
|
||||
let message = rpc_proto::Message {
|
||||
let message = proto::Message {
|
||||
from: Some(author.clone().to_bytes()),
|
||||
data: Some(data.clone()),
|
||||
seqno: Some(sequence_number.to_be_bytes().to_vec()),
|
||||
@ -2773,10 +2773,12 @@ where
|
||||
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
|
||||
.encode(&mut buf)
|
||||
.expect("Buffer has sufficient capacity");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
|
||||
// the signature is over the bytes "libp2p-pubsub:<protobuf-message>"
|
||||
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
|
||||
/// is not already an arc.
|
||||
fn send_message(
|
||||
&mut self,
|
||||
peer_id: PeerId,
|
||||
message: rpc_proto::Rpc,
|
||||
) -> Result<(), PublishError> {
|
||||
fn send_message(&mut self, peer_id: PeerId, message: proto::RPC) -> Result<(), PublishError> {
|
||||
// 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
|
||||
// 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
|
||||
// messages to be sent.
|
||||
fn fragment_message(&self, rpc: rpc_proto::Rpc) -> Result<Vec<rpc_proto::Rpc>, PublishError> {
|
||||
if rpc.encoded_len() < self.config.max_transmit_size() {
|
||||
fn fragment_message(&self, rpc: proto::RPC) -> Result<Vec<proto::RPC>, PublishError> {
|
||||
if rpc.get_size() < self.config.max_transmit_size() {
|
||||
return Ok(vec![rpc]);
|
||||
}
|
||||
|
||||
let new_rpc = rpc_proto::Rpc {
|
||||
let new_rpc = proto::RPC {
|
||||
subscriptions: Vec::new(),
|
||||
publish: Vec::new(),
|
||||
control: None,
|
||||
@ -2920,7 +2918,7 @@ where
|
||||
|
||||
// create a new RPC if the new object plus 5% of its size (for length prefix
|
||||
// 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()
|
||||
&& rpc_list[list_index] != new_rpc
|
||||
{
|
||||
@ -2932,7 +2930,7 @@ where
|
||||
|
||||
macro_rules! add_item {
|
||||
($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() {
|
||||
// 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
|
||||
// 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 control.encoded_len() + 2 > self.config.max_transmit_size() {
|
||||
if control.get_size() + 2 > self.config.max_transmit_size() {
|
||||
// fragment the RPC
|
||||
for ihave in &control.ihave {
|
||||
let len = ihave.encoded_len();
|
||||
let len = ihave.get_size();
|
||||
create_or_add_rpc!(len);
|
||||
rpc_list
|
||||
.last_mut()
|
||||
@ -2976,7 +2974,7 @@ where
|
||||
.push(ihave.clone());
|
||||
}
|
||||
for iwant in &control.iwant {
|
||||
let len = iwant.encoded_len();
|
||||
let len = iwant.get_size();
|
||||
create_or_add_rpc!(len);
|
||||
rpc_list
|
||||
.last_mut()
|
||||
@ -2987,7 +2985,7 @@ where
|
||||
.push(iwant.clone());
|
||||
}
|
||||
for graft in &control.graft {
|
||||
let len = graft.encoded_len();
|
||||
let len = graft.get_size();
|
||||
create_or_add_rpc!(len);
|
||||
rpc_list
|
||||
.last_mut()
|
||||
@ -2998,7 +2996,7 @@ where
|
||||
.push(graft.clone());
|
||||
}
|
||||
for prune in &control.prune {
|
||||
let len = prune.encoded_len();
|
||||
let len = prune.get_size();
|
||||
create_or_add_rpc!(len);
|
||||
rpc_list
|
||||
.last_mut()
|
||||
@ -3009,7 +3007,7 @@ where
|
||||
.push(prune.clone());
|
||||
}
|
||||
} else {
|
||||
let len = control.encoded_len();
|
||||
let len = control.get_size();
|
||||
create_or_add_rpc!(len);
|
||||
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
|
||||
|
||||
while rpc_proto.encoded_len() < max_transmit_size {
|
||||
while rpc_proto.get_size() < max_transmit_size {
|
||||
rpc.messages.push(test_message());
|
||||
rpc_proto = rpc.clone().into_protobuf();
|
||||
}
|
||||
@ -3786,7 +3784,7 @@ mod local_test {
|
||||
// all fragmented messages should be under the limit
|
||||
for message in fragmented_messages {
|
||||
assert!(
|
||||
message.encoded_len() < max_transmit_size,
|
||||
message.get_size() < max_transmit_size,
|
||||
"all messages should be less than the transmission size"
|
||||
);
|
||||
}
|
||||
@ -3813,7 +3811,7 @@ mod local_test {
|
||||
.fragment_message(rpc_proto.clone())
|
||||
.expect("Messages must be valid");
|
||||
|
||||
if rpc_proto.encoded_len() < max_transmit_size {
|
||||
if rpc_proto.get_size() < max_transmit_size {
|
||||
assert_eq!(
|
||||
fragmented_messages.len(),
|
||||
1,
|
||||
@ -3829,12 +3827,12 @@ mod local_test {
|
||||
// all fragmented messages should be under the limit
|
||||
for message in fragmented_messages {
|
||||
assert!(
|
||||
message.encoded_len() < max_transmit_size,
|
||||
"all messages should be less than the transmission size: list size {} max size{}", 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.get_size(), max_transmit_size
|
||||
);
|
||||
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ where
|
||||
}
|
||||
|
||||
// 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.
|
||||
let mut messages = Vec::with_capacity(rpc.publish.len());
|
||||
let rpc = rpc.clone();
|
||||
|
@ -100,7 +100,7 @@ pub enum HandlerError {
|
||||
#[error("Protocol negotiation failed.")]
|
||||
NegotiationProtocolError(ProtocolError),
|
||||
#[error("Failed to encode or decode")]
|
||||
Codec(#[from] prost_codec::Error),
|
||||
Codec(#[from] quick_protobuf_codec::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -136,7 +136,7 @@ impl std::error::Error for ValidationError {}
|
||||
|
||||
impl From<std::io::Error> for 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.
|
||||
|
||||
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
||||
use crate::rpc_proto::proto;
|
||||
use crate::types::{PeerKind, RawMessage, Rpc};
|
||||
use crate::{HandlerError, ValidationError};
|
||||
use asynchronous_codec::Framed;
|
||||
@ -67,7 +68,7 @@ pub enum HandlerEvent {
|
||||
#[derive(Debug)]
|
||||
pub enum HandlerIn {
|
||||
/// A gossipsub message to send.
|
||||
Message(crate::rpc_proto::Rpc),
|
||||
Message(proto::RPC),
|
||||
/// The peer has joined the mesh.
|
||||
JoinedMesh,
|
||||
/// The peer has left the mesh.
|
||||
@ -93,7 +94,7 @@ pub struct Handler {
|
||||
inbound_substream: Option<InboundSubstreamState>,
|
||||
|
||||
/// 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
|
||||
/// requests.
|
||||
@ -149,10 +150,7 @@ enum OutboundSubstreamState {
|
||||
/// Waiting for the user to send a message. The idle state for an outbound substream.
|
||||
WaitingOutput(Framed<NegotiatedSubstream, GossipsubCodec>),
|
||||
/// Waiting to send a message to the remote.
|
||||
PendingSend(
|
||||
Framed<NegotiatedSubstream, GossipsubCodec>,
|
||||
crate::rpc_proto::Rpc,
|
||||
),
|
||||
PendingSend(Framed<NegotiatedSubstream, GossipsubCodec>, proto::RPC),
|
||||
/// Waiting to flush the substream so that the data arrives to the remote.
|
||||
PendingFlush(Framed<NegotiatedSubstream, GossipsubCodec>),
|
||||
/// The substream is being closed. Used by either substream.
|
||||
@ -251,7 +249,7 @@ impl ConnectionHandler for Handler {
|
||||
type Error = HandlerError;
|
||||
type InboundOpenInfo = ();
|
||||
type InboundProtocol = ProtocolConfig;
|
||||
type OutboundOpenInfo = crate::rpc_proto::Rpc;
|
||||
type OutboundOpenInfo = proto::RPC;
|
||||
type OutboundProtocol = ProtocolConfig;
|
||||
|
||||
fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
|
||||
|
@ -24,7 +24,7 @@ use crate::topic::TopicHash;
|
||||
use crate::types::{
|
||||
ControlAction, MessageId, PeerInfo, PeerKind, RawMessage, Rpc, Subscription, SubscriptionAction,
|
||||
};
|
||||
use crate::{rpc_proto, Config};
|
||||
use crate::{rpc_proto::proto, Config};
|
||||
use crate::{HandlerError, ValidationError};
|
||||
use asynchronous_codec::{Decoder, Encoder, Framed};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
@ -35,7 +35,7 @@ use libp2p_core::{
|
||||
identity::PublicKey, InboundUpgrade, OutboundUpgrade, PeerId, ProtocolName, UpgradeInfo,
|
||||
};
|
||||
use log::{debug, warn};
|
||||
use prost::Message as _;
|
||||
use quick_protobuf::Writer;
|
||||
use std::pin::Pin;
|
||||
use unsigned_varint::codec;
|
||||
|
||||
@ -191,12 +191,12 @@ pub struct GossipsubCodec {
|
||||
/// Determines the level of validation performed on incoming messages.
|
||||
validation_mode: ValidationMode,
|
||||
/// 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 {
|
||||
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 {
|
||||
validation_mode,
|
||||
codec,
|
||||
@ -206,7 +206,9 @@ impl GossipsubCodec {
|
||||
/// 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
|
||||
/// 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() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
@ -258,10 +260,11 @@ impl GossipsubCodec {
|
||||
let mut message_sig = message.clone();
|
||||
message_sig.signature = 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
|
||||
.encode(&mut buf)
|
||||
.expect("Buffer has sufficient capacity");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
let mut signature_bytes = SIGNING_PREFIX.to_vec();
|
||||
signature_bytes.extend_from_slice(&buf);
|
||||
public_key.verify(&signature_bytes, signature)
|
||||
@ -269,7 +272,7 @@ impl GossipsubCodec {
|
||||
}
|
||||
|
||||
impl Encoder for GossipsubCodec {
|
||||
type Item = rpc_proto::Rpc;
|
||||
type Item = proto::RPC;
|
||||
type Error = 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
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// 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)]
|
||||
mod test {
|
||||
use crate::rpc_proto::proto::compat;
|
||||
use crate::IdentTopic as Topic;
|
||||
use libp2p_core::PeerId;
|
||||
use prost::Message;
|
||||
use quick_protobuf::{BytesReader, MessageRead, MessageWrite, Writer};
|
||||
use rand::Rng;
|
||||
|
||||
mod compat_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/compat.pb.rs"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_topic_message_compatibility() {
|
||||
let topic1 = Topic::new("t1").hash();
|
||||
let topic2 = Topic::new("t2").hash();
|
||||
|
||||
let new_message1 = super::Message {
|
||||
let new_message1 = super::proto::Message {
|
||||
from: Some(PeerId::random().to_bytes()),
|
||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().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()),
|
||||
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()),
|
||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().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()),
|
||||
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()),
|
||||
data: Some(rand::thread_rng().gen::<[u8; 32]>().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()),
|
||||
};
|
||||
|
||||
let mut new_message1b = Vec::with_capacity(new_message1.encoded_len());
|
||||
new_message1.encode(&mut new_message1b).unwrap();
|
||||
let mut new_message1b = Vec::with_capacity(new_message1.get_size());
|
||||
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());
|
||||
old_message1.encode(&mut old_message1b).unwrap();
|
||||
let mut old_message1b = Vec::with_capacity(old_message1.get_size());
|
||||
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());
|
||||
old_message2.encode(&mut old_message2b).unwrap();
|
||||
let mut old_message2b = Vec::with_capacity(old_message2.get_size());
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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()]);
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,10 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::rpc_proto;
|
||||
use crate::rpc_proto::proto;
|
||||
use base64::prelude::*;
|
||||
use prometheus_client::encoding::EncodeLabelSet;
|
||||
use prost::Message;
|
||||
use quick_protobuf::Writer;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::fmt;
|
||||
|
||||
@ -47,15 +47,18 @@ impl Hasher for Sha256Hash {
|
||||
/// Creates a [`TopicHash`] by SHA256 hashing the topic then base64 encoding the
|
||||
/// hash.
|
||||
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),
|
||||
auth: 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
|
||||
.encode(&mut bytes)
|
||||
.expect("buffer is large enough");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
let hash = BASE64_STANDARD.encode(Sha256::digest(&bytes));
|
||||
TopicHash { hash }
|
||||
}
|
||||
|
@ -19,15 +19,15 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
//! A collection of types using the Gossipsub system.
|
||||
use crate::rpc_proto;
|
||||
use crate::TopicHash;
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_swarm::ConnectionId;
|
||||
use prometheus_client::encoding::EncodeLabelValue;
|
||||
use prost::Message as _;
|
||||
use quick_protobuf::MessageWrite;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::rpc_proto::proto;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -136,7 +136,7 @@ pub struct RawMessage {
|
||||
impl RawMessage {
|
||||
/// Calculates the encoded length of this message (used for calculating metrics).
|
||||
pub fn raw_protobuf_len(&self) -> usize {
|
||||
let message = rpc_proto::Message {
|
||||
let message = proto::Message {
|
||||
from: self.source.map(|m| m.to_bytes()),
|
||||
data: Some(self.data.clone()),
|
||||
seqno: self.sequence_number.map(|s| s.to_be_bytes().to_vec()),
|
||||
@ -144,7 +144,7 @@ impl RawMessage {
|
||||
signature: self.signature.clone(),
|
||||
key: self.key.clone(),
|
||||
};
|
||||
message.encoded_len()
|
||||
message.get_size()
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,19 +250,19 @@ pub struct Rpc {
|
||||
impl Rpc {
|
||||
/// Converts the GossipsubRPC into its protobuf format.
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rpc> for rpc_proto::Rpc {
|
||||
impl From<Rpc> for proto::RPC {
|
||||
/// Converts the RPC into protobuf format.
|
||||
fn from(rpc: Rpc) -> Self {
|
||||
// Messages
|
||||
let mut publish = Vec::new();
|
||||
|
||||
for message in rpc.messages.into_iter() {
|
||||
let message = rpc_proto::Message {
|
||||
let message = proto::Message {
|
||||
from: message.source.map(|m| m.to_bytes()),
|
||||
data: Some(message.data),
|
||||
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
|
||||
.subscriptions
|
||||
.into_iter()
|
||||
.map(|sub| rpc_proto::rpc::SubOpts {
|
||||
.map(|sub| proto::SubOpts {
|
||||
subscribe: Some(sub.action == SubscriptionAction::Subscribe),
|
||||
topic_id: Some(sub.topic_hash.into_string()),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// control messages
|
||||
let mut control = rpc_proto::ControlMessage {
|
||||
let mut control = proto::ControlMessage {
|
||||
ihave: Vec::new(),
|
||||
iwant: Vec::new(),
|
||||
graft: Vec::new(),
|
||||
@ -301,20 +301,20 @@ impl From<Rpc> for rpc_proto::Rpc {
|
||||
topic_hash,
|
||||
message_ids,
|
||||
} => {
|
||||
let rpc_ihave = rpc_proto::ControlIHave {
|
||||
let rpc_ihave = proto::ControlIHave {
|
||||
topic_id: Some(topic_hash.into_string()),
|
||||
message_ids: message_ids.into_iter().map(|msg_id| msg_id.0).collect(),
|
||||
};
|
||||
control.ihave.push(rpc_ihave);
|
||||
}
|
||||
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(),
|
||||
};
|
||||
control.iwant.push(rpc_iwant);
|
||||
}
|
||||
ControlAction::Graft { topic_hash } => {
|
||||
let rpc_graft = rpc_proto::ControlGraft {
|
||||
let rpc_graft = proto::ControlGraft {
|
||||
topic_id: Some(topic_hash.into_string()),
|
||||
};
|
||||
control.graft.push(rpc_graft);
|
||||
@ -324,11 +324,11 @@ impl From<Rpc> for rpc_proto::Rpc {
|
||||
peers,
|
||||
backoff,
|
||||
} => {
|
||||
let rpc_prune = rpc_proto::ControlPrune {
|
||||
let rpc_prune = proto::ControlPrune {
|
||||
topic_id: Some(topic_hash.into_string()),
|
||||
peers: peers
|
||||
.into_iter()
|
||||
.map(|info| rpc_proto::PeerInfo {
|
||||
.map(|info| proto::PeerInfo {
|
||||
peer_id: info.peer_id.map(|id| id.to_bytes()),
|
||||
/// TODO, see https://github.com/libp2p/specs/pull/217
|
||||
signed_peer_record: None,
|
||||
@ -341,7 +341,7 @@ impl From<Rpc> for rpc_proto::Rpc {
|
||||
}
|
||||
}
|
||||
|
||||
rpc_proto::Rpc {
|
||||
proto::RPC {
|
||||
subscriptions,
|
||||
publish,
|
||||
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].
|
||||
|
||||
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||
|
||||
[PR 3208]: https://github.com/libp2p/rust-libp2p/pull/3208
|
||||
[PR 3344]: https://github.com/libp2p/rust-libp2p/pull/3344
|
||||
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||
|
||||
# 0.41.1
|
||||
|
||||
|
@ -18,8 +18,8 @@ libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
log = "0.4.1"
|
||||
lru = "0.9.0"
|
||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
||||
prost = "0.11"
|
||||
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||
quick-protobuf = "0.8"
|
||||
smallvec = "1.6.1"
|
||||
thiserror = "1.0"
|
||||
void = "1.0"
|
||||
@ -34,9 +34,6 @@ libp2p-noise = { path = "../../transports/noise" }
|
||||
libp2p-swarm = { path = "../../swarm", features = ["async-std"] }
|
||||
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.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
||||
[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 protocol;
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod structs_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/structs.rs"));
|
||||
mod proto {
|
||||
include!("generated/mod.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
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::structs_proto;
|
||||
use crate::proto;
|
||||
use asynchronous_codec::{FramedRead, FramedWrite};
|
||||
use futures::{future::BoxFuture, prelude::*};
|
||||
use libp2p_core::{
|
||||
@ -169,18 +169,18 @@ where
|
||||
|
||||
let pubkey_bytes = info.public_key.to_protobuf_encoding();
|
||||
|
||||
let message = structs_proto::Identify {
|
||||
agent_version: Some(info.agent_version),
|
||||
protocol_version: Some(info.protocol_version),
|
||||
public_key: Some(pubkey_bytes),
|
||||
listen_addrs,
|
||||
observed_addr: Some(info.observed_addr.to_vec()),
|
||||
let message = proto::Identify {
|
||||
agentVersion: Some(info.agent_version),
|
||||
protocolVersion: Some(info.protocol_version),
|
||||
publicKey: Some(pubkey_bytes),
|
||||
listenAddrs: listen_addrs,
|
||||
observedAddr: Some(info.observed_addr.to_vec()),
|
||||
protocols: info.protocols,
|
||||
};
|
||||
|
||||
let mut framed_io = FramedWrite::new(
|
||||
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?;
|
||||
@ -200,7 +200,7 @@ where
|
||||
|
||||
let info = FramedRead::new(
|
||||
socket,
|
||||
prost_codec::Codec::<structs_proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
||||
quick_protobuf_codec::Codec::<proto::Identify>::new(MAX_MESSAGE_SIZE_BYTES),
|
||||
)
|
||||
.next()
|
||||
.await
|
||||
@ -212,17 +212,17 @@ where
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
impl TryFrom<structs_proto::Identify> for Info {
|
||||
impl TryFrom<proto::Identify> for Info {
|
||||
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> {
|
||||
Multiaddr::try_from(bytes)
|
||||
}
|
||||
|
||||
let listen_addrs = {
|
||||
let mut addrs = Vec::new();
|
||||
for addr in msg.listen_addrs.into_iter() {
|
||||
for addr in msg.listenAddrs.into_iter() {
|
||||
match parse_multiaddr(addr) {
|
||||
Ok(a) => addrs.push(a),
|
||||
Err(e) => {
|
||||
@ -233,9 +233,9 @@ impl TryFrom<structs_proto::Identify> for Info {
|
||||
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,
|
||||
Err(e) => {
|
||||
debug!("Unable to parse multiaddr: {e:?}");
|
||||
@ -244,8 +244,8 @@ impl TryFrom<structs_proto::Identify> for Info {
|
||||
};
|
||||
let info = Info {
|
||||
public_key,
|
||||
protocol_version: msg.protocol_version.unwrap_or_default(),
|
||||
agent_version: msg.agent_version.unwrap_or_default(),
|
||||
protocol_version: msg.protocolVersion.unwrap_or_default(),
|
||||
agent_version: msg.agentVersion.unwrap_or_default(),
|
||||
listen_addrs,
|
||||
protocols: msg.protocols,
|
||||
observed_addr,
|
||||
@ -258,7 +258,7 @@ impl TryFrom<structs_proto::Identify> for Info {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UpgradeError {
|
||||
#[error(transparent)]
|
||||
Codec(#[from] prost_codec::Error),
|
||||
Codec(#[from] quick_protobuf_codec::Error),
|
||||
#[error("I/O interaction failed")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("Stream closed")]
|
||||
@ -375,13 +375,13 @@ mod tests {
|
||||
a
|
||||
};
|
||||
|
||||
let payload = structs_proto::Identify {
|
||||
agent_version: None,
|
||||
listen_addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||
observed_addr: None,
|
||||
protocol_version: None,
|
||||
let payload = proto::Identify {
|
||||
agentVersion: None,
|
||||
listenAddrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
|
||||
observedAddr: None,
|
||||
protocolVersion: None,
|
||||
protocols: vec![],
|
||||
public_key: Some(
|
||||
publicKey: Some(
|
||||
identity::Keypair::generate_ed25519()
|
||||
.public()
|
||||
.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.
|
||||
|
||||
- Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312].
|
||||
|
||||
[PR 3239]: https://github.com/libp2p/rust-libp2p/pull/3239
|
||||
[PR 3287]: https://github.com/libp2p/rust-libp2p/pull/3287
|
||||
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||
|
||||
# 0.42.1
|
||||
|
||||
|
@ -20,7 +20,7 @@ futures = "0.3.26"
|
||||
log = "0.4"
|
||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
prost = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
rand = "0.8"
|
||||
sha2 = "0.10.0"
|
||||
smallvec = "1.6.1"
|
||||
@ -39,9 +39,6 @@ libp2p-noise = { path = "../../transports/noise" }
|
||||
libp2p-yamux = { path = "../../muxers/yamux" }
|
||||
quickcheck = { package = "quickcheck-ext", path = "../../misc/quickcheck-ext" }
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
[features]
|
||||
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 query;
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod dht_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/dht.pb.rs"));
|
||||
mod proto {
|
||||
include!("generated/mod.rs");
|
||||
pub use self::dht::pb::{
|
||||
mod_Message::{ConnectionType, MessageType, Peer},
|
||||
Message, Record,
|
||||
};
|
||||
}
|
||||
|
||||
pub use addresses::Addresses;
|
||||
|
@ -26,7 +26,7 @@
|
||||
//! to poll the underlying transport for incoming messages, and the `Sink` component
|
||||
//! is used to send messages to remote peers.
|
||||
|
||||
use crate::dht_proto as proto;
|
||||
use crate::proto;
|
||||
use crate::record::{self, Record};
|
||||
use asynchronous_codec::Framed;
|
||||
use bytes::BytesMut;
|
||||
@ -35,7 +35,7 @@ use futures::prelude::*;
|
||||
use instant::Instant;
|
||||
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
||||
use libp2p_core::{Multiaddr, PeerId};
|
||||
use prost::Message;
|
||||
use quick_protobuf::{BytesReader, Writer};
|
||||
use std::{borrow::Cow, convert::TryFrom, time::Duration};
|
||||
use std::{io, iter};
|
||||
use unsigned_varint::codec;
|
||||
@ -59,26 +59,26 @@ pub enum KadConnectionType {
|
||||
CannotConnect = 3,
|
||||
}
|
||||
|
||||
impl From<proto::message::ConnectionType> for KadConnectionType {
|
||||
fn from(raw: proto::message::ConnectionType) -> KadConnectionType {
|
||||
use proto::message::ConnectionType::*;
|
||||
impl From<proto::ConnectionType> for KadConnectionType {
|
||||
fn from(raw: proto::ConnectionType) -> KadConnectionType {
|
||||
use proto::ConnectionType::*;
|
||||
match raw {
|
||||
NotConnected => KadConnectionType::NotConnected,
|
||||
Connected => KadConnectionType::Connected,
|
||||
CanConnect => KadConnectionType::CanConnect,
|
||||
CannotConnect => KadConnectionType::CannotConnect,
|
||||
NOT_CONNECTED => KadConnectionType::NotConnected,
|
||||
CONNECTED => KadConnectionType::Connected,
|
||||
CAN_CONNECT => KadConnectionType::CanConnect,
|
||||
CANNOT_CONNECT => KadConnectionType::CannotConnect,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KadConnectionType> for proto::message::ConnectionType {
|
||||
impl From<KadConnectionType> for proto::ConnectionType {
|
||||
fn from(val: KadConnectionType) -> Self {
|
||||
use proto::message::ConnectionType::*;
|
||||
use proto::ConnectionType::*;
|
||||
match val {
|
||||
KadConnectionType::NotConnected => NotConnected,
|
||||
KadConnectionType::Connected => Connected,
|
||||
KadConnectionType::CanConnect => CanConnect,
|
||||
KadConnectionType::CannotConnect => CannotConnect,
|
||||
KadConnectionType::NotConnected => NOT_CONNECTED,
|
||||
KadConnectionType::Connected => CONNECTED,
|
||||
KadConnectionType::CanConnect => CAN_CONNECT,
|
||||
KadConnectionType::CannotConnect => CANNOT_CONNECT,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,10 +95,10 @@ pub struct KadPeer {
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
// as a special case here
|
||||
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 {
|
||||
node_id,
|
||||
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 {
|
||||
proto::message::Peer {
|
||||
proto::Peer {
|
||||
id: peer.node_id.to_bytes(),
|
||||
addrs: peer.multiaddrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
connection: {
|
||||
let ct: proto::message::ConnectionType = peer.connection_ty.into();
|
||||
ct as i32
|
||||
},
|
||||
connection: peer.connection_ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,6 +188,8 @@ where
|
||||
type Error = io::Error;
|
||||
|
||||
fn upgrade_inbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
||||
use quick_protobuf::{MessageRead, MessageWrite};
|
||||
|
||||
let mut codec = UviBytes::default();
|
||||
codec.set_max_len(self.max_packet_size);
|
||||
|
||||
@ -203,14 +198,16 @@ where
|
||||
.err_into()
|
||||
.with::<_, _, fn(_) -> _, _>(|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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
future::ready(Ok(io::Cursor::new(buf)))
|
||||
})
|
||||
.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,
|
||||
Err(err) => return future::ready(Err(err.into())),
|
||||
};
|
||||
@ -229,6 +226,8 @@ where
|
||||
type Error = io::Error;
|
||||
|
||||
fn upgrade_outbound(self, incoming: C, _: Self::Info) -> Self::Future {
|
||||
use quick_protobuf::{MessageRead, MessageWrite};
|
||||
|
||||
let mut codec = UviBytes::default();
|
||||
codec.set_max_len(self.max_packet_size);
|
||||
|
||||
@ -237,14 +236,16 @@ where
|
||||
.err_into()
|
||||
.with::<_, _, fn(_) -> _, _>(|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
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
.write_message(&mut writer)
|
||||
.expect("Encoding to succeed");
|
||||
future::ready(Ok(io::Cursor::new(buf)))
|
||||
})
|
||||
.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,
|
||||
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 {
|
||||
match kad_msg {
|
||||
KadRequestMsg::Ping => proto::Message {
|
||||
r#type: proto::message::MessageType::Ping as i32,
|
||||
type_pb: proto::MessageType::PING,
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadRequestMsg::FindNode { key } => proto::Message {
|
||||
r#type: proto::message::MessageType::FindNode as i32,
|
||||
type_pb: proto::MessageType::FIND_NODE,
|
||||
key,
|
||||
cluster_level_raw: 10,
|
||||
clusterLevelRaw: 10,
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadRequestMsg::GetProviders { key } => proto::Message {
|
||||
r#type: proto::message::MessageType::GetProviders as i32,
|
||||
type_pb: proto::MessageType::GET_PROVIDERS,
|
||||
key: key.to_vec(),
|
||||
cluster_level_raw: 10,
|
||||
clusterLevelRaw: 10,
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadRequestMsg::AddProvider { key, provider } => proto::Message {
|
||||
r#type: proto::message::MessageType::AddProvider as i32,
|
||||
cluster_level_raw: 10,
|
||||
type_pb: proto::MessageType::ADD_PROVIDER,
|
||||
clusterLevelRaw: 10,
|
||||
key: key.to_vec(),
|
||||
provider_peers: vec![provider.into()],
|
||||
providerPeers: vec![provider.into()],
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadRequestMsg::GetValue { key } => proto::Message {
|
||||
r#type: proto::message::MessageType::GetValue as i32,
|
||||
cluster_level_raw: 10,
|
||||
type_pb: proto::MessageType::GET_VALUE,
|
||||
clusterLevelRaw: 10,
|
||||
key: key.to_vec(),
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadRequestMsg::PutValue { record } => proto::Message {
|
||||
r#type: proto::message::MessageType::PutValue as i32,
|
||||
type_pb: proto::MessageType::PUT_VALUE,
|
||||
key: record.key.to_vec(),
|
||||
record: Some(record_to_proto(record)),
|
||||
..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 {
|
||||
match kad_msg {
|
||||
KadResponseMsg::Pong => proto::Message {
|
||||
r#type: proto::message::MessageType::Ping as i32,
|
||||
type_pb: proto::MessageType::PING,
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadResponseMsg::FindNode { closer_peers } => proto::Message {
|
||||
r#type: proto::message::MessageType::FindNode as i32,
|
||||
cluster_level_raw: 9,
|
||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
type_pb: proto::MessageType::FIND_NODE,
|
||||
clusterLevelRaw: 9,
|
||||
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadResponseMsg::GetProviders {
|
||||
closer_peers,
|
||||
provider_peers,
|
||||
} => proto::Message {
|
||||
r#type: proto::message::MessageType::GetProviders as i32,
|
||||
cluster_level_raw: 9,
|
||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
provider_peers: provider_peers.into_iter().map(KadPeer::into).collect(),
|
||||
type_pb: proto::MessageType::GET_PROVIDERS,
|
||||
clusterLevelRaw: 9,
|
||||
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
providerPeers: provider_peers.into_iter().map(KadPeer::into).collect(),
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadResponseMsg::GetValue {
|
||||
record,
|
||||
closer_peers,
|
||||
} => proto::Message {
|
||||
r#type: proto::message::MessageType::GetValue as i32,
|
||||
cluster_level_raw: 9,
|
||||
closer_peers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
type_pb: proto::MessageType::GET_VALUE,
|
||||
clusterLevelRaw: 9,
|
||||
closerPeers: closer_peers.into_iter().map(KadPeer::into).collect(),
|
||||
record: record.map(record_to_proto),
|
||||
..proto::Message::default()
|
||||
},
|
||||
KadResponseMsg::PutValue { key, value } => proto::Message {
|
||||
r#type: proto::message::MessageType::PutValue as i32,
|
||||
type_pb: proto::MessageType::PUT_VALUE,
|
||||
key: key.to_vec(),
|
||||
record: Some(proto::Record {
|
||||
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.
|
||||
fn proto_to_req_msg(message: proto::Message) -> Result<KadRequestMsg, io::Error> {
|
||||
let msg_type = proto::message::MessageType::from_i32(message.r#type)
|
||||
.ok_or_else(|| invalid_data(format!("unknown message type: {}", message.r#type)))?;
|
||||
|
||||
match msg_type {
|
||||
proto::message::MessageType::Ping => Ok(KadRequestMsg::Ping),
|
||||
proto::message::MessageType::PutValue => {
|
||||
match message.type_pb {
|
||||
proto::MessageType::PING => Ok(KadRequestMsg::Ping),
|
||||
proto::MessageType::PUT_VALUE => {
|
||||
let record = record_from_proto(message.record.unwrap_or_default())?;
|
||||
Ok(KadRequestMsg::PutValue { record })
|
||||
}
|
||||
proto::message::MessageType::GetValue => Ok(KadRequestMsg::GetValue {
|
||||
proto::MessageType::GET_VALUE => Ok(KadRequestMsg::GetValue {
|
||||
key: record::Key::from(message.key),
|
||||
}),
|
||||
proto::message::MessageType::FindNode => Ok(KadRequestMsg::FindNode { key: message.key }),
|
||||
proto::message::MessageType::GetProviders => Ok(KadRequestMsg::GetProviders {
|
||||
proto::MessageType::FIND_NODE => Ok(KadRequestMsg::FindNode { key: message.key }),
|
||||
proto::MessageType::GET_PROVIDERS => Ok(KadRequestMsg::GetProviders {
|
||||
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
|
||||
// parsing errors for peers even when they are valid; we ignore these
|
||||
// errors for now, but ultimately we should just error altogether
|
||||
let provider = message
|
||||
.provider_peers
|
||||
.providerPeers
|
||||
.into_iter()
|
||||
.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.
|
||||
fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Error> {
|
||||
let msg_type = proto::message::MessageType::from_i32(message.r#type)
|
||||
.ok_or_else(|| invalid_data(format!("unknown message type: {}", message.r#type)))?;
|
||||
|
||||
match msg_type {
|
||||
proto::message::MessageType::Ping => Ok(KadResponseMsg::Pong),
|
||||
proto::message::MessageType::GetValue => {
|
||||
match message.type_pb {
|
||||
proto::MessageType::PING => Ok(KadResponseMsg::Pong),
|
||||
proto::MessageType::GET_VALUE => {
|
||||
let record = if let Some(r) = message.record {
|
||||
Some(record_from_proto(r)?)
|
||||
} else {
|
||||
@ -490,7 +485,7 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
||||
};
|
||||
|
||||
let closer_peers = message
|
||||
.closer_peers
|
||||
.closerPeers
|
||||
.into_iter()
|
||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||
.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
|
||||
.closer_peers
|
||||
.closerPeers
|
||||
.into_iter()
|
||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||
.collect();
|
||||
@ -511,15 +506,15 @@ fn proto_to_resp_msg(message: proto::Message) -> Result<KadResponseMsg, io::Erro
|
||||
Ok(KadResponseMsg::FindNode { closer_peers })
|
||||
}
|
||||
|
||||
proto::message::MessageType::GetProviders => {
|
||||
proto::MessageType::GET_PROVIDERS => {
|
||||
let closer_peers = message
|
||||
.closer_peers
|
||||
.closerPeers
|
||||
.into_iter()
|
||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||
.collect();
|
||||
|
||||
let provider_peers = message
|
||||
.provider_peers
|
||||
.providerPeers
|
||||
.into_iter()
|
||||
.filter_map(|peer| KadPeer::try_from(peer).ok())
|
||||
.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 rec = message
|
||||
.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"))
|
||||
}
|
||||
}
|
||||
@ -590,7 +585,7 @@ fn record_to_proto(record: Record) -> proto::Record {
|
||||
}
|
||||
})
|
||||
.unwrap_or(0),
|
||||
time_received: String::new(),
|
||||
timeReceived: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,10 +612,10 @@ mod tests {
|
||||
a
|
||||
};
|
||||
|
||||
let payload = proto::message::Peer {
|
||||
let payload = proto::Peer {
|
||||
id: PeerId::random().to_bytes(),
|
||||
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");
|
||||
|
@ -11,8 +11,11 @@
|
||||
|
||||
- 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
|
||||
[discussion 2174]: https://github.com/libp2p/rust-libp2p/issues/2174
|
||||
[PR 3312]: https://github.com/libp2p/rust-libp2p/pull/3312
|
||||
|
||||
# 0.14.0
|
||||
|
||||
|
@ -20,16 +20,13 @@ instant = "0.1.11"
|
||||
libp2p-core = { version = "0.39.0", path = "../../core" }
|
||||
libp2p-swarm = { version = "0.42.0", path = "../../swarm" }
|
||||
log = "0.4"
|
||||
prost-codec = { version = "0.3", path = "../../misc/prost-codec" }
|
||||
prost = "0.11"
|
||||
quick-protobuf = "0.8"
|
||||
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }
|
||||
rand = "0.8.4"
|
||||
static_assertions = "1"
|
||||
thiserror = "1.0"
|
||||
void = "1"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = "0.11"
|
||||
|
||||
[dev-dependencies]
|
||||
clap = { version = "4.1.6", features = ["derive"] }
|
||||
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;
|
||||
|
||||
use crate::behaviour::handler::Handler;
|
||||
use crate::message_proto;
|
||||
use crate::multiaddr_ext::MultiaddrExt;
|
||||
use crate::proto;
|
||||
use crate::protocol::{inbound_hop, outbound_stop};
|
||||
use either::Either;
|
||||
use instant::Instant;
|
||||
@ -381,7 +381,7 @@ impl NetworkBehaviour for Behaviour {
|
||||
peer_id: event_source,
|
||||
event: Either::Left(handler::In::DenyReservationReq {
|
||||
inbound_reservation_req,
|
||||
status: message_proto::Status::ResourceLimitExceeded,
|
||||
status: proto::Status::RESOURCE_LIMIT_EXCEEDED,
|
||||
}),
|
||||
}
|
||||
.into()
|
||||
@ -496,7 +496,7 @@ impl NetworkBehaviour for Behaviour {
|
||||
event: Either::Left(handler::In::DenyCircuitReq {
|
||||
circuit_id: None,
|
||||
inbound_circuit_req,
|
||||
status: message_proto::Status::ResourceLimitExceeded,
|
||||
status: proto::Status::RESOURCE_LIMIT_EXCEEDED,
|
||||
}),
|
||||
}
|
||||
} else if let Some(dst_conn) = self
|
||||
@ -532,7 +532,7 @@ impl NetworkBehaviour for Behaviour {
|
||||
event: Either::Left(handler::In::DenyCircuitReq {
|
||||
circuit_id: None,
|
||||
inbound_circuit_req,
|
||||
status: message_proto::Status::NoReservation,
|
||||
status: proto::Status::NO_RESERVATION,
|
||||
}),
|
||||
}
|
||||
};
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
use crate::behaviour::CircuitId;
|
||||
use crate::copy_future::CopyFuture;
|
||||
use crate::message_proto::Status;
|
||||
use crate::proto;
|
||||
use crate::protocol::{inbound_hop, outbound_stop};
|
||||
use bytes::Bytes;
|
||||
use either::Either;
|
||||
@ -58,12 +58,12 @@ pub enum In {
|
||||
},
|
||||
DenyReservationReq {
|
||||
inbound_reservation_req: inbound_hop::ReservationReq,
|
||||
status: Status,
|
||||
status: proto::Status,
|
||||
},
|
||||
DenyCircuitReq {
|
||||
circuit_id: Option<CircuitId>,
|
||||
inbound_circuit_req: inbound_hop::CircuitReq,
|
||||
status: Status,
|
||||
status: proto::Status,
|
||||
},
|
||||
NegotiateOutboundConnect {
|
||||
circuit_id: CircuitId,
|
||||
@ -208,7 +208,7 @@ pub enum Event {
|
||||
src_peer_id: PeerId,
|
||||
src_connection_id: ConnectionId,
|
||||
inbound_circuit_req: inbound_hop::CircuitReq,
|
||||
status: Status,
|
||||
status: proto::Status,
|
||||
error: ConnectionHandlerUpgrErr<outbound_stop::CircuitFailedReason>,
|
||||
},
|
||||
/// An inbound circuit has closed.
|
||||
@ -522,12 +522,14 @@ impl Handler {
|
||||
>,
|
||||
) {
|
||||
let (non_fatal_error, status) = match error {
|
||||
ConnectionHandlerUpgrErr::Timeout => {
|
||||
(ConnectionHandlerUpgrErr::Timeout, Status::ConnectionFailed)
|
||||
}
|
||||
ConnectionHandlerUpgrErr::Timer => {
|
||||
(ConnectionHandlerUpgrErr::Timer, Status::ConnectionFailed)
|
||||
}
|
||||
ConnectionHandlerUpgrErr::Timeout => (
|
||||
ConnectionHandlerUpgrErr::Timeout,
|
||||
proto::Status::CONNECTION_FAILED,
|
||||
),
|
||||
ConnectionHandlerUpgrErr::Timer => (
|
||||
ConnectionHandlerUpgrErr::Timer,
|
||||
proto::Status::CONNECTION_FAILED,
|
||||
),
|
||||
ConnectionHandlerUpgrErr::Upgrade(upgrade::UpgradeError::Select(
|
||||
upgrade::NegotiationError::Failed,
|
||||
)) => {
|
||||
@ -556,10 +558,10 @@ impl Handler {
|
||||
outbound_stop::UpgradeError::CircuitFailed(error) => {
|
||||
let status = match error {
|
||||
outbound_stop::CircuitFailedReason::ResourceLimitExceeded => {
|
||||
Status::ResourceLimitExceeded
|
||||
proto::Status::RESOURCE_LIMIT_EXCEEDED
|
||||
}
|
||||
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;
|
||||
pub mod v2;
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
mod message_proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/message_v2.pb.rs"));
|
||||
mod proto {
|
||||
include!("generated/mod.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};
|
||||
|
@ -18,8 +18,8 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::message_proto::Status;
|
||||
use crate::priv_client::transport;
|
||||
use crate::proto;
|
||||
use crate::protocol::{self, inbound_stop, outbound_hop};
|
||||
use either::Either;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
@ -218,7 +218,7 @@ impl Handler {
|
||||
.circuit_deny_futs
|
||||
.insert(
|
||||
src_peer_id,
|
||||
inbound_circuit.deny(Status::NoReservation).boxed(),
|
||||
inbound_circuit.deny(proto::Status::NO_RESERVATION).boxed(),
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::message_proto;
|
||||
use crate::proto;
|
||||
use std::time::Duration;
|
||||
|
||||
pub mod inbound_hop;
|
||||
@ -37,8 +37,8 @@ pub struct Limit {
|
||||
data_in_bytes: Option<u64>,
|
||||
}
|
||||
|
||||
impl From<message_proto::Limit> for Limit {
|
||||
fn from(limit: message_proto::Limit) -> Self {
|
||||
impl From<proto::Limit> for Limit {
|
||||
fn from(limit: proto::Limit) -> Self {
|
||||
Limit {
|
||||
duration: limit.duration.map(|d| Duration::from_secs(d.into())),
|
||||
data_in_bytes: limit.data,
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// 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 asynchronous_codec::{Framed, FramedParts};
|
||||
use bytes::Bytes;
|
||||
@ -51,11 +51,14 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
|
||||
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 {
|
||||
let HopMessage {
|
||||
r#type,
|
||||
let proto::HopMessage {
|
||||
type_pb,
|
||||
peer,
|
||||
reservation: _,
|
||||
limit: _,
|
||||
@ -65,21 +68,19 @@ impl upgrade::InboundUpgrade<NegotiatedSubstream> for Upgrade {
|
||||
.await
|
||||
.ok_or(FatalUpgradeError::StreamClosed)??;
|
||||
|
||||
let r#type =
|
||||
hop_message::Type::from_i32(r#type).ok_or(FatalUpgradeError::ParseTypeField)?;
|
||||
let req = match r#type {
|
||||
hop_message::Type::Reserve => Req::Reserve(ReservationReq {
|
||||
let req = match type_pb {
|
||||
proto::HopMessageType::RESERVE => Req::Reserve(ReservationReq {
|
||||
substream,
|
||||
reservation_duration: self.reservation_duration,
|
||||
max_circuit_duration: self.max_circuit_duration,
|
||||
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)
|
||||
.map_err(|_| FatalUpgradeError::ParsePeerId)?;
|
||||
Req::Connect(CircuitReq { dst, substream })
|
||||
}
|
||||
hop_message::Type::Status => {
|
||||
proto::HopMessageType::STATUS => {
|
||||
return Err(FatalUpgradeError::UnexpectedTypeStatus.into())
|
||||
}
|
||||
};
|
||||
@ -96,8 +97,8 @@ pub enum UpgradeError {
|
||||
Fatal(#[from] FatalUpgradeError),
|
||||
}
|
||||
|
||||
impl From<prost_codec::Error> for UpgradeError {
|
||||
fn from(error: prost_codec::Error) -> Self {
|
||||
impl From<quick_protobuf_codec::Error> for UpgradeError {
|
||||
fn from(error: quick_protobuf_codec::Error) -> Self {
|
||||
Self::Fatal(error.into())
|
||||
}
|
||||
}
|
||||
@ -105,7 +106,7 @@ impl From<prost_codec::Error> for UpgradeError {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FatalUpgradeError {
|
||||
#[error(transparent)]
|
||||
Codec(#[from] prost_codec::Error),
|
||||
Codec(#[from] quick_protobuf_codec::Error),
|
||||
#[error("Stream closed")]
|
||||
StreamClosed,
|
||||
#[error("Failed to parse response type field.")]
|
||||
@ -124,7 +125,7 @@ pub enum Req {
|
||||
}
|
||||
|
||||
pub struct ReservationReq {
|
||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HopMessage>>,
|
||||
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HopMessage>>,
|
||||
reservation_duration: Duration,
|
||||
max_circuit_duration: Duration,
|
||||
max_circuit_bytes: u64,
|
||||
@ -132,10 +133,10 @@ pub struct ReservationReq {
|
||||
|
||||
impl ReservationReq {
|
||||
pub async fn accept(self, addrs: Vec<Multiaddr>) -> Result<(), UpgradeError> {
|
||||
let msg = HopMessage {
|
||||
r#type: hop_message::Type::Status.into(),
|
||||
let msg = proto::HopMessage {
|
||||
type_pb: proto::HopMessageType::STATUS,
|
||||
peer: None,
|
||||
reservation: Some(Reservation {
|
||||
reservation: Some(proto::Reservation {
|
||||
addrs: addrs.into_iter().map(|a| a.to_vec()).collect(),
|
||||
expire: (SystemTime::now() + self.reservation_duration)
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
@ -143,7 +144,7 @@ impl ReservationReq {
|
||||
.as_secs(),
|
||||
voucher: None,
|
||||
}),
|
||||
limit: Some(Limit {
|
||||
limit: Some(proto::Limit {
|
||||
duration: Some(
|
||||
self.max_circuit_duration
|
||||
.as_secs()
|
||||
@ -152,25 +153,25 @@ impl ReservationReq {
|
||||
),
|
||||
data: Some(self.max_circuit_bytes),
|
||||
}),
|
||||
status: Some(Status::Ok.into()),
|
||||
status: Some(proto::Status::OK),
|
||||
};
|
||||
|
||||
self.send(msg).await
|
||||
}
|
||||
|
||||
pub async fn deny(self, status: Status) -> Result<(), UpgradeError> {
|
||||
let msg = HopMessage {
|
||||
r#type: hop_message::Type::Status.into(),
|
||||
pub async fn deny(self, status: proto::Status) -> Result<(), UpgradeError> {
|
||||
let msg = proto::HopMessage {
|
||||
type_pb: proto::HopMessageType::STATUS,
|
||||
peer: None,
|
||||
reservation: None,
|
||||
limit: None,
|
||||
status: Some(status.into()),
|
||||
status: Some(status),
|
||||
};
|
||||
|
||||
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.flush().await?;
|
||||
self.substream.close().await?;
|
||||
@ -181,7 +182,7 @@ impl ReservationReq {
|
||||
|
||||
pub struct CircuitReq {
|
||||
dst: PeerId,
|
||||
substream: Framed<NegotiatedSubstream, prost_codec::Codec<HopMessage>>,
|
||||
substream: Framed<NegotiatedSubstream, quick_protobuf_codec::Codec<proto::HopMessage>>,
|
||||
}
|
||||
|
||||
impl CircuitReq {
|
||||
@ -190,12 +191,12 @@ impl CircuitReq {
|
||||
}
|
||||
|
||||
pub async fn accept(mut self) -> Result<(NegotiatedSubstream, Bytes), UpgradeError> {
|
||||
let msg = HopMessage {
|
||||
r#type: hop_message::Type::Status.into(),
|
||||
let msg = proto::HopMessage {
|
||||
type_pb: proto::HopMessageType::STATUS,
|
||||
peer: None,
|
||||
reservation: None,
|
||||
limit: None,
|
||||
status: Some(Status::Ok.into()),
|
||||
status: Some(proto::Status::OK),
|
||||
};
|
||||
|
||||
self.send(msg).await?;
|
||||
@ -214,19 +215,19 @@ impl CircuitReq {
|
||||
Ok((io, read_buffer.freeze()))
|
||||
}
|
||||
|
||||
pub async fn deny(mut self, status: Status) -> Result<(), UpgradeError> {
|
||||
let msg = HopMessage {
|
||||
r#type: hop_message::Type::Status.into(),
|
||||
pub async fn deny(mut self, status: proto::Status) -> Result<(), UpgradeError> {
|
||||
let msg = proto::HopMessage {
|
||||
type_pb: proto::HopMessageType::STATUS,
|
||||
peer: None,
|
||||
reservation: None,
|
||||
limit: None,
|
||||
status: Some(status.into()),
|
||||
status: Some(status),
|
||||
};
|
||||
self.send(msg).await?;
|
||||
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.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