Skip to content

Commit

Permalink
Add versioning for network peers
Browse files Browse the repository at this point in the history
  • Loading branch information
herr-seppia committed Sep 5, 2024
1 parent d4786d4 commit ea16e27
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 59 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ socket2 = "0.4"
serde_derive = "1"
serde = "1"
humantime-serde = "1"
semver = "1"

[dev-dependencies]
clap = "2.33.3"
Expand Down
5 changes: 5 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ pub struct Config {

/// FEC configuration
pub fec: FECConfig,

pub version: String,
pub version_match: String,
}

impl Default for Config {
Expand All @@ -105,6 +108,8 @@ impl Default for Config {
network: NetworkConfig::default(),
bucket: BucketConfig::default(),
fec: FECConfig::default(),
version: "0.0.1".to_string(),
version_match: "*".to_string(),
}
}
}
Expand Down
21 changes: 16 additions & 5 deletions src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod tests {
use std::io::{BufReader, BufWriter, Cursor, Read, Seek};

use rand::RngCore;
use semver::Version;

use super::Marshallable;
use crate::encoding::header::Header;
Expand All @@ -33,16 +34,18 @@ mod tests {
use crate::peer::PeerNode;
use crate::tests::Result;

const VERSION: Version = Version::new(1, 0, 0);

#[test]
fn test_encode_ping() -> Result<()> {
let peer = PeerNode::generate("192.168.0.1:666", 0)?;
let a = Message::Ping(peer.to_header());
let a = Message::Ping(peer.to_header(), VERSION);
test_kadkast_marshal(a)
}
#[test]
fn test_encode_pong() -> Result<()> {
let peer = PeerNode::generate("192.168.0.1:666", 0)?;
let a = Message::Pong(peer.to_header());
let a = Message::Pong(peer.to_header(), VERSION);
test_kadkast_marshal(a)
}

Expand All @@ -51,7 +54,7 @@ mod tests {
let peer = PeerNode::generate("192.168.0.1:666", 0)?;
let target =
*PeerNode::generate("192.168.1.1:666", 0)?.id().as_binary();
let a = Message::FindNodes(peer.to_header(), target);
let a = Message::FindNodes(peer.to_header(), VERSION, target);
test_kadkast_marshal(a)
}

Expand All @@ -68,14 +71,22 @@ mod tests {
.iter()
.map(|f| f.as_peer_info())
.collect();
let a = Message::Nodes(peer.to_header(), NodePayload { peers: nodes });
let a = Message::Nodes(
peer.to_header(),
VERSION,
NodePayload { peers: nodes },
);
test_kadkast_marshal(a)
}

#[test]
fn test_encode_empty_nodes() -> Result<()> {
let peer = PeerNode::generate("192.168.0.1:666", 0)?;
let a = Message::Nodes(peer.to_header(), NodePayload { peers: vec![] });
let a = Message::Nodes(
peer.to_header(),
VERSION,
NodePayload { peers: vec![] },
);
test_kadkast_marshal(a)
}
#[test]
Expand Down
11 changes: 7 additions & 4 deletions src/encoding/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
use std::io::{self, Error, ErrorKind, Read, Write};

use super::Marshallable;
use crate::{kbucket::BinaryID, K_ID_LEN_BYTES, K_NONCE_LEN};
use crate::{
kbucket::{BinaryID, BinaryKey},
K_ID_LEN_BYTES, K_NONCE_LEN,
};

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Header {
Expand Down Expand Up @@ -49,7 +52,7 @@ impl Marshallable for Header {

let mut port_buffer = [0; 2];
reader.read_exact(&mut port_buffer)?;
let port = u16::from_le_bytes(port_buffer);
let sender_port = u16::from_le_bytes(port_buffer);

let mut network_id = [0; 1];
reader.read_exact(&mut network_id)?;
Expand All @@ -60,9 +63,9 @@ impl Marshallable for Header {

Ok(Header {
binary_id,
sender_port: port,
reserved,
sender_port,
network_id,
reserved,
})
}
}
102 changes: 76 additions & 26 deletions src/encoding/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use std::io::{self, Error, ErrorKind, Read, Write};

use semver::Version;

pub(crate) use super::payload::{BroadcastPayload, NodePayload};
pub use super::{header::Header, Marshallable};
use crate::kbucket::BinaryKey;
Expand All @@ -27,31 +29,31 @@ const ID_MSG_BROADCAST: u8 = 10;

#[derive(Debug, PartialEq)]
pub(crate) enum Message {
Ping(Header),
Pong(Header),
FindNodes(Header, BinaryKey),
Nodes(Header, NodePayload), //should we pass node[] as ref?
Ping(Header, Version),
Pong(Header, Version),
FindNodes(Header, Version, BinaryKey),
Nodes(Header, Version, NodePayload), //should we pass node[] as ref?
Broadcast(Header, BroadcastPayload),
}

impl Message {
pub(crate) fn type_byte(&self) -> u8 {
match self {
Message::Ping(_) => ID_MSG_PING,
Message::Pong(_) => ID_MSG_PONG,
Message::FindNodes(_, _) => ID_MSG_FIND_NODES,
Message::Nodes(_, _) => ID_MSG_NODES,
Message::Broadcast(_, _) => ID_MSG_BROADCAST,
Message::Ping(..) => ID_MSG_PING,
Message::Pong(..) => ID_MSG_PONG,
Message::FindNodes(..) => ID_MSG_FIND_NODES,
Message::Nodes(..) => ID_MSG_NODES,
Message::Broadcast(..) => ID_MSG_BROADCAST,
}
}

pub(crate) fn header(&self) -> &Header {
match self {
Message::Ping(header) => header,
Message::Pong(header) => header,
Message::FindNodes(header, _) => header,
Message::Nodes(header, _) => header,
Message::Broadcast(header, _) => header,
Message::Ping(header, ..) => header,
Message::Pong(header, ..) => header,
Message::FindNodes(header, ..) => header,
Message::Nodes(header, ..) => header,
Message::Broadcast(header, ..) => header,
}
}

Expand All @@ -60,25 +62,65 @@ impl Message {
self.marshal_binary(&mut bytes)?;
Ok(bytes)
}

pub(crate) fn version(&self) -> Option<&Version> {
match self {
Message::Ping(_, version) => Some(version),
Message::Pong(_, version) => Some(version),
Message::FindNodes(_, version, _) => Some(version),
Message::Nodes(_, version, _) => Some(version),

_ => None,
}
}
}

impl Marshallable for semver::Version {
fn marshal_binary<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&[self.major as u8])?;
writer.write_all(&(self.minor as u16).to_le_bytes())?;
writer.write_all(&(self.patch as u16).to_le_bytes())?;
Ok(())
}

fn unmarshal_binary<R: Read>(reader: &mut R) -> io::Result<Self>
where
Self: Sized,
{
let mut maj = [0; 1];
reader.read_exact(&mut maj)?;

let mut min = [0; 2];
reader.read_exact(&mut min)?;

let mut patch = [0; 2];
reader.read_exact(&mut patch)?;

Ok(semver::Version::new(
maj[0] as u64,
u16::from_le_bytes(min) as u64,
u16::from_le_bytes(patch) as u64,
))
}
}

impl Marshallable for Message {
fn marshal_binary<W: Write>(&self, writer: &mut W) -> io::Result<()> {
writer.write_all(&[self.type_byte()])?;
self.header().marshal_binary(writer)?;
match self {
Message::Ping(header) | Message::Pong(header) => {
header.marshal_binary(writer)?
Message::Ping(_, version) | Message::Pong(_, version) => {
version.marshal_binary(writer)?;
}
Message::FindNodes(header, target) => {
header.marshal_binary(writer)?;
Message::FindNodes(_, version, target) => {
version.marshal_binary(writer)?;
target.marshal_binary(writer)?;
}
Message::Nodes(header, node_payload) => {
header.marshal_binary(writer)?;
Message::Nodes(_, version, node_payload) => {
version.marshal_binary(writer)?;
node_payload.marshal_binary(writer)?;
}
Message::Broadcast(header, broadcast_payload) => {
header.marshal_binary(writer)?;
Message::Broadcast(_, broadcast_payload) => {
broadcast_payload.marshal_binary(writer)?;
}
};
Expand All @@ -91,15 +133,23 @@ impl Marshallable for Message {
reader.read_exact(&mut message_type)?;
let header = Header::unmarshal_binary(reader)?;
match message_type[0] {
ID_MSG_PING => Ok(Message::Ping(header)),
ID_MSG_PONG => Ok(Message::Pong(header)),
ID_MSG_PING => {
let version = Version::unmarshal_binary(reader)?;
Ok(Message::Ping(header, version))
}
ID_MSG_PONG => {
let version = Version::unmarshal_binary(reader)?;
Ok(Message::Pong(header, version))
}
ID_MSG_FIND_NODES => {
let version = Version::unmarshal_binary(reader)?;
let target = BinaryKey::unmarshal_binary(reader)?;
Ok(Message::FindNodes(header, target))
Ok(Message::FindNodes(header, version, target))
}
ID_MSG_NODES => {
let version = Version::unmarshal_binary(reader)?;
let payload = NodePayload::unmarshal_binary(reader)?;
Ok(Message::Nodes(header, payload))
Ok(Message::Nodes(header, version, payload))
}
ID_MSG_BROADCAST => {
let payload = BroadcastPayload::unmarshal_binary(reader)?;
Expand Down
Loading

0 comments on commit ea16e27

Please sign in to comment.