Просмотр исходного кода

Make "util" module not depend on "rpc" (and in turn "net").

Luther Blissett 3 лет назад
Родитель
Сommit
c10d4f140b
6 измененных файлов с 140 добавлено и 132 удалено
  1. 0 2
      Cargo.toml
  2. 129 0
      src/rpc/clock_sync.rs
  3. 3 0
      src/rpc/mod.rs
  4. 5 0
      src/util/async_util.rs
  5. 1 2
      src/util/mod.rs
  6. 2 128
      src/util/time.rs

+ 0 - 2
Cargo.toml

@@ -169,7 +169,6 @@ util = [
     "termion",
 
     "async-runtime",
-    "rpc",
     "serial",
 ]
 
@@ -329,7 +328,6 @@ name = "lead"
 path = "example/lead.rs"
 required-features = ["node"]
 
-
 [[example]]
 name = "crypsinous"
 path = "example/crypsinous.rs"

+ 129 - 0
src/rpc/clock_sync.rs

@@ -0,0 +1,129 @@
+//! Clock sync module
+use std::{net::UdpSocket, time::Duration};
+
+use log::debug;
+use rand::prelude::SliceRandom;
+use serde_json::json;
+use url::Url;
+
+use super::{client::RpcClient, jsonrpc::JsonRequest};
+use crate::{util::time::Timestamp, Error, Result};
+
+/// Clock sync parameters
+const RETRIES: u8 = 10;
+/// TODO: Loop through set of ntps, get their average response concurrenyly.
+const NTP_ADDRESS: &str = "pool.ntp.org:123";
+const EPOCH: i64 = 2208988800; // 1900
+
+/// JSON-RPC request to a network peer (randomly selected), to
+/// retrieve their current system clock.
+async fn peer_request(peers: &[Url]) -> Result<Option<Timestamp>> {
+    // Select peer, None if vector is empty.
+    let peer = peers.choose(&mut rand::thread_rng());
+    match peer {
+        None => Ok(None),
+        Some(p) => {
+            // Create RPC client
+            let rpc_client = RpcClient::new(p.clone()).await?;
+
+            // Execute request
+            let req = JsonRequest::new("clock", json!([]));
+            let rep = rpc_client.oneshot_request(req).await?;
+
+            // Parse response
+            let timestamp: Timestamp = serde_json::from_value(rep)?;
+
+            Ok(Some(timestamp))
+        }
+    }
+}
+
+/// Raw NTP request execution
+pub async fn ntp_request() -> Result<Timestamp> {
+    // Create socket
+    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)))?;
+
+    // Execute request
+    let mut packet = [0u8; 48];
+    packet[0] = (3 << 6) | (4 << 3) | 3;
+    sock.send_to(&packet, NTP_ADDRESS)?;
+
+    // Parse response
+    sock.recv(&mut packet[..])?;
+    let (bytes, _) = packet[40..44].split_at(core::mem::size_of::<u32>());
+    let num = u32::from_be_bytes(bytes.try_into().unwrap());
+    let timestamp = Timestamp(num as i64 - EPOCH);
+
+    Ok(timestamp)
+}
+
+/// This is a very simple check to verify that the system time is correct.
+/// Retry loop is used in case discrepancies are found.
+/// If all retries fail, system clock is considered invalid.
+/// TODO: 1. Add proxy functionality in order not to leak connections
+pub async fn check_clock(peers: &[Url]) -> Result<()> {
+    debug!("System clock check started...");
+    let mut r = 0;
+    while r < RETRIES {
+        if let Err(e) = clock_check(peers).await {
+            debug!("Error during clock check: {:#?}", e);
+            r += 1;
+            continue
+        };
+        break
+    }
+
+    debug!("System clock check finished. Retries: {}", r);
+    if r == RETRIES {
+        return Err(Error::InvalidClock)
+    }
+
+    Ok(())
+}
+
+async fn clock_check(peers: &[Url]) -> Result<()> {
+    // Start elapsed time counter to cover for all requests and processing time
+    let requests_start = Timestamp::current_time();
+    // Poll one of the peers for their current UTC timestamp
+    let peer_time = peer_request(peers).await?;
+
+    // Start elapsed time counter to cover for NTP request and processing time
+    let ntp_request_start = Timestamp::current_time();
+    // Poll ntp.org for current timestamp
+    let mut ntp_time = ntp_request().await?;
+
+    // Stop elapsed time counters
+    let ntp_elapsed_time = ntp_request_start.elapsed() as i64;
+    let requests_elapsed_time = requests_start.elapsed() as i64;
+
+    // Current system time
+    let system_time = Timestamp::current_time();
+
+    // Add elapsed time to response times
+    ntp_time.add(ntp_elapsed_time);
+    let peer_time = match peer_time {
+        None => None,
+        Some(p) => {
+            let mut t = p;
+            t.add(requests_elapsed_time);
+            Some(t)
+        }
+    };
+
+    debug!("peer_time: {:#?}", peer_time);
+    debug!("ntp_time: {:#?}", ntp_time);
+    debug!("system_time: {:#?}", system_time);
+
+    // We verify that system time is equal to peer (if exists) and ntp times
+    let check = match peer_time {
+        Some(p) => (system_time == p) && (system_time == ntp_time),
+        None => system_time == ntp_time,
+    };
+
+    match check {
+        true => Ok(()),
+        false => Err(Error::InvalidClock),
+    }
+}

+ 3 - 0
src/rpc/mod.rs

@@ -10,3 +10,6 @@ pub mod server;
 #[cfg(feature = "websockets")]
 /// Websockets client
 pub mod websockets;
+
+/// Clock sync utility module
+pub mod clock_sync;

+ 5 - 0
src/util/async_util.rs

@@ -5,3 +5,8 @@ use std::time::Duration;
 pub async fn sleep(seconds: u64) {
     Timer::after(Duration::from_secs(seconds)).await;
 }
+
+/// Sleep for any number of milliseconds.
+pub async fn msleep(millis: u64) {
+    Timer::after(Duration::from_millis(millis)).await;
+}

+ 1 - 2
src/util/mod.rs

@@ -1,4 +1,3 @@
-#[cfg(feature = "async-runtime")]
 /// async utility functions
 pub mod async_util;
 
@@ -21,7 +20,7 @@ pub mod parse;
 /// Filesystem path utilities
 pub mod path;
 
-/// Time utilities (TODO: Util should **not** depend on `net` feature, so remove ntp from here)
+/// Time utilities
 pub mod time;
 
 // =======================

+ 2 - 128
src/util/time.rs

@@ -1,20 +1,11 @@
-use std::{
-    mem,
-    net::UdpSocket,
-    time::{Duration, UNIX_EPOCH},
-};
+use std::time::UNIX_EPOCH;
 
 use chrono::{NaiveDateTime, Utc};
-use log::debug;
-use rand::seq::SliceRandom;
 use serde::{Deserialize, Serialize};
-use serde_json::json;
-use url::Url;
 
 use crate::{
-    rpc::{client::RpcClient, jsonrpc::JsonRequest},
     serial::{SerialDecodable, SerialEncodable},
-    Error, Result,
+    Result,
 };
 
 /// Wrapper struct to represent [`chrono`] UTC timestamps.
@@ -85,123 +76,6 @@ impl std::fmt::Display for NanoTimestamp {
     }
 }
 
-// Clock sync parameters
-const RETRIES: u8 = 10;
-///TODO loop through set of ntps, get their average response concurrently.
-const NTP_ADDRESS: &str = "pool.ntp.org:123";
-const EPOCH: i64 = 2208988800; //1900
-
-// JsonRPC request to a network peer(randomly selected),
-// to retrieve their current system clock.
-async fn peer_request(peers: &Vec<Url>) -> Result<Option<Timestamp>> {
-    // Select peer, None if vector is empty
-    let peer = peers.choose(&mut rand::thread_rng());
-    match peer {
-        None => Ok(None),
-        Some(p) => {
-            // Create rpc client
-            let rpc_client = RpcClient::new(p.clone()).await?;
-
-            // Execute request
-            let req = JsonRequest::new("clock", json!([]));
-            let rep = rpc_client.oneshot_request(req).await?;
-
-            // Parse response
-            let timestamp: Timestamp = serde_json::from_value(rep)?;
-
-            Ok(Some(timestamp))
-        }
-    }
-}
-
-// Raw ntp request execution
-pub async fn ntp_request() -> Result<Timestamp> {
-    // Create socket
-    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)))?;
-
-    // Execute request
-    let mut packet = [0u8; 48];
-    packet[0] = (3 << 6) | (4 << 3) | 3;
-    sock.send_to(&packet, NTP_ADDRESS)?;
-
-    // Parse response
-    sock.recv(&mut packet[..])?;
-    let (bytes, _) = packet[40..44].split_at(mem::size_of::<u32>());
-    let num = u32::from_be_bytes(bytes.try_into().unwrap());
-    let timestamp = Timestamp(num as i64 - EPOCH);
-
-    Ok(timestamp)
-}
-
-// This is a very simple check to verify that system time is correct.
-// Retry loop is used to in case discrepancies are found.
-// If all retries fail, system clock is considered invalid.
-// TODO: 1. Add proxy functionality in order not to leak connections
-pub async fn check_clock(peers: Vec<Url>) -> Result<()> {
-    debug!("System clock check started...");
-    let mut r = 0;
-    while r < RETRIES {
-        if let Err(e) = clock_check(&peers).await {
-            debug!("Error during clock check: {:#?}", e);
-            r += 1;
-            continue
-        };
-        break
-    }
-
-    debug!("System clock check finished. Retries: {:#?}", r);
-    match r {
-        RETRIES => Err(Error::InvalidClock),
-        _ => Ok(()),
-    }
-}
-
-async fn clock_check(peers: &Vec<Url>) -> Result<()> {
-    // Start elapsed time counter to cover for all requests and processing time
-    let requests_start = Timestamp::current_time();
-    // Poll one of peers for their current UTC timestamp
-    let peer_time = peer_request(peers).await?;
-
-    // Start elapsed time counter to cover for ntp request and processing time
-    let ntp_request_start = Timestamp::current_time();
-    // Poll ntp.org for current timestamp
-    let mut ntp_time = ntp_request().await?;
-
-    // Stop elapsed time counters
-    let ntp_elapsed_time = ntp_request_start.elapsed() as i64;
-    let requests_elapsed_time = requests_start.elapsed() as i64;
-
-    // Current system time
-    let system_time = Timestamp::current_time();
-
-    // Add elapsed time to respone times
-    ntp_time.add(ntp_elapsed_time);
-    let peer_time = match peer_time {
-        None => None,
-        Some(p) => {
-            let mut t = p;
-            t.add(requests_elapsed_time);
-            Some(t)
-        }
-    };
-
-    debug!("peer_time: {:#?}", peer_time);
-    debug!("ntp_time: {:#?}", ntp_time);
-    debug!("system_time: {:#?}", system_time);
-
-    // We verify that system time is equal to peer(if exists) and ntp times
-    let check = match peer_time {
-        Some(p) => (system_time == p) && (system_time == ntp_time),
-        None => system_time == ntp_time,
-    };
-    match check {
-        true => Ok(()),
-        false => Err(Error::InvalidClock),
-    }
-}
-
 pub enum DateFormat {
     Default,
     Date,