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
/*!
# Example

```rust
fn main() {
    let address = "0.pool.ntp.org:123";
    let response: ntp::packet::Packet = ntp::request(address).unwrap();
    let ntp_time = response.transmit_time;
    println!("{}", ntp_time);
}
```
*/

#![recursion_limit = "1024"] 

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate conv;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate log;
extern crate byteorder;
extern crate time;

use std::io::Cursor;
use std::net::{ToSocketAddrs,UdpSocket};
use std::time::Duration;



pub mod errors;
pub mod formats;
pub mod packet;

pub fn request<A: ToSocketAddrs>(addr: A) -> errors::Result<packet::Packet> {
    let data: Vec<u8> = packet::Packet::new_client().into();
    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(&data, addr)?;
    debug!("{:?}", sock.local_addr());
    debug!("sent: {}", sz);
    let mut buf = vec![0; 48];
    let res = sock.recv(&mut buf)?;
    debug!("recv: {:?}", res);
    debug!("{:?}", &buf[..]);
    let rdr = Cursor::new(&buf);
    return Ok(packet::Packet::try_from(rdr)?);
}

#[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");
}