use serde::{Serialize, Deserialize};
use bincode;
use sha2::{Sha512, Digest};
use std::net::{Ipv4Addr, Ipv6Addr, IpAddr};
use std::sync::Mutex;
use std::collections::HashMap;
use crate::crypto::dh::DH;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PeerId {
pub(crate) inner: [u8; 16]
}
impl PeerId {
pub fn new(username: &str, dh: DH) -> PeerId {
let mut id = [0u8; 16];
id[0] = 42u8 ^ 69u8;
let public_key_bytes = dh.generate_public_key_bytes();
for i in 1..8 {
id[i] = public_key_bytes[i];
}
let mut hasher = Sha512::new();
hasher.update(username);
let result = hasher.finalize();
for i in 0..8 {
for j in 0..8 {
id[8 + j] ^= result[i*8 + j];
}
}
PeerId {
inner: id
}
}
pub fn serialize(&self) -> Vec<u8> {
bincode::serialize(&self).unwrap()
}
#[track_caller]
pub fn deserialize(bytes: Vec<u8>) -> PeerId {
match bincode::deserialize(&bytes) {
Ok(peer_id) => peer_id,
Err(_) => panic!("Wrong size of `PeerId`"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct Peer {
pub(crate) id: PeerId,
pub name: String
}
impl Peer {
pub fn new(username: &str, dh: DH) -> Peer {
Peer {
id: PeerId::new(username, dh),
name: String::from(username)
}
}
pub fn get_public_key(&self) -> u64 {
let mut be_bytes = [0u8; 8];
for i in 1..8 {
be_bytes[i] = self.id.inner[i];
}
u64::from_be_bytes(be_bytes)
}
pub fn serialize(&self) -> Vec<u8> {
bincode::serialize(&self).unwrap()
}
#[track_caller]
pub fn deserialize(bytes: Vec<u8>) -> Peer {
match bincode::deserialize(&bytes) {
Ok(peer) => peer,
Err(_) => panic!("Wrong size of `Peer`"),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum AddrType {
Dynamic, Static }
#[allow(non_snake_case)] #[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub struct Addr {
addr_t: AddrType,
pub V4: Option<Ipv4Addr>,
pub V6: Option<Ipv6Addr>
}
impl Addr {
pub fn satisfies(&self, ip_addr: IpAddr) -> bool {
if let Some(ipv4_addr) = self.V4 {
if ipv4_addr == ip_addr {
return true;
}
}
if let Some(ipv6_addr) = self.V6 {
if ipv6_addr == ip_addr {
return true;
}
}
return false;
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Node {
pub peer: Peer,
pub device: u16,
pub(crate) addrs: Mutex<Addr>
}
impl Node {
pub fn new(peer: Peer, device: u16, addrs: Addr) -> Node {
Node {
peer,
device,
addrs: Mutex::new(addrs)
}
}
pub fn set_ips(&self, addr_t: AddrType, ipv4: Option<Ipv4Addr>, ipv6: Option<Ipv6Addr>) {
let mut ips = self.addrs.lock().unwrap();
*ips = Addr {
addr_t,
V4: ipv4,
V6: ipv6
};
}
pub fn set_ipv4(&self, ipv4: Option<Ipv4Addr>) {
let mut ips = self.addrs.lock().unwrap();
(*ips).V4 = ipv4;
}
pub fn set_ipv6(&self, ipv6: Option<Ipv6Addr>) {
let mut ips = self.addrs.lock().unwrap();
(*ips).V6 = ipv6;
}
pub fn get_ips(&self) -> Addr {
self.addrs.lock().unwrap().to_owned()
}
pub fn get_ipv4(&self) -> Option<Ipv4Addr> {
self.addrs.lock().unwrap().V4
}
pub fn get_ipv6(&self) -> Option<Ipv6Addr> {
self.addrs.lock().unwrap().V6
}
pub fn is_static(&self) -> bool {
self.addrs.lock().unwrap().addr_t == AddrType::Static
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Contact {
pub peer: Peer,
pub(crate) addrs: Mutex<HashMap<u16, (Addr, u16)>>
}
impl Contact {
pub fn new(peer: &Peer, nodes: &Vec<(Node, u16)>) -> Contact {
let mut addrs: HashMap<u16, (Addr, u16)> = HashMap::with_capacity(nodes.len());
for node in nodes {
addrs.insert(
node.0.device,
(node.0.get_ips(), node.1)
);
}
Contact {
peer: peer.clone(),
addrs: Mutex::new(addrs)
}
}
pub fn set_or_add_node(&self, node: (&Node, u16)) {
(
*self.addrs.lock().unwrap()
).insert(
node.0.device,
(node.0.get_ips(), node.1)
);
}
pub(crate) fn set_or_add_addr(&self, device: u16, address: (Addr, u16)) {
(
*self.addrs.lock().unwrap()
).insert(
device,
address
);
}
pub fn remove_node(&self, node: &Node) {
(
*self.addrs.lock().unwrap()
).remove(&node.device);
}
pub(crate) fn remove_addr(&self, device: u16) {
(
*self.addrs.lock().unwrap()
).remove(&device);
}
pub(crate) fn devices(&self) -> Vec<u16> {
(
*self.addrs.lock().unwrap()
).keys().cloned().collect()
}
pub(crate) fn get_addr(&self, device_id: u16) -> Option<(Addr, u16)> {
(
*self.addrs.lock().unwrap()
).get(&device_id).copied()
}
pub fn serialize(&self) -> Vec<u8> {
bincode::serialize(&self).unwrap()
}
#[track_caller]
pub fn deserialize(bytes: Vec<u8>) -> Contact {
match bincode::deserialize(&bytes) {
Ok(contact) => contact,
Err(_) => panic!("Wrong size of `Contact`"),
}
}
}