use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr}; use std::collections::{hash_map, HashMap}; use std::fmt; use super::cloud::{InterfaceMessage, Error}; use super::util::{as_obj, as_bytes}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum IpAddress { V4(Ipv4Addr), V6(Ipv6Addr) } #[derive(PartialEq)] pub enum IpHeader { V4{src: Ipv4Addr, dst: Ipv4Addr}, V6{src: Ipv6Addr, dst: Ipv6Addr} } impl fmt::Debug for IpHeader { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { &IpHeader::V4{src, dst} => write!(formatter, "src: {}, dst: {}", src, dst), &IpHeader::V6{src, dst} => write!(formatter, "src: {}, dst: {}", src, dst) } } } impl InterfaceMessage for IpHeader { type Address = IpAddress; fn src(&self) -> Self::Address { match self { &IpHeader::V4{src, dst: _} => IpAddress::V4(src), &IpHeader::V6{src, dst: _} => IpAddress::V6(src) } } fn dst(&self) -> Self::Address { match self { &IpHeader::V4{src: _, dst} => IpAddress::V4(dst), &IpHeader::V6{src: _, dst} => IpAddress::V6(dst) } } fn encode_to(&self, payload: &[u8], data: &mut [u8]) -> usize { unimplemented!() } fn parse_from(data: &[u8]) -> Result<(Self, &[u8]), Error> { unimplemented!() } } struct RoutingEntry { address: SocketAddr, bytes: Vec, prefix_len: u8 } pub struct RoutingTable(HashMap, Vec>); impl RoutingTable { pub fn new() -> Self { RoutingTable(HashMap::new()) } pub fn add(&mut self, bytes: Vec, prefix_len: u8, address: SocketAddr) { let group_len = (prefix_len as usize / 16) * 2; let group_bytes: Vec = bytes[..group_len].iter().map(|b| *b).collect(); let routing_entry = RoutingEntry{address: address, bytes: bytes, prefix_len: prefix_len}; match self.0.entry(group_bytes) { hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry), hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () } } } pub fn lookup(&self, bytes: Vec) -> Option { let mut len = bytes.len()/2 * 2; for i in 0..len/2 { if let Some(group) = self.0.get(&bytes[0..len-2*i]) { for entry in group { if entry.bytes.len() != bytes.len() { continue; } let mut match_len = 0; for i in 0..bytes.len() { let b = bytes[i] ^ entry.bytes[i]; if b == 0 { match_len += 8; } else { match_len += b.leading_zeros(); break; } } if match_len as u8 >= entry.prefix_len { return Some(entry.address); } } } } None } }