Implemented P2P traffic encryption.
Changed serialization format of P2P messages. Refactored P2P network code.
This commit is contained in:
+10
-28
@@ -7,8 +7,8 @@ use crate::Bytes;
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Message {
|
||||
Error,
|
||||
Hand { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, public: bool, #[serde(default)] rand: String },
|
||||
Shake { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, ok: bool, height: u64 },
|
||||
Hand { app_version: String, origin: String, version: u32, public: bool, rand_id: String, },
|
||||
Shake { app_version: String, origin: String, version: u32, public: bool, rand_id: String, height: u64 },
|
||||
Ping { height: u64, hash: Bytes },
|
||||
Pong { height: u64, hash: Bytes },
|
||||
Twin,
|
||||
@@ -16,24 +16,23 @@ pub enum Message {
|
||||
GetPeers,
|
||||
Peers { peers: Vec<String> },
|
||||
GetBlock { index: u64 },
|
||||
Block { index: u64, block: String },
|
||||
Block { index: u64, block: Vec<u8> },
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, ()> {
|
||||
let text = String::from_utf8(bytes).unwrap_or(String::from("Error{}"));
|
||||
match serde_json::from_str(&text) {
|
||||
match serde_cbor::from_slice(bytes.as_slice()) {
|
||||
Ok(cmd) => Ok(cmd),
|
||||
Err(_) => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand: &str) -> Self {
|
||||
Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand: rand.to_owned() }
|
||||
pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str) -> Self {
|
||||
Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned() }
|
||||
}
|
||||
|
||||
pub fn shake(app_version: &str, origin: &str, version: u32, ok: bool, height: u64) -> Self {
|
||||
Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, ok, height }
|
||||
pub fn shake(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str, height: u64) -> Self {
|
||||
Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned(), height }
|
||||
}
|
||||
|
||||
pub fn ping(height: u64, hash: Bytes) -> Self {
|
||||
@@ -44,24 +43,7 @@ impl Message {
|
||||
Message::Pong { height, hash }
|
||||
}
|
||||
|
||||
pub fn block(height: u64, str: String) -> Self {
|
||||
Message::Block { index: height, block: str }
|
||||
pub fn block(height: u64, block: Vec<u8>) -> Self {
|
||||
Message::Block { index: height, block }
|
||||
}
|
||||
}
|
||||
|
||||
fn default_version() -> String {
|
||||
String::from("0.0.0")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::p2p::Message;
|
||||
|
||||
#[test]
|
||||
pub fn test_hand() {
|
||||
assert!(serde_json::from_str::<Message>("\"Error\"").is_ok());
|
||||
assert!(serde_json::from_str::<Message>("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false,\"rand\":\"123\"}}").is_ok());
|
||||
assert!(serde_json::from_str::<Message>("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false}}").is_ok());
|
||||
}
|
||||
|
||||
}
|
||||
+683
-441
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ use std::collections::HashMap;
|
||||
use mio::net::TcpStream;
|
||||
use crate::p2p::State;
|
||||
use crate::Block;
|
||||
use crate::crypto::Chacha;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Peer {
|
||||
@@ -16,6 +17,7 @@ pub struct Peer {
|
||||
active: bool,
|
||||
reconnects: u32,
|
||||
received_block: u64,
|
||||
cipher: Option<Chacha>,
|
||||
fork: HashMap<u64, Block>
|
||||
}
|
||||
|
||||
@@ -32,10 +34,26 @@ impl Peer {
|
||||
active: false,
|
||||
reconnects: 0,
|
||||
received_block: 0,
|
||||
cipher: None,
|
||||
fork: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_cipher(&mut self, cipher: Chacha) {
|
||||
self.cipher = Some(cipher);
|
||||
}
|
||||
|
||||
pub fn get_cipher(&self) -> &Option<Chacha> {
|
||||
&self.cipher
|
||||
}
|
||||
|
||||
pub fn get_nonce(&self) -> &[u8; 12] {
|
||||
match &self.cipher {
|
||||
None => { &crate::crypto::ZERO_NONCE }
|
||||
Some(chacha) => { chacha.get_nonce() }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_addr(&self) -> SocketAddr {
|
||||
self.addr.clone()
|
||||
}
|
||||
|
||||
+22
-1
@@ -12,7 +12,6 @@ use rand::seq::IteratorRandom;
|
||||
use crate::{Bytes, commons};
|
||||
use crate::commons::*;
|
||||
use crate::p2p::{Message, Peer, State};
|
||||
use crate::commons::next;
|
||||
use std::io;
|
||||
|
||||
const PING_PERIOD: u64 = 30;
|
||||
@@ -84,6 +83,12 @@ impl Peers {
|
||||
State::Twin => {
|
||||
info!("Peer connection {} to {:?} is a twin", &token.0, &peer.get_addr());
|
||||
}
|
||||
State::ServerHandshake => {
|
||||
info!("Peer connection {} from {:?} didn't shake hands", &token.0, &peer.get_addr());
|
||||
}
|
||||
State::HandshakeFinished => {
|
||||
info!("Peer connection {} from {:?} shaked hands, but then failed", &token.0, &peer.get_addr());
|
||||
}
|
||||
}
|
||||
|
||||
self.peers.remove(token);
|
||||
@@ -193,6 +198,15 @@ impl Peers {
|
||||
count
|
||||
}
|
||||
|
||||
pub fn is_tween_connect(&self, id: &str) -> bool {
|
||||
for (_, peer) in self.peers.iter() {
|
||||
if peer.active() && peer.get_id() == id {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn get_peers_banned_count(&self) -> usize {
|
||||
self.ignored.len()
|
||||
}
|
||||
@@ -401,6 +415,13 @@ impl Peers {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets new token from old token, mutating the last
|
||||
pub fn next(current: &mut Token) -> Token {
|
||||
let next = current.0;
|
||||
current.0 += 1;
|
||||
Token(next)
|
||||
}
|
||||
|
||||
fn skip_private_addr(addr: &SocketAddr) -> bool {
|
||||
if addr.ip().is_loopback() {
|
||||
return true;
|
||||
|
||||
+4
-2
@@ -5,6 +5,8 @@ use crate::p2p::Message;
|
||||
pub enum State {
|
||||
Connecting,
|
||||
Connected,
|
||||
ServerHandshake,
|
||||
HandshakeFinished,
|
||||
Idle { from: Instant },
|
||||
Message { data: Vec<u8> },
|
||||
Error,
|
||||
@@ -25,8 +27,8 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn message(message: Message) -> Self {
|
||||
let response = serde_json::to_string(&message).unwrap();
|
||||
State::Message {data: Vec::from(response.as_bytes()) }
|
||||
let data = serde_cbor::to_vec(&message).unwrap();
|
||||
State::Message { data }
|
||||
}
|
||||
|
||||
pub fn is_idle(&self) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user