1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#![recursion_limit = "1024"]
#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate conv;
#[macro_use]
extern crate log;
extern crate byteorder;
use protocol::{ReadBytes, ConstPackedSizeBytes, WriteBytes};
use std::io;
use std::net::{ToSocketAddrs, UdpSocket};
use std::time::Duration;
pub mod protocol;
pub mod unix_time;
pub fn request<A: ToSocketAddrs>(addr: A) -> io::Result<protocol::Packet> {
let mut packet = {
let leap_indicator = protocol::LeapIndicator::default();
let version = protocol::Version::V4;
let mode = protocol::Mode::Client;
let poll = 0;
let precision = 0;
let root_delay = protocol::ShortFormat::default();
let root_dispersion = protocol::ShortFormat::default();
let transmit_timestamp = unix_time::Instant::now().into();
let stratum = protocol::Stratum::UNSPECIFIED;
let src = protocol::PrimarySource::Null;
let reference_id = protocol::ReferenceIdentifier::PrimarySource(src);
let reference_timestamp = protocol::TimestampFormat::default();
let receive_timestamp = protocol::TimestampFormat::default();
let origin_timestamp = protocol::TimestampFormat::default();
protocol::Packet {
leap_indicator,
version,
mode,
stratum,
poll,
precision,
root_delay,
root_dispersion,
reference_id,
reference_timestamp,
origin_timestamp,
receive_timestamp,
transmit_timestamp,
}
};
let mut bytes = [0u8; protocol::Packet::PACKED_SIZE_BYTES];
(&mut bytes[..]).write_bytes(&packet)?;
let sock = UdpSocket::bind("0.0.0.0:0")?;
sock.set_read_timeout(Some(Duration::from_secs(5)))?;
sock.set_write_timeout(Some(Duration::from_secs(5)))?;
let sz = sock.send_to(&bytes, addr)?;
debug!("{:?}", sock.local_addr());
debug!("sent: {}", sz);
let res = sock.recv(&mut bytes[..])?;
debug!("recv: {:?}", res);
debug!("{:?}", &bytes[..]);
packet = (&bytes[..]).read_bytes()?;
Ok(packet)
}
#[test]
fn test_request_ntp_org() {
let res = request("0.pool.ntp.org:123");
let _ = res.expect("Failed to get a ntp packet from ntp.org");
}
#[test]
fn test_request_google() {
let res = request("time.google.com:123");
let _ = res.expect("Failed to get a ntp packet from time.google.com");
}