diff --git a/src/ethcloud.rs b/src/ethcloud.rs index 5e58759..d174b3b 100644 --- a/src/ethcloud.rs +++ b/src/ethcloud.rs @@ -12,12 +12,31 @@ use epoll; use super::{ethernet, udpmessage}; use super::udpmessage::{Options, Message}; -use super::ethernet::MacTable; -use super::tuntap::{TunTapDevice, DeviceType}; - +use super::ethernet::{TapDevice, MacTable}; pub type NetworkId = u64; +pub trait Table { + type Address; + fn learn(&mut self, Self::Address, SocketAddr); + fn lookup(&self, Self::Address) -> Option; + fn housekeep(&mut self); +} + +pub trait InterfaceMessage: fmt::Debug + Sized { + type Address; + fn src(&self) -> Self::Address; + fn dst(&self) -> Self::Address; + fn encode_to(&self, &[u8], &mut [u8]) -> usize; + fn parse_from(&[u8]) -> Result<(Self, &[u8]), Error>; +} + +pub trait VirtualInterface: AsRawFd { + fn read<'a, T: InterfaceMessage>(&mut self, &'a mut [u8]) -> Result<(T, &'a[u8]), Error>; + fn write(&mut self, &T, &[u8]) -> Result<(), Error>; +} + + #[derive(Debug)] pub enum Error { ParseError(&'static str), @@ -94,70 +113,42 @@ impl PeerList { } } -pub trait Table { - type Address; - fn learn(&mut self, Self::Address, SocketAddr); - fn lookup(&self, Self::Address) -> Option; - fn housekeep(&mut self); -} - -pub trait InterfaceMessage { - type Address; - fn src(&self) -> Self::Address; - fn dst(&self) -> Self::Address; -} - -pub trait VirtualInterface { - type Message: InterfaceMessage; - fn read(&mut self) -> Result; - fn write(&mut self, Self::Message) -> Result<(), Error>; -} - -pub struct EthCloud, M: InterfaceMessage, I: VirtualInterface> { +pub struct EthCloud, M: InterfaceMessage, I: VirtualInterface> { peers: PeerList, reconnect_peers: Vec, - table: MacTable, + table: T, socket: UdpSocket, - tapdev: TunTapDevice, + device: I, network_id: Option, next_peerlist: SteadyTime, update_freq: Duration, buffer_out: [u8; 64*1024], next_housekeep: SteadyTime, - _dummy_t: PhantomData, _dummy_m: PhantomData, - _dummy_i: PhantomData, } -impl, M: InterfaceMessage, I: VirtualInterface> EthCloud { - pub fn new(device: &str, listen: String, network_id: Option, mac_timeout: Duration, peer_timeout: Duration) -> Self { +impl, M: InterfaceMessage, I: VirtualInterface> EthCloud { + pub fn new(device: I, listen: String, network_id: Option, table: T, peer_timeout: Duration) -> Self { let socket = match UdpSocket::bind(&listen as &str) { Ok(socket) => socket, _ => panic!("Failed to open socket") }; - let tapdev = match TunTapDevice::new(device, DeviceType::TapDevice) { - Ok(tapdev) => tapdev, - _ => panic!("Failed to open tap device") - }; - info!("Opened tap device {}", tapdev.ifname()); EthCloud{ peers: PeerList::new(peer_timeout), reconnect_peers: Vec::new(), - table: MacTable::new(mac_timeout), + table: table, socket: socket, - tapdev: tapdev, + device: device, network_id: network_id, next_peerlist: SteadyTime::now(), update_freq: peer_timeout/2, buffer_out: [0; 64*1024], next_housekeep: SteadyTime::now(), - _dummy_t: PhantomData, _dummy_m: PhantomData, - _dummy_i: PhantomData } } - fn send_msg(&mut self, addr: Addr, msg: &Message) -> Result<(), Error> { + fn send_msg(&mut self, addr: Addr, msg: &Message) -> Result<(), Error> { debug!("Sending {:?} to {}", msg, addr); let mut options = Options::default(); options.network_id = self.network_id; @@ -214,16 +205,16 @@ impl, M: InterfaceMessage, I: VirtualInterface Ok(()) } - fn handle_interface_data(&mut self, frame: ethernet::Frame) -> Result<(), Error> { - debug!("Read ethernet frame from tap {:?}", frame); - match self.table.lookup(frame.dst()) { + fn handle_interface_data(&mut self, header: M, payload: &[u8]) -> Result<(), Error> { + debug!("Read data from interface {:?}, {} bytes", header, payload.len()); + match self.table.lookup(header.dst()) { Some(addr) => { - debug!("Found destination for {:?} => {}", frame.dst(), addr); - try!(self.send_msg(addr, &Message::Frame(frame))) + debug!("Found destination for {:?} => {}", header.dst(), addr); + try!(self.send_msg(addr, &Message::Frame(header, payload))) }, None => { - debug!("No destination for {:?} found, broadcasting", frame.dst()); - let msg = Message::Frame(frame); + debug!("No destination for {:?} found, broadcasting", header.dst()); + let msg = Message::Frame(header, payload); for addr in &self.peers.as_vec() { try!(self.send_msg(addr, &msg)); } @@ -232,7 +223,7 @@ impl, M: InterfaceMessage, I: VirtualInterface Ok(()) } - fn handle_net_message(&mut self, peer: SocketAddr, options: Options, msg: Message) -> Result<(), Error> { + fn handle_net_message(&mut self, peer: SocketAddr, options: Options, msg: Message) -> Result<(), Error> { if let Some(id) = self.network_id { if options.network_id != Some(id) { info!("Ignoring message from {} with wrong token {:?}", peer, options.network_id); @@ -241,10 +232,9 @@ impl, M: InterfaceMessage, I: VirtualInterface } debug!("Recieved {:?} from {}", msg, peer); match msg { - Message::Frame(frame) => { - let size = ethernet::encode(&frame, &mut self.buffer_out); - debug!("Writing ethernet frame to tap: {:?}", frame); - match self.tapdev.write(&self.buffer_out[..size]) { + Message::Frame(header, payload) => { + debug!("Writing data to device: {:?}, {} bytes", header, payload.len()); + match self.device.write(&header, &payload) { Ok(()) => (), Err(e) => { error!("Failed to send via tap device {:?}", e); @@ -252,7 +242,7 @@ impl, M: InterfaceMessage, I: VirtualInterface } } self.peers.add(&peer); - self.table.learn(frame.src, peer); + self.table.learn(header.src(), peer); }, Message::Peers(peers) => { self.peers.add(&peer); @@ -277,11 +267,11 @@ impl, M: InterfaceMessage, I: VirtualInterface pub fn run(&mut self) { let epoll_handle = epoll::create1(0).expect("Failed to create epoll handle"); let socket_fd = self.socket.as_raw_fd(); - let tapdev_fd = self.tapdev.as_raw_fd(); + let device_fd = self.device.as_raw_fd(); let mut socket_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 0}; - let mut tapdev_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 1}; + let mut device_event = epoll::EpollEvent{events: epoll::util::event_type::EPOLLIN, data: 1}; epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, socket_fd, &mut socket_event).expect("Failed to add socket to epoll handle"); - epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, tapdev_fd, &mut tapdev_event).expect("Failed to add tapdev to epoll handle"); + epoll::ctl(epoll_handle, epoll::util::ctl_op::ADD, device_fd, &mut device_event).expect("Failed to add device to epoll handle"); let mut events = [epoll::EpollEvent{events: 0, data: 0}; 2]; let mut buffer = [0; 64*1024]; loop { @@ -298,12 +288,10 @@ impl, M: InterfaceMessage, I: VirtualInterface }, Err(_error) => panic!("Failed to read from network socket") }, - &1 => match self.tapdev.read(&mut buffer) { - Ok(size) => { - match ethernet::decode(&mut buffer[..size]).and_then(|frame| self.handle_interface_data(frame)) { - Ok(_) => (), - Err(e) => error!("Error: {:?}", e) - } + &1 => match self.device.read(&mut buffer) { + Ok((header, payload)) => match self.handle_interface_data(header, payload) { + Ok(_) => (), + Err(e) => error!("Error: {:?}", e) }, Err(_error) => panic!("Failed to read from tap device") }, @@ -321,3 +309,17 @@ impl, M: InterfaceMessage, I: VirtualInterface } } } + +pub type TapCloud = EthCloud; + +impl TapCloud { + pub fn new_tap_cloud(device: &str, listen: String, network_id: Option, mac_timeout: Duration, peer_timeout: Duration) -> Self { + let device = match TapDevice::new(device) { + Ok(device) => device, + _ => panic!("Failed to open tap device") + }; + info!("Opened tap device {}", device.ifname()); + let table = MacTable::new(mac_timeout); + Self::new(device, listen, network_id, table, peer_timeout) + } +} diff --git a/src/ethernet.rs b/src/ethernet.rs index 7162bbe..b3bf4a3 100644 --- a/src/ethernet.rs +++ b/src/ethernet.rs @@ -1,13 +1,17 @@ -use std::{mem, ptr, fmt}; +use std::{mem, ptr, fmt, fs}; use std::net::SocketAddr; use std::collections::HashMap; -use std::marker::PhantomData; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::io::{Result as IoResult, Error as IoError, Read, Write}; use super::ethcloud::{Error, Table, InterfaceMessage, VirtualInterface}; use super::util::{as_bytes, as_obj}; use time::{Duration, SteadyTime}; +extern { + fn setup_tap_device(fd: i32, ifname: *mut u8) -> i32; +} #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Mac(pub [u8; 6]); @@ -28,20 +32,18 @@ pub struct EthAddr { } #[derive(PartialEq)] -pub struct Frame<'a> { +pub struct Frame { pub src: EthAddr, - pub dst: EthAddr, - pub payload: &'a [u8] + pub dst: EthAddr } -impl<'a> fmt::Debug for Frame<'a> { +impl fmt::Debug for Frame { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(formatter, "src: {:?}, dst: {:?}, vlan: {}, payload: {} bytes", - self.src.mac, self.dst.mac, self.src.vlan, self.payload.len()) + write!(formatter, "src: {:?}, dst: {:?}, vlan: {}", self.src.mac, self.dst.mac, self.src.vlan) } } -impl<'a> InterfaceMessage for Frame<'a> { +impl InterfaceMessage for Frame { type Address = EthAddr; fn src(&self) -> Self::Address { @@ -51,68 +53,103 @@ impl<'a> InterfaceMessage for Frame<'a> { fn dst(&self) -> Self::Address { self.dst } -} -pub struct TapDevice<'a>(PhantomData<&'a ()>); - -impl<'a> VirtualInterface for TapDevice<'a> { - type Message = Frame<'a>; - - fn read(&mut self) -> Result { - unimplemented!(); - } - - fn write(&mut self, msg: Self::Message) -> Result<(), Error> { - unimplemented!(); - } -} - -pub fn decode(data: &[u8]) -> Result { - if data.len() < 14 { - return Err(Error::ParseError("Frame is too short")); - } - let mut pos = 0; - let dst = *unsafe { as_obj::(&data[pos..]) }; - pos += mem::size_of::(); - let src = *unsafe { as_obj::(&data[pos..]) }; - pos += mem::size_of::(); - let mut vlan = 0; - let mut payload = &data[pos..]; - if data[pos] == 0x81 && data[pos+1] == 0x00 { - pos += 2; - if data.len() < pos + 2 { - return Err(Error::ParseError("Vlan frame is too short")); + fn encode_to(&self, payload: &[u8], data: &mut [u8]) -> usize { + assert!(data.len() >= 16 + payload.len()); + let mut pos = 0; + unsafe { + let dst_dat = as_bytes::(&self.dst.mac); + ptr::copy_nonoverlapping(dst_dat.as_ptr(), data[pos..].as_mut_ptr(), dst_dat.len()); + pos += dst_dat.len(); + let src_dat = as_bytes::(&self.src.mac); + ptr::copy_nonoverlapping(src_dat.as_ptr(), data[pos..].as_mut_ptr(), src_dat.len()); + pos += src_dat.len(); + if self.src.vlan != 0 { + data[pos] = 0x81; data[pos+1] = 0x00; + pos += 2; + let vlan_dat = mem::transmute::(self.src.vlan.to_be()); + ptr::copy_nonoverlapping(vlan_dat.as_ptr(), data[pos..].as_mut_ptr(), vlan_dat.len()); + pos += vlan_dat.len(); + } + ptr::copy_nonoverlapping(payload.as_ptr(), data[pos..].as_mut_ptr(), payload.len()); } - vlan = u16::from_be(* unsafe { as_obj::(&data[pos..]) }); - pos += 2; - payload = &data[pos..]; + pos += payload.len(); + pos } - Ok(Frame{src: EthAddr{mac: src, vlan: vlan}, dst: EthAddr{mac: dst, vlan: vlan}, payload: payload}) -} -pub fn encode(frame: &Frame, buf: &mut [u8]) -> usize { - assert!(buf.len() >= 16 + frame.payload.len()); - let mut pos = 0; - unsafe { - let dst_dat = as_bytes::(&frame.dst.mac); - ptr::copy_nonoverlapping(dst_dat.as_ptr(), buf[pos..].as_mut_ptr(), dst_dat.len()); - pos += dst_dat.len(); - let src_dat = as_bytes::(&frame.src.mac); - ptr::copy_nonoverlapping(src_dat.as_ptr(), buf[pos..].as_mut_ptr(), src_dat.len()); - pos += src_dat.len(); - if frame.src.vlan != 0 { - buf[pos] = 0x81; buf[pos+1] = 0x00; + fn parse_from(data: &[u8]) -> Result<(Frame, &[u8]), Error> { + if data.len() < 14 { + return Err(Error::ParseError("Frame is too short")); + } + let mut pos = 0; + let dst = *unsafe { as_obj::(&data[pos..]) }; + pos += mem::size_of::(); + let src = *unsafe { as_obj::(&data[pos..]) }; + pos += mem::size_of::(); + let mut vlan = 0; + let mut payload = &data[pos..]; + if data[pos] == 0x81 && data[pos+1] == 0x00 { pos += 2; - let vlan_dat = mem::transmute::(frame.src.vlan.to_be()); - ptr::copy_nonoverlapping(vlan_dat.as_ptr(), buf[pos..].as_mut_ptr(), vlan_dat.len()); - pos += vlan_dat.len(); + if data.len() < pos + 2 { + return Err(Error::ParseError("Vlan frame is too short")); + } + vlan = u16::from_be(* unsafe { as_obj::(&data[pos..]) }); + pos += 2; + payload = &data[pos..]; } - ptr::copy_nonoverlapping(frame.payload.as_ptr(), buf[pos..].as_mut_ptr(), frame.payload.len()); + Ok((Frame{src: EthAddr{mac: src, vlan: vlan}, dst: EthAddr{mac: dst, vlan: vlan}}, payload)) } - pos += frame.payload.len(); - pos } +pub struct TapDevice { + fd: fs::File, + ifname: String +} + +impl TapDevice { + pub fn new(ifname: &str) -> IoResult { + let fd = try!(fs::OpenOptions::new().read(true).write(true).open("/dev/net/tun")); + let mut ifname_string = String::with_capacity(32); + ifname_string.push_str(ifname); + ifname_string.push('\0'); + let mut ifname_c = ifname_string.into_bytes(); + let res = unsafe { setup_tap_device(fd.as_raw_fd(), ifname_c.as_mut_ptr()) }; + match res { + 0 => Ok(TapDevice{fd: fd, ifname: String::from_utf8(ifname_c).unwrap()}), + _ => Err(IoError::last_os_error()) + } + } + + #[inline(always)] + pub fn ifname(&self) -> &str { + &self.ifname + } +} + +impl AsRawFd for TapDevice { + fn as_raw_fd(&self) -> RawFd { + self.fd.as_raw_fd() + } +} + +impl VirtualInterface for TapDevice { + fn read<'a, T: InterfaceMessage>(&mut self, mut buffer: &'a mut [u8]) -> Result<(T, &'a[u8]), Error> { + let size = match self.fd.read(&mut buffer) { + Ok(size) => size, + Err(_) => return Err(Error::TunTapDevError("Read error")) + }; + T::parse_from(&buffer[..size]) + } + + fn write(&mut self, msg: &T, payload: &[u8]) -> Result<(), Error> { + let mut buffer = [0u8; 64*1024]; + let size = msg.encode_to(payload, &mut buffer); + match self.fd.write_all(&buffer[..size]) { + Ok(_) => Ok(()), + Err(_) => Err(Error::TunTapDevError("Write error")) + } + } +} struct MacTableValue { address: SocketAddr, @@ -169,12 +206,13 @@ fn without_vlan() { let dst = Mac([6,5,4,3,2,1]); let payload = [1,2,3,4,5,6,7,8]; let mut buf = [0u8; 1024]; - let frame = Frame{src: EthAddr{mac: src, vlan: 0}, dst: EthAddr{mac: dst, vlan: 0}, payload: &payload}; - let size = encode(&frame, &mut buf); + let frame = Frame{src: EthAddr{mac: src, vlan: 0}, dst: EthAddr{mac: dst, vlan: 0}}; + let size = frame.encode_to(&payload, &mut buf); assert_eq!(size, 20); assert_eq!(&buf[..size], &[6,5,4,3,2,1,1,2,3,4,5,6,1,2,3,4,5,6,7,8]); - let frame2 = decode(&buf[..size]).unwrap(); + let (frame2, payload2) = Frame::parse_from(&buf[..size]).unwrap(); assert_eq!(frame, frame2); + assert_eq!(payload, payload2); } #[test] @@ -183,10 +221,11 @@ fn with_vlan() { let dst = Mac([6,5,4,3,2,1]); let payload = [1,2,3,4,5,6,7,8]; let mut buf = [0u8; 1024]; - let frame = Frame{src: EthAddr{mac: src, vlan: 0}, dst: EthAddr{mac: dst, vlan: 0}, payload: &payload}; - let size = encode(&frame, &mut buf); + let frame = Frame{src: EthAddr{mac: src, vlan: 1234}, dst: EthAddr{mac: dst, vlan: 1234}}; + let size = frame.encode_to(&payload, &mut buf); assert_eq!(size, 24); assert_eq!(&buf[..size], &[6,5,4,3,2,1,1,2,3,4,5,6,0x81,0,4,210,1,2,3,4,5,6,7,8]); - let frame2 = decode(&buf[..size]).unwrap(); + let (frame2, payload2) = Frame::parse_from(&buf[..size]).unwrap(); assert_eq!(frame, frame2); + assert_eq!(payload, payload2); } diff --git a/src/main.rs b/src/main.rs index 637284d..8de54dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,6 @@ extern crate epoll; mod util; mod udpmessage; -mod tuntap; mod ethernet; mod ip; mod ethcloud; @@ -16,7 +15,7 @@ use docopt::Docopt; use std::hash::{Hash, SipHasher, Hasher}; -use ethcloud::{Error, EthCloud}; +use ethcloud::{Error, TapCloud}; //TODO: Implement IPv6 @@ -81,7 +80,7 @@ fn main() { Box::new(SimpleLogger) }).unwrap(); debug!("Args: {:?}", args); - let mut tapcloud = EthCloud::::new( + let mut tapcloud = TapCloud::new_tap_cloud( &args.flag_device, args.flag_listen, args.flag_network_id.map(|name| { diff --git a/src/tuntap.rs b/src/tuntap.rs deleted file mode 100644 index 6abd011..0000000 --- a/src/tuntap.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::fs; -use std::io::{Read, Write, Result as IoResult, Error as IoError}; -use std::os::unix::io::{AsRawFd, RawFd}; - -extern { - fn setup_tap_device(fd: i32, ifname: *mut u8) -> i32; - fn setup_tun_device(fd: i32, ifname: *mut u8) -> i32; -} - -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)] -pub enum DeviceType { - TunDevice, TapDevice -} - -pub struct TunTapDevice { - fd: fs::File, - ifname: String, - iftype: DeviceType -} - -impl TunTapDevice { - pub fn new(ifname: &str, iftype: DeviceType) -> IoResult { - let fd = try!(fs::OpenOptions::new().read(true).write(true).open("/dev/net/tun")); - let mut ifname_string = String::with_capacity(32); - ifname_string.push_str(ifname); - ifname_string.push('\0'); - let mut ifname_c = ifname_string.into_bytes(); - let res = match iftype { - DeviceType::TapDevice => unsafe { setup_tap_device(fd.as_raw_fd(), ifname_c.as_mut_ptr()) }, - DeviceType::TunDevice => unsafe { setup_tun_device(fd.as_raw_fd(), ifname_c.as_mut_ptr()) } - }; - match res { - 0 => Ok(TunTapDevice{fd: fd, ifname: String::from_utf8(ifname_c).unwrap(), iftype: iftype}), - _ => Err(IoError::last_os_error()) - } - } - - #[inline(always)] - pub fn ifname(&self) -> &str { - &self.ifname - } - - #[inline(always)] - pub fn iftype(&self) -> DeviceType { - self.iftype - } - - #[inline(always)] - pub fn read(&mut self, buffer: &mut [u8]) -> IoResult { - self.fd.read(buffer) - } - - #[inline(always)] - pub fn write(&mut self, buffer: &[u8]) -> IoResult<()> { - self.fd.write_all(buffer) - } -} - -impl AsRawFd for TunTapDevice { - #[inline(always)] - fn as_raw_fd(&self) -> RawFd { - self.fd.as_raw_fd() - } -} diff --git a/src/udpmessage.rs b/src/udpmessage.rs index 1d34c04..20f5b59 100644 --- a/src/udpmessage.rs +++ b/src/udpmessage.rs @@ -2,7 +2,7 @@ use std::{mem, ptr, fmt}; use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; use std::u16; -use super::ethcloud::{Error, NetworkId}; +use super::ethcloud::{Error, NetworkId, InterfaceMessage}; use super::ethernet; use super::util::{as_obj, as_bytes}; @@ -31,17 +31,17 @@ pub struct Options { #[derive(PartialEq)] -pub enum Message<'a> { - Frame(ethernet::Frame<'a>), +pub enum Message<'a, M: InterfaceMessage> { + Frame(M, &'a[u8]), Peers(Vec), GetPeers, Close, } -impl<'a> fmt::Debug for Message<'a> { +impl<'a, M: InterfaceMessage> fmt::Debug for Message<'a, M> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - &Message::Frame(ref frame) => write!(formatter, "Frame({:?})", frame), + &Message::Frame(ref frame, ref payload) => write!(formatter, "Frame({:?}, payload: {})", frame, payload.len()), &Message::Peers(ref peers) => { try!(write!(formatter, "Peers [")); let mut first = true; @@ -60,7 +60,7 @@ impl<'a> fmt::Debug for Message<'a> { } } -pub fn decode(data: &[u8]) -> Result<(Options, Message), Error> { +pub fn decode(data: &[u8]) -> Result<(Options, Message), Error> { if data.len() < mem::size_of::() { return Err(Error::ParseError("Empty message")); } @@ -83,7 +83,10 @@ pub fn decode(data: &[u8]) -> Result<(Options, Message), Error> { pos += 8; } let msg = match header.msgtype { - 0 => Message::Frame(try!(ethernet::decode(&data[pos..]))), + 0 => { + let (header, payload) = try!(M::parse_from(&data[pos..])); + Message::Frame(header, payload) + }, 1 => { if data.len() < pos + 1 { return Err(Error::ParseError("Empty peers")); @@ -116,12 +119,12 @@ pub fn decode(data: &[u8]) -> Result<(Options, Message), Error> { Ok((options, msg)) } -pub fn encode(options: &Options, msg: &Message, buf: &mut [u8]) -> usize { +pub fn encode(options: &Options, msg: &Message, buf: &mut [u8]) -> usize { assert!(buf.len() >= mem::size_of::()); let mut pos = 0; let mut header = TopHeader::default(); header.msgtype = match msg { - &Message::Frame(_) => 0, + &Message::Frame(_, _) => 0, &Message::Peers(_) => 1, &Message::GetPeers => 2, &Message::Close => 3 @@ -141,8 +144,8 @@ pub fn encode(options: &Options, msg: &Message, buf: &mut [u8]) -> usize { pos += 8; } match msg { - &Message::Frame(ref frame) => { - pos += ethernet::encode(&frame, &mut buf[pos..]) + &Message::Frame(ref header, ref payload) => { + pos += header.encode_to(&payload, &mut buf[pos..]) }, &Message::Peers(ref peers) => { let count_pos = pos; @@ -186,8 +189,8 @@ 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 frame = ethernet::Frame{src: ethernet::EthAddr{mac: src, vlan: 0}, dst: ethernet::EthAddr{mac: dst, vlan: 0}, payload: &payload}; - let msg = Message::Frame(frame); + let frame = ethernet::Frame{src: ethernet::EthAddr{mac: src, vlan: 0}, dst: ethernet::EthAddr{mac: dst, vlan: 0}}; + let msg = Message::Frame(frame, &payload); let mut buf = [0; 1024]; let size = encode(&options, &msg, &mut buf[..]); assert_eq!(size, 25); @@ -201,7 +204,7 @@ fn encode_message_packet() { fn encode_message_peers() { use std::str::FromStr; let options = Options::default(); - let msg = Message::Peers(vec![SocketAddr::from_str("1.2.3.4:123").unwrap(), SocketAddr::from_str("5.6.7.8:12345").unwrap()]); + let msg: Message = Message::Peers(vec![SocketAddr::from_str("1.2.3.4:123").unwrap(), SocketAddr::from_str("5.6.7.8:12345").unwrap()]); let mut buf = [0; 1024]; let size = encode(&options, &msg, &mut buf[..]); assert_eq!(size, 22); @@ -215,7 +218,7 @@ fn encode_message_peers() { fn encode_option_network_id() { let mut options = Options::default(); options.network_id = Some(134); - let msg = Message::GetPeers; + let msg: Message = Message::GetPeers; let mut buf = [0; 1024]; let size = encode(&options, &msg, &mut buf[..]); assert_eq!(size, 16); @@ -228,7 +231,7 @@ fn encode_option_network_id() { #[test] fn encode_message_getpeers() { let options = Options::default(); - let msg = Message::GetPeers; + let msg: Message = Message::GetPeers; let mut buf = [0; 1024]; let size = encode(&options, &msg, &mut buf[..]); assert_eq!(size, 8); @@ -241,7 +244,7 @@ fn encode_message_getpeers() { #[test] fn encode_message_close() { let options = Options::default(); - let msg = Message::Close; + let msg: Message = Message::Close; let mut buf = [0; 1024]; let size = encode(&options, &msg, &mut buf[..]); assert_eq!(size, 8);