#![allow(dead_code)] use crate::infohash::v1::U160; use crate::infohash::InfoHashCapable; use bytes::BytesMut; use serde::export::fmt::Debug; use serde_derive::{Deserialize, Serialize}; use std::cmp::min; use std::convert::TryInto; use std::fmt::{Display, Formatter}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::str::FromStr; mod consts; pub mod infohash; pub mod ip; pub mod metainfo; pub mod peer_storage; pub mod utils; pub use consts::*; pub fn peer_id(input: [u8; 12]) -> [u8; 20] { let peer_id = format!( "eT{:0>2}{:0>2}{:0>2}AAAAAAAAAAAA", env!("CARGO_PKG_VERSION_MAJOR"), env!("CARGO_PKG_VERSION_MINOR"), env!("CARGO_PKG_VERSION_PATCH") ); let mut peer_id: [u8; 20] = peer_id.as_bytes().try_into().unwrap(); &peer_id[8..20].copy_from_slice(&input); peer_id } pub fn compact_peer_id() -> [u8; 4] { [ b'e', b'T', u8::from_str(env!("CARGO_PKG_VERSION_MAJOR")).unwrap(), u8::from_str(env!("CARGO_PKG_VERSION_MINOR")).unwrap(), ] } pub trait CompactContact: Sized { fn to_compact_contact(&self) -> Vec; fn from_compact_contact>(input: T) -> Result; } impl CompactContact for SocketAddr { fn to_compact_contact(&self) -> Vec { match self.ip() { IpAddr::V4(ref v4) => { let mut compact = [0u8; 6]; compact[..4].copy_from_slice(&v4.octets()); compact[4..].copy_from_slice(&self.port().to_be_bytes()[..]); compact.to_vec() } IpAddr::V6(ref v6) => { let mut compact = [0u8; 18]; compact[..16].copy_from_slice(&v6.octets()); compact[16..].copy_from_slice(&self.port().to_be_bytes()); compact.to_vec() } } } fn from_compact_contact>(input: T) -> Result { let b = input.as_ref(); if b.len() == 6 { let ipv4: [u8; 4] = b[..4].try_into().unwrap(); Ok(SocketAddr::new( Ipv4Addr::from(ipv4).into(), u16::from_be_bytes(b[4..].try_into().unwrap()), )) } else if b.len() == 18 { let ipv6: [u8; 16] = b[..16].try_into().unwrap(); Ok(SocketAddr::new( Ipv6Addr::from(ipv6).into(), u16::from_be_bytes(b[16..].try_into().unwrap()), )) } else { Err(ParsingError) } } } #[derive(Debug)] pub struct ParsingError; impl std::error::Error for ParsingError {} impl Display for ParsingError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "there was a parsing error.") } } #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] pub struct ContactInfo { pub id: U160, pub contact: SocketAddr, } impl ContactInfo { pub fn to_bytes(&self) -> Vec { let contact = self.contact.to_compact_contact(); let mut bytes = self.id.to_bytes().to_vec(); bytes.extend(contact); bytes } pub fn from_bytes>(input: T) -> Result { let b = input.as_ref(); if b.len() == 26 || b.len() == 38 { Ok(ContactInfo { id: U160::from_bytes(&b[..20]).map_err(|_| ParsingError)?, contact: SocketAddr::from_compact_contact(&b[20..])?, }) } else { Err(ParsingError) } } } #[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] pub struct Bitfield(BytesMut, usize); impl Bitfield { pub fn size(&self) -> usize { self.1 } pub fn new>(field: T, size: usize) -> Bitfield { Bitfield(BytesMut::from(field.as_ref()), size) } pub fn with_size(size: usize) -> Bitfield { Bitfield( { let mut field = BytesMut::new(); field.resize((size / 8) + if size % 8 > 0 { 1 } else { 0 }, 0); field }, size, ) } pub fn set(&mut self, index: u32) { debug_assert!(index < self.1 as u32, "index out of bounds"); let byte_index = index / 8; let bitmask = 1 << (7 - (index % 8)); self.0[byte_index as usize] |= bitmask; } pub fn unset(&mut self, index: u32) { debug_assert!(index < self.1 as u32, "index out of bounds"); let byte_index = index / 8; let bitmask = 1 << (7 - (index % 8)); self.0[byte_index as usize] &= !bitmask; } pub fn get(&self, index: u32) -> bool { debug_assert!(index < self.1 as u32, "index out of bounds"); let byte_index = index / 8; let bitmask = 1 << (7 - (index % 8)); (self.0[byte_index as usize] & bitmask) > 0 } pub fn add>(&mut self, field: T) { let field = field.as_ref(); let max = min(self.0.len(), field.len()); for i in 0..max { self.0[i] |= field[i] } } pub fn all(&self) -> bool { for i in 0..self.0.len() { let byte = self.0[i]; if i + 1 == self.0.len() { let left = self.1 % 8; if left != 0 { return byte == 255 ^ (255 >> left); } } if byte != u8::MAX { return false; } } return true; } } impl Debug for Bitfield { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "Bitfield(")?; for i in 0..self.0.len() { let byte = self.0[i]; if i + 1 == self.0.len() { write!( f, "{}", &format!("{:0>8b}", byte)[0..(if self.1 % 8 == 0 { 8 } else { self.1 % 8 })] )?; } else { write!(f, "{:b}", byte)?; } } write!(f, ")") } } impl AsRef<[u8]> for Bitfield { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } #[derive(Ord, PartialOrd, Eq, PartialEq, Copy, Clone)] pub enum LookupFilter { IPv6, IPv4, All, } #[cfg(test)] mod tests { use crate::{compact_peer_id, peer_id, Bitfield}; use rand::random; #[test] fn test_peer_id() { let x = peer_id(random()); assert_eq!(String::from_utf8_lossy(&x[0..8]), "eT000100"); assert_eq!(&compact_peer_id(), b"eT\x00\x01"); } #[test] fn test_bitfield() { let mut field = Bitfield::with_size(3); field.set(0); assert!(field.get(0)); field.unset(0); assert_eq!(false, field.get(0)); field.set(2); let other_field = Bitfield::with_size(3); field.add(other_field); assert_eq!(true, field.get(2)); assert!(!field.all()); field.set(1); field.set(0); println!("{} = {:?}", field.as_ref()[0], field); assert!(field.all()); } }