Skip to content

Commit 610c48b

Browse files
committed
Improved error handling
Reintroduces use of unstable features, though a number of them are stabilized in fix rust-lang/rust#23430
1 parent 27f7164 commit 610c48b

File tree

2 files changed

+51
-46
lines changed

2 files changed

+51
-46
lines changed

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate byteorder;
33

44
mod ntp;
55

6-
use std::net::{UdpSocket};
6+
use std::net::UdpSocket;
77
use time::Timespec;
88

99
const NTP_PORT: u16 = 123;
@@ -16,7 +16,7 @@ const UDP_LOCAL: &'static str = "0.0.0.0:35000";
1616
/// * `host` - The NTP server (i.e. sundial.columbia.edu).
1717
pub fn retrieve_ntp_timestamp(host: &str) -> Result<Timespec, std::io::Error> {
1818
let header = ntp::NTPHeader::new();
19-
let message = header.encode();
19+
let message = try!(header.encode());
2020

2121
let socket = try!(UdpSocket::bind(UDP_LOCAL));
2222

@@ -30,7 +30,7 @@ pub fn retrieve_ntp_timestamp(host: &str) -> Result<Timespec, std::io::Error> {
3030

3131
drop(socket);
3232

33-
let header = ntp::NTPHeader::decode(amt, &buf);
33+
let header = try!(ntp::NTPHeader::decode(amt, &buf));
3434

3535
Ok(header.transmit_timestamp.as_timespec())
3636
}

src/ntp.rs

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::num::Float;
44
use time::Timespec;
55
use std::io::Cursor;
66
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
7+
use std::io::Error as IoError;
8+
use std::io::ErrorKind as IoErrorKind;
79

810
const NTP_CLIENT: u8 = 3;
911
const NTP_HEADER_SIZE: usize = 48; // 12 words
@@ -61,66 +63,69 @@ impl NTPHeader {
6163
}
6264
}
6365

64-
fn encode_first_word<T>(&self, w: &mut T) where T: WriteBytesExt {
65-
w.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode).unwrap();
66-
w.write_u8(self.stratum).unwrap();
67-
w.write_u8(self.poll).unwrap();
68-
w.write_u8(self.precision).unwrap();
66+
fn encode_first_word<T>(&self, w: &mut T) -> Result<(), IoError> where T: WriteBytesExt {
67+
try!(w.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode));
68+
try!(w.write_u8(self.stratum));
69+
try!(w.write_u8(self.poll));
70+
try!(w.write_u8(self.precision));
71+
Ok(())
6972
}
7073

71-
pub fn encode(&self) -> Vec<u8> {
74+
pub fn encode(&self) -> Result<Vec<u8>, IoError> {
7275
let mut vec = Vec::<u8>::new();
7376

7477
// TODO: since Vec still implements old_io::Write trait the next 4 lines does not compile
75-
//vec.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode).unwrap();
76-
//vec.write_u8(self.stratum).unwrap();
77-
//vec.write_u8(self.poll).unwrap();
78-
//vec.write_u8(self.precision).unwrap();
78+
//try!(vec.write_u8(self.leap << LEAP_SHIFT | self.version << VERSION_SHIFT | self.mode));
79+
//try!(vec.write_u8(self.stratum));
80+
//try!(vec.write_u8(self.poll));
81+
//try!(vec.write_u8(self.precision));
7982

8083
// TODO: remove workaround when possible
81-
self.encode_first_word(&mut vec);
82-
83-
vec.write_u32::<BigEndian>(self.root_delay).unwrap();
84-
vec.write_u32::<BigEndian>(self.root_dispersion).unwrap();
85-
vec.write_u32::<BigEndian>(self.reference_id).unwrap();
86-
vec.write_u32::<BigEndian>(self.reference_timestamp.seconds).unwrap();
87-
vec.write_u32::<BigEndian>(self.reference_timestamp.fraction).unwrap();
88-
vec.write_u32::<BigEndian>(self.origin_timestamp.seconds).unwrap();
89-
vec.write_u32::<BigEndian>(self.origin_timestamp.fraction).unwrap();
90-
vec.write_u32::<BigEndian>(self.receive_timestamp.seconds).unwrap();
91-
vec.write_u32::<BigEndian>(self.receive_timestamp.fraction).unwrap();
92-
vec.write_u32::<BigEndian>(self.transmit_timestamp.seconds).unwrap();
93-
vec.write_u32::<BigEndian>(self.transmit_timestamp.fraction).unwrap();
94-
vec
84+
try!(self.encode_first_word(&mut vec));
85+
86+
try!(vec.write_u32::<BigEndian>(self.root_delay));
87+
try!(vec.write_u32::<BigEndian>(self.root_dispersion));
88+
try!(vec.write_u32::<BigEndian>(self.reference_id));
89+
try!(vec.write_u32::<BigEndian>(self.reference_timestamp.seconds));
90+
try!(vec.write_u32::<BigEndian>(self.reference_timestamp.fraction));
91+
try!(vec.write_u32::<BigEndian>(self.origin_timestamp.seconds));
92+
try!(vec.write_u32::<BigEndian>(self.origin_timestamp.fraction));
93+
try!(vec.write_u32::<BigEndian>(self.receive_timestamp.seconds));
94+
try!(vec.write_u32::<BigEndian>(self.receive_timestamp.fraction));
95+
try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.seconds));
96+
try!(vec.write_u32::<BigEndian>(self.transmit_timestamp.fraction));
97+
Ok(vec)
9598
}
9699

97-
pub fn decode(size: usize, buf: & [u8]) -> NTPHeader {
100+
pub fn decode(size: usize, buf: & [u8]) -> Result<NTPHeader, IoError> {
98101
let mut reader = Cursor::new(buf);
99102
let mut header = NTPHeader::new();
100103

101104
if size < NTP_HEADER_SIZE {
102-
panic!("{} bytes expected in NTP header; {} bytes received", NTP_HEADER_SIZE, size);
105+
return Err(IoError::new(IoErrorKind::Other,
106+
"Unexpected number of bytes in NTP datagram",
107+
Option::Some(format!("{} bytes expected in NTP header; {} bytes received", NTP_HEADER_SIZE, size))));
103108
}
104109

105-
let leap_version_mode = reader.read_u8().unwrap();
110+
let leap_version_mode = try!(reader.read_u8());
106111
header.leap = (leap_version_mode >> LEAP_SHIFT) & 0b11;
107112
header.version = (leap_version_mode >> VERSION_SHIFT) & 0b111;
108113
header.mode = leap_version_mode & 0b111;
109-
header.stratum = reader.read_u8().unwrap();
110-
header.poll = reader.read_u8().unwrap();
111-
header.precision = reader.read_u8().unwrap();
112-
header.root_delay = reader.read_u32::<BigEndian>().unwrap();
113-
header.root_dispersion = reader.read_u32::<BigEndian>().unwrap();
114-
header.reference_id = reader.read_u32::<BigEndian>().unwrap();
115-
header.reference_timestamp.seconds = reader.read_u32::<BigEndian>().unwrap();
116-
header.reference_timestamp.fraction = reader.read_u32::<BigEndian>().unwrap();
117-
header.origin_timestamp.seconds = reader.read_u32::<BigEndian>().unwrap();
118-
header.origin_timestamp.fraction = reader.read_u32::<BigEndian>().unwrap();
119-
header.receive_timestamp.seconds = reader.read_u32::<BigEndian>().unwrap();
120-
header.receive_timestamp.fraction = reader.read_u32::<BigEndian>().unwrap();
121-
header.transmit_timestamp.seconds = reader.read_u32::<BigEndian>().unwrap();
122-
header.transmit_timestamp.fraction = reader.read_u32::<BigEndian>().unwrap();
123-
124-
header
114+
header.stratum = try!(reader.read_u8());
115+
header.poll = try!(reader.read_u8());
116+
header.precision = try!(reader.read_u8());
117+
header.root_delay = try!(reader.read_u32::<BigEndian>());
118+
header.root_dispersion = try!(reader.read_u32::<BigEndian>());
119+
header.reference_id = try!(reader.read_u32::<BigEndian>());
120+
header.reference_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
121+
header.reference_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
122+
header.origin_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
123+
header.origin_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
124+
header.receive_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
125+
header.receive_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
126+
header.transmit_timestamp.seconds = try!(reader.read_u32::<BigEndian>());
127+
header.transmit_timestamp.fraction = try!(reader.read_u32::<BigEndian>());
128+
129+
Ok(header)
125130
}
126131
}

0 commit comments

Comments
 (0)