@@ -4,6 +4,8 @@ use std::num::Float;
4
4
use time:: Timespec ;
5
5
use std:: io:: Cursor ;
6
6
use byteorder:: { BigEndian , ReadBytesExt , WriteBytesExt } ;
7
+ use std:: io:: Error as IoError ;
8
+ use std:: io:: ErrorKind as IoErrorKind ;
7
9
8
10
const NTP_CLIENT : u8 = 3 ;
9
11
const NTP_HEADER_SIZE : usize = 48 ; // 12 words
@@ -61,66 +63,69 @@ impl NTPHeader {
61
63
}
62
64
}
63
65
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 ( ( ) )
69
72
}
70
73
71
- pub fn encode ( & self ) -> Vec < u8 > {
74
+ pub fn encode ( & self ) -> Result < Vec < u8 > , IoError > {
72
75
let mut vec = Vec :: < u8 > :: new ( ) ;
73
76
74
77
// 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));
79
82
80
83
// 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)
95
98
}
96
99
97
- pub fn decode ( size : usize , buf : & [ u8 ] ) -> NTPHeader {
100
+ pub fn decode ( size : usize , buf : & [ u8 ] ) -> Result < NTPHeader , IoError > {
98
101
let mut reader = Cursor :: new ( buf) ;
99
102
let mut header = NTPHeader :: new ( ) ;
100
103
101
104
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) ) ) ) ;
103
108
}
104
109
105
- let leap_version_mode = reader. read_u8 ( ) . unwrap ( ) ;
110
+ let leap_version_mode = try! ( reader. read_u8 ( ) ) ;
106
111
header. leap = ( leap_version_mode >> LEAP_SHIFT ) & 0b11 ;
107
112
header. version = ( leap_version_mode >> VERSION_SHIFT ) & 0b111 ;
108
113
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)
125
130
}
126
131
}
0 commit comments