More tests, bugfixes and code cleanup

This commit is contained in:
Dennis Schwerdel 2016-07-06 21:14:09 +02:00
parent 3488d2d2a3
commit 0bcdfbe21e
10 changed files with 84 additions and 60 deletions

View File

@ -4,6 +4,7 @@ This project follows [semantic versioning](http://semver.org).
### UNRELEASED ### UNRELEASED
- [added] Added more tests
- [added] Added pluggable polling system - [added] Added pluggable polling system
- [added] Added documentation - [added] Added documentation
- [changed] Code cleanup - [changed] Code cleanup
@ -14,6 +15,7 @@ This project follows [semantic versioning](http://semver.org).
- [fixed] Reconnecting to lost peers when receiving from them or sending to them - [fixed] Reconnecting to lost peers when receiving from them or sending to them
- [fixed] Sending peer list more often to prevent timeouts - [fixed] Sending peer list more often to prevent timeouts
- [fixed] Removing learnt addresses of lost peers - [fixed] Removing learnt addresses of lost peers
- [fixed] Fixed possible crash in message decoding
### v0.6.0 (2016-06-02) ### v0.6.0 (2016-06-02)

View File

@ -237,10 +237,10 @@ impl<P: Protocol> GenericCloud<P> {
}; };
try!(match socket.send_to(msg_data, addr) { try!(match socket.send_to(msg_data, addr) {
Ok(written) if written == msg_data.len() => Ok(()), Ok(written) if written == msg_data.len() => Ok(()),
Ok(_) => Err(Error::SocketError("Sent out truncated packet")), Ok(_) => Err(Error::Socket("Sent out truncated packet")),
Err(e) => { Err(e) => {
error!("Failed to send via network {:?}", e); error!("Failed to send via network {:?}", e);
Err(Error::SocketError("IOError when sending")) Err(Error::Socket("IOError when sending"))
} }
}) })
} }
@ -263,10 +263,10 @@ impl<P: Protocol> GenericCloud<P> {
}; };
match socket.send_to(msg_data, addr) { match socket.send_to(msg_data, addr) {
Ok(written) if written == msg_data.len() => Ok(()), Ok(written) if written == msg_data.len() => Ok(()),
Ok(_) => Err(Error::SocketError("Sent out truncated packet")), Ok(_) => Err(Error::Socket("Sent out truncated packet")),
Err(e) => { Err(e) => {
error!("Failed to send via network {:?}", e); error!("Failed to send via network {:?}", e);
Err(Error::SocketError("IOError when sending")) Err(Error::Socket("IOError when sending"))
} }
} }
} }
@ -504,7 +504,7 @@ impl<P: Protocol> GenericCloud<P> {
Ok(()) => (), Ok(()) => (),
Err(e) => { Err(e) => {
error!("Failed to send via device: {}", e); error!("Failed to send via device: {}", e);
return Err(Error::TunTapDevError("Failed to write to device")); return Err(Error::TunTapDev("Failed to write to device"));
} }
} }
if self.learning { if self.learning {

View File

@ -259,7 +259,7 @@ impl Crypto {
) }; ) };
match res { match res {
0 => Ok(mlen as usize), 0 => Ok(mlen as usize),
_ => Err(Error::CryptoError("Failed to decrypt")) _ => Err(Error::Crypto("Failed to decrypt"))
} }
}, },
Crypto::AES256GCM{ref state, ..} => { Crypto::AES256GCM{ref state, ..} => {
@ -277,7 +277,7 @@ impl Crypto {
) }; ) };
match res { match res {
0 => Ok(mlen as usize), 0 => Ok(mlen as usize),
_ => Err(Error::CryptoError("Failed to decrypt")) _ => Err(Error::Crypto("Failed to decrypt"))
} }
} }
} }

View File

@ -133,7 +133,7 @@ impl Device {
/// This method will return an error if the underlying read call fails. /// This method will return an error if the underlying read call fails.
#[inline] #[inline]
pub fn read(&mut self, mut buffer: &mut [u8]) -> Result<(usize, usize), Error> { pub fn read(&mut self, mut buffer: &mut [u8]) -> Result<(usize, usize), Error> {
let read = try!(self.fd.read(&mut buffer).map_err(|_| Error::TunTapDevError("Read error"))); let read = try!(self.fd.read(&mut buffer).map_err(|_| Error::TunTapDev("Read error")));
let (start, read) = self.correct_data_after_read(&mut buffer, 0, read); let (start, read) = self.correct_data_after_read(&mut buffer, 0, read);
Ok((start, read)) Ok((start, read))
} }
@ -171,8 +171,8 @@ impl Device {
pub fn write(&mut self, mut data: &mut [u8], start: usize) -> Result<(), Error> { pub fn write(&mut self, mut data: &mut [u8], start: usize) -> Result<(), Error> {
let start = self.correct_data_before_write(&mut data, start); let start = self.correct_data_before_write(&mut data, start);
match self.fd.write_all(&data[start..]) { match self.fd.write_all(&data[start..]) {
Ok(_) => self.fd.flush().map_err(|_| Error::TunTapDevError("Flush error")), Ok(_) => self.fd.flush().map_err(|_| Error::TunTapDev("Flush error")),
Err(_) => Err(Error::TunTapDevError("Write error")) Err(_) => Err(Error::TunTapDev("Write error"))
} }
} }

View File

@ -26,7 +26,7 @@ impl Protocol for Frame {
/// This method will fail when the given data is not a valid ethernet frame. /// This method will fail when the given data is not a valid ethernet frame.
fn parse(data: &[u8]) -> Result<(Address, Address), Error> { fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
if data.len() < 14 { if data.len() < 14 {
return Err(Error::ParseError("Frame is too short")); return Err(Error::Parse("Frame is too short"));
} }
let mut pos = 0; let mut pos = 0;
let dst_data = &data[pos..pos+6]; let dst_data = &data[pos..pos+6];
@ -36,7 +36,7 @@ impl Protocol for Frame {
if data[pos] == 0x81 && data[pos+1] == 0x00 { if data[pos] == 0x81 && data[pos+1] == 0x00 {
pos += 2; pos += 2;
if data.len() < pos + 2 { if data.len() < pos + 2 {
return Err(Error::ParseError("Vlan frame is too short")); return Err(Error::Parse("Vlan frame is too short"));
} }
let mut src = [0; 16]; let mut src = [0; 16];
let mut dst = [0; 16]; let mut dst = [0; 16];

View File

@ -25,13 +25,13 @@ impl Protocol for Packet {
/// This method will fail when the given data is not a valid ipv4 and ipv6 packet. /// This method will fail when the given data is not a valid ipv4 and ipv6 packet.
fn parse(data: &[u8]) -> Result<(Address, Address), Error> { fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
if data.len() < 1 { if data.len() < 1 {
return Err(Error::ParseError("Empty header")); return Err(Error::Parse("Empty header"));
} }
let version = data[0] >> 4; let version = data[0] >> 4;
match version { match version {
4 => { 4 => {
if data.len() < 20 { if data.len() < 20 {
return Err(Error::ParseError("Truncated IPv4 header")); return Err(Error::Parse("Truncated IPv4 header"));
} }
let src = try!(Address::read_from_fixed(&data[12..], 4)); let src = try!(Address::read_from_fixed(&data[12..], 4));
let dst = try!(Address::read_from_fixed(&data[16..], 4)); let dst = try!(Address::read_from_fixed(&data[16..], 4));
@ -39,13 +39,13 @@ impl Protocol for Packet {
}, },
6 => { 6 => {
if data.len() < 40 { if data.len() < 40 {
return Err(Error::ParseError("Truncated IPv6 header")); return Err(Error::Parse("Truncated IPv6 header"));
} }
let src = try!(Address::read_from_fixed(&data[8..], 16)); let src = try!(Address::read_from_fixed(&data[8..], 16));
let dst = try!(Address::read_from_fixed(&data[24..], 16)); let dst = try!(Address::read_from_fixed(&data[24..], 16));
Ok((src, dst)) Ok((src, dst))
}, },
_ => Err(Error::ParseError("Invalid version")) _ => Err(Error::Parse("Invalid version"))
} }
} }
} }

View File

@ -7,7 +7,7 @@ use std::str::FromStr;
use super::ethernet::{Frame, SwitchTable}; use super::ethernet::{Frame, SwitchTable};
use super::ip::{RoutingTable, Packet}; use super::ip::{RoutingTable, Packet};
use super::types::{Error, Protocol, Address, Range, Table}; use super::types::{Protocol, Address, Range, Table};
use super::udpmessage::{Options, Message, decode, encode}; use super::udpmessage::{Options, Message, decode, encode};
use super::crypto::{Crypto, CryptoMethod}; use super::crypto::{Crypto, CryptoMethod};
@ -109,6 +109,14 @@ fn udpmessage_peers() {
let (options2, msg2) = decode(&mut should, &mut crypto).unwrap(); let (options2, msg2) = decode(&mut should, &mut crypto).unwrap();
assert_eq!(options, options2); assert_eq!(options, options2);
assert_eq!(msg, msg2); assert_eq!(msg, msg2);
// Missing IPv4 count
assert!(decode(&mut[118,112,110,1,0,0,0,1], &mut crypto).is_err());
// Truncated IPv4
assert!(decode(&mut[118,112,110,1,0,0,0,1,1], &mut crypto).is_err());
// Missing IPv6 count
assert!(decode(&mut[118,112,110,1,0,0,0,1,1,1,2,3,4,0,0], &mut crypto).is_err());
// Truncated IPv6
assert!(decode(&mut[118,112,110,1,0,0,0,1,1,1,2,3,4,0,0,1], &mut crypto).is_err());
} }
#[test] #[test]
@ -292,6 +300,8 @@ fn routing_table() {
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), peer3.clone()); table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), peer3.clone());
assert_eq!(table.lookup(&Address::from_str("192.168.2.31").unwrap()), Some(peer3)); assert_eq!(table.lookup(&Address::from_str("192.168.2.31").unwrap()), Some(peer3));
assert_eq!(table.lookup(&Address::from_str("192.168.2.32").unwrap()), Some(peer1)); assert_eq!(table.lookup(&Address::from_str("192.168.2.32").unwrap()), Some(peer1));
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(28), peer3.clone());
assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer3));
} }
#[test] #[test]
@ -301,7 +311,7 @@ fn address_parse_fmt() {
assert_eq!(format!("{}", Address{data: [3,56,120,45,22,5,1,2,0,0,0,0,0,0,0,0], len: 8}), "vlan824/78:2d:16:05:01:02"); assert_eq!(format!("{}", Address{data: [3,56,120,45,22,5,1,2,0,0,0,0,0,0,0,0], len: 8}), "vlan824/78:2d:16:05:01:02");
assert_eq!(format!("{}", Address::from_str("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f").unwrap()), "0001:0203:0405:0607:0809:0a0b:0c0d:0e0f"); assert_eq!(format!("{}", Address::from_str("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f").unwrap()), "0001:0203:0405:0607:0809:0a0b:0c0d:0e0f");
assert_eq!(format!("{:?}", Address{data: [1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0], len: 2}), "0102"); assert_eq!(format!("{:?}", Address{data: [1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0], len: 2}), "0102");
assert_eq!(Address::from_str(""), Err(Error::ParseError("Failed to parse address"))); assert!(Address::from_str("").is_err()); // Failed to parse address
} }
#[test] #[test]
@ -317,11 +327,30 @@ fn address_decode_encode() {
assert_eq!(&buf[0..7], &[6, 0x78, 0x2d, 0x16, 0x05, 0x01, 0x02]); assert_eq!(&buf[0..7], &[6, 0x78, 0x2d, 0x16, 0x05, 0x01, 0x02]);
assert_eq!((addr, 7), Address::read_from(&buf).unwrap()); assert_eq!((addr, 7), Address::read_from(&buf).unwrap());
assert_eq!(addr, Address::read_from_fixed(&buf[1..], 6).unwrap()); assert_eq!(addr, Address::read_from_fixed(&buf[1..], 6).unwrap());
assert_eq!(Address::read_from(&buf[0..0]), Err(Error::ParseError("Address too short"))); assert!(Address::read_from(&buf[0..0]).is_err()); // Address too short
buf[0] = 100; buf[0] = 100;
assert_eq!(Address::read_from(&buf), Err(Error::ParseError("Invalid address, too long"))); assert!(Address::read_from(&buf).is_err()); // Invalid address, too long
buf[0] = 5; buf[0] = 5;
assert_eq!(Address::read_from(&buf[0..4]), Err(Error::ParseError("Address too short"))); assert!(Address::read_from(&buf[0..4]).is_err()); // Address too short
}
#[test]
fn address_eq() {
assert!(Address::read_from_fixed(&[1,2,3,4], 4) == Address::read_from_fixed(&[1,2,3,4], 4));
assert!(Address::read_from_fixed(&[1,2,3,4], 4) != Address::read_from_fixed(&[1,2,3,5], 4));
assert!(Address::read_from_fixed(&[1,2,3,4], 3) == Address::read_from_fixed(&[1,2,3,5], 3));
assert!(Address::read_from_fixed(&[1,2,3,4], 3) != Address::read_from_fixed(&[1,2,3,4], 4));
}
#[test]
fn address_range_decode_encode() {
let mut buf = [0; 32];
let range = Range{base: Address{data: [0,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0], len: 4}, prefix_len: 24};
assert_eq!(range.write_to(&mut buf), 6);
assert_eq!(&buf[0..6], &[4, 0, 1, 2, 3, 24]);
assert_eq!((range, 6), Range::read_from(&buf).unwrap());
buf[0] = 17;
assert!(Range::read_from(&buf).is_err());
} }
#[test] #[test]

View File

@ -25,7 +25,7 @@ impl Address {
#[inline] #[inline]
pub fn read_from(data: &[u8]) -> Result<(Address, usize), Error> { pub fn read_from(data: &[u8]) -> Result<(Address, usize), Error> {
if data.len() < 1 { if data.len() < 1 {
return Err(Error::ParseError("Address too short")); return Err(Error::Parse("Address too short"));
} }
let len = data[0] as usize; let len = data[0] as usize;
let addr = try!(Address::read_from_fixed(&data[1..], len)); let addr = try!(Address::read_from_fixed(&data[1..], len));
@ -35,10 +35,10 @@ impl Address {
#[inline] #[inline]
pub fn read_from_fixed(data: &[u8], len: usize) -> Result<Address, Error> { pub fn read_from_fixed(data: &[u8], len: usize) -> Result<Address, Error> {
if len > 16 { if len > 16 {
return Err(Error::ParseError("Invalid address, too long")); return Err(Error::Parse("Invalid address, too long"));
} }
if data.len() < len { if data.len() < len {
return Err(Error::ParseError("Address too short")); return Err(Error::Parse("Address too short"));
} }
let mut bytes = [0; 16]; let mut bytes = [0; 16];
bytes[0..len].copy_from_slice(&data[0..len]); bytes[0..len].copy_from_slice(&data[0..len]);
@ -59,15 +59,7 @@ impl Address {
impl PartialEq for Address { impl PartialEq for Address {
#[inline] #[inline]
fn eq(&self, rhs: &Self) -> bool { fn eq(&self, rhs: &Self) -> bool {
if self.len != rhs.len { self.len == rhs.len && self.data[..self.len as usize] == rhs.data[..self.len as usize]
return false;
}
for i in 0..self.len as usize {
if self.data[i] != rhs.data[i] {
return false;
}
}
true
} }
} }
@ -129,11 +121,11 @@ impl FromStr for Address {
if parts.len() == 6 { if parts.len() == 6 {
let mut bytes = [0; 16]; let mut bytes = [0; 16];
for i in 0..6 { for i in 0..6 {
bytes[i] = try!(u8::from_str_radix(&parts[i], 16).map_err(|_| Error::ParseError("Failed to parse mac"))); bytes[i] = try!(u8::from_str_radix(&parts[i], 16).map_err(|_| Error::Parse("Failed to parse mac")));
} }
return Ok(Address{data: bytes, len: 6}); return Ok(Address{data: bytes, len: 6});
} }
Err(Error::ParseError("Failed to parse address")) Err(Error::Parse("Failed to parse address"))
} }
} }
@ -149,7 +141,7 @@ impl Range {
pub fn read_from(data: &[u8]) -> Result<(Range, usize), Error> { pub fn read_from(data: &[u8]) -> Result<(Range, usize), Error> {
let (address, read) = try!(Address::read_from(data)); let (address, read) = try!(Address::read_from(data));
if data.len() < read + 1 { if data.len() < read + 1 {
return Err(Error::ParseError("Range too short")); return Err(Error::Parse("Range too short"));
} }
let prefix_len = data[read]; let prefix_len = data[read];
Ok((Range{base: address, prefix_len: prefix_len}, read + 1)) Ok((Range{base: address, prefix_len: prefix_len}, read + 1))
@ -170,10 +162,10 @@ impl FromStr for Range {
fn from_str(text: &str) -> Result<Self, Self::Err> { fn from_str(text: &str) -> Result<Self, Self::Err> {
let pos = match text.find('/') { let pos = match text.find('/') {
Some(pos) => pos, Some(pos) => pos,
None => return Err(Error::ParseError("Invalid range format")) None => return Err(Error::Parse("Invalid range format"))
}; };
let prefix_len = try!(u8::from_str(&text[pos+1..]) let prefix_len = try!(u8::from_str(&text[pos+1..])
.map_err(|_| Error::ParseError("Failed to parse prefix length"))); .map_err(|_| Error::Parse("Failed to parse prefix length")));
let base = try!(Address::from_str(&text[..pos])); let base = try!(Address::from_str(&text[..pos]));
Ok(Range{base: base, prefix_len: prefix_len}) Ok(Range{base: base, prefix_len: prefix_len})
} }
@ -221,21 +213,19 @@ pub trait Protocol: Sized {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Error { pub enum Error {
ParseError(&'static str), Parse(&'static str),
WrongNetwork(Option<NetworkId>), WrongNetwork(Option<NetworkId>),
SocketError(&'static str), Socket(&'static str),
NameError(String), Name(String),
TunTapDevError(&'static str), TunTapDev(&'static str),
CryptoError(&'static str) Crypto(&'static str)
} }
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self { match *self {
Error::ParseError(ref msg) => write!(formatter, "{}", msg), Error::Parse(ref msg) | Error::Socket(ref msg) |
Error::SocketError(ref msg) => write!(formatter, "{}", msg), Error::TunTapDev(ref msg) | Error::Crypto(ref msg) => write!(formatter, "{}", msg),
Error::TunTapDevError(ref msg) => write!(formatter, "{}", msg), Error::Name(ref name) => write!(formatter, "failed to resolve name '{}'", name),
Error::CryptoError(ref msg) => write!(formatter, "{}", msg),
Error::NameError(ref name) => write!(formatter, "failed to resolve name '{}'", name),
Error::WrongNetwork(Some(net)) => write!(formatter, "wrong network id: {}", net), Error::WrongNetwork(Some(net)) => write!(formatter, "wrong network id: {}", net),
Error::WrongNetwork(None) => write!(formatter, "wrong network id: none"), Error::WrongNetwork(None) => write!(formatter, "wrong network id: none"),
} }

View File

@ -33,7 +33,7 @@ impl TopHeader {
pub fn read_from(data: &[u8]) -> Result<(TopHeader, usize), Error> { pub fn read_from(data: &[u8]) -> Result<(TopHeader, usize), Error> {
if data.len() < TopHeader::size() { if data.len() < TopHeader::size() {
return Err(Error::ParseError("Empty message")); return Err(Error::Parse("Empty message"));
} }
let mut header = TopHeader::default(); let mut header = TopHeader::default();
header.magic.copy_from_slice(&data[0..3]); header.magic.copy_from_slice(&data[0..3]);
@ -100,18 +100,18 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
let mut end = data.len(); let mut end = data.len();
let (header, mut pos) = try!(TopHeader::read_from(&data[..end])); let (header, mut pos) = try!(TopHeader::read_from(&data[..end]));
if header.magic != MAGIC { if header.magic != MAGIC {
return Err(Error::ParseError("Wrong protocol")); return Err(Error::Parse("Wrong protocol"));
} }
if header.version != VERSION { if header.version != VERSION {
return Err(Error::ParseError("Wrong version")); return Err(Error::Parse("Wrong version"));
} }
if header.crypto_method != crypto.method() { if header.crypto_method != crypto.method() {
return Err(Error::CryptoError("Wrong crypto method")); return Err(Error::Crypto("Wrong crypto method"));
} }
if crypto.method() > 0 { if crypto.method() > 0 {
let len = crypto.nonce_bytes(); let len = crypto.nonce_bytes();
if end < pos + len { if end < pos + len {
return Err(Error::ParseError("Truncated crypto header")); return Err(Error::Parse("Truncated crypto header"));
} }
{ {
let (before, after) = data.split_at_mut(pos); let (before, after) = data.split_at_mut(pos);
@ -124,7 +124,7 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
let mut options = Options::default(); let mut options = Options::default();
if header.flags & 0x01 > 0 { if header.flags & 0x01 > 0 {
if end < pos + NETWORK_ID_BYTES { if end < pos + NETWORK_ID_BYTES {
return Err(Error::ParseError("Truncated options")); return Err(Error::Parse("Truncated options"));
} }
options.network_id = Some(Encoder::read_u64(&data[pos..pos+NETWORK_ID_BYTES])); options.network_id = Some(Encoder::read_u64(&data[pos..pos+NETWORK_ID_BYTES]));
pos += NETWORK_ID_BYTES; pos += NETWORK_ID_BYTES;
@ -133,14 +133,14 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
0 => Message::Data(data, pos, end), 0 => Message::Data(data, pos, end),
1 => { 1 => {
if end < pos + 1 { if end < pos + 1 {
return Err(Error::ParseError("Empty peers")); return Err(Error::Parse("Missing IPv4 count"));
} }
let mut peers = Vec::new(); let mut peers = Vec::new();
let count = data[pos]; let count = data[pos];
pos += 1; pos += 1;
let len = count as usize * 6; let len = count as usize * 6;
if end < pos + len { if end < pos + len {
return Err(Error::ParseError("Peer data too short")); return Err(Error::Parse("IPv4 peer data too short"));
} }
for _ in 0..count { for _ in 0..count {
let ip = &data[pos..]; let ip = &data[pos..];
@ -150,11 +150,14 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), port)); let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), port));
peers.push(addr); peers.push(addr);
} }
if end < pos + 1 {
return Err(Error::Parse("Missing IPv6 count"));
}
let count = data[pos]; let count = data[pos];
pos += 1; pos += 1;
let len = count as usize * 18; let len = count as usize * 18;
if end < pos + len { if end < pos + len {
return Err(Error::ParseError("Peer data too short")); return Err(Error::Parse("IPv6 peer data too short"));
} }
for _ in 0..count { for _ in 0..count {
let mut ip = [0u16; 8]; let mut ip = [0u16; 8];
@ -172,7 +175,7 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
}, },
2 => { 2 => {
if end < pos + 2 + NODE_ID_BYTES { if end < pos + 2 + NODE_ID_BYTES {
return Err(Error::ParseError("Init data too short")); return Err(Error::Parse("Init data too short"));
} }
let stage = data[pos]; let stage = data[pos];
pos += 1; pos += 1;
@ -190,7 +193,7 @@ pub fn decode<'a>(data: &'a mut [u8], crypto: &mut Crypto) -> Result<(Options, M
Message::Init(stage, node_id, addrs) Message::Init(stage, node_id, addrs)
}, },
3 => Message::Close, 3 => Message::Close,
_ => return Err(Error::ParseError("Unknown message type")) _ => return Err(Error::Parse("Unknown message type"))
}; };
Ok((options, msg)) Ok((options, msg))
} }

View File

@ -110,7 +110,7 @@ macro_rules! try_fail {
pub fn resolve<Addr: ToSocketAddrs+fmt::Display>(addr: Addr) -> Result<Vec<SocketAddr>, Error> { pub fn resolve<Addr: ToSocketAddrs+fmt::Display>(addr: Addr) -> Result<Vec<SocketAddr>, Error> {
let addrs = try!(addr.to_socket_addrs().map_err(|_| Error::NameError(format!("{}", addr)))); let addrs = try!(addr.to_socket_addrs().map_err(|_| Error::Name(format!("{}", addr))));
// Remove duplicates in addrs (why are there duplicates???) // Remove duplicates in addrs (why are there duplicates???)
let mut addrs = addrs.collect::<Vec<_>>(); let mut addrs = addrs.collect::<Vec<_>>();
addrs.dedup(); addrs.dedup();