vpncloud/src/ip.rs

76 lines
2.2 KiB
Rust
Raw Normal View History

2015-11-22 16:28:04 +00:00
use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
2015-11-21 15:50:50 +00:00
use std::collections::{hash_map, HashMap};
2015-11-22 16:28:04 +00:00
2015-11-22 17:05:15 +00:00
use super::cloud::{Protocol, Error};
2015-11-22 16:28:04 +00:00
use super::util::{as_obj, as_bytes};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IpAddress {
V4(Ipv4Addr),
V6(Ipv6Addr)
}
2015-11-22 17:05:15 +00:00
pub struct InternetProtocol;
2015-11-22 16:28:04 +00:00
2015-11-22 17:05:15 +00:00
impl Protocol for InternetProtocol {
2015-11-22 16:28:04 +00:00
type Address = IpAddress;
2015-11-22 17:05:15 +00:00
fn parse(data: &[u8]) -> Result<(IpAddress, IpAddress), Error> {
2015-11-22 16:28:04 +00:00
unimplemented!()
}
}
2015-11-21 15:50:50 +00:00
struct RoutingEntry {
address: SocketAddr,
bytes: Vec<u8>,
prefix_len: u8
}
pub struct RoutingTable(HashMap<Vec<u8>, Vec<RoutingEntry>>);
impl RoutingTable {
pub fn new() -> Self {
RoutingTable(HashMap::new())
}
pub fn add(&mut self, bytes: Vec<u8>, prefix_len: u8, address: SocketAddr) {
let group_len = (prefix_len as usize / 16) * 2;
let group_bytes: Vec<u8> = 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<u8>) -> Option<SocketAddr> {
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
}
}