diff --git a/src/ethcloud.rs b/src/ethcloud.rs index 7702a65..2ab709b 100644 --- a/src/ethcloud.rs +++ b/src/ethcloud.rs @@ -11,9 +11,8 @@ use std::time::Duration as StdDuration; use time::{Duration, SteadyTime}; -pub use ethernet::{encode as eth_encode, decode as eth_decode, Frame as EthernetFrame}; -pub use tapdev::TapDevice; -pub use udpmessage::{encode as udp_encode, decode as udp_decode, Message as UdpMessage}; +use super::{ethernet, udpmessage}; +use super::tapdev::TapDevice; #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] @@ -180,10 +179,10 @@ impl EthCloud { })) } - fn send_msg(&self, addr: A, msg: &UdpMessage) -> Result<(), Error> { + fn send_msg(&self, addr: A, msg: &udpmessage::Message) -> Result<(), Error> { debug!("Sending {:?} to {}", msg, addr); let mut buffer = [0u8; 64*1024]; - let size = udp_encode(self.token, msg, &mut buffer); + let size = udpmessage::encode(self.token, msg, &mut buffer); match self.socket.lock().expect("Lock poisoned").send_to(&buffer[..size], addr) { Ok(written) if written == size => Ok(()), Ok(_) => Err(Error::SocketError("Sent out truncated packet")), @@ -196,7 +195,7 @@ impl EthCloud { pub fn connect(&self, addr: A) -> Result<(), Error> { info!("Connecting to {}", addr); - self.send_msg(addr, &UdpMessage::GetPeers) + self.send_msg(addr, &udpmessage::Message::GetPeers) } fn housekeep(&self) -> Result<(), Error> { @@ -206,7 +205,7 @@ impl EthCloud { if *next_peerlist <= SteadyTime::now() { debug!("Send peer list to all peers"); let peers = self.peers.lock().expect("Lock poisoned").as_vec(); - let msg = UdpMessage::Peers(peers.clone()); + let msg = udpmessage::Message::Peers(peers.clone()); for addr in &peers { try!(self.send_msg(addr, &msg)); } @@ -215,16 +214,16 @@ impl EthCloud { Ok(()) } - fn handle_ethernet_frame(&self, frame: EthernetFrame) -> Result<(), Error> { + fn handle_ethernet_frame(&self, frame: ethernet::Frame) -> Result<(), Error> { debug!("Read ethernet frame from tap {:?}", frame); match self.mactable.lock().expect("Lock poisoned").lookup(frame.dst, frame.vlan) { Some(addr) => { debug!("Found destination for {:?} (vlan {}) => {}", frame.dst, frame.vlan, addr); - try!(self.send_msg(addr, &UdpMessage::Frame(frame))) + try!(self.send_msg(addr, &udpmessage::Message::Frame(frame))) }, None => { debug!("No destination for {:?} (vlan {}) found, broadcasting", frame.dst, frame.vlan); - let msg = UdpMessage::Frame(frame); + let msg = udpmessage::Message::Frame(frame); for addr in &self.peers.lock().expect("Lock poisoned").as_vec() { try!(self.send_msg(addr, &msg)); } @@ -233,16 +232,16 @@ impl EthCloud { Ok(()) } - fn handle_net_message(&self, peer: SocketAddr, token: Token, msg: UdpMessage) -> Result<(), Error> { + fn handle_net_message(&self, peer: SocketAddr, token: Token, msg: udpmessage::Message) -> Result<(), Error> { if token != self.token { info!("Ignoring message from {} with wrong token {}", peer, token); return Err(Error::WrongToken(token)); } debug!("Recieved {:?} from {}", msg, peer); match msg { - UdpMessage::Frame(frame) => { + udpmessage::Message::Frame(frame) => { let mut buffer = [0u8; 64*1024]; - let size = eth_encode(&frame, &mut buffer); + let size = ethernet::encode(&frame, &mut buffer); debug!("Writing ethernet frame to tap: {:?}", frame); match self.tapdev.lock().expect("Lock poisoned").write(&buffer[..size]) { Ok(()) => (), @@ -254,7 +253,7 @@ impl EthCloud { self.peers.lock().expect("Lock poisoned").add(&peer); self.mactable.lock().expect("Lock poisoned").learn(frame.src, frame.vlan, &peer); }, - UdpMessage::Peers(peers) => { + udpmessage::Message::Peers(peers) => { self.peers.lock().expect("Lock poisoned").add(&peer); for p in &peers { if ! self.peers.lock().expect("Lock poisoned").contains(p) { @@ -262,12 +261,12 @@ impl EthCloud { } } }, - UdpMessage::GetPeers => { + udpmessage::Message::GetPeers => { self.peers.lock().expect("Lock poisoned").add(&peer); let peers = self.peers.lock().expect("Lock poisoned").as_vec(); - try!(self.send_msg(peer, &UdpMessage::Peers(peers))); + try!(self.send_msg(peer, &udpmessage::Message::Peers(peers))); }, - UdpMessage::Close => self.peers.lock().expect("Lock poisoned").remove(&peer) + udpmessage::Message::Close => self.peers.lock().expect("Lock poisoned").remove(&peer) } Ok(()) } @@ -278,7 +277,7 @@ impl EthCloud { loop { match tapdev.read(&mut buffer) { Ok(size) => { - match eth_decode(&buffer[..size]).and_then(|frame| self.handle_ethernet_frame(frame)) { + match ethernet::decode(&mut buffer[..size]).and_then(|frame| self.handle_ethernet_frame(frame)) { Ok(_) => (), Err(e) => error!("Error: {:?}", e) } @@ -294,7 +293,7 @@ impl EthCloud { loop { match socket.recv_from(&mut buffer) { Ok((size, src)) => { - match udp_decode(&buffer[..size]).and_then(|(token, msg)| self.handle_net_message(src, token, msg)) { + match udpmessage::decode(&buffer[..size]).and_then(|(token, msg)| self.handle_net_message(src, token, msg)) { Ok(_) => (), Err(e) => error!("Error: {:?}", e) } diff --git a/src/ethernet.rs b/src/ethernet.rs index d7a6c98..ab42780 100644 --- a/src/ethernet.rs +++ b/src/ethernet.rs @@ -1,15 +1,7 @@ -use std::{mem, slice, ptr, fmt}; +use std::{mem, ptr, fmt}; -pub use super::{Mac, Error}; - -unsafe fn as_bytes(obj: &T) -> &[u8] { - slice::from_raw_parts(mem::transmute::<&T, *const u8>(obj), mem::size_of::()) -} - -unsafe fn as_obj(data: &[u8]) -> &T { - assert!(data.len() >= mem::size_of::()); - mem::transmute(data.as_ptr()) -} +use super::ethcloud::{Mac, Error}; +use super::util::{as_bytes, as_obj}; #[derive(PartialEq)] pub struct Frame<'a> { diff --git a/src/main.rs b/src/main.rs index c3cded4..13dd0aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate time; extern crate docopt; extern crate rustc_serialize; +mod util; mod udpmessage; mod tapdev; mod ethernet; @@ -11,12 +12,13 @@ mod ethcloud; use time::Duration; use docopt::Docopt; -pub use ethcloud::{Error, Mac, Token, EthCloud}; -pub use ethernet::{encode as eth_encode, decode as eth_decode, Frame as EthernetFrame}; -pub use tapdev::TapDevice; -pub use udpmessage::{encode as udp_encode, decode as udp_decode, Message as UdpMessage}; +use ethcloud::{Error, Token, EthCloud}; +//FIXME: Send peer list in several packets when too large. The current behaviour panics at about +// 10000 peers. +//TODO: Implement IPv6 + struct SimpleLogger; diff --git a/src/udpmessage.rs b/src/udpmessage.rs index d4a8191..f1b72b9 100644 --- a/src/udpmessage.rs +++ b/src/udpmessage.rs @@ -2,16 +2,14 @@ use std::{mem, ptr, fmt}; use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; use std::u16; -pub use super::{Mac, Error, Token, EthernetFrame, eth_decode, eth_encode}; +use super::ethcloud::{Mac, Error, Token}; +use super::ethernet; +use super::util::as_obj; -unsafe fn as_obj(data: &[u8]) -> &T { - assert!(data.len() >= mem::size_of::()); - mem::transmute(data.as_ptr()) -} #[derive(PartialEq)] pub enum Message<'a> { - Frame(EthernetFrame<'a>), + Frame(ethernet::Frame<'a>), Peers(Vec), GetPeers, Close, @@ -49,7 +47,7 @@ pub fn decode(data: &[u8]) -> Result<(Token, Message), Error> { match data[pos] { 0 => { pos += 1; - Ok((token, Message::Frame(try!(eth_decode(&data[pos..]))))) + Ok((token, Message::Frame(try!(ethernet::decode(&data[pos..]))))) }, 1 => { pos += 1; @@ -93,7 +91,7 @@ pub fn encode(token: Token, msg: &Message, buf: &mut [u8]) -> usize { &Message::Frame(ref frame) => { buf[pos] = 0; pos += 1; - pos += eth_encode(&frame, &mut buf[pos..]) + pos += ethernet::encode(&frame, &mut buf[pos..]) }, &Message::Peers(ref peers) => { buf[pos] = 1; @@ -140,7 +138,7 @@ fn encode_message_packet() { let src = Mac([1,2,3,4,5,6]); let dst = Mac([7,8,9,10,11,12]); let payload = [1,2,3,4,5]; - let msg = Message::Frame(EthernetFrame{src: &src, dst: &dst, vlan: 0, payload: &payload}); + let msg = Message::Frame(ethernet::Frame{src: &src, dst: &dst, vlan: 0, payload: &payload}); let mut buf = [0; 1024]; let size = encode(token, &msg, &mut buf[..]); assert_eq!(size, 26); diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..95cc955 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,10 @@ +use std::{mem, slice}; + +pub unsafe fn as_bytes(obj: &T) -> &[u8] { + slice::from_raw_parts(mem::transmute::<&T, *const u8>(obj), mem::size_of::()) +} + +pub unsafe fn as_obj(data: &[u8]) -> &T { + assert!(data.len() >= mem::size_of::()); + mem::transmute(data.as_ptr()) +}