diff --git a/src/handler/api.rs b/src/handler/api.rs index ce35e47..7573fca 100644 --- a/src/handler/api.rs +++ b/src/handler/api.rs @@ -3,7 +3,7 @@ use crate::message::api::*; use crate::message::Message; use crate::network::{Connection, ServerHandler}; use crate::procedures::Procedures; -use crate::routing::identifier::{Identifier, Identify}; +use crate::routing::identifier::{IdentifierU256, Identify}; use crate::routing::Routing; use crate::storage::Key; use std::error::Error; @@ -31,13 +31,13 @@ impl ApiHandler { } } - fn closest_peer(&self, identifier: Identifier) -> SocketAddr { + fn closest_peer(&self, identifier: IdentifierU256) -> SocketAddr { let routing = self.routing.lock().unwrap(); **routing.closest_peer(identifier) } - fn find_peer(&self, identifier: Identifier) -> crate::Result { + fn find_peer(&self, identifier: IdentifierU256) -> crate::Result { let closest_peer = self.closest_peer(identifier); self.procedures.find_peer(identifier, closest_peer) diff --git a/src/handler/p2p.rs b/src/handler/p2p.rs index 579fab2..adb41e0 100644 --- a/src/handler/p2p.rs +++ b/src/handler/p2p.rs @@ -2,7 +2,7 @@ use crate::error::MessageError; use crate::message::p2p::*; use crate::message::Message; use crate::network::{Connection, ServerHandler}; -use crate::routing::identifier::{Identifier, Identify}; +use crate::routing::identifier::{IdentifierU256, Identify}; use crate::routing::Routing; use crate::storage::Key; use std::collections::HashMap; @@ -30,13 +30,13 @@ impl P2PHandler { Self { routing, storage } } - fn responsible_for(&self, identifier: Identifier) -> bool { + fn responsible_for(&self, identifier: IdentifierU256) -> bool { let routing = self.routing.lock().unwrap(); routing.responsible_for(identifier) } - fn closest_peer(&self, identifier: Identifier) -> SocketAddr { + fn closest_peer(&self, identifier: IdentifierU256) -> SocketAddr { let routing = self.routing.lock().unwrap(); **routing.closest_peer(identifier) diff --git a/src/message/p2p.rs b/src/message/p2p.rs index 02287af..bee81df 100644 --- a/src/message/p2p.rs +++ b/src/message/p2p.rs @@ -1,5 +1,5 @@ use super::MessagePayload; -use crate::routing::identifier::Identifier; +use crate::routing::identifier::IdentifierU256; use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt}; use std::io; use std::io::prelude::*; @@ -71,7 +71,7 @@ pub struct StorageFailure { /// This can be implemented using finger tables. #[derive(Debug, PartialEq)] pub struct PeerFind { - pub identifier: Identifier, + pub identifier: IdentifierU256, } /// If, after a [`PeerFind`] operation, a node has been found which is closest @@ -82,7 +82,7 @@ pub struct PeerFind { /// [`PeerFind`]: struct.PeerFind.html #[derive(Debug, PartialEq)] pub struct PeerFound { - pub identifier: Identifier, + pub identifier: IdentifierU256, pub socket_addr: SocketAddr, } @@ -224,7 +224,7 @@ impl MessagePayload for PeerFind { fn parse(reader: &mut Read) -> io::Result { let mut id_arr = [0; 32]; reader.read_exact(&mut id_arr)?; - let identifier = Identifier::new(&id_arr); + let identifier = IdentifierU256::new(&id_arr); Ok(PeerFind { identifier }) } @@ -240,7 +240,7 @@ impl MessagePayload for PeerFound { fn parse(reader: &mut Read) -> io::Result { let mut id_arr = [0; 32]; reader.read_exact(&mut id_arr)?; - let identifier = Identifier::new(&id_arr); + let identifier = IdentifierU256::new(&id_arr); let mut ip_arr = [0; 16]; reader.read_exact(&mut ip_arr)?; @@ -445,7 +445,7 @@ mod tests { ]; let msg = PeerFind { - identifier: Identifier::new(&[5; 32]), + identifier: IdentifierU256::new(&[5; 32]), }; test_message_payload(&buf, msg); @@ -465,7 +465,7 @@ mod tests { ]; let msg = PeerFound { - identifier: Identifier::new(&[5; 32]), + identifier: IdentifierU256::new(&[5; 32]), socket_addr: "127.0.0.1:8080".parse().unwrap(), }; @@ -486,7 +486,7 @@ mod tests { ]; let msg = PeerFound { - identifier: Identifier::new(&[5; 32]), + identifier: IdentifierU256::new(&[5; 32]), socket_addr: "[2001:db8:85a3::8a23:370:7334]:8080".parse().unwrap(), }; diff --git a/src/procedures.rs b/src/procedures.rs index 61cc265..0eafbfe 100644 --- a/src/procedures.rs +++ b/src/procedures.rs @@ -4,7 +4,7 @@ use crate::error::MessageError; use crate::message::p2p::{PeerFind, PredecessorNotify, StorageGet, StoragePut}; use crate::message::Message; use crate::network::Connection; -use crate::routing::identifier::Identifier; +use crate::routing::identifier::IdentifierU256; use crate::storage::Key; use std::net::SocketAddr; @@ -23,7 +23,7 @@ impl Procedures { /// beginning with `peer_addr` which could be taken from a finger table. pub fn find_peer( &self, - identifier: Identifier, + identifier: IdentifierU256, mut peer_addr: SocketAddr, ) -> crate::Result { debug!("Finding peer for identifier {}", identifier); diff --git a/src/routing/identifier.rs b/src/routing/identifier.rs index 4b7b787..3e1f783 100644 --- a/src/routing/identifier.rs +++ b/src/routing/identifier.rs @@ -23,10 +23,32 @@ use std::ops::Deref; use std::ops::{Add, Sub}; /// A 256 bit identifier on an identifier circle -#[derive(Copy, Clone, PartialEq)] -pub struct Identifier(U256); +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct Identifier(T); -impl Identifier { +pub type IdentifierU256 = Identifier; + +pub trait IdentifierArithmetic: Sized + PartialOrd + Copy + fmt::Debug { + fn overflowing_add(self, other: Self) -> (Self, bool); + fn overflowing_sub(self, other: Self) -> (Self, bool); + fn leading_zeros(&self) -> u32; +} + +impl IdentifierArithmetic for U256 { + fn overflowing_add(self, other: Self) -> (Self, bool) { + U256::overflowing_add(self, other) + } + + fn overflowing_sub(self, other: Self) -> (Self, bool) { + U256::overflowing_sub(self, other) + } + + fn leading_zeros(&self) -> u32 { + U256::leading_zeros(self) + } +} + +impl IdentifierU256 { /// Creates a new identifier from a byte slice. /// /// This method does not perform any hashing but interprets the bytes as @@ -53,6 +75,25 @@ impl Identifier { Self::new(dig.as_ref()) } + /// Returns the raw bytes of this identifier. + /// + /// # Examples + /// + /// ``` + /// # use chord::routing::identifier::Identifier; + /// # + /// let id = Identifier::new(&[5; 32]); + /// + /// assert_eq!([5; 32], id.as_bytes()); + /// ``` + pub fn as_bytes(&self) -> [u8; 32] { + let mut bytes = [0; 32]; + self.0.to_big_endian(&mut bytes); + bytes + } +} + +impl Identifier { /// Returns whether this identifier is between `first` and `second` on the /// identifier circle. /// @@ -73,7 +114,7 @@ impl Identifier { /// assert!(id3.is_between(&id2, &id1)); /// assert!(!id3.is_between(&id1, &id2)); /// ``` - pub fn is_between(&self, first: &Identifier, second: &Identifier) -> bool { + pub fn is_between(&self, first: &Self, second: &Self) -> bool { let (diff1, _) = second.0.overflowing_sub(self.0); let (diff2, _) = second.0.overflowing_sub(first.0); @@ -99,27 +140,10 @@ impl Identifier { pub fn leading_zeros(&self) -> u32 { self.0.leading_zeros() } - - /// Returns the raw bytes of this identifier. - /// - /// # Examples - /// - /// ``` - /// # use chord::routing::identifier::Identifier; - /// # - /// let id = Identifier::new(&[5; 32]); - /// - /// assert_eq!([5; 32], id.as_bytes()); - /// ``` - pub fn as_bytes(&self) -> [u8; 32] { - let mut bytes = [0; 32]; - self.0.to_big_endian(&mut bytes); - bytes - } } /// Implement overflowing addition for identifiers -impl Add for Identifier { +impl Add for Identifier { type Output = Self; fn add(self, other: Self) -> Self { @@ -130,7 +154,7 @@ impl Add for Identifier { } /// Implement overflowing subtraction for identifiers -impl Sub for Identifier { +impl Sub for Identifier { type Output = Self; fn sub(self, other: Self) -> Self { @@ -140,50 +164,43 @@ impl Sub for Identifier { } } -impl fmt::Display for Identifier { +impl fmt::Display for Identifier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "‹{}›", self.0) } } -impl fmt::Debug for Identifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let bytes = self.as_bytes(); - let mut iter = bytes.iter(); - - write!(f, "‹{:02x}", iter.next().unwrap())?; - - for byte in iter { - write!(f, ":{:02x}", byte)?; - } - - write!(f, "›") - } -} - /// Trait to obtain an identifier from a data structure pub trait Identify { + type Output: IdentifierArithmetic; + /// Generates an identifier for this object. - fn identifier(&self) -> Identifier; + fn identifier(&self) -> Identifier; } /// Obtains an identifier by hashing the four octets of the ip address. impl Identify for SocketAddrV4 { - fn identifier(&self) -> Identifier { + type Output = U256; + + fn identifier(&self) -> IdentifierU256 { Identifier::generate(self.ip().octets().as_ref()) } } /// Obtains an identifier by hashing the first eight octets of the ip address. impl Identify for SocketAddrV6 { - fn identifier(&self) -> Identifier { + type Output = U256; + + fn identifier(&self) -> IdentifierU256 { Identifier::generate(self.ip().octets()[..8].as_ref()) } } /// Get the identifier for a V4 or V6 socket address. impl Identify for SocketAddr { - fn identifier(&self) -> Identifier { + type Output = U256; + + fn identifier(&self) -> IdentifierU256 { match self { SocketAddr::V4(v4) => v4.identifier(), SocketAddr::V6(v6) => v6.identifier(), @@ -193,7 +210,9 @@ impl Identify for SocketAddr { /// Hashes the raw key and its replication index. impl Identify for Key { - fn identifier(&self) -> Identifier { + type Output = U256; + + fn identifier(&self) -> IdentifierU256 { let mut bytes = [0; 33]; bytes[..32].copy_from_slice(&self.raw_key); bytes[32] = self.replication_index; @@ -203,9 +222,9 @@ impl Identify for Key { /// Container for a value and its identifier #[derive(Clone, Copy, Debug)] -pub struct IdentifierValue { +pub struct IdentifierValue { value: T, - identifier: Identifier, + identifier: Identifier, } impl IdentifierValue { @@ -231,12 +250,12 @@ impl IdentifierValue { /// /// assert_eq!(value.identifier(), idv.identifier()); /// ``` - pub fn identifier(&self) -> Identifier { + pub fn identifier(&self) -> Identifier { self.identifier } } -impl Deref for IdentifierValue { +impl Deref for IdentifierValue { type Target = T; fn deref(&self) -> &::Target { @@ -256,16 +275,16 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - let expected = Identifier::new(&bytes); + let expected = IdentifierU256::new(&bytes); - assert_eq!(expected, Identifier::with_bit(128)); + assert_eq!(expected, IdentifierU256::with_bit(128)); } #[test] fn is_between() { - let id1 = Identifier::new(&[1; 32]); - let id2 = Identifier::new(&[2; 32]); - let id3 = Identifier::new(&[3; 32]); + let id1 = IdentifierU256::new(&[1; 32]); + let id2 = IdentifierU256::new(&[2; 32]); + let id3 = IdentifierU256::new(&[3; 32]); assert!(id1.is_between(&id3, &id2)); assert!(!id1.is_between(&id2, &id3)); @@ -279,8 +298,8 @@ mod tests { #[test] fn is_between_edges() { - let id1 = Identifier::new(&[1; 32]); - let id2 = Identifier::new(&[2; 32]); + let id1 = IdentifierU256::new(&[1; 32]); + let id2 = IdentifierU256::new(&[2; 32]); // the right id is included while the left one is excluded assert!(id1.is_between(&id2, &id1)); @@ -294,7 +313,7 @@ mod tests { #[test] fn leading_zeros() { #[rustfmt::skip] - let identifier = Identifier::new(&[ + let identifier = IdentifierU256::new(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, ]); @@ -304,50 +323,50 @@ mod tests { #[test] fn leading_zeros_min() { - let identifier = Identifier::new(&[0; 32]); + let identifier = IdentifierU256::new(&[0; 32]); assert_eq!(256, identifier.leading_zeros()); } #[test] fn leading_zeros_max() { - let identifier = Identifier::new(&[0xff; 32]); + let identifier = IdentifierU256::new(&[0xff; 32]); assert_eq!(0, identifier.leading_zeros()); } #[test] fn identifier_add() { - let id1 = Identifier::new(&[1; 32]); - let id2 = Identifier::new(&[2; 32]); - let id3 = Identifier::new(&[3; 32]); + let id1 = IdentifierU256::new(&[1; 32]); + let id2 = IdentifierU256::new(&[2; 32]); + let id3 = IdentifierU256::new(&[3; 32]); assert_eq!(id3, id1 + id2); } #[test] fn identifier_add_overflow() { - let id1 = Identifier::new(&[0xff; 32]); - let id2 = Identifier::with_bit(0); - let id3 = Identifier::new(&[0; 32]); + let id1 = IdentifierU256::new(&[0xff; 32]); + let id2 = IdentifierU256::with_bit(0); + let id3 = IdentifierU256::new(&[0; 32]); assert_eq!(id3, id1 + id2); } #[test] fn identifier_sub() { - let id1 = Identifier::new(&[1; 32]); - let id2 = Identifier::new(&[2; 32]); - let id3 = Identifier::new(&[3; 32]); + let id1 = IdentifierU256::new(&[1; 32]); + let id2 = IdentifierU256::new(&[2; 32]); + let id3 = IdentifierU256::new(&[3; 32]); assert_eq!(id1, id3 - id2); } #[test] fn identifier_sub_overflow() { - let id1 = Identifier::new(&[0xff; 32]); - let id2 = Identifier::with_bit(0); - let id3 = Identifier::new(&[0; 32]); + let id1 = IdentifierU256::new(&[0xff; 32]); + let id2 = IdentifierU256::with_bit(0); + let id3 = IdentifierU256::new(&[0; 32]); assert_eq!(id1, id3 - id2); } diff --git a/src/routing/mod.rs b/src/routing/mod.rs index d46b5a9..ca60d75 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -25,7 +25,7 @@ pub mod identifier; /// The type parameter `T` is used to describe the identifying property of a /// peer, for example its socket address. #[derive(Debug)] -pub struct Routing { +pub struct Routing { /// Address where this peer is listening for peer-to-peer messages pub current: IdentifierValue, /// Closest predecessor of this pee @@ -76,12 +76,12 @@ impl Routing { } /// Checks whether this peer is responsible for the given identifier. - pub fn responsible_for(&self, identifier: Identifier) -> bool { + pub fn responsible_for(&self, identifier: Identifier) -> bool { identifier.is_between(&self.predecessor.identifier(), &self.current.identifier()) } /// Returns the peer closest to the given identifier. - pub fn closest_peer(&self, identifier: Identifier) -> &IdentifierValue { + pub fn closest_peer(&self, identifier: Identifier) -> &IdentifierValue { if self.responsible_for(identifier) { return &self.current; }