diff options
139 files changed, 679 insertions, 318 deletions
diff --git a/Cargo.lock b/Cargo.lock index b7429afda..8317d42b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,6 +275,7 @@ dependencies = [ "trycmd", "visibility", "walkdir", + "web-time-compat", "winapi", ] @@ -298,6 +299,7 @@ dependencies = [ "tor-rtcompat", "tracing", "tracing-subscriber", + "web-time-compat", ] [[package]] @@ -362,6 +364,7 @@ dependencies = [ "tracing-test", "visibility", "void", + "web-time-compat", ] [[package]] @@ -3980,6 +3983,7 @@ dependencies = [ "tor-proto", "tor-rtcompat", "tracing-subscriber", + "web-time-compat", ] [[package]] @@ -5076,6 +5080,7 @@ dependencies = [ "derive_more", "humantime", "thiserror 2.0.18", + "web-time", ] [[package]] @@ -6608,6 +6613,7 @@ dependencies = [ "smallvec", "thiserror 2.0.18", "weak-table", + "web-time-compat", ] [[package]] @@ -6678,6 +6684,7 @@ dependencies = [ "tor-checkable", "tor-error", "tor-llcrypto", + "web-time-compat", ] [[package]] @@ -6694,6 +6701,7 @@ dependencies = [ "tor-basic-utils", "tor-error", "tor-llcrypto", + "web-time-compat", "x509-cert", ] @@ -6740,6 +6748,7 @@ dependencies = [ "tracing", "url", "void", + "web-time-compat", ] [[package]] @@ -6750,6 +6759,7 @@ dependencies = [ "signature", "thiserror 2.0.18", "tor-llcrypto", + "web-time-compat", ] [[package]] @@ -6803,6 +6813,7 @@ dependencies = [ "visibility", "void", "weak-table", + "web-time-compat", ] [[package]] @@ -6904,6 +6915,7 @@ dependencies = [ "tor-rtcompat", "tor-rtmock", "tracing", + "web-time-compat", ] [[package]] @@ -6987,6 +6999,7 @@ dependencies = [ "tracing", "tracing-test", "void", + "web-time-compat", ] [[package]] @@ -7046,6 +7059,7 @@ dependencies = [ "tracing", "tracing-test", "void", + "web-time-compat", ] [[package]] @@ -7126,6 +7140,7 @@ dependencies = [ "tor-rtmock", "tor-units", "tracing", + "web-time-compat", ] [[package]] @@ -7174,6 +7189,7 @@ dependencies = [ "tor-rtmock", "tracing", "tracing-test", + "web-time-compat", ] [[package]] @@ -7207,6 +7223,7 @@ dependencies = [ "tor-memquota", "tor-units", "void", + "web-time-compat", "zeroize", ] @@ -7309,6 +7326,7 @@ dependencies = [ "tracing-test", "void", "walkdir", + "web-time-compat", ] [[package]] @@ -7373,6 +7391,7 @@ dependencies = [ "tracing", "visibility", "walkdir", + "web-time-compat", "zeroize", ] @@ -7460,6 +7479,7 @@ dependencies = [ "tor-rtcompat", "tracing", "weak-table", + "web-time-compat", ] [[package]] @@ -7542,6 +7562,7 @@ dependencies = [ "tracing", "typed-index-collections", "visibility", + "web-time-compat", ] [[package]] @@ -7592,6 +7613,7 @@ dependencies = [ "visibility", "visible", "void", + "web-time-compat", "zeroize", ] @@ -7625,6 +7647,7 @@ dependencies = [ "tracing", "tracing-test", "void", + "web-time-compat", ] [[package]] @@ -7701,6 +7724,7 @@ dependencies = [ "typenum", "visibility", "void", + "web-time-compat", "zeroize", ] @@ -7745,6 +7769,7 @@ dependencies = [ "tracing", "tracing-subscriber", "visibility", + "web-time-compat", ] [[package]] @@ -7761,6 +7786,7 @@ dependencies = [ "tor-keymgr", "tor-llcrypto", "tor-persist", + "web-time-compat", ] [[package]] @@ -7868,6 +7894,7 @@ dependencies = [ "tor-general-addr", "tracing", "void", + "web-time-compat", "zeroize", ] @@ -7899,6 +7926,7 @@ dependencies = [ "tracing", "tracing-test", "void", + "web-time-compat", ] [[package]] @@ -8541,6 +8569,13 @@ dependencies = [ ] [[package]] +name = "web-time-compat" +version = "0.1.0" +dependencies = [ + "web-time", +] + +[[package]] name = "webpki-root-certs" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index a0164df82..71baa6570 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ # https://blog.iany.me/2020/10/gotchas-to-publish-rust-crates-in-a-workspace/#cyclic-dependencies members = [ "crates/oneshot-fused-workaround", + "crates/web-time-compat", "crates/slotmap-careful", "crates/test-temp-dir", "crates/fslock-guard", diff --git a/clippy.toml b/clippy.toml index 437f9e3b9..d92cee20b 100644 --- a/clippy.toml +++ b/clippy.toml @@ -20,4 +20,7 @@ disallowed-methods = [ { path = "weak_table::WeakKeyHashMap::retain", reason = "`WeakKeyHashMap::retain` is buggy; see https://github.com/tov/weak-table-rs/issues/22" }, { path = "weak_table::WeakValueHashMap::retain", reason = "`WeakValueHashMap::retain` is buggy; see https://github.com/tov/weak-table-rs/issues/22" }, { path = "weak_table::WeakWeakHashMap::retain", reason = "`WeakWeakHashMap::retain` is buggy; see https://github.com/tov/weak-table-rs/issues/22" }, + { path = "std::time::Instant::now", reason = "For wasm compatibility, use `web_time_compat::InstantExt::get` instead." }, + { path = "std::time::SystemTime::now", reason = "For wasm compatibility, use `web_time_compat::SystemTimeExt::get` instead." }, + { path = "time::OffsetDateTime::now_utc", reason = "For wasm compatibility, use `web_time_compat::SystemTimeExt::get().into()` instead." }, ] diff --git a/crates/arti-bench/Cargo.toml b/crates/arti-bench/Cargo.toml index 370a0b773..1fb43d641 100644 --- a/crates/arti-bench/Cargo.toml +++ b/crates/arti-bench/Cargo.toml @@ -32,6 +32,7 @@ tor-config = { path = "../tor-config", version = "0.40.0" } tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0", features = ["tokio", "native-tls"] } tracing = "0.1.36" tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [features] full = [ diff --git a/crates/arti-bench/src/main.rs b/crates/arti-bench/src/main.rs index d76c36a4f..1ee55dab7 100644 --- a/crates/arti-bench/src/main.rs +++ b/crates/arti-bench/src/main.rs @@ -71,12 +71,12 @@ use std::ops::Deref; use std::str::FromStr; use std::sync::Arc; use std::thread::JoinHandle; -use std::time::SystemTime; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use tokio_socks::tcp::Socks5Stream; use tor_config::{ConfigurationSource, ConfigurationSources}; use tor_rtcompat::ToplevelRuntime; use tracing::info; +use web_time_compat::{SystemTime, SystemTimeExt}; /// Generate a random payload of bytes of the given size fn random_payload(size: usize) -> Vec<u8> { @@ -181,18 +181,18 @@ fn run_timing(mut stream: TcpStream, send: &Arc<[u8]>, receive: &Arc<[u8]>) -> R let mut total_read = 0; info!("Accepted connection from {}", peer_addr); - let accepted_ts = SystemTime::now(); + let accepted_ts = SystemTime::get(); let mut data: &[u8] = send.deref(); let copied = std::io::copy(&mut data, &mut stream)?; stream.flush()?; - let copied_ts = SystemTime::now(); + let copied_ts = SystemTime::get(); assert_eq!(copied, send.len() as u64); info!("Copied {} bytes payload to {}.", copied, peer_addr); let read = stream.read(&mut received)?; if read == 0 { panic!("unexpected EOF"); } - let first_byte_ts = SystemTime::now(); + let first_byte_ts = SystemTime::get(); if received[0..read] != expected[0..read] { mismatch = true; } @@ -209,7 +209,7 @@ fn run_timing(mut stream: TcpStream, send: &Arc<[u8]>, receive: &Arc<[u8]>) -> R expected = &expected[read..]; total_read += read; } - let read_done_ts = SystemTime::now(); + let read_done_ts = SystemTime::get(); info!("Received {} bytes payload from {}.", total_read, peer_addr); // Check we actually got what we thought we would get. if mismatch { @@ -252,22 +252,22 @@ async fn client<S: AsyncRead + AsyncWrite + Unpin>( ) -> Result<ClientTiming> { // Do this potentially costly allocation before we do all the timing stuff. let mut received = vec![0_u8; receive.len()]; - let started_ts = SystemTime::now(); + let started_ts = SystemTime::get(); let read = socket.read(&mut received).await?; if read == 0 { return Err(anyhow!("unexpected EOF")); } - let first_byte_ts = SystemTime::now(); + let first_byte_ts = SystemTime::get(); socket.read_exact(&mut received[read..]).await?; - let read_done_ts = SystemTime::now(); + let read_done_ts = SystemTime::get(); info!("Received {} bytes payload.", received.len()); let mut send_data = &send as &[u8]; tokio::io::copy(&mut send_data, &mut socket).await?; socket.flush().await?; info!("Sent {} bytes payload.", send.len()); - let copied_ts = SystemTime::now(); + let copied_ts = SystemTime::get(); // Check we actually got what we thought we would get. if received != receive.deref() { diff --git a/crates/arti-client/Cargo.toml b/crates/arti-client/Cargo.toml index 69a14e72c..6c2235473 100644 --- a/crates/arti-client/Cargo.toml +++ b/crates/arti-client/Cargo.toml @@ -215,6 +215,7 @@ tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0" } tracing = "0.1.36" visibility = { version = "0.1.0", optional = true } void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } # TODO wasm: Remove this once there is a supported wasm StateMgr. [target.'cfg(all(target_arch="wasm32", target_os="unknown"))'.dependencies] diff --git a/crates/arti-client/src/builder.rs b/crates/arti-client/src/builder.rs index 0fea83741..2520658d3 100644 --- a/crates/arti-client/src/builder.rs +++ b/crates/arti-client/src/builder.rs @@ -5,15 +5,12 @@ use crate::{ BootstrapBehavior, InertTorClient, Result, TorClient, TorClientConfig, err::ErrorDetail, }; -use std::{ - result::Result as StdResult, - sync::Arc, - time::{Duration, Instant}, -}; +use std::{result::Result as StdResult, sync::Arc}; use tor_dirmgr::{DirMgrConfig, DirMgrStore}; use tor_error::{ErrorKind, HasKind as _}; use tor_rtcompat::Runtime; use tracing::instrument; +use web_time_compat::{Duration, Instant, InstantExt}; /// An object that knows how to construct some kind of DirProvider. /// @@ -187,11 +184,11 @@ impl<R: Runtime> TorClientBuilder<R> { #[instrument(skip_all, level = "trace")] pub fn create_unbootstrapped(&self) -> Result<TorClient<R>> { let timeout = self.local_resource_timeout_or(Duration::from_millis(0))?; - let give_up_at = Instant::now() + timeout; + let give_up_at = Instant::get() + timeout; let mut first_attempt = true; loop { - match self.create_unbootstrapped_inner(Instant::now, give_up_at, first_attempt) { + match self.create_unbootstrapped_inner(Instant::get, give_up_at, first_attempt) { Err(delay) => { first_attempt = false; std::thread::sleep(delay); diff --git a/crates/arti-client/src/status.rs b/crates/arti-client/src/status.rs index 36e12ce51..2fb131a1b 100644 --- a/crates/arti-client/src/status.rs +++ b/crates/arti-client/src/status.rs @@ -1,7 +1,7 @@ //! Code to collect and publish information about a client's bootstrapping //! status. -use std::{borrow::Cow, fmt, fmt::Display, time::SystemTime}; +use std::{borrow::Cow, fmt, fmt::Display}; use educe::Educe; use futures::{Stream, StreamExt}; @@ -10,6 +10,7 @@ use tor_chanmgr::{ConnBlockage, ConnStatus, ConnStatusEvents}; use tor_circmgr::{ClockSkewEvents, SkewEstimate}; use tor_dirmgr::{DirBlockage, DirBootstrapStatus}; use tracing::debug; +use web_time_compat::{SystemTime, SystemTimeExt}; /// Information about how ready a [`crate::TorClient`] is to handle requests. /// @@ -40,7 +41,7 @@ impl BootstrapStatus { /// 0 is defined as "just started"; 1 is defined as "ready to use." pub fn as_frac(&self) -> f32 { // Coefficients chosen arbitrarily. - self.conn_status.frac() * 0.15 + self.dir_status.frac_at(SystemTime::now()) * 0.85 + self.conn_status.frac() * 0.15 + self.dir_status.frac_at(SystemTime::get()) * 0.85 } /// Return true if the status indicates that the client is ready for @@ -49,7 +50,7 @@ impl BootstrapStatus { /// For the purposes of this function, the client is "ready for traffic" if, /// as far as we know, we can start acting on a new client request immediately. pub fn ready_for_traffic(&self) -> bool { - let now = SystemTime::now(); + let now = SystemTime::get(); self.conn_status.usable() && self.dir_status.usable_at(now) } @@ -84,7 +85,7 @@ impl BootstrapStatus { } else { Some(Blockage { kind, message }) } - } else if let Some(b) = self.dir_status.blockage(SystemTime::now()) { + } else if let Some(b) = self.dir_status.blockage(SystemTime::get()) { let message = b.to_string().into(); let kind = b.into(); Some(Blockage { kind, message }) diff --git a/crates/arti/Cargo.toml b/crates/arti/Cargo.toml index 3a92b56f1..e61404b82 100644 --- a/crates/arti/Cargo.toml +++ b/crates/arti/Cargo.toml @@ -225,10 +225,10 @@ tor-socksproto = { path = "../tor-socksproto", version = "0.40.0" } tracing = "0.1.36" tracing-appender = "0.2.0" tracing-journald = { version = "0.3.0", optional = true } - tracing-opentelemetry = { version = "0.32.0", optional = true } tracing-subscriber = { version = "0.3.20", features = ["env-filter"] } visibility = { version = "0.1.0", optional = true } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.8", features = ["winerror"] } diff --git a/crates/arti/src/logging/time.rs b/crates/arti/src/logging/time.rs index b2e0ec532..24563c533 100644 --- a/crates/arti/src/logging/time.rs +++ b/crates/arti/src/logging/time.rs @@ -7,6 +7,7 @@ use std::num::NonZeroU8; use time::format_description; +use web_time_compat::{SystemTime, SystemTimeExt}; /// Construct a new [`FormatTime`](tracing_subscriber::fmt::time::FormatTime) /// from a given user-supplied description of the desired log granularity. @@ -215,11 +216,8 @@ impl LogTimer { impl tracing_subscriber::fmt::time::FormatTime for LogTimer { fn format_time(&self, w: &mut tracing_subscriber::fmt::format::Writer<'_>) -> std::fmt::Result { // See NOTE above: This function mustn't panic. - w.write_str( - &self - .time_to_string(time::OffsetDateTime::now_utc()) - .map_err(|_| std::fmt::Error)?, - ) + let now_utc: time::OffsetDateTime = SystemTime::get().into(); + w.write_str(&self.time_to_string(now_utc).map_err(|_| std::fmt::Error)?) } } diff --git a/crates/retry-error/Cargo.toml b/crates/retry-error/Cargo.toml index f4fc34493..5e439a25f 100644 --- a/crates/retry-error/Cargo.toml +++ b/crates/retry-error/Cargo.toml @@ -22,5 +22,9 @@ humantime = "2" [features] full = [] + [package.metadata.docs.rs] all-features = true + +[target.'cfg(all(target_arch="wasm32", target_os="unknown"))'.dependencies] +web-time = "1.1.0" diff --git a/crates/retry-error/src/lib.rs b/crates/retry-error/src/lib.rs index 5d00eb4aa..2ca7a9893 100644 --- a/crates/retry-error/src/lib.rs +++ b/crates/retry-error/src/lib.rs @@ -49,7 +49,13 @@ use std::error::Error; use std::fmt::{self, Debug, Display, Error as FmtError, Formatter}; use std::iter; -use std::time::{Duration, Instant, SystemTime}; +use std::time::{Duration, SystemTime}; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +use web_time::Instant; + +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +use std::time::Instant; /// An error type for use when we're going to do something a few times, /// and they might all fail. @@ -135,6 +141,7 @@ impl<E> RetryError<E> { /// /// # Example /// ``` + /// # #![allow(clippy::disallowed_methods)] /// # use retry_error::RetryError; /// # use std::time::{Instant, SystemTime}; /// let mut retry_err: RetryError<&str> = RetryError::in_attempt_to("connect"); @@ -169,7 +176,7 @@ impl<E> RetryError<E> { where T: Into<E>, { - self.push_timed(err, Instant::now(), Some(SystemTime::now())); + self.push_timed(err, current_instant(), Some(current_system_time())); } /// Return an iterator over all of the reasons that the attempt @@ -515,6 +522,32 @@ pub fn fmt_error_with_sources(mut e: &dyn Error, f: &mut fmt::Formatter) -> fmt: Ok(()) } +/// Return the current system time. +/// +/// (This is a separate method for compatibility with wasm32.) +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +fn current_system_time() -> SystemTime { + use web_time::web::SystemTimeExt as _; + web_time::SystemTime::now().to_std() +} + +/// Return the current system time. +/// +/// (This is a separate method for compatibility with wasm32.) +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +fn current_system_time() -> SystemTime { + #![allow(clippy::disallowed_methods)] + SystemTime::now() +} + +/// Return the current Instant. +/// +/// (This is a separate method for compatibility with wasm32.) +fn current_instant() -> Instant { + #![allow(clippy::disallowed_methods)] + Instant::now() +} + #[cfg(test)] mod test { // @@ begin test lint list maintained by maint/add_warning @@ diff --git a/crates/tor-basic-utils/Cargo.toml b/crates/tor-basic-utils/Cargo.toml index 783a38bd5..ade411c07 100644 --- a/crates/tor-basic-utils/Cargo.toml +++ b/crates/tor-basic-utils/Cargo.toml @@ -24,6 +24,7 @@ slab = "0.4.7" smallvec = "1.10" thiserror = "2" weak-table = "0.3.0" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] derive_more = { version = "2.0.1", features = ["full"] } diff --git a/crates/tor-basic-utils/src/rangebounds.rs b/crates/tor-basic-utils/src/rangebounds.rs index 14c8f9c75..77a353484 100644 --- a/crates/tor-basic-utils/src/rangebounds.rs +++ b/crates/tor-basic-utils/src/rangebounds.rs @@ -114,7 +114,7 @@ mod test { use super::*; use Bound::{Excluded as Excl, Included as Incl, Unbounded}; use std::fmt::Debug; - use std::time::{Duration, SystemTime}; + use web_time_compat::{Duration, SystemTime, SystemTimeExt}; /// A helper that computes the intersection of `range1` and `range2`. /// @@ -247,7 +247,7 @@ mod test { // [t1, t2]: [.......] // [t3, t4]: [.......] // intersection: [...] - let now = SystemTime::now(); + let now = SystemTime::get(); let t1 = now; let t2 = now + 2 * MIN; diff --git a/crates/tor-cert-x509/Cargo.toml b/crates/tor-cert-x509/Cargo.toml index 3ab1499bd..97c680c99 100644 --- a/crates/tor-cert-x509/Cargo.toml +++ b/crates/tor-cert-x509/Cargo.toml @@ -34,3 +34,4 @@ x509-cert = { version = "0.2.5", features = ["builder", "hazmat"] } [dev-dependencies] tor-basic-utils = { path = "../tor-basic-utils", version = "0.40.0" } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } diff --git a/crates/tor-cert-x509/src/lib.rs b/crates/tor-cert-x509/src/lib.rs index 1e231d7e2..182676573 100644 --- a/crates/tor-cert-x509/src/lib.rs +++ b/crates/tor-cert-x509/src/lib.rs @@ -411,6 +411,7 @@ mod test { use super::*; use tor_basic_utils::test_rng::testing_rng; + use web_time_compat::SystemTimeExt; #[test] fn identity_cert_generation() { @@ -418,7 +419,7 @@ mod test { let keypair = RsaKeypair::generate(&mut rng).unwrap(); let cert = create_legacy_rsa_id_cert( &mut rng, - SystemTime::now(), + SystemTime::get(), "www.house-of-pancakes.example.com", &keypair, ) @@ -438,7 +439,7 @@ mod test { let mut rng = testing_rng(); let certified = TlsKeyAndCert::create( &mut rng, - SystemTime::now(), + SystemTime::get(), "foo.example.com", "bar.example.com", ) diff --git a/crates/tor-cert/Cargo.toml b/crates/tor-cert/Cargo.toml index b4e92cb0c..26fa6c909 100644 --- a/crates/tor-cert/Cargo.toml +++ b/crates/tor-cert/Cargo.toml @@ -49,6 +49,7 @@ tor-cert-x509 = { path = "../tor-cert-x509", version = "0.40.0", optional = true tor-checkable = { path = "../tor-checkable", version = "0.40.0" } tor-error = { path = "../tor-error", version = "0.40.0" } tor-llcrypto = { path = "../tor-llcrypto", version = "0.40.0" } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] base64ct = "1.5.1" diff --git a/crates/tor-cert/src/encode.rs b/crates/tor-cert/src/encode.rs index de05a8122..ebf7394bb 100644 --- a/crates/tor-cert/src/encode.rs +++ b/crates/tor-cert/src/encode.rs @@ -220,14 +220,14 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; use crate::CertifiedKey; - use std::time::Duration; use tor_checkable::{SelfSigned, Timebound}; + use web_time_compat::{Duration, SystemTimeExt}; #[test] fn signed_cert_without_key() { let mut rng = rand::rng(); let keypair = ed25519::Keypair::generate(&mut rng); - let now = SystemTime::now(); + let now = SystemTime::get(); let day = Duration::from_secs(86400); let encoded = Ed25519Cert::constructor() .expiration(now + day * 30) diff --git a/crates/tor-cert/src/lib.rs b/crates/tor-cert/src/lib.rs index 69638af59..07c2f2643 100644 --- a/crates/tor-cert/src/lib.rs +++ b/crates/tor-cert/src/lib.rs @@ -57,7 +57,7 @@ use tor_bytes::{Error as BytesError, Result as BytesResult}; use tor_bytes::{Readable, Reader}; use tor_llcrypto::pk::*; -use std::time; +use web_time_compat as time; pub use err::CertError; @@ -625,7 +625,7 @@ struct ExpiryHours(u32); /// The number of seconds in an hour. const SEC_PER_HOUR: u64 = 3600; -impl From<ExpiryHours> for std::time::SystemTime { +impl From<ExpiryHours> for time::SystemTime { fn from(value: ExpiryHours) -> Self { // TODO MSRV 1.91; use from_hours. let d = std::time::Duration::from_secs(u64::from(value.0) * SEC_PER_HOUR); @@ -636,9 +636,9 @@ impl From<ExpiryHours> for std::time::SystemTime { #[cfg(feature = "encode")] impl ExpiryHours { /// Return the earliest possible `ExpiryHours` that is no earlier than `expiry`. - fn try_from_systemtime_ceil(expiry: std::time::SystemTime) -> Result<Self, CertEncodeError> { + fn try_from_systemtime_ceil(expiry: time::SystemTime) -> Result<Self, CertEncodeError> { let d = expiry - .duration_since(std::time::SystemTime::UNIX_EPOCH) + .duration_since(time::SystemTime::UNIX_EPOCH) .map_err(|_| CertEncodeError::InvalidExpiration)?; let sec_ceil = d.as_secs() + if d.subsec_nanos() > 0 { 1 } else { 0 }; let hours = sec_ceil @@ -684,6 +684,7 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; use hex_literal::hex; + use web_time_compat::SystemTimeExt; #[test] fn parse_unrecognized_ext() -> BytesResult<()> { @@ -736,7 +737,7 @@ mod test { fn expiry_hours_ceil() { use std::time::{Duration, SystemTime}; - let now = SystemTime::now(); + let now = SystemTime::get(); let mut exp = now + Duration::from_secs(24 * 60 * 60); for _ in 0..=3600 { let eh = ExpiryHours::try_from_systemtime_ceil(exp).unwrap(); diff --git a/crates/tor-cert/src/rsa/encode.rs b/crates/tor-cert/src/rsa/encode.rs index 858146ce0..de09f54c3 100644 --- a/crates/tor-cert/src/rsa/encode.rs +++ b/crates/tor-cert/src/rsa/encode.rs @@ -1,6 +1,6 @@ //! RSA cross-cert generation -use std::time::SystemTime; +use web_time_compat::SystemTime; use derive_more::{AsRef, Deref, Into}; use tor_bytes::Writer as _; @@ -81,6 +81,7 @@ mod test { use tor_basic_utils::test_rng::testing_rng; use tor_checkable::{ExternallySigned, Timebound}; + use web_time_compat::SystemTimeExt; use crate::SEC_PER_HOUR; use crate::rsa::RsaCrosscert; @@ -95,7 +96,7 @@ mod test { ed25519::Ed25519Identity::from_base64("dGhhdW1hdHVyZ3kgaXMgc3RvcmVkIGluIHRoZSBvcmI") .unwrap(); - let now = SystemTime::now(); + let now = SystemTime::get(); let expiry = now + Duration::from_secs(24 * SEC_PER_HOUR); let cert = EncodedRsaCrosscert::encode_and_sign(&keypair, &ed_id, expiry).unwrap(); diff --git a/crates/tor-chanmgr/Cargo.toml b/crates/tor-chanmgr/Cargo.toml index 537fc35b9..544d4d6fb 100644 --- a/crates/tor-chanmgr/Cargo.toml +++ b/crates/tor-chanmgr/Cargo.toml @@ -79,6 +79,7 @@ tor-units = { path = "../tor-units", version = "0.40.0" } tracing = "0.1.36" url = "2.5.8" void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] float_eq = "1.0.0" diff --git a/crates/tor-chanmgr/src/event.rs b/crates/tor-chanmgr/src/event.rs index ef5c4428a..9d016aa2f 100644 --- a/crates/tor-chanmgr/src/event.rs +++ b/crates/tor-chanmgr/src/event.rs @@ -4,11 +4,9 @@ use educe::Educe; use futures::{Stream, StreamExt}; use postage::watch; -use std::{ - fmt, - time::{Duration, Instant}, -}; +use std::fmt; use tor_basic_utils::skip_fmt; +use web_time_compat::{Duration, Instant, InstantExt}; /// The status of our connection to the internet. #[derive(Default, Debug, Clone)] @@ -344,12 +342,12 @@ impl ChanMgrEventSender { /// Note that an attempt to connect has been started. pub(crate) fn record_attempt(&mut self) { self.mgr_status.record_attempt(); - self.push_at(Instant::now()); + self.push_at(Instant::get()); } /// Note that we've successfully done a TCP handshake with an alleged relay. pub(crate) fn record_tcp_success(&mut self) { - let now = Instant::now(); + let now = Instant::get(); self.mgr_status.record_tcp_success(now); self.push_at(now); } @@ -358,7 +356,7 @@ impl ChanMgrEventSender { /// /// (Its identity won't be verified till the next step.) pub(crate) fn record_tls_finished(&mut self) { - let now = Instant::now(); + let now = Instant::get(); self.mgr_status.record_tls_finished(now); self.push_at(now); } @@ -366,7 +364,7 @@ impl ChanMgrEventSender { /// Record that a handshake has succeeded _except for the certificate /// timeliness check, which may indicate a skewed clock. pub(crate) fn record_handshake_done_with_skewed_clock(&mut self) { - let now = Instant::now(); + let now = Instant::get(); self.mgr_status.record_handshake_done_with_skewed_clock(now); self.push_at(now); } @@ -376,7 +374,7 @@ impl ChanMgrEventSender { /// (This includes performing the TLS handshake, and verifying that the /// relay was indeed the one that we wanted to reach.) pub(crate) fn record_handshake_done(&mut self) { - let now = Instant::now(); + let now = Instant::get(); self.mgr_status.record_handshake_done(now); self.push_at(now); } @@ -388,7 +386,7 @@ pub(crate) fn channel() -> (ChanMgrEventSender, ConnStatusEvents) { let receiver = ConnStatusEvents { inner: receiver }; let sender = ChanMgrEventSender { last_conn_status: ConnStatus::default(), - mgr_status: ChanMgrStatus::new_at(Instant::now()), + mgr_status: ChanMgrStatus::new_at(Instant::get()), sender, }; (sender, receiver) @@ -485,7 +483,7 @@ mod test { #[test] fn derive_status() { - let start = Instant::now(); + let start = Instant::get(); let sec = Duration::from_secs(1); let hour = Duration::from_secs(3600); diff --git a/crates/tor-checkable/Cargo.toml b/crates/tor-checkable/Cargo.toml index 6da1fd288..67c3cf1a3 100644 --- a/crates/tor-checkable/Cargo.toml +++ b/crates/tor-checkable/Cargo.toml @@ -22,6 +22,7 @@ humantime = "2" signature = "2" thiserror = "2" tor-llcrypto = { path = "../tor-llcrypto", version = "0.40.0" } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [package.metadata.docs.rs] all-features = true [dev-dependencies] diff --git a/crates/tor-checkable/src/lib.rs b/crates/tor-checkable/src/lib.rs index 521ff4e70..3efc5dd8c 100644 --- a/crates/tor-checkable/src/lib.rs +++ b/crates/tor-checkable/src/lib.rs @@ -48,6 +48,7 @@ use std::time; use thiserror::Error; +use web_time_compat::{SystemTime, SystemTimeExt}; pub mod signed; pub mod timed; @@ -93,7 +94,7 @@ pub trait Timebound<T>: Sized { /// Unwrap this Timebound object if it is valid now. fn check_valid_now(self) -> Result<T, Self::Error> { - self.check_valid_at(&time::SystemTime::now()) + self.check_valid_at(&SystemTime::get()) } /// Unwrap this object if it is valid at the provided time t. diff --git a/crates/tor-checkable/src/timed.rs b/crates/tor-checkable/src/timed.rs index 72fd7dfb9..a187212e2 100644 --- a/crates/tor-checkable/src/timed.rs +++ b/crates/tor-checkable/src/timed.rs @@ -1,7 +1,7 @@ //! Convenience implementation of a TimeBound object. use std::ops::{Bound, Deref, RangeBounds}; -use std::time; +use web_time_compat as time; /// A TimeBound object that is valid for a specified range of time. /// @@ -9,10 +9,10 @@ use std::time; /// /// /// ``` -/// use std::time::{SystemTime, Duration}; +/// use web_time_compat::{SystemTime, SystemTimeExt, Duration}; /// use tor_checkable::{Timebound, TimeValidityError, timed::TimerangeBound}; /// -/// let now = SystemTime::now(); +/// let now = SystemTime::get(); /// let one_hour = Duration::new(3600, 0); /// /// // This seven is only valid for another hour! @@ -222,7 +222,7 @@ mod test { use super::*; use crate::{TimeValidityError, Timebound}; use humantime::parse_rfc3339; - use std::time::{Duration, SystemTime}; + use web_time_compat::{Duration, SystemTime, SystemTimeExt}; #[test] fn test_bounds() { @@ -309,7 +309,7 @@ mod test { assert_eq!(tr.check_valid_at_opt(None), Ok("hello world")); let tr = TimerangeBound::new("hello world", de..); assert_eq!( - tr.check_valid_at_opt(Some(SystemTime::now())), + tr.check_valid_at_opt(Some(SystemTime::get())), Ok("hello world") ); let tr = TimerangeBound::new("hello world", ..za); @@ -318,7 +318,7 @@ mod test { #[test] fn test_dangerous() { - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let t2 = t1 + Duration::from_secs(60 * 525600); let tr = TimerangeBound::new("cups of coffee", t1..=t2); @@ -332,7 +332,7 @@ mod test { #[test] fn test_map() { - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let min = Duration::from_secs(60); let tb = TimerangeBound::new(17_u32, t1..t1 + 5 * min); @@ -346,7 +346,7 @@ mod test { #[test] fn test_as_ref() { - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let min = Duration::from_secs(60); let tb1: TimerangeBound<String> = TimerangeBound::new("hi".into(), t1..t1 + 5 * min); diff --git a/crates/tor-circmgr/Cargo.toml b/crates/tor-circmgr/Cargo.toml index 6b1380a6e..e28361d92 100644 --- a/crates/tor-circmgr/Cargo.toml +++ b/crates/tor-circmgr/Cargo.toml @@ -114,6 +114,7 @@ tracing = "0.1.36" visibility = { version = "0.1.0", optional = true } void = "1.0" weak-table = "0.3.0" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] futures-await-test = "0.3.0" diff --git a/crates/tor-circmgr/src/build.rs b/crates/tor-circmgr/src/build.rs index 75edc577e..fed6c6555 100644 --- a/crates/tor-circmgr/src/build.rs +++ b/crates/tor-circmgr/src/build.rs @@ -10,7 +10,6 @@ use std::sync::{ Arc, atomic::{AtomicU32, Ordering}, }; -use std::time::{Duration, Instant}; use tor_chanmgr::{ChanMgr, ChanProvenance, ChannelUsage}; use tor_error::into_internal; use tor_guardmgr::GuardStatus; @@ -23,6 +22,7 @@ use tor_rtcompat::SpawnExt; use tor_rtcompat::{Runtime, SleepProviderExt}; use tor_units::Percentage; use tracing::instrument; +use web_time_compat::{Duration, Instant}; #[cfg(all(feature = "vanguards", feature = "hs-common"))] use tor_guardmgr::vanguards::VanguardMgr; diff --git a/crates/tor-circmgr/src/err.rs b/crates/tor-circmgr/src/err.rs index 0570284e0..758614f6d 100644 --- a/crates/tor-circmgr/src/err.rs +++ b/crates/tor-circmgr/src/err.rs @@ -1,6 +1,6 @@ //! Declare an error type for tor-circmgr -use std::{sync::Arc, time::Instant}; +use std::sync::Arc; use futures::task::SpawnError; use retry_error::RetryError; @@ -10,6 +10,7 @@ use oneshot_fused_workaround as oneshot; use tor_error::{Bug, ErrorKind, HasKind, HasRetryTime}; use tor_linkspec::{LoggedChanTarget, OwnedChanTarget}; use tor_proto::circuit::UniqId; +use web_time_compat::Instant; use crate::mgr::RestrictionFailed; diff --git a/crates/tor-circmgr/src/hspool.rs b/crates/tor-circmgr/src/hspool.rs index 307c92939..a92bb1da7 100644 --- a/crates/tor-circmgr/src/hspool.rs +++ b/crates/tor-circmgr/src/hspool.rs @@ -7,7 +7,6 @@ mod pool; use std::{ ops::Deref, sync::{Arc, Mutex, Weak}, - time::Duration, }; use crate::{ @@ -35,6 +34,7 @@ use tor_rtcompat::{ scheduler::{TaskHandle, TaskSchedule}, }; use tracing::{debug, instrument, trace, warn}; +use web_time_compat::{Duration, Instant, SystemTime}; use std::result::Result as StdResult; @@ -373,12 +373,12 @@ impl<R: Runtime> HsCircPool<R> { /// /// This provides mockable time for use in error tracking and other /// time-sensitive operations. - pub fn now(&self) -> std::time::Instant { + pub fn now(&self) -> Instant { self.0.circmgr.mgr.peek_runtime().now() } /// Return the current wall-clock time from the runtime. - pub fn wallclock(&self) -> std::time::SystemTime { + pub fn wallclock(&self) -> SystemTime { self.0.circmgr.mgr.peek_runtime().wallclock() } } diff --git a/crates/tor-circmgr/src/hspool/pool.rs b/crates/tor-circmgr/src/hspool/pool.rs index cf078d044..763665dca 100644 --- a/crates/tor-circmgr/src/hspool/pool.rs +++ b/crates/tor-circmgr/src/hspool/pool.rs @@ -1,6 +1,6 @@ //! An internal pool object that we use to implement HsCircPool. -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; use crate::{ AbstractTunnel, diff --git a/crates/tor-circmgr/src/impls.rs b/crates/tor-circmgr/src/impls.rs index 01a046e8f..8544b1de1 100644 --- a/crates/tor-circmgr/src/impls.rs +++ b/crates/tor-circmgr/src/impls.rs @@ -19,6 +19,7 @@ use tor_proto::circuit::UniqId; use tor_proto::client::circuit::{CircParameters, Path}; use tor_rtcompat::Runtime; use tracing::instrument; +use web_time_compat::Instant; #[async_trait] impl mgr::AbstractTunnel for tor_proto::ClientTunnel { @@ -65,7 +66,7 @@ impl mgr::AbstractTunnel for tor_proto::ClientTunnel { circ.extend(target, params).await } - async fn last_known_to_be_used_at(&self) -> tor_proto::Result<Option<std::time::Instant>> { + async fn last_known_to_be_used_at(&self) -> tor_proto::Result<Option<Instant>> { self.disused_since().await } } diff --git a/crates/tor-circmgr/src/lib.rs b/crates/tor-circmgr/src/lib.rs index 8b0a56524..9aa7c2c3d 100644 --- a/crates/tor-circmgr/src/lib.rs +++ b/crates/tor-circmgr/src/lib.rs @@ -67,9 +67,9 @@ use tor_linkspec::IntoOwnedChanTarget; use futures::StreamExt; use std::sync::{Arc, Mutex, Weak}; -use std::time::{Duration, Instant}; use tor_rtcompat::SpawnExt; use tracing::{debug, info, instrument, trace, warn}; +use web_time_compat::{Duration, Instant, InstantExt}; #[cfg(feature = "testing")] pub use config::test_config::TestConfig; @@ -574,7 +574,8 @@ impl<B: AbstractTunnelBuilder<R> + 'static, R: Runtime> CircMgrInner<B, R> { #[cfg(feature = "geoip")] country_code: Option<CountryCode>, ) -> Result<Arc<B::Tunnel>> { self.expire_circuits().await; - let time = Instant::now(); + // TODO #2428: Shouldn't we look at runtime.now() instead? + let time = Instant::get(); { let mut predictive = self.predictor.lock().expect("preemptive lock poisoned"); if ports.is_empty() { diff --git a/crates/tor-circmgr/src/mgr.rs b/crates/tor-circmgr/src/mgr.rs index a8a501491..0e024bf0e 100644 --- a/crates/tor-circmgr/src/mgr.rs +++ b/crates/tor-circmgr/src/mgr.rs @@ -47,9 +47,9 @@ use std::fmt::Debug; use std::hash::Hash; use std::panic::AssertUnwindSafe; use std::sync::{self, Arc, Weak}; -use std::time::{Duration, Instant}; use tor_rtcompat::SpawnExt; use tracing::{debug, instrument, trace, warn}; +use web_time_compat::{Duration, Instant}; mod streams; /// Alias to force use of RandomState, regardless of features enabled in `weak_tables`. @@ -1879,6 +1879,7 @@ mod test { use tor_persist::TestingStateMgr; use tor_rtcompat::SleepProvider; use tor_rtmock::MockRuntime; + use web_time_compat::InstantExt; #[allow(deprecated)] // TODO #1885 use tor_rtmock::MockSleepRuntime; @@ -2432,7 +2433,7 @@ mod test { let (ep_none, ep_web, ep_full) = get_exit_policies(); let fake_circ = FakeCirc { id: FakeId::next() }; let expiration = ExpirationInfo::Unused { - created: Instant::now(), + created: Instant::get(), }; let mut entry_none = OpenEntry::new( diff --git a/crates/tor-circmgr/src/mocks.rs b/crates/tor-circmgr/src/mocks.rs index 274e6969d..776dd2c9b 100644 --- a/crates/tor-circmgr/src/mocks.rs +++ b/crates/tor-circmgr/src/mocks.rs @@ -9,6 +9,7 @@ use tor_persist::StateMgr; use tor_proto::circuit::UniqId; use tor_proto::client::circuit::{CircParameters, Path}; use tor_rtcompat::Runtime; +use web_time_compat::Instant; use async_trait::async_trait; use std::sync::{self, Arc}; @@ -74,7 +75,7 @@ impl AbstractTunnel for FakeCirc { todo!() } - async fn last_known_to_be_used_at(&self) -> tor_proto::Result<Option<std::time::Instant>> { + async fn last_known_to_be_used_at(&self) -> tor_proto::Result<Option<Instant>> { Ok(None) } } diff --git a/crates/tor-circmgr/src/path/exitpath.rs b/crates/tor-circmgr/src/path/exitpath.rs index 793496444..63379cf2d 100644 --- a/crates/tor-circmgr/src/path/exitpath.rs +++ b/crates/tor-circmgr/src/path/exitpath.rs @@ -219,6 +219,7 @@ mod test { use tor_persist::TestingStateMgr; use tor_relay_selection::LowLevelRelayPredicate; use tor_rtcompat::SleepProvider; + use web_time_compat::SystemTimeExt; impl<'a> MaybeOwnedRelay<'a> { fn can_share_circuit( @@ -283,7 +284,7 @@ mod test { let guards = tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap(); guards.install_test_netdir(&netdir); - let now = SystemTime::now(); + let now = SystemTime::get(); for _ in 0..1000 { let (path, _, _) = ExitPathBuilder::from_target_ports(ports.clone()) @@ -317,7 +318,7 @@ mod test { let guards = tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap(); guards.install_test_netdir(&netdir); - let now = SystemTime::now(); + let now = SystemTime::get(); let config = PathConfig::default(); for _ in 0..1000 { @@ -372,7 +373,7 @@ mod test { tor_guardmgr::GuardMgr::new(rt.clone(), statemgr, &TestConfig::default()).unwrap(); guards.install_test_netdir(&netdir); let config = PathConfig::default(); - let now = SystemTime::now(); + let now = SystemTime::get(); // With target ports let outcome = ExitPathBuilder::from_target_ports(vec![TargetPort::ipv4(80)]) diff --git a/crates/tor-circmgr/src/path/hspath.rs b/crates/tor-circmgr/src/path/hspath.rs index 2adba60d9..4c581fdf7 100644 --- a/crates/tor-circmgr/src/path/hspath.rs +++ b/crates/tor-circmgr/src/path/hspath.rs @@ -429,6 +429,7 @@ mod test { use tor_netdoc::doc::netstatus::RelayWeight; use tor_netdoc::types::relay_flags::RelayFlag; use tor_rtmock::MockRuntime; + use web_time_compat::SystemTimeExt; #[cfg(all(feature = "vanguards", feature = "hs-common"))] use { @@ -601,7 +602,8 @@ mod test { let netdir_provider: Arc<dyn NetDirProvider> = netdir_provider; guards.install_netdir_provider(&netdir_provider).unwrap(); let config = PathConfig::default(); - let now = SystemTime::now(); + // TODO #2428. (This is just testing, though) + let now = SystemTime::get(); let dirinfo = (netdir).into(); HsPathBuilder::new(target.cloned(), stem_kind, circ_kind) .pick_path_with_vanguards(&mut rng, dirinfo, &guards, &vanguardmgr, &config, now) @@ -616,7 +618,8 @@ mod test { ) -> Result<TorPath<'a>> { let mut rng = testing_rng(); let config = PathConfig::default(); - let now = SystemTime::now(); + // TODO #2428. (This is just testing, though) + let now = SystemTime::get(); let dirinfo = (netdir).into(); let guards = tor_guardmgr::GuardMgr::new( MockRuntime::new(), diff --git a/crates/tor-circmgr/src/preemptive.rs b/crates/tor-circmgr/src/preemptive.rs index 589237e68..ff2ee6e67 100644 --- a/crates/tor-circmgr/src/preemptive.rs +++ b/crates/tor-circmgr/src/preemptive.rs @@ -3,8 +3,8 @@ use crate::{PathConfig, PreemptiveCircuitConfig, TargetPort, TargetTunnelUsage}; use std::collections::HashMap; use std::sync::Arc; -use std::time::Instant; use tracing::warn; +use web_time_compat::{Instant, InstantExt}; /// Predicts what circuits might be used in future based on past activity, and suggests /// circuits to preemptively build as a result. @@ -25,11 +25,11 @@ impl PreemptiveCircuitPredictor { let mut usages = HashMap::new(); for port in &config.initial_predicted_ports { // TODO(nickm) should this be IPv6? Should we have a way to configure IPv6 initial ports? - usages.insert(Some(TargetPort::ipv4(*port)), Instant::now()); + usages.insert(Some(TargetPort::ipv4(*port)), Instant::get()); } // We want to build circuits for resolving DNS, too. - usages.insert(None, Instant::now()); + usages.insert(None, Instant::get()); Self { usages, @@ -57,7 +57,7 @@ impl PreemptiveCircuitPredictor { /// Make some predictions for what circuits should be built. pub(crate) fn predict(&self, path_config: &PathConfig) -> Vec<TargetTunnelUsage> { let config = self.config(); - let now = Instant::now(); + let now = Instant::get(); let circs = config.min_exit_circs_for_port; self.usages .iter() @@ -110,7 +110,7 @@ mod test { PathConfig, PreemptiveCircuitConfig, PreemptiveCircuitPredictor, TargetPort, TargetTunnelUsage, }; - use std::time::{Duration, Instant}; + use web_time_compat::{Duration, Instant, InstantExt}; use crate::isolation::test::{IsolationTokenEq, assert_isoleq}; @@ -175,7 +175,7 @@ mod test { }] ); - predictor.note_usage(Some(TargetPort::ipv4(1234)), Instant::now()); + predictor.note_usage(Some(TargetPort::ipv4(1234)), Instant::get()); let results = predictor.predict(&path_config); assert_eq!(results.len(), 2); @@ -206,7 +206,7 @@ mod test { cfg.set_initial_predicted_ports(vec![]); cfg.prediction_lifetime(Duration::from_secs(2)); let mut predictor = PreemptiveCircuitPredictor::new(cfg.build().unwrap()); - let now = Instant::now(); + let now = Instant::get(); let three_seconds_ago = now - Duration::from_secs(2 + 1); predictor.note_usage(Some(TargetPort::ipv4(2345)), three_seconds_ago); diff --git a/crates/tor-circmgr/src/usage.rs b/crates/tor-circmgr/src/usage.rs index a2b24a8b5..5b0666ee9 100644 --- a/crates/tor-circmgr/src/usage.rs +++ b/crates/tor-circmgr/src/usage.rs @@ -620,6 +620,7 @@ pub(crate) mod test { use tor_llcrypto::pk::ed25519::Ed25519Identity; use tor_netdir::testnet; use tor_persist::TestingStateMgr; + use web_time_compat::SystemTimeExt; impl IsolationTokenEq for TargetTunnelUsage { fn isol_eq(&self, other: &Self) -> bool { @@ -956,7 +957,7 @@ pub(crate) mod test { tor_guardmgr::GuardMgr::new(rt.clone(), statemgr.clone(), &TestConfig::default()) .unwrap(); guards.install_test_netdir(&netdir); - let now = SystemTime::now(); + let now = SystemTime::get(); // Only doing basic tests for now. We'll test the path // building code a lot more closely in the tests for TorPath @@ -1071,7 +1072,7 @@ pub(crate) mod test { tor_guardmgr::GuardMgr::new(rt.clone(), statemgr.clone(), &TestConfig::default()) .unwrap(); guards.install_test_netdir(&netdir); - let now = SystemTime::now(); + let now = SystemTime::get(); #[cfg(all(feature = "vanguards", feature = "hs-common"))] let vanguards = diff --git a/crates/tor-dirclient/Cargo.toml b/crates/tor-dirclient/Cargo.toml index f9dae948b..f04f8ac8c 100644 --- a/crates/tor-dirclient/Cargo.toml +++ b/crates/tor-dirclient/Cargo.toml @@ -64,6 +64,7 @@ tor-netdoc = { path = "../tor-netdoc", version = "0.40.0" } tor-proto = { path = "../tor-proto", version = "0.40.0" } tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0" } tracing = "0.1.36" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] futures-await-test = "0.3.0" diff --git a/crates/tor-dirclient/src/lib.rs b/crates/tor-dirclient/src/lib.rs index 5939cc2ba..923423a26 100644 --- a/crates/tor-dirclient/src/lib.rs +++ b/crates/tor-dirclient/src/lib.rs @@ -593,6 +593,7 @@ mod test { use tor_rtmock::io::stream_pair; use tor_rtmock::simple_time::SimpleMockTimeProvider; + use web_time_compat::{SystemTime, SystemTimeExt}; use futures_await_test::async_test; @@ -633,7 +634,7 @@ mod test { // We don't need to do anything fancy here, since we aren't simulating // a timeout. #[allow(deprecated)] // TODO #1885 - let mock_time = SimpleMockTimeProvider::from_wallclock(std::time::SystemTime::now()); + let mock_time = SimpleMockTimeProvider::from_wallclock(SystemTime::get()); let mut output = Vec::new(); let mut stream = match get_decoder(data, encoding, AnonymizedRequest::Direct) { diff --git a/crates/tor-dirclient/src/request.rs b/crates/tor-dirclient/src/request.rs index ab4412a3f..476b86124 100644 --- a/crates/tor-dirclient/src/request.rs +++ b/crates/tor-dirclient/src/request.rs @@ -831,6 +831,7 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::sealed::RequestableInner; use super::*; + use web_time_compat::SystemTimeExt; #[test] fn test_md_request() -> Result<()> { @@ -915,7 +916,7 @@ mod test { .unwrap(); let d2 = b"blah blah blah 12 blah blah blah"; - let d3 = SystemTime::now(); + let d3 = SystemTime::get(); let mut req = ConsensusRequest::default(); let when = httpdate::fmt_http_date(d3); diff --git a/crates/tor-dirmgr/Cargo.toml b/crates/tor-dirmgr/Cargo.toml index 41ad825d1..e340f2471 100644 --- a/crates/tor-dirmgr/Cargo.toml +++ b/crates/tor-dirmgr/Cargo.toml @@ -115,6 +115,7 @@ tor-protover = { path = "../tor-protover", version = "0.40.0", features = ["serd tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0" } tracing = "0.1.36" void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [target.'cfg(not(all(target_arch = "wasm32", target_os = "unknown")))'.dependencies] fslock = "0.2.0" diff --git a/crates/tor-dirmgr/src/bootstrap.rs b/crates/tor-dirmgr/src/bootstrap.rs index f6a38332f..68ccfdd68 100644 --- a/crates/tor-dirmgr/src/bootstrap.rs +++ b/crates/tor-dirmgr/src/bootstrap.rs @@ -748,10 +748,11 @@ mod test { use tor_dircommon::retry::DownloadSchedule; use tor_netdoc::doc::microdesc::MdDigest; use tor_rtcompat::SleepProvider; + use web_time_compat::SystemTimeExt; #[test] fn week() { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_day = Duration::new(86400, 0); assert_eq!(no_more_than_a_week_from(now, None), now + one_day * 7); diff --git a/crates/tor-dirmgr/src/bridgedesc.rs b/crates/tor-dirmgr/src/bridgedesc.rs index ecce442c6..b866937a5 100644 --- a/crates/tor-dirmgr/src/bridgedesc.rs +++ b/crates/tor-dirmgr/src/bridgedesc.rs @@ -7,7 +7,6 @@ use std::fmt::{self, Debug, Display}; use std::num::NonZeroU8; use std::panic::AssertUnwindSafe; use std::sync::{Arc, Mutex, MutexGuard, Weak}; -use std::time::{Duration, Instant, SystemTime}; use async_trait::async_trait; use derive_more::{Deref, DerefMut}; @@ -29,6 +28,7 @@ use tor_guardmgr::bridge::{BridgeConfig, BridgeDesc}; use tor_guardmgr::bridge::{BridgeDescError, BridgeDescEvent, BridgeDescList, BridgeDescProvider}; use tor_netdoc::doc::routerdesc::RouterDesc; use tor_rtcompat::{Runtime, SpawnExt as _}; +use web_time_compat::{Duration, Instant, SystemTime}; use crate::event::FlagPublisher; use crate::storage::CachedBridgeDescriptor; diff --git a/crates/tor-dirmgr/src/event.rs b/crates/tor-dirmgr/src/event.rs index 5d9a7e94a..0744206b3 100644 --- a/crates/tor-dirmgr/src/event.rs +++ b/crates/tor-dirmgr/src/event.rs @@ -839,6 +839,7 @@ mod test { use float_eq::assert_float_eq; use futures::stream::StreamExt; use tor_rtcompat::test_with_all_runtimes; + use web_time_compat::SystemTimeExt; #[test] fn subscribe_and_publish() { @@ -965,7 +966,7 @@ mod test { #[test] fn dir_status_basics() { - let now = SystemTime::now(); + let now = SystemTime::get(); let hour = Duration::new(3600, 0); let nothing = DirStatus { diff --git a/crates/tor-dirmgr/src/lib.rs b/crates/tor-dirmgr/src/lib.rs index bcdd4c9d4..5398dfa85 100644 --- a/crates/tor-dirmgr/src/lib.rs +++ b/crates/tor-dirmgr/src/lib.rs @@ -91,6 +91,7 @@ use tor_netdoc::doc::netstatus::ProtoStatuses; use tor_rtcompat::scheduler::{TaskHandle, TaskSchedule}; use tor_rtcompat::{Runtime, SpawnExt}; use tracing::{debug, info, instrument, trace, warn}; +use web_time_compat::SystemTimeExt; use std::marker::PhantomData; use std::sync::atomic::{AtomicBool, Ordering}; @@ -182,7 +183,8 @@ impl<R: Runtime> NetDirProvider for DirMgr<R> { .extend_lifetime(netdir.lifetime()), Timeliness::Unchecked => return Ok(netdir), }; - let now = SystemTime::now(); + // TODO #2384 -- we have a runtime here; we should use it. + let now = SystemTime::get(); if lifetime.valid_after() > now { Err(NetDirError::DirNotYetValid) } else if lifetime.valid_until() < now { diff --git a/crates/tor-dirmgr/src/storage/sqlite.rs b/crates/tor-dirmgr/src/storage/sqlite.rs index db42e893e..4967ce6bb 100644 --- a/crates/tor-dirmgr/src/storage/sqlite.rs +++ b/crates/tor-dirmgr/src/storage/sqlite.rs @@ -17,6 +17,7 @@ use tor_netdoc::doc::microdesc::MdDigest; use tor_netdoc::doc::netstatus::{ConsensusFlavor, Lifetime}; #[cfg(feature = "routerdesc")] use tor_netdoc::doc::routerdesc::RdDigest; +use web_time_compat::SystemTimeExt; #[cfg(feature = "bridge-client")] pub(crate) use {crate::storage::CachedBridgeDescriptor, tor_guardmgr::bridge::BridgeConfig}; @@ -610,7 +611,7 @@ impl Store for SqliteStore { names }; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); tx.execute(DROP_OLD_EXTDOCS, [])?; // In theory bad system clocks might generate table rows with times far in the future. @@ -1166,6 +1167,11 @@ fn cmeta_from_row(row: &rusqlite::Row<'_>) -> Result<ConsensusMeta> { )) } +/// Return `SystemTime::get()` as an OffsetDateTime in UTC. +fn now_utc() -> OffsetDateTime { + SystemTime::get().into() +} + /// Set up the tables for the arti cache schema in a sqlite database. const INSTALL_V0_SCHEMA: &str = " -- Helps us version the schema. The schema here corresponds to a @@ -1538,7 +1544,7 @@ pub(crate) mod test { fn blobs() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_week = 1.weeks(); let fname1 = store.save_blob( @@ -1598,7 +1604,7 @@ pub(crate) mod test { use tor_netdoc::doc::netstatus; let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_hour = 1.hours(); assert_eq!( @@ -1702,7 +1708,7 @@ pub(crate) mod test { #[test] fn authcerts() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_hour = 1.hours(); let keyids = AuthCertKeyIds { @@ -1729,7 +1735,7 @@ pub(crate) mod test { fn microdescs() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_day = 1.days(); let d1 = [5_u8; 32]; @@ -1770,7 +1776,7 @@ pub(crate) mod test { fn routerdescs() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_day = 1.days(); let long_ago: OffsetDateTime = now - one_day * 100; let recently = now - one_day; @@ -1843,7 +1849,7 @@ pub(crate) mod test { */ assert_eq!(store.blob_dir.read_directory(".")?.count(), 0); - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_week = 1.weeks(); let _fname_good = store.save_blob( b"Goodbye, dear friends", @@ -1880,7 +1886,7 @@ pub(crate) mod test { fn unreferenced_consensus_blob() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_week = 1.weeks(); // Make a blob that claims to be a consensus, and which has not yet expired, but which is @@ -1918,7 +1924,7 @@ pub(crate) mod test { fn vanished_blob_cleanup() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = OffsetDateTime::now_utc(); + let now = now_utc(); let one_week = 1.weeks(); // Make a few blobs. @@ -1972,7 +1978,7 @@ pub(crate) mod test { fn protocol_statuses() -> Result<()> { let (_tmp_dir, mut store) = new_empty()?; - let now = SystemTime::now(); + let now = SystemTime::get(); let hour = 1.hours(); let valid_after = now; diff --git a/crates/tor-error/Cargo.toml b/crates/tor-error/Cargo.toml index f801dd950..0cf0c73be 100644 --- a/crates/tor-error/Cargo.toml +++ b/crates/tor-error/Cargo.toml @@ -32,12 +32,13 @@ derive_more = { version = "2.0.1", features = ["full"] } futures = { version = "0.3", optional = true } http = { version = "1.3.1", optional = true } paste = "1.0.3" -retry-error = { path = "../retry-error", version = "0.11.0" } # WRONG should be 0.4.3 +retry-error = { path = "../retry-error", version = "0.11.0" } # WRONG should be 0.4.3 static_assertions = { version = "1", optional = true } strum = { version = "0.28.0", features = ["derive"] } thiserror = "2" tracing = { version = "0.1.36", optional = true } void = "1" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] anyhow = "1.0.72" diff --git a/crates/tor-error/src/retriable.rs b/crates/tor-error/src/retriable.rs index 87fcbdd32..8f77e1091 100644 --- a/crates/tor-error/src/retriable.rs +++ b/crates/tor-error/src/retriable.rs @@ -1,11 +1,9 @@ //! Declare the `RetryTime` enumeration and related code. use derive_more::{From, Into}; -use std::{ - cmp::Ordering, - time::{Duration, Instant}, -}; +use std::{cmp::Ordering, time::Duration}; use strum::EnumDiscriminants; +use web_time_compat::Instant; /// A description of when an operation may be retried. /// @@ -87,7 +85,7 @@ pub enum RetryTime { /// The operation can be retried at some particular time in the future. /// /// The recipient of this this `RetryTime` variant should wait until the - /// current time (as returned by `Instant::now` or `SleepProvider::now` as + /// current time (as returned by `Instant::get` or `SleepProvider::now` as /// appropriate) is at least this given instant. /// /// This case is appropriate for when we have a failure condition caused by @@ -274,13 +272,15 @@ mod test { #![allow(clippy::useless_vec)] #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> + use super::*; + use web_time_compat::InstantExt; #[test] fn comparison() { use RetryTime as RT; let sec = Duration::from_secs(1); - let now = Instant::now(); + let now = Instant::get(); let sorted = vec![ RT::Immediate, @@ -304,7 +304,7 @@ mod test { fn abs_comparison() { use AbsRetryTime as ART; let sec = Duration::from_secs(1); - let now = Instant::now(); + let now = Instant::get(); let sorted = vec![ ART::Immediate, @@ -324,7 +324,7 @@ mod test { #[test] fn earliest_absolute() { let sec = Duration::from_secs(1); - let now = Instant::now(); + let now = Instant::get(); let times = vec![RetryTime::AfterWaiting, RetryTime::Never]; @@ -337,7 +337,7 @@ mod test { #[test] fn abs_from_sum() { - let base = Instant::now(); + let base = Instant::get(); let delta = Duration::from_secs(1); assert_eq!( AbsRetryTime::from_sum(base, delta), diff --git a/crates/tor-guardmgr/Cargo.toml b/crates/tor-guardmgr/Cargo.toml index 60468a9ec..097eefaf6 100644 --- a/crates/tor-guardmgr/Cargo.toml +++ b/crates/tor-guardmgr/Cargo.toml @@ -96,6 +96,7 @@ tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0" } tor-rtmock = { path = "../tor-rtmock", version = "0.40.0", optional = true } tor-units = { path = "../tor-units", version = "0.40.0" } tracing = "0.1.36" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] float_eq = "1.0.0" diff --git a/crates/tor-guardmgr/src/bridge/descs.rs b/crates/tor-guardmgr/src/bridge/descs.rs index 7eee3cf25..4dd1a0c14 100644 --- a/crates/tor-guardmgr/src/bridge/descs.rs +++ b/crates/tor-guardmgr/src/bridge/descs.rs @@ -5,7 +5,6 @@ use std::collections::HashMap; use std::sync::Arc; -use std::time::SystemTime; use crate::{ bridge::BridgeConfig, @@ -20,6 +19,7 @@ use tor_linkspec::{ChanTarget, HasChanMethod, HasRelayIds, OwnedChanTarget}; use tor_llcrypto::pk::{ed25519::Ed25519Identity, rsa::RsaIdentity}; use tor_netdir::RelayWeight; use tor_netdoc::doc::routerdesc::RouterDesc; +use web_time_compat::{SystemTime, SystemTimeExt}; use super::BridgeRelay; @@ -239,13 +239,13 @@ impl Universe for BridgeSet { } } - fn timestamp(&self) -> std::time::SystemTime { + fn timestamp(&self) -> SystemTime { // We just use the current time as the timestamp of this BridgeSet. // This makes the guard code treat a BridgeSet as _continuously updated_: // anything listed in the guard set is treated as listed right up to this // moment, and anything unlisted is treated as unlisted right up to this // moment. - SystemTime::now() + SystemTime::get() } /// Note that for a BridgeSet, we always treat the current weight as 0 and diff --git a/crates/tor-guardmgr/src/dirstatus.rs b/crates/tor-guardmgr/src/dirstatus.rs index 7b3736e40..d3329da93 100644 --- a/crates/tor-guardmgr/src/dirstatus.rs +++ b/crates/tor-guardmgr/src/dirstatus.rs @@ -1,7 +1,7 @@ //! Types and code to track the readiness status of a directory cache. -use std::time::{Duration, Instant}; use tor_basic_utils::retry::RetryDelay; +use web_time_compat::{Duration, Instant}; /// Status information about whether a /// [`FallbackDir`](tor_dircommon::fallback::FallbackDir) or @@ -78,10 +78,11 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; + use web_time_compat::InstantExt; #[test] fn status_basics() { - let now = Instant::now(); + let now = Instant::get(); /// floor to use for testing. const FLOOR: Duration = Duration::from_secs(99); diff --git a/crates/tor-guardmgr/src/err.rs b/crates/tor-guardmgr/src/err.rs index a93183e5e..f59544c45 100644 --- a/crates/tor-guardmgr/src/err.rs +++ b/crates/tor-guardmgr/src/err.rs @@ -2,9 +2,9 @@ use futures::task::SpawnError; use std::sync::Arc; -use std::time::Instant; use tor_basic_utils::iter::FilterCount; use tor_error::{Bug, ErrorKind, HasKind}; +use web_time_compat::{Instant, InstantExt}; /// A error caused by a failure to pick a guard. #[derive(Clone, Debug, thiserror::Error)] @@ -19,7 +19,7 @@ pub enum PickGuardError { suitable.display_frac_rejected(), filtered.display_frac_rejected(), if let Some(retry_at) = retry_at { - format!(" Retrying in {}.", humantime::format_duration(*retry_at - Instant::now())) + format!(" Retrying in {}.", humantime::format_duration(*retry_at - Instant::get())) } else { "".to_string() }, diff --git a/crates/tor-guardmgr/src/fallback.rs b/crates/tor-guardmgr/src/fallback.rs index 323870d29..8047254c8 100644 --- a/crates/tor-guardmgr/src/fallback.rs +++ b/crates/tor-guardmgr/src/fallback.rs @@ -6,9 +6,9 @@ use crate::{dirstatus::DirStatus, skew::SkewObservation}; use rand::seq::IteratorRandom; -use std::time::{Duration, Instant}; use tor_dircommon::fallback::{FallbackDir, FallbackList}; use tor_linkspec::HasRelayIds; +use web_time_compat::{Duration, Instant}; use crate::{PickGuardError, ids::FallbackId}; use tor_basic_utils::iter::{FilterCount, IteratorExt as _}; @@ -201,6 +201,7 @@ mod test { use super::*; use rand::Rng; use tor_basic_utils::test_rng::testing_rng; + use web_time_compat::InstantExt; /// Construct a `FallbackDir` with random identity keys and addresses. /// @@ -297,7 +298,7 @@ mod test { let filter = crate::GuardFilter::unfiltered(); let mut counts = [0_usize; 4]; - let now = Instant::now(); + let now = Instant::get(); dbg!("A"); fn lookup_idx(set: &FallbackState, id: &impl HasRelayIds) -> Option<usize> { set.fallbacks @@ -365,7 +366,7 @@ mod test { .map(|ent| FallbackId::from_relay_ids(&ent.fallback)) .collect(); - let now = Instant::now(); + let now = Instant::get(); // There's no "next retry time" when everybody's up. assert!(set.next_retry().is_none()); diff --git a/crates/tor-guardmgr/src/guard.rs b/crates/tor-guardmgr/src/guard.rs index 6e876340b..1fa6b2d52 100644 --- a/crates/tor-guardmgr/src/guard.rs +++ b/crates/tor-guardmgr/src/guard.rs @@ -6,8 +6,8 @@ use itertools::Itertools; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::SocketAddr; -use std::time::{Duration, Instant, SystemTime}; use tracing::{info, trace, warn}; +use web_time_compat::{Duration, Instant, InstantExt, SystemTime}; use crate::dirstatus::DirStatus; use crate::sample::Candidate; @@ -448,7 +448,7 @@ impl Guard { Some(retry_at) => warn!( "Could not connect to guard {}. Retrying in {}.", self, - humantime::format_duration(retry_at - Instant::now()), + humantime::format_duration(retry_at - Instant::get()), ), None => warn!( "Could not connect to guard {}. Next retry time unknown.", @@ -951,6 +951,7 @@ mod test { use crate::ids::FirstHopId; use tor_linkspec::{HasRelayIds, RelayId}; use tor_llcrypto::pk::ed25519::Ed25519Identity; + use web_time_compat::SystemTimeExt; #[test] fn crate_id() { @@ -965,7 +966,7 @@ mod test { fn basic_guard() -> Guard { let id = basic_id(); let ports = vec!["127.0.0.7:7777".parse().unwrap()]; - let added = SystemTime::now(); + let added = SystemTime::get(); Guard::new(id, ports, None, added) } @@ -1055,9 +1056,9 @@ mod test { #[test] fn record_attempt() { - let t1 = Instant::now() - Duration::from_secs(10); - let t2 = Instant::now() - Duration::from_secs(5); - let t3 = Instant::now(); + let t1 = Instant::get() - Duration::from_secs(10); + let t2 = Instant::get() - Duration::from_secs(5); + let t3 = Instant::get(); let mut g = basic_guard(); @@ -1072,8 +1073,8 @@ mod test { #[test] fn record_failure() { - let t1 = Instant::now() - Duration::from_secs(10); - let t2 = Instant::now(); + let t1 = Instant::get() - Duration::from_secs(10); + let t2 = Instant::get(); let mut g = basic_guard(); g.record_failure(t1, true); @@ -1090,11 +1091,11 @@ mod test { #[test] fn record_success() { - let t1 = Instant::now() - Duration::from_secs(10); + let t1 = Instant::get() - Duration::from_secs(10); // has to be in the future, since the guard's "added_at" time is based on now. - let now = SystemTime::now(); + let now = SystemTime::get(); let t2 = now + Duration::from_secs(300 * 86400); - let t3 = Instant::now() + Duration::from_secs(310 * 86400); + let t3 = Instant::get() + Duration::from_secs(310 * 86400); let t4 = now + Duration::from_secs(320 * 86400); let mut g = basic_guard(); @@ -1121,7 +1122,7 @@ mod test { #[test] fn retry() { - let t1 = Instant::now(); + let t1 = Instant::get(); let mut g = basic_guard(); g.record_failure(t1, true); @@ -1148,7 +1149,7 @@ mod test { fn expiration() { const DAY: Duration = Duration::from_secs(24 * 60 * 60); let params = GuardParams::default(); - let now = SystemTime::now(); + let now = SystemTime::get(); let g = basic_guard(); assert!(!g.is_expired(¶ms, now)); @@ -1176,7 +1177,7 @@ mod test { use tor_netdir::testnet; let netdir = testnet::construct_netdir().unwrap_if_sufficient().unwrap(); let params = GuardParams::default(); - let now = SystemTime::now(); + let now = SystemTime::get(); // Construct a guard from a relay from the netdir. let relay22 = netdir.by_id(&Ed25519Identity::from([22; 32])).unwrap(); @@ -1226,7 +1227,7 @@ mod test { .unwrap(); //let params = GuardParams::default(); - let now = SystemTime::now(); + let now = SystemTime::get(); // Try a guard that isn't in the netdir at all. let mut guard255 = Guard::new( @@ -1283,7 +1284,7 @@ mod test { #[test] fn pending() { let mut g = basic_guard(); - let t1 = Instant::now(); + let t1 = Instant::get(); let t2 = t1 + Duration::from_secs(100); let t3 = t1 + Duration::from_secs(200); @@ -1320,7 +1321,7 @@ mod test { let mut g = basic_guard(); let params = GuardParams::default(); - let now = SystemTime::now(); + let now = SystemTime::get(); let _ignore = g.record_success(now, ¶ms); for _ in 0..13 { @@ -1374,8 +1375,8 @@ mod test { use crate::GuardUsageBuilder; let mut g = basic_guard(); - let inst = Instant::now(); - let st = SystemTime::now(); + let inst = Instant::get(); + let st = SystemTime::get(); let sec = Duration::from_secs(1); let params = GuardParams::default(); let dir_usage = GuardUsageBuilder::new() diff --git a/crates/tor-guardmgr/src/lib.rs b/crates/tor-guardmgr/src/lib.rs index 6f54146d4..9e0534eae 100644 --- a/crates/tor-guardmgr/src/lib.rs +++ b/crates/tor-guardmgr/src/lib.rs @@ -62,7 +62,6 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::SocketAddr; use std::sync::{Arc, Mutex, Weak}; -use std::time::{Duration, Instant, SystemTime}; #[cfg(feature = "bridge-client")] use tor_error::internal; use tor_linkspec::{OwnedChanTarget, OwnedCircTarget, RelayId, RelayIdSet}; @@ -71,6 +70,7 @@ use tor_proto::ClockSkew; use tor_rtcompat::SpawnExt; use tor_units::BoundedInt32; use tracing::{debug, info, instrument, trace, warn}; +use web_time_compat::{Duration, Instant, SystemTime}; use tor_config::derive::prelude::*; use tor_config::{ExplicitOrAuto, impl_standard_builder}; diff --git a/crates/tor-guardmgr/src/pending.rs b/crates/tor-guardmgr/src/pending.rs index 051291e85..f9bef8536 100644 --- a/crates/tor-guardmgr/src/pending.rs +++ b/crates/tor-guardmgr/src/pending.rs @@ -17,8 +17,8 @@ use std::fmt::Debug; use std::pin::Pin; use std::sync::atomic::{AtomicU64, Ordering}; use std::task::{Context, Poll}; -use std::time::Instant; use tor_proto::ClockSkew; +use web_time_compat::Instant; use tor_basic_utils::skip_fmt; diff --git a/crates/tor-guardmgr/src/sample.rs b/crates/tor-guardmgr/src/sample.rs index b0c2eae80..524f45556 100644 --- a/crates/tor-guardmgr/src/sample.rs +++ b/crates/tor-guardmgr/src/sample.rs @@ -18,8 +18,8 @@ use rand::seq::IndexedRandom; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::time::{Instant, SystemTime}; use tracing::{debug, info}; +use web_time_compat::{Instant, SystemTime}; #[allow(unused_imports)] pub(crate) use candidate::{Candidate, CandidateStatus, Universe, UniverseRef, WeightThreshold}; @@ -1033,6 +1033,7 @@ mod test { use tor_netdir::NetDir; use tor_netdoc::doc::netstatus::RelayWeight; use tor_netdoc::types::relay_flags::RelayFlag; + use web_time_compat::{InstantExt, SystemTimeExt}; use super::*; use crate::FirstHopId; @@ -1093,7 +1094,7 @@ mod test { let mut samples: Vec<HashSet<GuardId>> = Vec::new(); for _ in 0..3 { let mut guards = GuardSet::default(); - guards.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); assert_eq!(guards.guards.len(), params.min_filtered_sample_size); assert_eq!(guards.confirmed.len(), 0); assert_eq!(guards.primary.len(), 0); @@ -1107,12 +1108,12 @@ mod test { assert!(relay.low_level_details().is_dir_cache()); assert!(guards.guards.by_all_ids(&relay).is_some()); { - assert!(!guard.is_expired(¶ms, SystemTime::now())); + assert!(!guard.is_expired(¶ms, SystemTime::get())); } } // Make sure that the sample doesn't expand any further. - guards.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); assert_eq!(guards.guards.len(), params.min_filtered_sample_size); guards.assert_consistency(); @@ -1132,7 +1133,7 @@ mod test { ..GuardParams::default() }; - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let t2 = t1 + Duration::from_secs(20); let mut guards = GuardSet::default(); @@ -1176,7 +1177,7 @@ mod test { n_primary: 4, ..GuardParams::default() }; - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let t2 = t1 + Duration::from_secs(20); let t3 = t2 + Duration::from_secs(30); @@ -1222,7 +1223,7 @@ mod test { fn expiration() { let netdir = netdir(); let params = GuardParams::default(); - let t1 = SystemTime::now(); + let t1 = SystemTime::get(); let mut guards = GuardSet::default(); guards.extend_sample_as_needed(t1, ¶ms, &netdir); @@ -1256,8 +1257,8 @@ mod test { n_primary: 2, ..GuardParams::default() }; - let st1 = SystemTime::now(); - let i1 = Instant::now(); + let st1 = SystemTime::get(); + let i1 = Instant::get(); let sec = Duration::from_secs(1); let mut guards = GuardSet::default(); @@ -1383,8 +1384,8 @@ mod test { max_sample_bw_fraction: 1.0, ..GuardParams::default() }; - let mut st = SystemTime::now(); - let mut inst = Instant::now(); + let mut st = SystemTime::get(); + let mut inst = Instant::get(); let sec = Duration::from_secs(1); let usage = crate::GuardUsageBuilder::default().build().unwrap(); @@ -1425,7 +1426,7 @@ mod test { let mut guards = GuardSet::default(); - guards.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); guards.select_primary_guards(¶ms); assert_eq!(guards.primary.len(), 2); @@ -1433,25 +1434,25 @@ mod test { // Let one primary guard fail. let (kind, p_id1) = guards - .pick_guard_id(&usage, ¶ms, Instant::now()) + .pick_guard_id(&usage, ¶ms, Instant::get()) .unwrap(); assert_eq!(kind, ListKind::Primary); - guards.record_failure(&p_id1, None, Instant::now()); + guards.record_failure(&p_id1, None, Instant::get()); assert!(!guards.all_primary_guards_are_unreachable()); // Now let the other one fail. let (kind, p_id2) = guards - .pick_guard_id(&usage, ¶ms, Instant::now()) + .pick_guard_id(&usage, ¶ms, Instant::get()) .unwrap(); assert_eq!(kind, ListKind::Primary); - guards.record_failure(&p_id2, None, Instant::now()); + guards.record_failure(&p_id2, None, Instant::get()); assert!(guards.all_primary_guards_are_unreachable()); // Now mark the guards retriable. guards.mark_primary_guards_retriable(); assert!(!guards.all_primary_guards_are_unreachable()); let (kind, p_id3) = guards - .pick_guard_id(&usage, ¶ms, Instant::now()) + .pick_guard_id(&usage, ¶ms, Instant::get()) .unwrap(); assert_eq!(kind, ListKind::Primary); assert_eq!(p_id3, p_id1); @@ -1468,14 +1469,14 @@ mod test { }; let usage = crate::GuardUsageBuilder::default().build().unwrap(); let mut guards = GuardSet::default(); - guards.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); guards.select_primary_guards(¶ms); assert_eq!(guards.primary.len(), 2); let (_kind, p_id1) = guards - .pick_guard_id(&usage, ¶ms, Instant::now()) + .pick_guard_id(&usage, ¶ms, Instant::get()) .unwrap(); - guards.record_success(&p_id1, ¶ms, None, SystemTime::now()); + guards.record_success(&p_id1, ¶ms, None, SystemTime::get()); assert_eq!(guards.n_primary_without_id_info_in(&netdir), 0); use tor_netdir::testnet; @@ -1502,17 +1503,17 @@ mod test { ..GuardParams::default() }; let mut guards1 = GuardSet::default(); - guards1.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards1.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); guards1.select_primary_guards(¶ms); let mut guards2 = guards1.clone(); // Make a persistent change in guards1, and a different persistent change in guards2. let id1 = guards1.primary[0].clone(); let id2 = guards1.primary[1].clone(); - guards1.record_success(&id1, ¶ms, None, SystemTime::now()); - guards2.record_success(&id2, ¶ms, None, SystemTime::now()); + guards1.record_success(&id1, ¶ms, None, SystemTime::get()); + guards2.record_success(&id2, ¶ms, None, SystemTime::get()); // Make a non-persistent change in guards2. - guards2.record_failure(&id2, None, Instant::now()); + guards2.record_failure(&id2, None, Instant::get()); // Copy status: make sure non-persistent status changed, and persistent didn't. guards1.copy_ephemeral_status_into_newly_loaded_state(guards2); @@ -1537,7 +1538,7 @@ mod test { for _ in 0..4 { // There is roughly a 1-in-5000 chance of getting the same set // twice, so we loop until that doesn't happen. - guards3.extend_sample_as_needed(SystemTime::now(), ¶ms, &netdir); + guards3.extend_sample_as_needed(SystemTime::get(), ¶ms, &netdir); guards3.select_primary_guards(¶ms); g3_set = guards3 .guards diff --git a/crates/tor-guardmgr/src/skew.rs b/crates/tor-guardmgr/src/skew.rs index a1ed084ed..99090f07d 100644 --- a/crates/tor-guardmgr/src/skew.rs +++ b/crates/tor-guardmgr/src/skew.rs @@ -7,7 +7,7 @@ // of bridges is very small, see if we can still use that to make a // low-confidence value. -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; use tor_proto::ClockSkew; @@ -245,6 +245,7 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; use float_eq::assert_float_eq; + use web_time_compat::InstantExt; /// Tolerance for float comparison. const TOL: f64 = 0.00001; @@ -327,7 +328,7 @@ mod test { #[test] fn estimate_with_no_data() { // zero inputs -> output is none. - let now = Instant::now(); + let now = Instant::get(); let est = SkewEstimate::estimate_skew([].iter(), now); assert!(est.is_none()); @@ -365,7 +366,7 @@ mod test { mins.iter() .map(|m| SkewObservation { skew: ClockSkew::from_secs_f64(m * 60.0).unwrap(), - when: Instant::now(), + when: Instant::get(), }) .collect() } @@ -383,7 +384,7 @@ mod test { // confidence. let obs = from_minutes(&[-20.0, -10.0, -20.0, -25.0, 0.0, -18.0, -22.0, -22.0]); - let est = SkewEstimate::estimate_skew(obs.iter(), Instant::now()).unwrap(); + let est = SkewEstimate::estimate_skew(obs.iter(), Instant::get()).unwrap(); assert_eq!( est.to_string(), "slow by around 17m 7s (based on 8 recent observations, with some confidence)" @@ -401,7 +402,7 @@ mod test { -100.0, 100.0, -3.0, -2.0, 0.0, 1.0, 0.5, 6.0, 3.0, 0.5, 99.0, ]); - let est = SkewEstimate::estimate_skew(obs.iter(), Instant::now()).unwrap(); + let est = SkewEstimate::estimate_skew(obs.iter(), Instant::get()).unwrap(); assert_eq!( est.to_string(), "not skewed by more than 15m (based on 8 recent observations, with high confidence)" diff --git a/crates/tor-guardmgr/src/util.rs b/crates/tor-guardmgr/src/util.rs index bc27314fd..eea47b091 100644 --- a/crates/tor-guardmgr/src/util.rs +++ b/crates/tor-guardmgr/src/util.rs @@ -77,10 +77,11 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; use tor_basic_utils::test_rng::testing_rng; + use web_time_compat::SystemTimeExt; #[test] fn test_randomize_time() { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_hour = humantime::parse_duration("1hr").unwrap(); let ten_sec = humantime::parse_duration("10s").unwrap(); let mut rng = testing_rng(); diff --git a/crates/tor-hsclient/Cargo.toml b/crates/tor-hsclient/Cargo.toml index 354e48673..cb6542792 100644 --- a/crates/tor-hsclient/Cargo.toml +++ b/crates/tor-hsclient/Cargo.toml @@ -90,6 +90,7 @@ tor-proto = { version = "0.40.0", path = "../tor-proto", features = ["hs-client" tor-protover = { version = "0.40.0", path = "../tor-protover" } tor-rtcompat = { version = "0.40.0", path = "../tor-rtcompat" } tracing = "0.1.36" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] humantime = "2" diff --git a/crates/tor-hsclient/src/connect.rs b/crates/tor-hsclient/src/connect.rs index 11b4f14e4..c547343d2 100644 --- a/crates/tor-hsclient/src/connect.rs +++ b/crates/tor-hsclient/src/connect.rs @@ -1,12 +1,9 @@ //! Main implementation of the connection functionality -use std::time::Duration; - use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::Arc; -use std::time::Instant; use async_trait::async_trait; use educe::Educe; @@ -27,6 +24,7 @@ use tor_hscrypto::Subcredential; use tor_proto::TargetHop; use tor_proto::client::circuit::handshake::hs_ntor; use tracing::{debug, instrument, trace}; +use web_time_compat::{Duration, Instant}; use retry_error::RetryError; use safelog::{DispRedacted, Sensitive}; diff --git a/crates/tor-hsclient/src/pow/v1.rs b/crates/tor-hsclient/src/pow/v1.rs index 9993442cc..1b8a6b5ba 100644 --- a/crates/tor-hsclient/src/pow/v1.rs +++ b/crates/tor-hsclient/src/pow/v1.rs @@ -1,7 +1,6 @@ //! Client support for the `v1` onion service proof of work scheme use crate::err::ProofOfWorkError; -use std::time::Instant; use tor_async_utils::oneshot; use tor_async_utils::oneshot::Canceled; use tor_cell::relaycell::hs::pow::v1::ProofOfWorkV1; @@ -10,6 +9,7 @@ use tor_hscrypto::pk::HsBlindId; use tor_hscrypto::pow::v1::{Effort, Instance, SolverInput}; use tor_netdoc::doc::hsdesc::pow::v1::PowParamsV1; use tracing::debug; +use web_time_compat::{Instant, InstantExt}; /// Double effort at retry until this threshold. /// @@ -93,7 +93,7 @@ impl HsPowClientV1 { // TODO: config option input.runtime(Default::default()); - let start_time = Instant::now(); + let start_time = Instant::get(); debug!("beginning solve, {:?}", self.effort); let (result_sender, result_receiver) = oneshot::channel(); diff --git a/crates/tor-hsclient/src/state.rs b/crates/tor-hsclient/src/state.rs index b3fc983d2..239613287 100644 --- a/crates/tor-hsclient/src/state.rs +++ b/crates/tor-hsclient/src/state.rs @@ -5,7 +5,6 @@ use std::fmt::Debug; use std::mem; use std::panic::AssertUnwindSafe; use std::sync::{Arc, Mutex, MutexGuard}; -use std::time::{Duration, Instant}; use futures::FutureExt as _; use futures::task::SpawnError; @@ -23,6 +22,7 @@ use tor_error::{Bug, ErrorReport as _, debug_report, error_report, internal}; use tor_hscrypto::pk::HsId; use tor_netdir::NetDir; use tor_rtcompat::{Runtime, SpawnExt as _}; +use web_time_compat::{Duration, Instant}; use crate::isol_map; use crate::{ConnError, HsClientConnector, HsClientSecretKeys}; diff --git a/crates/tor-hscrypto/Cargo.toml b/crates/tor-hscrypto/Cargo.toml index d2cf0160b..05c2b020b 100644 --- a/crates/tor-hscrypto/Cargo.toml +++ b/crates/tor-hscrypto/Cargo.toml @@ -67,6 +67,7 @@ tor-llcrypto = { version = "0.40.0", path = "../tor-llcrypto", features = ["hsv3 tor-memquota = { version = "0.40.0", path = "../tor-memquota", default-features = false, optional = true } tor-units = { path = "../tor-units", version = "0.40.0" } void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } zeroize = { version = "1", optional = true } [dev-dependencies] diff --git a/crates/tor-hscrypto/src/pk.rs b/crates/tor-hscrypto/src/pk.rs index 4a56a004e..ba9e4d39a 100644 --- a/crates/tor-hscrypto/src/pk.rs +++ b/crates/tor-hscrypto/src/pk.rs @@ -818,8 +818,8 @@ mod test { use hex_literal::hex; use itertools::izip; - use std::time::{Duration, SystemTime}; use tor_basic_utils::test_rng::testing_rng; + use web_time_compat::{Duration, SystemTime, SystemTimeExt}; use super::*; @@ -872,7 +872,7 @@ mod test { fn key_blinding_blackbox() { let mut rng = testing_rng(); let offset = Duration::new(12 * 60 * 60, 0); - let when = TimePeriod::new(Duration::from_secs(3600), SystemTime::now(), offset).unwrap(); + let when = TimePeriod::new(Duration::from_secs(3600), SystemTime::get(), offset).unwrap(); let keypair = ed25519::Keypair::generate(&mut rng); let id_pub = HsIdKey::from(keypair.verifying_key()); let id_keypair = HsIdKeypair::from(ed25519::ExpandedKeypair::from(&keypair)); diff --git a/crates/tor-hscrypto/src/time.rs b/crates/tor-hscrypto/src/time.rs index a4d7ea831..e70c2f667 100644 --- a/crates/tor-hscrypto/src/time.rs +++ b/crates/tor-hscrypto/src/time.rs @@ -1,12 +1,10 @@ //! Manipulate time periods (as used in the onion service system) -use std::{ - fmt::Display, - time::{Duration, SystemTime}, -}; +use std::fmt::Display; use humantime::format_rfc3339_seconds; use tor_units::IntegerMinutes; +use web_time_compat::{Duration, SystemTime}; use serde::{Deserialize, Serialize}; diff --git a/crates/tor-hsservice/Cargo.toml b/crates/tor-hsservice/Cargo.toml index bf200636b..e9a4ff0f5 100644 --- a/crates/tor-hsservice/Cargo.toml +++ b/crates/tor-hsservice/Cargo.toml @@ -140,6 +140,7 @@ tor-relay-selection = { path = "../tor-relay-selection", version = "0.40.0" } tor-rtcompat = { version = "0.40.0", path = "../tor-rtcompat" } tracing = "0.1.36" void = "1" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] libc = { version = "0.2", default-features = false } diff --git a/crates/tor-hsservice/src/internal_prelude.rs b/crates/tor-hsservice/src/internal_prelude.rs index ed17f48bd..f3e3f77c9 100644 --- a/crates/tor-hsservice/src/internal_prelude.rs +++ b/crates/tor-hsservice/src/internal_prelude.rs @@ -37,7 +37,6 @@ pub(crate) use { std::path::{Path, PathBuf}, std::str::FromStr, std::sync::{Arc, Mutex, MutexGuard}, - std::time::{Duration, Instant, SystemTime}, }; //---------- upstreams ---------- @@ -110,6 +109,7 @@ pub(crate) use { tor_proto::client::stream::DataStream, tor_rtcompat::SleepProvider, tor_rtcompat::{Runtime, SleepProviderExt as _}, + web_time_compat::{Duration, Instant, SystemTime}, }; //---------- names from this crate ---------- diff --git a/crates/tor-hsservice/src/pow/v1.rs b/crates/tor-hsservice/src/pow/v1.rs index e791f0bb5..b92972491 100644 --- a/crates/tor-hsservice/src/pow/v1.rs +++ b/crates/tor-hsservice/src/pow/v1.rs @@ -8,7 +8,6 @@ use std::{ collections::{BTreeSet, HashMap, VecDeque}, sync::{Arc, Mutex, RwLock}, task::Waker, - time::{Duration, Instant, SystemTime}, }; use arrayvec::ArrayVec; @@ -39,6 +38,7 @@ use tor_persist::{ }; use tor_rtcompat::Runtime; use tor_rtcompat::SpawnExt; +use web_time_compat::{Duration, Instant, InstantExt, SystemTime, SystemTimeExt}; use crate::{ BlindIdPublicKeySpecifier, OnionServiceConfig, RendRequest, ReplayError, StartupError, @@ -426,7 +426,7 @@ impl<R: Runtime, Q: MockableRendRequest + Send + 'static> PowManagerGeneric<R, Q .checked_sub(SEED_EARLY_ROTATION_TIME) .expect("SEED_EARLY_ROTATION_TIME too high, or EXPIRATION_TIME_MINS_MIN too low."); let delay = next_update_time - .map(|x| x.duration_since(SystemTime::now()).unwrap_or(MAX_DELAY)) + .map(|x| x.duration_since(SystemTime::get()).unwrap_or(MAX_DELAY)) .unwrap_or(MAX_DELAY) .min(MAX_DELAY) .min(suggested_effort_update_delay); @@ -439,7 +439,7 @@ impl<R: Runtime, Q: MockableRendRequest + Send + 'static> PowManagerGeneric<R, Q /// Make a randomized seed expiration time. fn make_next_expiration_time<Rng: RngCore + CryptoRng>(rng: &mut Rng) -> SystemTime { - SystemTime::now() + SystemTime::get() + Duration::from_secs( 60 * rng .gen_range_checked(EXPIRATION_TIME_MINS_MIN..=EXPIRATION_TIME_MINS_MAX) @@ -519,7 +519,7 @@ impl<R: Runtime, Q: MockableRendRequest + Send + 'static> PowManagerGeneric<R, Q let rotation_time = Self::calculate_early_rotation_time(info.next_expiration_time); update_times.push(rotation_time); - if rotation_time <= SystemTime::now() { + if rotation_time <= SystemTime::get() { // This does not allow for easy testing, but because we're in a async function, it's // non-trivial to pass in a Rng from the outside world. If we end up writing tests that // require that, we can take a function to generate a Rng, but for now, just using the @@ -774,7 +774,7 @@ impl<Q: MockableRendRequest> RendRequestOrdByEffort<Q> { request, pow, max_effort, - recv_time: Instant::now(), + recv_time: Instant::get(), request_num, }) } diff --git a/crates/tor-hsservice/src/publish.rs b/crates/tor-hsservice/src/publish.rs index bb0040316..2ee1b9a56 100644 --- a/crates/tor-hsservice/src/publish.rs +++ b/crates/tor-hsservice/src/publish.rs @@ -169,7 +169,6 @@ mod test { use std::sync::Mutex; use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::{Context, Poll}; - use std::time::Duration; use async_trait::async_trait; use fs_mistrust::Mistrust; diff --git a/crates/tor-hsservice/src/publish/reupload_timer.rs b/crates/tor-hsservice/src/publish/reupload_timer.rs index 565895d9f..60c2a7e79 100644 --- a/crates/tor-hsservice/src/publish/reupload_timer.rs +++ b/crates/tor-hsservice/src/publish/reupload_timer.rs @@ -53,15 +53,15 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use std::collections::BinaryHeap; - use std::time::Duration; use super::*; + use web_time_compat::InstantExt; #[test] fn reupload_for_time_period_ordering() { const ONE_SEC: Duration = Duration::from_secs(1); - let now = Instant::now(); + let now = Instant::get(); let later = now + ONE_SEC; let later_still = now + ONE_SEC * 2; let timer1 = ReuploadTimer { diff --git a/crates/tor-hsservice/src/rend_handshake.rs b/crates/tor-hsservice/src/rend_handshake.rs index ea1599b6c..c4e6f9141 100644 --- a/crates/tor-hsservice/src/rend_handshake.rs +++ b/crates/tor-hsservice/src/rend_handshake.rs @@ -176,10 +176,10 @@ pub(crate) trait RendCircConnector: Send + Sync { /// Return the current time instant from the runtime. /// /// This provides mockable time for use in error tracking. - fn now(&self) -> std::time::Instant; + fn now(&self) -> Instant; /// Return the current wall-clock time from the runtime. - fn wallclock(&self) -> std::time::SystemTime; + fn wallclock(&self) -> SystemTime; } #[async_trait] @@ -192,11 +192,11 @@ impl<R: Runtime> RendCircConnector for HsCircPool<R> { HsCircPool::get_or_launch_svc_rend(self, netdir, target).await } - fn now(&self) -> std::time::Instant { + fn now(&self) -> Instant { HsCircPool::now(self) } - fn wallclock(&self) -> std::time::SystemTime { + fn wallclock(&self) -> SystemTime { HsCircPool::wallclock(self) } } diff --git a/crates/tor-hsservice/src/time_store.rs b/crates/tor-hsservice/src/time_store.rs index 54be02664..cf3e247bf 100644 --- a/crates/tor-hsservice/src/time_store.rs +++ b/crates/tor-hsservice/src/time_store.rs @@ -26,8 +26,8 @@ //! //! ``` //! use serde::{Serialize, Deserialize}; -//! use std::time::{Duration, Instant}; //! use tor_rtcompat::{PreferredRuntime, SleepProvider as _}; +//! use web_time_compat::{Duration, Instant}; //! //! # use tor_hsservice::time_store_for_doctests_unstable_no_semver_guarantees as time_store; //! # #[cfg(all)] // works like #[cfg(FALSE)]. Instead, we have this workaround ^. @@ -80,7 +80,7 @@ use std::fmt::{self, Display}; use std::str::FromStr; -use std::time::{Duration, Instant, SystemTime}; +use web_time_compat::{Duration, Instant, SystemTime}; use derive_deftly::{Deftly, define_derive_deftly}; use serde::{Deserialize, Serialize}; @@ -492,6 +492,7 @@ mod test { use humantime::parse_rfc3339; use itertools::{Itertools, chain}; use tor_rtmock::{MockRuntime, simple_time::SimpleMockTimeProvider}; + use web_time_compat::InstantExt; fn secs(s: u64) -> Duration { Duration::from_secs(s) @@ -561,7 +562,7 @@ mod test { s2: FutureTimestamp, } - let real_instant = Instant::now(); + let real_instant = Instant::get(); let test_systime = parse_rfc3339("2008-08-02T00:00:00Z").unwrap(); let mk_runtime = |instant, systime| { diff --git a/crates/tor-hsservice/src/timeout_track.rs b/crates/tor-hsservice/src/timeout_track.rs index f6fd2ab2f..65a747dd7 100644 --- a/crates/tor-hsservice/src/timeout_track.rs +++ b/crates/tor-hsservice/src/timeout_track.rs @@ -147,7 +147,7 @@ use std::cell::Cell; use std::cmp::Ordering; -use std::time::{Duration, Instant, SystemTime}; +use web_time_compat::{Duration, Instant, SystemTime}; use derive_deftly::{Deftly, define_derive_deftly}; use futures::{FutureExt as _, future, select_biased}; @@ -634,6 +634,7 @@ mod test { use std::task::Poll; use tor_rtcompat::ToplevelBlockOn; use tor_rtmock::MockRuntime; + use web_time_compat::InstantExt; fn parse_rfc3339(s: &str) -> SystemTime { humantime::parse_rfc3339(s).unwrap() @@ -715,7 +716,7 @@ mod test { #[test] fn arith_instant_combined() { // Adding 1Ms gives us some headroom, since we don't want to underflow - let earliest = Instant::now() + secs(1000000); + let earliest = Instant::get() + secs(1000000); let middle_d = secs(200); let middle = earliest + middle_d; let later_d = secs(300); diff --git a/crates/tor-keymgr/Cargo.toml b/crates/tor-keymgr/Cargo.toml index 3afa474ac..909dd51b5 100644 --- a/crates/tor-keymgr/Cargo.toml +++ b/crates/tor-keymgr/Cargo.toml @@ -83,6 +83,7 @@ tor-persist = { path = "../tor-persist", version = "0.40.0" } tracing = "0.1.36" visibility = { version = "0.1.0" } walkdir = { version = "2" } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } zeroize = "1" [dev-dependencies] diff --git a/crates/tor-keymgr/src/keystore/arti.rs b/crates/tor-keymgr/src/keystore/arti.rs index 354561545..8afbc739f 100644 --- a/crates/tor-keymgr/src/keystore/arti.rs +++ b/crates/tor-keymgr/src/keystore/arti.rs @@ -421,12 +421,12 @@ mod tests { use std::cmp::Ordering; use std::fs; use std::path::PathBuf; - use std::time::{Duration, SystemTime}; use tempfile::{TempDir, tempdir}; use tor_cert::{CertifiedKey, Ed25519Cert}; use tor_checkable::{SelfSigned, Timebound}; use tor_key_forge::{CertType, KeyType, ParsedEd25519Cert}; use tor_llcrypto::pk::ed25519::{self, Ed25519PublicKey as _}; + use web_time_compat::{Duration, SystemTime}; #[cfg(unix)] use std::os::unix::fs::PermissionsExt; diff --git a/crates/tor-keymgr/src/mgr.rs b/crates/tor-keymgr/src/mgr.rs index 66933e4bb..26473dc06 100644 --- a/crates/tor-keymgr/src/mgr.rs +++ b/crates/tor-keymgr/src/mgr.rs @@ -859,7 +859,6 @@ mod tests { use std::result::Result as StdResult; use std::str::FromStr; use std::sync::{Arc, RwLock}; - use std::time::{Duration, SystemTime}; use tor_basic_utils::test_rng::testing_rng; use tor_cert::CertifiedKey; use tor_cert::Ed25519Cert; @@ -871,6 +870,7 @@ mod tests { }; use tor_llcrypto::pk::ed25519::{self, Ed25519PublicKey as _}; use tor_llcrypto::rng::FakeEntropicRng; + use web_time_compat::{Duration, SystemTime, SystemTimeExt}; #[cfg(feature = "experimental-api")] use { @@ -2079,7 +2079,7 @@ mod tests { let keypair = ed25519::Keypair::generate(&mut rng); let encoded_cert = Ed25519Cert::constructor() .cert_type(tor_cert::CertType::IDENTITY_V_SIGNING) - .expiration(SystemTime::now() + Duration::from_secs(180)) + .expiration(SystemTime::get() + Duration::from_secs(180)) .signing_key(keypair.public_key().into()) .cert_key(CertifiedKey::Ed25519(keypair.public_key().into())) .encode_and_sign(&keypair) diff --git a/crates/tor-log-ratelim/Cargo.toml b/crates/tor-log-ratelim/Cargo.toml index 95e41e6f3..539190d3c 100644 --- a/crates/tor-log-ratelim/Cargo.toml +++ b/crates/tor-log-ratelim/Cargo.toml @@ -25,6 +25,7 @@ tor-error = { path = "../tor-error", version = "0.40.0" } tor-rtcompat = { path = "../tor-rtcompat", version = "0.40.0" } tracing = "0.1.36" weak-table = "0.3.0" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] diff --git a/crates/tor-log-ratelim/src/ratelim.rs b/crates/tor-log-ratelim/src/ratelim.rs index 5a05db325..525a88575 100644 --- a/crates/tor-log-ratelim/src/ratelim.rs +++ b/crates/tor-log-ratelim/src/ratelim.rs @@ -14,7 +14,7 @@ use tor_rtcompat::SpawnExt as _; pub(crate) mod rt { use futures::{future::BoxFuture, task::Spawn}; use std::sync::OnceLock; - use std::time::{Duration, Instant}; + use web_time_compat::{Duration, Instant}; /// A dyn-safe view of the parts of an async runtime that we need for rate-limiting. pub trait RuntimeSupport: Spawn + 'static + Sync + Send { diff --git a/crates/tor-netdir/Cargo.toml b/crates/tor-netdir/Cargo.toml index 4d41c2e5f..5d0817ed1 100644 --- a/crates/tor-netdir/Cargo.toml +++ b/crates/tor-netdir/Cargo.toml @@ -82,6 +82,7 @@ tor-units = { path = "../tor-units", version = "0.40.0" } tracing = "0.1.36" typed-index-collections = "3.2.3" visibility = { version = "0.1.0", optional = true } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] float_eq = "1.0.0" diff --git a/crates/tor-netdir/src/testnet.rs b/crates/tor-netdir/src/testnet.rs index fdea84985..d928e702d 100644 --- a/crates/tor-netdir/src/testnet.rs +++ b/crates/tor-netdir/src/testnet.rs @@ -15,7 +15,6 @@ use crate::{MdReceiver, PartialNetDir}; use std::iter; use std::net::SocketAddr; -use std::time::{Duration, SystemTime}; #[cfg(feature = "geoip")] use tor_geoip::GeoipDb; use tor_netdoc::doc::microdesc::{Microdesc, MicrodescBuilder}; @@ -23,6 +22,7 @@ use tor_netdoc::doc::netstatus::{Lifetime, MdRouterStatusBuilder, RelayWeight}; use tor_netdoc::doc::netstatus::{MdConsensus, MdConsensusBuilder}; use tor_netdoc::types::relay_flags::RelayFlag; pub use tor_netdoc::{BuildError, BuildResult}; +use web_time_compat::{Duration, SystemTime, SystemTimeExt}; /// A set of builder objects for a single node. #[derive(Debug, Clone)] @@ -201,7 +201,7 @@ where ]; let lifetime = lifetime.map(Ok).unwrap_or_else(|| { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_day = Duration::new(86400, 0); Lifetime::new(now, now + one_day / 2, now + one_day) diff --git a/crates/tor-netdir/src/weight.rs b/crates/tor-netdir/src/weight.rs index 8acceb8fa..d47e34fd2 100644 --- a/crates/tor-netdir/src/weight.rs +++ b/crates/tor-netdir/src/weight.rs @@ -427,6 +427,7 @@ mod test { use tor_basic_utils::test_rng::testing_rng; use tor_netdoc::doc::netstatus::{Lifetime, MdRouterStatusBuilder}; use tor_netdoc::types::relay_flags::{RelayFlag, RelayFlags}; + use web_time_compat::SystemTimeExt; #[test] fn t_clamp() { @@ -642,7 +643,7 @@ mod test { #[test] fn weightset_from_consensus() { use rand::Rng; - let now = SystemTime::now(); + let now = SystemTime::get(); let one_hour = Duration::new(3600, 0); let mut rng = testing_rng(); let mut bld = MdConsensus::builder(); diff --git a/crates/tor-netdoc/Cargo.toml b/crates/tor-netdoc/Cargo.toml index 0430e50b6..1a31c5a4e 100644 --- a/crates/tor-netdoc/Cargo.toml +++ b/crates/tor-netdoc/Cargo.toml @@ -137,6 +137,7 @@ tor-units = { version = "0.40.0", path = "../tor-units", optional = true } visibility = { version = "0.1.0", optional = true } visible = { version = "0.0.1", optional = true } void = "1" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } zeroize = "1" [dev-dependencies] diff --git a/crates/tor-netdoc/src/doc/authcert/build.rs b/crates/tor-netdoc/src/doc/authcert/build.rs index 234bf350a..8383e72ef 100644 --- a/crates/tor-netdoc/src/doc/authcert/build.rs +++ b/crates/tor-netdoc/src/doc/authcert/build.rs @@ -152,6 +152,7 @@ mod test { use super::*; use hex_literal::hex; use std::time::Duration; + use web_time_compat::SystemTimeExt; fn rsa1() -> rsa::PublicKey { let der = hex!( @@ -169,7 +170,7 @@ mod test { #[test] fn simple_cert() { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_hour = Duration::new(3600, 0); let later = now + one_hour * 2; let addr = "192.0.0.1:9090".parse().unwrap(); @@ -189,7 +190,7 @@ mod test { #[test] fn failing_cert() { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_hour = Duration::new(3600, 0); let later = now + one_hour * 2; diff --git a/crates/tor-netdoc/src/doc/hsdesc/build.rs b/crates/tor-netdoc/src/doc/hsdesc/build.rs index 86304f55c..431ce2fb7 100644 --- a/crates/tor-netdoc/src/doc/hsdesc/build.rs +++ b/crates/tor-netdoc/src/doc/hsdesc/build.rs @@ -320,6 +320,7 @@ mod test { use tor_hscrypto::time::TimePeriod; use tor_linkspec::LinkSpec; use tor_llcrypto::pk::{curve25519, ed25519::ExpandedKeypair}; + use web_time_compat::SystemTimeExt; // TODO: move the test helpers to a separate module and make them more broadly available if // necessary. @@ -410,7 +411,7 @@ mod test { .compute_blinded_key(period) .unwrap(); - let expiry = SystemTime::now() + Duration::from_secs(CERT_EXPIRY_SECS); + let expiry = SystemTime::get() + Duration::from_secs(CERT_EXPIRY_SECS); let mut rng = Config::Deterministic.into_rng(); let intro_points = vec![IntroPointDesc { link_specifiers: vec![ diff --git a/crates/tor-netdoc/src/doc/netstatus/build/each_flavor.rs b/crates/tor-netdoc/src/doc/netstatus/build/each_flavor.rs index a628b331d..2523d4ac2 100644 --- a/crates/tor-netdoc/src/doc/netstatus/build/each_flavor.rs +++ b/crates/tor-netdoc/src/doc/netstatus/build/each_flavor.rs @@ -416,11 +416,11 @@ mod test { use crate::types::relay_flags::RelayFlag; use std::net::SocketAddr; - use std::time::{Duration, SystemTime}; + use web_time_compat::{Duration, SystemTime, SystemTimeExt}; #[test] fn consensus() { - let now = SystemTime::now(); + let now = SystemTime::get(); let one_hour = Duration::new(3600, 0); let mut builder = crate::doc::netstatus::MdConsensus::builder(); diff --git a/crates/tor-persist/Cargo.toml b/crates/tor-persist/Cargo.toml index fbdffa151..733fcbcb0 100644 --- a/crates/tor-persist/Cargo.toml +++ b/crates/tor-persist/Cargo.toml @@ -51,6 +51,7 @@ tor-basic-utils = { path = "../tor-basic-utils", version = "0.40.0" } tor-error = { path = "../tor-error", version = "0.40.0", features = ["tracing"] } tracing = "0.1.36" void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] anyhow = { version = "1.0.23" } diff --git a/crates/tor-persist/src/fs.rs b/crates/tor-persist/src/fs.rs index 1e46abda2..c70cff429 100644 --- a/crates/tor-persist/src/fs.rs +++ b/crates/tor-persist/src/fs.rs @@ -14,9 +14,9 @@ use oneshot_fused_workaround as oneshot; use serde::{Serialize, de::DeserializeOwned}; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; -use std::time::SystemTime; use tor_error::warn_report; use tracing::info; +use web_time_compat::{SystemTime, SystemTimeExt}; /// Implementation of StateMgr that stores state as JSON files on disk. /// @@ -223,7 +223,7 @@ impl StateMgr for FsStateMgr { .try_lock() .map_err(|e| Error::new(e, Action::Locking, self.err_resource_lock()))? { - self.clean(SystemTime::now()); + self.clean(SystemTime::get()); Ok(LockStatus::NewlyAcquired) } else { Ok(LockStatus::NoLock) @@ -341,7 +341,7 @@ mod test { assert_eq!(count, 3); // two files, one lock. // Now we can make sure that "clean" actually removes the right file. - store.clean(SystemTime::now() + Duration::from_secs(365 * 86400)); + store.clean(SystemTime::get() + Duration::from_secs(365 * 86400)); let lst: Vec<_> = statedir.read_dir().unwrap().collect(); assert_eq!(lst.len(), 2); // one file, one lock. assert!( @@ -374,7 +374,7 @@ mod test { // Make the store directory read-only and make sure that we can't delete from it. std::fs::set_permissions(&statedir, ro_dir).unwrap(); - store.clean(SystemTime::now() + Duration::from_secs(365 * 86400)); + store.clean(SystemTime::get() + Duration::from_secs(365 * 86400)); let lst: Vec<_> = statedir.read_dir().unwrap().collect(); if lst.len() == 2 { // We must be root. Don't do any more tests here. diff --git a/crates/tor-persist/src/fs/clean.rs b/crates/tor-persist/src/fs/clean.rs index 887cb1dc3..103a07261 100644 --- a/crates/tor-persist/src/fs/clean.rs +++ b/crates/tor-persist/src/fs/clean.rs @@ -1,14 +1,12 @@ //! Code to remove obsolete and extraneous files from a filesystem-based state //! directory. -use std::{ - path::{Path, PathBuf}, - time::{Duration, SystemTime}, -}; +use std::path::{Path, PathBuf}; use tor_basic_utils::PathExt as _; use tor_error::warn_report; use tracing::warn; +use web_time_compat::{Duration, SystemTime}; /// Return true if `path` looks like a filename we'd like to remove from our /// state directory. @@ -114,6 +112,7 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; + use web_time_compat::SystemTimeExt; #[test] fn fnames() { @@ -135,7 +134,7 @@ mod test { let dir = tempfile::TempDir::new().unwrap(); let fname1 = dir.path().join("quokka"); - let now = SystemTime::now(); + let now = SystemTime::get(); std::fs::write(fname1, "hello world").unwrap(); let mut r = std::fs::read_dir(dir.path()).unwrap(); @@ -147,7 +146,7 @@ mod test { #[test] fn list() { let dir = tempfile::TempDir::new().unwrap(); - let now = SystemTime::now(); + let now = SystemTime::get(); let fname1 = dir.path().join("quokka.toml"); std::fs::write(fname1, "hello world").unwrap(); @@ -171,7 +170,7 @@ mod test { fn absent() { let dir = tempfile::TempDir::new().unwrap(); let dir2 = dir.path().join("subdir_that_doesnt_exist"); - let r = files_to_delete(&dir2, SystemTime::now()); + let r = files_to_delete(&dir2, SystemTime::get()); assert!(r.is_empty()); } } diff --git a/crates/tor-persist/src/slug/timestamp.rs b/crates/tor-persist/src/slug/timestamp.rs index 502efade0..079d3e79f 100644 --- a/crates/tor-persist/src/slug/timestamp.rs +++ b/crates/tor-persist/src/slug/timestamp.rs @@ -4,7 +4,6 @@ use crate::slug::{BadSlug, Slug}; use std::fmt; use std::str::FromStr; -use std::time::SystemTime; use derive_more::{From, Into}; use thiserror::Error; @@ -12,6 +11,7 @@ use time::format_description::FormatItem; use time::macros::format_description; use time::{OffsetDateTime, PrimitiveDateTime}; use tor_error::{Bug, into_internal}; +use web_time_compat::SystemTime; /// A UTC timestamp that can be encoded in ISO 8601 format, /// and that can be used as a `Slug`. diff --git a/crates/tor-persist/src/state_dir.rs b/crates/tor-persist/src/state_dir.rs index 5fa099655..61069fb4c 100644 --- a/crates/tor-persist/src/state_dir.rs +++ b/crates/tor-persist/src/state_dir.rs @@ -70,6 +70,7 @@ //! use tor_persist::state_dir; //! use state_dir::{InstanceIdentity, InstancePurgeHandler}; //! use state_dir::{InstancePurgeInfo, InstanceStateHandle, StateDirectory, StorageHandle}; +//! use web_time_compat::SystemTimeExt; //! # //! # // fake up some things; we do this rather than using real ones //! # // since this example will move, with the module, to a lower level crate. @@ -134,7 +135,7 @@ //! retain_for: Duration, //! ) -> Result<(), Error> { //! state_dir.purge_instances( -//! SystemTime::now(), +//! SystemTime::get(), //! &mut PurgeHandler(currently_configured_nicks, retain_for), //! )?; //! Ok(()) @@ -174,7 +175,7 @@ use std::io; use std::marker::PhantomData; use std::path::Path; use std::sync::Arc; -use std::time::{Duration, SystemTime}; +use web_time_compat::{Duration, SystemTime, SystemTimeExt}; use derive_deftly::{Deftly, define_derive_deftly}; use derive_more::{AsRef, Deref}; @@ -1013,7 +1014,8 @@ fn touch_instance_dir(dir: &CheckedDir) -> Result<()> { let dir = dir.as_path(); let resource = || Resource::Directory { dir: dir.into() }; - filetime::set_file_mtime(dir, filetime::FileTime::now()) + let mtime = filetime::FileTime::from_system_time(SystemTime::get()); + filetime::set_file_mtime(dir, mtime) .map_err(|source| Error::new(source, Action::Initializing, resource())) } @@ -1137,6 +1139,7 @@ mod test { use tor_basic_utils::PathExt as _; use tor_error::HasKind as _; use tracing_test::traced_test; + use web_time_compat::SystemTimeExt; use tor_error::ErrorKind as TEK; @@ -1147,7 +1150,7 @@ mod test { } fn now() -> SystemTime { - SystemTime::now() + SystemTime::get() } struct Garlic(Slug); diff --git a/crates/tor-proto/Cargo.toml b/crates/tor-proto/Cargo.toml index 28f528de2..e44d6ae93 100644 --- a/crates/tor-proto/Cargo.toml +++ b/crates/tor-proto/Cargo.toml @@ -143,6 +143,7 @@ tracing = "0.1.36" typenum = "1.12" visibility = { version = "0.1.0" } void = "1" +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } zeroize = "1" [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dev-dependencies] diff --git a/crates/tor-proto/src/channel/handshake.rs b/crates/tor-proto/src/channel/handshake.rs index 3c95cb036..f805ac346 100644 --- a/crates/tor-proto/src/channel/handshake.rs +++ b/crates/tor-proto/src/channel/handshake.rs @@ -5,7 +5,6 @@ use futures::sink::SinkExt; use futures::stream::{Stream, StreamExt}; use std::net::IpAddr; use std::sync::Arc; -use std::time::SystemTime; use tor_llcrypto::pk::ValidatableSignature; use crate::channel::{Canonicity, ChannelFrame, UniqId}; @@ -26,6 +25,7 @@ use tor_linkspec::{ use tor_llcrypto as ll; use tor_llcrypto::pk::ed25519::Ed25519Identity; use tor_rtcompat::{CoarseTimeProvider, SleepProvider, StreamOps}; +use web_time_compat::{SystemTime, SystemTimeExt}; use digest::Digest; @@ -656,7 +656,7 @@ impl< use tor_cert::CertType; // Replace 'now' with the real time to use. - let now = now.unwrap_or_else(SystemTime::now); + let now = now.unwrap_or_else(SystemTime::get); // We are a client initiating a channel to a relay or a bridge. We have received a CERTS // cell and we need to verify these certs: @@ -732,7 +732,7 @@ pub(crate) fn verify_link_auth_cert( use tor_cert::CertType; // Replace 'now' with the real time to use. - let now = now.unwrap_or_else(SystemTime::now); + let now = now.unwrap_or_else(SystemTime::get); // Now look at the signing->TLS cert and check it against the // peer certificate. @@ -956,7 +956,7 @@ pub(super) mod test { { let mb = MsgBuf::new(input); let handshake = ClientInitiatorHandshake::new(mb, None, sleep_prov, fake_mq()); - handshake.connect(SystemTime::now).await.err().unwrap() + handshake.connect(SystemTime::get).await.err().unwrap() } #[test] diff --git a/crates/tor-proto/src/channel/padding.rs b/crates/tor-proto/src/channel/padding.rs index 7d2af56ce..dc3d40b17 100644 --- a/crates/tor-proto/src/channel/padding.rs +++ b/crates/tor-proto/src/channel/padding.rs @@ -29,7 +29,7 @@ use std::pin::Pin; // TODO, coarsetime maybe? But see arti#496 and also we want to use the mockable SleepProvider -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; use derive_builder::Builder; use educe::Educe; @@ -400,7 +400,7 @@ impl<R: SleepProvider> Timer<R> { self.as_mut().select_fresh_timeout(); // Bet that we will be going to sleep again, and set up the new trigger time - // and waker now. This will save us a future call to Instant::now. + // and waker now. This will save us a future call to Instant::get. self.as_mut().prepare_to_sleep(Some(now)); Padding::new() diff --git a/crates/tor-proto/src/circuit/circhop.rs b/crates/tor-proto/src/circuit/circhop.rs index 13680c0ad..98e87c748 100644 --- a/crates/tor-proto/src/circuit/circhop.rs +++ b/crates/tor-proto/src/circuit/circhop.rs @@ -39,7 +39,7 @@ use std::num::NonZeroU32; use std::pin::Pin; use std::result::Result as StdResult; use std::sync::{Arc, Mutex}; -use std::time::Instant; +use web_time_compat::Instant; #[cfg(test)] use tor_cell::relaycell::msg::SendmeTag; diff --git a/crates/tor-proto/src/client.rs b/crates/tor-proto/src/client.rs index 89ab120ef..da3b30dc8 100644 --- a/crates/tor-proto/src/client.rs +++ b/crates/tor-proto/src/client.rs @@ -198,7 +198,7 @@ impl ClientTunnel { /// NOTE that the Instant returned by this method is not affected by /// any runtime mocking; it is the output of an ordinary call to /// `Instant::now()`. - pub async fn disused_since(&self) -> Result<Option<std::time::Instant>> { + pub async fn disused_since(&self) -> Result<Option<web_time_compat::Instant>> { self.circ.disused_since().await } diff --git a/crates/tor-proto/src/client/channel/handshake.rs b/crates/tor-proto/src/client/channel/handshake.rs index 48a594c45..a0130458e 100644 --- a/crates/tor-proto/src/client/channel/handshake.rs +++ b/crates/tor-proto/src/client/channel/handshake.rs @@ -93,7 +93,7 @@ impl< /// the relay's handshake information. /// /// Takes a function that reports the current time. In theory, this can just be - /// `SystemTime::now()`. + /// `SystemTime::get()`. #[instrument(skip_all, level = "trace")] pub async fn connect<F>(mut self, now_fn: F) -> Result<UnverifiedClientChannel<T, S>> where diff --git a/crates/tor-proto/src/client/circuit.rs b/crates/tor-proto/src/client/circuit.rs index bbd333b17..8ae369d2f 100644 --- a/crates/tor-proto/src/client/circuit.rs +++ b/crates/tor-proto/src/client/circuit.rs @@ -69,6 +69,7 @@ use tor_error::{bad_api_usage, internal, into_internal}; use tor_linkspec::{CircTarget, LinkSpecType, OwnedChanTarget, RelayIdType}; use tor_protover::named; use tor_rtcompat::DynTimeProvider; +use web_time_compat::Instant; use crate::circuit::UniqId; @@ -488,8 +489,8 @@ impl ClientCirc { /// /// NOTE that the Instant returned by this method is not affected by /// any runtime mocking; it is the output of an ordinary call to - /// `Instant::now()`. - pub async fn disused_since(&self) -> Result<Option<std::time::Instant>> { + /// `Instant::get()`. + pub async fn disused_since(&self) -> Result<Option<Instant>> { let (tx, rx) = oneshot::channel(); self.command .unbounded_send(CtrlCmd::GetTunnelActivity { sender: tx }) diff --git a/crates/tor-proto/src/client/circuit/padding/maybenot_padding.rs b/crates/tor-proto/src/client/circuit/padding/maybenot_padding.rs index 449ae8caf..c24a79154 100644 --- a/crates/tor-proto/src/client/circuit/padding/maybenot_padding.rs +++ b/crates/tor-proto/src/client/circuit/padding/maybenot_padding.rs @@ -31,7 +31,7 @@ use backend::PaddingBackend; /// The type of Instant that we'll use for our padding machines. /// /// We use a separate type alias here in case we want to move to coarsetime. -type Instant = std::time::Instant; +type Instant = web_time_compat::Instant; /// The type of Duration that we'll use for our padding machines. /// diff --git a/crates/tor-proto/src/client/circuit/padding/maybenot_padding/backend.rs b/crates/tor-proto/src/client/circuit/padding/maybenot_padding/backend.rs index 903db79ad..66b52793a 100644 --- a/crates/tor-proto/src/client/circuit/padding/maybenot_padding/backend.rs +++ b/crates/tor-proto/src/client/circuit/padding/maybenot_padding/backend.rs @@ -24,6 +24,7 @@ use std::{sync::Arc, task::Waker}; use maybenot::{MachineId, TriggerEvent}; use smallvec::SmallVec; +use web_time_compat::InstantExt; use super::{Bypass, Duration, Instant, PerHopPaddingEvent, PerHopPaddingEventVec, Replace}; @@ -341,7 +342,8 @@ impl<const N: usize> MaybenotPadder<N> { rules.machines.clone(), rules.max_outbound_padding_frac, rules.max_outbound_blocking_frac, - Instant::now(), + // TODO #2428 PADDING: We should be taking this from a SleepProvider! + Instant::get(), ThisThreadRng, )?; Ok(Self::from_framework(framework)) diff --git a/crates/tor-proto/src/client/reactor/circuit.rs b/crates/tor-proto/src/client/reactor/circuit.rs index 9bd4a7083..331e8ca02 100644 --- a/crates/tor-proto/src/client/reactor/circuit.rs +++ b/crates/tor-proto/src/client/reactor/circuit.rs @@ -52,6 +52,7 @@ use tor_error::{Bug, internal}; use tor_linkspec::RelayIds; use tor_llcrypto::pk; use tor_memquota::mq_queue::{ChannelSpec as _, MpscSpec}; +use web_time_compat::{Duration, Instant, SystemTime}; use futures::SinkExt as _; use oneshot_fused_workaround as oneshot; @@ -69,7 +70,6 @@ use std::borrow::Borrow; use std::pin::Pin; use std::result::Result as StdResult; use std::sync::Arc; -use std::time::{Duration, Instant, SystemTime}; use extender::HandshakeAuxDataHandler; diff --git a/crates/tor-proto/src/client/reactor/circuit/circhop.rs b/crates/tor-proto/src/client/reactor/circuit/circhop.rs index fc6b90404..d2b72a38d 100644 --- a/crates/tor-proto/src/client/reactor/circuit/circhop.rs +++ b/crates/tor-proto/src/client/reactor/circuit/circhop.rs @@ -27,6 +27,7 @@ use tor_cell::relaycell::{ AnyRelayMsgOuter, RelayCellDecoder, RelayCellDecoderResult, RelayCellFormat, StreamId, UnparsedRelayMsg, }; +use web_time_compat::Instant; use safelog::sensitive as sv; use tor_error::Bug; @@ -35,7 +36,6 @@ use tracing::instrument; use std::result::Result as StdResult; use std::sync::{Arc, Mutex, MutexGuard}; use std::task::Poll; -use std::time::Instant; #[cfg(test)] use tor_cell::relaycell::msg::SendmeTag; diff --git a/crates/tor-proto/src/congestion/rtt.rs b/crates/tor-proto/src/congestion/rtt.rs index 14b939f5b..ac04112f3 100644 --- a/crates/tor-proto/src/congestion/rtt.rs +++ b/crates/tor-proto/src/congestion/rtt.rs @@ -3,7 +3,7 @@ use std::cmp::{max, min}; use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; use super::params::RoundTripEstimatorParams; use super::{CongestionWindow, State}; @@ -269,7 +269,7 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> - use std::time::{Duration, Instant}; + use web_time_compat::{Duration, Instant, InstantExt}; use crate::congestion::test_utils::{new_cwnd, new_rtt_estimator}; @@ -333,7 +333,7 @@ mod test { #[test] fn test_vectors() { let mut rtt = new_rtt_estimator(); - let now = Instant::now(); + let now = Instant::get(); // from C-tor src/test/test_congestion_control.c let vectors = [ [100000, 200000, 124, 1, 100000, 100000, 100000], diff --git a/crates/tor-proto/src/congestion/vegas.rs b/crates/tor-proto/src/congestion/vegas.rs index 0ad46deef..e0f2af68a 100644 --- a/crates/tor-proto/src/congestion/vegas.rs +++ b/crates/tor-proto/src/congestion/vegas.rs @@ -343,11 +343,9 @@ pub(crate) mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> - use std::{ - collections::VecDeque, - time::{Duration, Instant}, - }; + use std::collections::VecDeque; use tor_units::Percentage; + use web_time_compat::{Duration, Instant, InstantExt}; use super::*; use crate::congestion::{ @@ -433,7 +431,7 @@ pub(crate) mod test { self.vegas.set_inflight(p.inflight_in); self.vegas.set_is_blocked_on_chan(p.or_conn_blocked_in); - let now = Instant::now(); + let now = Instant::get(); self.rtt .expect_sendme(now + Duration::from_micros(p.sent_usec_in)); let ret = self.rtt.update( diff --git a/crates/tor-proto/src/relay/channel/handshake.rs b/crates/tor-proto/src/relay/channel/handshake.rs index dda1d2602..748d4a177 100644 --- a/crates/tor-proto/src/relay/channel/handshake.rs +++ b/crates/tor-proto/src/relay/channel/handshake.rs @@ -108,7 +108,7 @@ impl< /// Connect to another relay as the relay Initiator. /// /// Takes a function that reports the current time. In theory, this can just be - /// `SystemTime::now()`. + /// `SystemTime::get()`. pub async fn connect<F>(mut self, now_fn: F) -> Result<UnverifiedInitiatorRelayChannel<T, S>> where F: FnOnce() -> SystemTime, @@ -237,7 +237,7 @@ impl< /// Begin the handshake process. /// /// Takes a function that reports the current time. In theory, this can just be - /// `SystemTime::now()`. + /// `SystemTime::get()`. pub async fn handshake<F>( mut self, now_fn: F, diff --git a/crates/tor-proto/src/relay/channel/responder.rs b/crates/tor-proto/src/relay/channel/responder.rs index 4633e641b..09e55def7 100644 --- a/crates/tor-proto/src/relay/channel/responder.rs +++ b/crates/tor-proto/src/relay/channel/responder.rs @@ -8,7 +8,7 @@ use digest::Digest; use futures::{AsyncRead, AsyncWrite}; use safelog::{MaybeSensitive, Sensitive}; -use std::{net::IpAddr, ops::Deref, sync::Arc, time::SystemTime}; +use std::{net::IpAddr, ops::Deref, sync::Arc}; use subtle::ConstantTimeEq; use tracing::instrument; @@ -16,6 +16,7 @@ use tor_cell::chancell::msg; use tor_linkspec::{OwnedChanTarget, RelayIds}; use tor_llcrypto as ll; use tor_rtcompat::{CertifiedConn, CoarseTimeProvider, SleepProvider, StreamOps}; +use web_time_compat::{SystemTime, SystemTimeExt}; use crate::{ ClockSkew, Error, RelayIdentities, Result, @@ -132,7 +133,7 @@ where let initiator_auth_cell = self.auth_cell; let my_addrs = self.my_addrs; - let now = now.unwrap_or_else(SystemTime::now); + let now = now.unwrap_or_else(SystemTime::get); // We are a client initiating a channel to a relay or a bridge. We have received a CERTS // cell and we need to verify these certs: diff --git a/crates/tor-proto/src/streammap.rs b/crates/tor-proto/src/streammap.rs index 0840e4608..82b6d1b27 100644 --- a/crates/tor-proto/src/streammap.rs +++ b/crates/tor-proto/src/streammap.rs @@ -22,8 +22,8 @@ use std::collections::hash_map; use std::num::NonZeroU16; use std::pin::Pin; use std::task::{Poll, Waker}; -use std::time::Instant; use tor_error::{bad_api_usage, internal}; +use web_time_compat::Instant; use rand::Rng; @@ -590,6 +590,7 @@ mod test { use crate::client::circuit::test::fake_mpsc; use crate::stream::queue::fake_stream_queue; use crate::{client::stream::OutboundDataCmdChecker, congestion::sendme::StreamSendWindow}; + use web_time_compat::InstantExt; #[test] fn test_wrapping_next_stream_id() { @@ -650,7 +651,7 @@ mod test { // Test terminate use TerminateReason as TR; - let expiry = Instant::now(); // dummy value, unused outside of the reactor + let expiry = Instant::get(); // dummy value, unused outside of the reactor assert!(map.terminate(nonesuch_id, TR::ExplicitEnd, expiry).is_err()); assert_eq!(map.n_open_streams(), 127); assert_eq!( diff --git a/crates/tor-proto/src/util/skew.rs b/crates/tor-proto/src/util/skew.rs index a75d51e57..6648cda46 100644 --- a/crates/tor-proto/src/util/skew.rs +++ b/crates/tor-proto/src/util/skew.rs @@ -161,10 +161,11 @@ mod test { use super::*; use tor_basic_utils::test_rng::testing_rng; + use web_time_compat::SystemTimeExt; #[test] fn make_skew() { - let now = SystemTime::now(); + let now = SystemTime::get(); let later = now + Duration::from_secs(777); let earlier = now - Duration::from_secs(333); let window = Duration::from_secs(30); diff --git a/crates/tor-proto/src/util/token_bucket/bucket.rs b/crates/tor-proto/src/util/token_bucket/bucket.rs index ff39b1fe6..2e58f5cbe 100644 --- a/crates/tor-proto/src/util/token_bucket/bucket.rs +++ b/crates/tor-proto/src/util/token_bucket/bucket.rs @@ -1,7 +1,7 @@ //! A token bucket implementation. use std::fmt::Debug; -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; /// A token bucket. /// diff --git a/crates/tor-proto/src/util/token_bucket/writer.rs b/crates/tor-proto/src/util/token_bucket/writer.rs index 9e5b05ab6..6fd6d3eb5 100644 --- a/crates/tor-proto/src/util/token_bucket/writer.rs +++ b/crates/tor-proto/src/util/token_bucket/writer.rs @@ -4,7 +4,7 @@ use std::future::Future; use std::num::NonZero; use std::pin::Pin; use std::task::{Context, Poll}; -use std::time::{Duration, Instant}; +use web_time_compat::{Duration, Instant}; use futures::AsyncWrite; use futures::io::Error; @@ -26,7 +26,9 @@ pub(crate) struct RateLimitedWriter<W: AsyncWrite, P: SleepProvider> { /// /// While we use [`Instant`] for the time, we should always get the time from this /// [`SleepProvider`]. - /// For example, use [`SleepProvider::now()`], not [`Instant::now()`]. + /// For example, use [`SleepProvider::now()`], + /// not [`Instant::now()`](std::time::Instant::now) or + /// [`InstantExt::get`](web_time_compat::InstantExt::get). #[educe(Debug(ignore))] sleep_provider: P, /// See [`RateLimitedWriterConfig::wake_when_bytes_available`]. diff --git a/crates/tor-proto/src/util/tunnel_activity.rs b/crates/tor-proto/src/util/tunnel_activity.rs index 62307fd0c..a51bb71e4 100644 --- a/crates/tor-proto/src/util/tunnel_activity.rs +++ b/crates/tor-proto/src/util/tunnel_activity.rs @@ -1,7 +1,8 @@ //! Helpers for tracking whether a tunnel or circuit is still active. use derive_deftly::Deftly; -use std::{num::NonZeroUsize, time::Instant}; +use std::num::NonZeroUsize; +use web_time_compat::{Instant, InstantExt}; /// An object to track whether a tunnel or circuit should still be considered active. /// @@ -132,7 +133,7 @@ impl TunnelActivity { *n_open_streams = new_value; } else { self.inner = Inner::Disused { - since: Instant::now(), + since: Instant::get(), }; } } @@ -154,7 +155,7 @@ impl TunnelActivity { /// /// # A note about time /// - /// The returned Instant value is a direct result of an earlier call to `Instant::now()`. + /// The returned Instant value is a direct result of an earlier call to `Instant::get()`. /// It is not affected by any runtime mocking. pub(crate) fn disused_since(&self) -> Option<Instant> { match self.inner { @@ -189,7 +190,7 @@ mod test { #[test] fn ordering() { use Inner::*; - let t1 = Instant::now(); + let t1 = Instant::get(); let t2 = t1 + Duration::new(60, 0); let t3 = t2 + Duration::new(120, 0); let sorted = vec![ diff --git a/crates/tor-ptmgr/Cargo.toml b/crates/tor-ptmgr/Cargo.toml index 1c76a0b37..dbfda0855 100644 --- a/crates/tor-ptmgr/Cargo.toml +++ b/crates/tor-ptmgr/Cargo.toml @@ -59,6 +59,7 @@ tor-rtcompat = { version = "0.40.0", path = "../tor-rtcompat" } tor-socksproto = { version = "0.40.0", path = "../tor-socksproto" } tracing = "0.1.36" visibility = { version = "0.1.0", optional = true } +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] anyhow = "1.0.23" diff --git a/crates/tor-ptmgr/src/ipc.rs b/crates/tor-ptmgr/src/ipc.rs index 62fb5d1e6..08f553145 100644 --- a/crates/tor-ptmgr/src/ipc.rs +++ b/crates/tor-ptmgr/src/ipc.rs @@ -19,7 +19,6 @@ use std::path::PathBuf; use std::process::{Child, Command, Stdio}; use std::str::FromStr; use std::sync::Arc; -use std::time::{Duration, Instant}; use std::{io, thread}; use tor_basic_utils::PathExt as _; use tor_error::{internal, warn_report}; @@ -27,6 +26,7 @@ use tor_linkspec::PtTransportName; use tor_rtcompat::{Runtime, SleepProviderExt}; use tor_socksproto::SocksVersion; use tracing::{debug, error, info, trace, warn}; +use web_time_compat::{Duration, Instant, InstantExt}; /// Amount of time we give a pluggable transport child process to exit gracefully. const GRACEFUL_EXIT_TIME: Duration = Duration::from_secs(5); @@ -601,7 +601,7 @@ pub(crate) mod sealed { match rt .timeout( // FIXME(eta): It'd be nice if SleepProviderExt took an `Instant` natively. - deadline.saturating_duration_since(Instant::now()), + deadline.saturating_duration_since(Instant::get()), async_child.recv(), ) .await @@ -916,7 +916,7 @@ impl PluggableClientTransport { all_env_vars, )?; - let deadline = Instant::now() + self.common_params.timeout.unwrap_or(PT_START_TIMEOUT); + let deadline = Instant::get() + self.common_params.timeout.unwrap_or(PT_START_TIMEOUT); let mut cmethods = HashMap::new(); let mut proxy_done = self.client_params.proxy_uri.is_none(); @@ -1070,7 +1070,7 @@ impl PluggableServerTransport { all_env_vars, )?; - let deadline = Instant::now() + self.common_params.timeout.unwrap_or(PT_START_TIMEOUT); + let deadline = Instant::get() + self.common_params.timeout.unwrap_or(PT_START_TIMEOUT); let mut smethods = HashMap::new(); loop { diff --git a/crates/tor-relay-crypto/Cargo.toml b/crates/tor-relay-crypto/Cargo.toml index 282fe0bdb..ad35fcfde 100644 --- a/crates/tor-relay-crypto/Cargo.toml +++ b/crates/tor-relay-crypto/Cargo.toml @@ -34,6 +34,7 @@ tor-key-forge = { path = "../tor-key-forge", version = "0.40.0" } tor-keymgr = { path = "../tor-keymgr", version = "0.40.0", features = ["experimental-api"] } tor-llcrypto = { path = "../tor-llcrypto", version = "0.40.0" } tor-persist = { path = "../tor-persist", version = "0.40.0" } +web-time-compat = { path = "../web-time-compat", version = "0.1.0" } [dev-dependencies] tor-keymgr = { version = "0.40.0", path = "../tor-keymgr", features = ["testing"] } diff --git a/crates/tor-relay-crypto/src/certs.rs b/crates/tor-relay-crypto/src/certs.rs index 7dc80e220..69f2d0299 100644 --- a/crates/tor-relay-crypto/src/certs.rs +++ b/crates/tor-relay-crypto/src/certs.rs @@ -1,11 +1,10 @@ //! Certificate related types and functions for an arti relay. -use std::time::SystemTime; - use tor_cert::{CertEncodeError, CertType, CertifiedKey, Ed25519Cert, EncodedEd25519Cert}; use tor_checkable::{SelfSigned, Timebound}; use tor_key_forge::{InvalidCertError, ParsedEd25519Cert, ToEncodableCert}; use tor_llcrypto::pk::ed25519::{self, Ed25519Identity}; +use web_time_compat::{SystemTime, SystemTimeExt}; use crate::pk::{RelayIdentityKeypair, RelayLinkSigningKeypair, RelaySigningKeypair}; @@ -113,7 +112,7 @@ impl ToEncodableCert<RelaySigningKeypair> for RelaySigningKeyCert { signed_with: &Self::SigningKey, ) -> Result<Self, InvalidCertError> { // TODO: take the time/time provider as an arg? - let now = SystemTime::now(); + let now = SystemTime::get(); validate_ed25519_cert( cert, &subject.public().into(), @@ -140,7 +139,7 @@ impl ToEncodableCert<RelayLinkSigningKeypair> for RelayLinkSigningKeyCert { signed_with: &Self::SigningKey, ) -> Result<Self, InvalidCertError> { // TODO: take the time/time provider as an arg? - let now = SystemTime::now(); + let now = SystemTime::get(); validate_ed25519_cert( cert, &subject.public().into(), diff --git a/crates/tor-relay-crypto/src/pk.rs b/crates/tor-relay-crypto/src/pk.rs index 5302b8813..d2980cd5f 100644 --- a/crates/tor-relay-crypto/src/pk.rs +++ b/crates/tor-relay-crypto/src/pk.rs @@ -2,7 +2,6 @@ //! KeyMgr so some of them can be stored on disk. use std::fmt; -use std::time::SystemTime; use derive_deftly::Deftly; use derive_more::Constructor; @@ -15,6 +14,7 @@ use tor_keymgr::{ derive_deftly_template_CertSpecifier, derive_deftly_template_KeySpecifier, }; use tor_persist::slug::{Slug, timestamp::Iso8601TimeSlug}; +use web_time_compat::SystemTime; define_ed25519_keypair!( /// [KP_relayid_ed] Long-term identity keypair. Never rotates. diff --git a/crates/tor-rtcompat/Cargo.toml b/crates/tor-rtcompat/Cargo.toml index e8b980209..2682ccfc0 100644 --- a/crates/tor-rtcompat/Cargo.toml +++ b/crates/tor-rtcompat/Cargo.toml @@ -107,6 +107,7 @@ tor-error = { version = "0.40.0", path = "../tor-error", features = ["tracing"] tor-general-addr = { version = "0.40.0", path = "../tor-general-addr" } tracing = "0.1.36" void = "1" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } zeroize = "1" [target.'cfg(not(all(target_arch="wasm32", target_os="unknown")))'.dependencies] diff --git a/crates/tor-rtcompat/src/compound.rs b/crates/tor-rtcompat/src/compound.rs index 715d40a65..041eccf49 100644 --- a/crates/tor-rtcompat/src/compound.rs +++ b/crates/tor-rtcompat/src/compound.rs @@ -10,9 +10,9 @@ use educe::Educe; use futures::{future::FutureObj, task::Spawn}; use std::future::Future; use std::io::Result as IoResult; -use std::time::{Instant, SystemTime}; use tor_general_addr::unix; use tracing::instrument; +use web_time_compat::{Instant, SystemTime}; /// A runtime made of several parts, each of which implements one trait-group. /// diff --git a/crates/tor-rtcompat/src/dyn_time.rs b/crates/tor-rtcompat/src/dyn_time.rs index f6d04c91e..80d46a19f 100644 --- a/crates/tor-rtcompat/src/dyn_time.rs +++ b/crates/tor-rtcompat/src/dyn_time.rs @@ -3,7 +3,7 @@ use std::future::Future; use std::mem::{self, MaybeUninit}; use std::pin::Pin; -use std::time::{Duration, Instant, SystemTime}; +use web_time_compat::{Duration, Instant, SystemTime}; use dyn_clone::DynClone; use educe::Educe; diff --git a/crates/tor-rtcompat/src/lib.rs b/crates/tor-rtcompat/src/lib.rs index 534275fdb..9d2e2b808 100644 --- a/crates/tor-rtcompat/src/lib.rs +++ b/crates/tor-rtcompat/src/lib.rs @@ -438,17 +438,17 @@ mod test { use std::io::Result as IoResult; use std::net::SocketAddr; use std::net::{Ipv4Addr, SocketAddrV4}; - use std::time::{Duration, Instant}; + use web_time_compat::{Duration, Instant, InstantExt, SystemTimeExt}; // Test "sleep" with a tiny delay, and make sure that at least that // much delay happens. fn small_delay<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> { let rt = runtime.clone(); runtime.block_on(async { - let i1 = Instant::now(); + let i1 = Instant::get(); let one_msec = Duration::from_millis(1); rt.sleep(one_msec).await; - let i2 = Instant::now(); + let i2 = Instant::get(); assert!(i2 >= i1 + one_msec); }); Ok(()) @@ -488,14 +488,14 @@ mod test { fn tiny_wallclock<R: ToplevelRuntime>(runtime: &R) -> IoResult<()> { let rt = runtime.clone(); runtime.block_on(async { - let i1 = Instant::now(); + let i1 = Instant::get(); let now = runtime.wallclock(); let one_millis = Duration::from_millis(1); let one_millis_later = now + one_millis; rt.sleep_until_wallclock(one_millis_later).await; - let i2 = Instant::now(); + let i2 = Instant::get(); let newtime = runtime.wallclock(); assert!(newtime >= one_millis_later); assert!(i2 - i1 >= one_millis); @@ -687,7 +687,7 @@ mod test { let mut rng = tor_basic_utils::test_rng::testing_rng(); let tls_cert = tor_cert_x509::TlsKeyAndCert::create( &mut rng, - std::time::SystemTime::now(), + std::time::SystemTime::get(), "prospit.example.org", "derse.example.org", ) diff --git a/crates/tor-rtcompat/src/scheduler.rs b/crates/tor-rtcompat/src/scheduler.rs index ef41ea33e..a290e9ff6 100644 --- a/crates/tor-rtcompat/src/scheduler.rs +++ b/crates/tor-rtcompat/src/scheduler.rs @@ -7,7 +7,7 @@ use futures::{Stream, StreamExt}; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; -use std::time::{Duration, Instant, SystemTime}; +use web_time_compat::{Duration, Instant, SystemTime}; use pin_project::pin_project; @@ -267,7 +267,7 @@ mod test { use crate::{SleepProvider, test_with_all_runtimes}; use futures::FutureExt; use futures::StreamExt; - use std::time::{Duration, Instant}; + use web_time_compat::{Duration, Instant, InstantExt}; #[test] fn it_fires_immediately() { @@ -335,7 +335,7 @@ mod test { let (mut sch, hdl) = TaskSchedule::new(rt); assert!(sch.next().now_or_never().is_some()); - hdl.fire_at(Instant::now() + Duration::from_millis(100)); + hdl.fire_at(Instant::get() + Duration::from_millis(100)); assert!(sch.next().now_or_never().is_none()); assert!(sch.next().await.is_some()); @@ -354,7 +354,7 @@ mod test { let (mut sch, hdl) = TaskSchedule::new(rt.clone()); assert!(sch.next().now_or_never().is_some()); - hdl.fire_at(Instant::now() + Duration::from_millis(100)); + hdl.fire_at(Instant::get() + Duration::from_millis(100)); assert!(sch.next().now_or_never().is_none()); @@ -378,7 +378,7 @@ mod test { let (mut sch, hdl) = TaskSchedule::new(rt.clone()); assert!(sch.next().now_or_never().is_some()); - hdl.fire_at(Instant::now() + Duration::from_millis(100)); + hdl.fire_at(Instant::get() + Duration::from_millis(100)); hdl.fire(); assert!(sch.next().now_or_never().is_some()); diff --git a/crates/tor-rtcompat/src/timer.rs b/crates/tor-rtcompat/src/timer.rs index 26236d6a8..abb055af2 100644 --- a/crates/tor-rtcompat/src/timer.rs +++ b/crates/tor-rtcompat/src/timer.rs @@ -6,8 +6,8 @@ use pin_project::pin_project; use std::{ pin::Pin, task::{Context, Poll}, - time::{Duration, SystemTime}, }; +use web_time_compat::{Duration, SystemTime}; /// An error value given when a function times out. /// @@ -207,6 +207,7 @@ mod test { #![allow(clippy::needless_pass_by_value)] //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> #![allow(clippy::erasing_op)] + use web_time_compat::SystemTimeExt; #[cfg(not(miri))] use super::*; @@ -219,7 +220,7 @@ mod test { } let minute = Duration::from_secs(60); let second = Duration::from_secs(1); - let start = SystemTime::now(); + let start = SystemTime::get(); let target = start + 30 * minute; diff --git a/crates/tor-rtcompat/src/traits.rs b/crates/tor-rtcompat/src/traits.rs index 3ff7b9d05..4ef6b5c71 100644 --- a/crates/tor-rtcompat/src/traits.rs +++ b/crates/tor-rtcompat/src/traits.rs @@ -9,8 +9,8 @@ use std::borrow::Cow; use std::fmt::Debug; use std::io::{self, Result as IoResult}; use std::net; -use std::time::{Duration, Instant, SystemTime}; use tor_general_addr::unix; +use web_time_compat::{Duration, Instant, InstantExt, SystemTime, SystemTimeExt}; #[cfg(feature = "tls-server")] use tor_cert_x509::TlsKeyAndCert; @@ -121,14 +121,14 @@ pub trait SleepProvider: Clone + Send + Sync + 'static { /// /// (This is the same as `Instant::now`, if not running in test mode.) fn now(&self) -> Instant { - Instant::now() + Instant::get() } /// Return the SleepProvider's view of the current wall-clock time. /// /// (This is the same as `SystemTime::now`, if not running in test mode.) fn wallclock(&self) -> SystemTime { - SystemTime::now() + SystemTime::get() } /// Signify that a test running under mock time shouldn't advance time yet, with a given diff --git a/crates/tor-rtmock/Cargo.toml b/crates/tor-rtmock/Cargo.toml index c18abd0bd..58a564f34 100644 --- a/crates/tor-rtmock/Cargo.toml +++ b/crates/tor-rtmock/Cargo.toml @@ -33,6 +33,7 @@ tor-rtcompat = { version = "0.40.0", path = "../tor-rtcompat" } tracing = "0.1.36" tracing-test = "0.2.4" void = "1" +web-time-compat = { version = "0.1.0", path = "../web-time-compat" } [dev-dependencies] futures-await-test = "0.3.0" diff --git a/crates/tor-rtmock/src/simple_time.rs b/crates/tor-rtmock/src/simple_time.rs index 084716581..2e2da094a 100644 --- a/crates/tor-rtmock/src/simple_time.rs +++ b/crates/tor-rtmock/src/simple_time.rs @@ -7,7 +7,7 @@ use std::future::Future; use std::pin::Pin; use std::sync::{Arc, Mutex, MutexGuard}; use std::task::{Context, Poll, Waker}; -use std::time::{Duration, Instant, SystemTime}; +use web_time_compat::{Duration, Instant, InstantExt, SystemTime, SystemTimeExt}; use derive_more::AsMut; use priority_queue::priority_queue::PriorityQueue; @@ -121,7 +121,7 @@ impl Provider { /// Like any [`SimpleMockTimeProvider`], the time is frozen and only changes /// due to calls to `advance`. pub fn from_real() -> Self { - Provider::from_wallclock(SystemTime::now()) + Provider::from_wallclock(SystemTime::get()) } /// Return a new mock time provider starting at a specified wallclock time /// @@ -131,7 +131,7 @@ impl Provider { /// nor can a fixed `Instant` be constructed, /// so this is usually sufficient for a reproducible test.) pub fn from_wallclock(wallclock: SystemTime) -> Self { - Provider::new(Instant::now(), wallclock) + Provider::new(Instant::get(), wallclock) } /// Advance the simulated time by `d` @@ -320,7 +320,7 @@ mod test { FUT: Future<Output = ()>, { let sp = Provider::new( - Instant::now(), // it would have been nice to make this fixed for the test + Instant::get(), // it would have been nice to make this fixed for the test parse_rfc3339("2000-01-01T00:00:00Z").unwrap(), ); let exec = MockExecutor::new(); diff --git a/crates/tor-rtmock/src/sleep_runtime.rs b/crates/tor-rtmock/src/sleep_runtime.rs index a9ba811a7..04a5cb74b 100644 --- a/crates/tor-rtmock/src/sleep_runtime.rs +++ b/crates/tor-rtmock/src/sleep_runtime.rs @@ -33,7 +33,7 @@ impl<R: Runtime> MockSleepRuntime<R> { /// Create a new runtime that wraps `runtime`, but overrides /// its view of time with a [`MockSleepProvider`]. pub fn new(runtime: R) -> Self { - let sleep = MockSleepProvider::new(SystemTime::now()); + let sleep = MockSleepProvider::new(SystemTime::get()); MockSleepRuntime { runtime, sleep } } diff --git a/crates/tor-rtmock/src/time.rs b/crates/tor-rtmock/src/time.rs index 56be8c117..e5608ffaa 100644 --- a/crates/tor-rtmock/src/time.rs +++ b/crates/tor-rtmock/src/time.rs @@ -20,8 +20,8 @@ use std::{ pin::Pin, sync::{Arc, Mutex, Weak}, task::{Context, Poll, Waker}, - time::{Duration, Instant, SystemTime}, }; +use web_time_compat::{Duration, Instant, InstantExt, SystemTime}; use futures::Future; use tracing::trace; @@ -211,7 +211,7 @@ impl Default for MockSleepProvider { impl MockSleepProvider { /// Create a new MockSleepProvider, starting at a given wall-clock time. pub fn new(wallclock: SystemTime) -> Self { - let instant = Instant::now(); + let instant = Instant::get(); let sleepers = BinaryHeap::new(); let core = MockTimeCore::new(instant, wallclock); let state = SleepSchedule { @@ -590,10 +590,11 @@ mod test { //! <!-- @@ end test lint list maintained by maint/add_warning @@ --> use super::*; use tor_rtcompat::test_with_all_runtimes; + use web_time_compat::SystemTimeExt; #[test] fn basics_of_time_travel() { - let w1 = SystemTime::now(); + let w1 = SystemTime::get(); let sp = MockSleepProvider::new(w1); let i1 = sp.now(); assert_eq!(sp.wallclock(), w1); @@ -615,7 +616,7 @@ mod test { use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; - let sp = MockSleepProvider::new(SystemTime::now()); + let sp = MockSleepProvider::new(SystemTime::get()); let one_hour = Duration::new(3600, 0); let (s1, r1) = oneshot::channel(); @@ -626,7 +627,7 @@ mod test { let b2 = AtomicBool::new(false); let b3 = AtomicBool::new(false); - let real_start = Instant::now(); + let real_start = Instant::get(); futures::join!( async { @@ -662,7 +663,7 @@ mod test { assert!(b1.load(Ordering::SeqCst)); assert!(b2.load(Ordering::SeqCst)); assert!(b3.load(Ordering::SeqCst)); - let real_end = Instant::now(); + let real_end = Instant::get(); assert!(real_end - real_start < one_hour); } diff --git a/crates/tor-rtmock/src/time_core.rs b/crates/tor-rtmock/src/time_core.rs index 98ac5b9eb..35fdb60ef 100644 --- a/crates/tor-rtmock/src/time_core.rs +++ b/crates/tor-rtmock/src/time_core.rs @@ -1,9 +1,9 @@ //! [`MockTimeCore`] and [`MockCoarseTimeProvider`] use derive_deftly::{Deftly, define_derive_deftly}; -use std::time::{Duration, Instant, SystemTime}; use tor_rtcompat::{CoarseDuration, CoarseInstant}; use tor_rtcompat::{CoarseTimeProvider, RealCoarseTimeProvider}; +use web_time_compat::{Duration, Instant, SystemTime}; define_derive_deftly! { /// Derive getters for struct fields. diff --git a/crates/tor-rtmock/src/util.rs b/crates/tor-rtmock/src/util.rs index 0245cb5ce..6c5b77cd0 100644 --- a/crates/tor-rtmock/src/util.rs +++ b/crates/tor-rtmock/src/util.rs @@ -190,11 +190,11 @@ pub(crate) mod impl_runtime_prelude { pub(crate) use futures::task::{FutureObj, Spawn, SpawnError}; pub(crate) use std::io::Result as IoResult; pub(crate) use std::net::SocketAddr; - pub(crate) use std::time::{Duration, Instant, SystemTime}; pub(crate) use tor_rtcompat::{ Blocking, CoarseInstant, CoarseTimeProvider, NetStreamProvider, Runtime, SleepProvider, TlsProvider, ToplevelBlockOn, UdpProvider, unimpl::FakeListener, unimpl::FakeStream, }; + pub(crate) use web_time_compat::{Duration, Instant, SystemTime, SystemTimeExt}; } /// Wrapper for `futures::channel::mpsc::channel` that embodies the `#[allow]` diff --git a/crates/tor-rtmock/tests/rtcompat_timing.rs b/crates/tor-rtmock/tests/rtcompat_timing.rs index 6d74f3b1c..f88cb65f5 100644 --- a/crates/tor-rtmock/tests/rtcompat_timing.rs +++ b/crates/tor-rtmock/tests/rtcompat_timing.rs @@ -22,7 +22,7 @@ use tor_rtmock::time::MockSleepProvider; use futures::FutureExt; use oneshot_fused_workaround as oneshot; use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::{Duration, SystemTime}; +use web_time_compat::{Duration, SystemTime, SystemTimeExt}; #[test] fn timeouts() { @@ -31,7 +31,7 @@ fn timeouts() { oneshot::Sender<()>, Timeout<oneshot::Receiver<()>, tor_rtmock::time::Sleeping>, ) { - let start = SystemTime::now(); + let start = SystemTime::get(); let (send, recv) = oneshot::channel::<()>(); let mock_sp = MockSleepProvider::new(start); let ten_min = Duration::new(10 * 60, 0); diff --git a/crates/web-time-compat/Cargo.toml b/crates/web-time-compat/Cargo.toml new file mode 100644 index 000000000..3b4f4118a --- /dev/null +++ b/crates/web-time-compat/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "web-time-compat" +version = "0.1.0" +authors = ["The Tor Project, Inc.", "Nick Mathewson <[email protected]>"] +edition = "2024" +rust-version = "1.89" +license = "MIT OR Apache-2.0" +homepage = "https://gitlab.torproject.org/tpo/core/arti/-/wikis/home" +description = "Compatibility layer for web-time" +keywords = ["js", "wasm", "time"] +# We must put *something* here and this will do +categories = ["rust-patterns"] +repository = "https://gitlab.torproject.org/tpo/core/arti.git/" +[package.metadata.docs.rs] +all-features = true + +[features] +default = [] +full = [] + +[dependencies] + +[dev-dependencies] + +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +web-time = "1.1.0" diff --git a/crates/web-time-compat/README.md b/crates/web-time-compat/README.md new file mode 100644 index 000000000..9acc3de82 --- /dev/null +++ b/crates/web-time-compat/README.md @@ -0,0 +1,37 @@ +# web-time-compat + +Small compatibility layer for [`web-time`]. + +Unlike [`web-time`], this crate does not require you to stop using +[`std::time::SystemTime`]. +Instead, it provides an extension trait to replace the `now` +method of `SystemTime` types with a `get` method that works on +wasm32-unknown-unknown. + +With `Instant`, it isn't possible to continue using `std::time::Instant`, +since that type is not interconvertible with `web_time::Instant`. Instead, +we provide an extension trait to make it easier for you to make sure that you +are only using the version of Instant you want. + +## How to use this crate + +(This isn't the only way, but it's what we recommend.) + +- Replace all references to `std::time::Instant` with `web_time_compat::Instant`. +- You may, if you like, also use `web_time_compat::{Duration, SystemTime}`. + They are just aliases for the standard Duration and SystemTimetypes. +- Instead of `SystemTime::now()`, use `SystemTimeExt::get()`. +- Instead of `Instant::now()`, use `Instant::get()`. +- Add `std::time::SystemTime::now` and `std::time::Instant::now` to your + [`disallowed-methods`] list in your `clippy.toml` file, + to prevent them from being used accidentally. +- If you use any other time libraries (such as `time` or `chrono`), you may + want to add their "now" methods to `disallowed-methods`, depending + on whether you have configured them for wasm compatibility. + +[`web-time`]: https://docs.rs/web-time/latest/web_time/ +[`disallowed-methods`]: https://doc.rust-lang.org/stable/clippy/lint_configuration.html#disallowed-methods + +---- + +License: MIT OR Apache-2.0 diff --git a/crates/web-time-compat/src/lib.rs b/crates/web-time-compat/src/lib.rs new file mode 100644 index 000000000..31abd17f5 --- /dev/null +++ b/crates/web-time-compat/src/lib.rs @@ -0,0 +1,112 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc = include_str!("../README.md")] +// @@ begin lint list maintained by maint/add_warning @@ +#![allow(renamed_and_removed_lints)] // @@REMOVE_WHEN(ci_arti_stable) +#![allow(unknown_lints)] // @@REMOVE_WHEN(ci_arti_nightly) +#![warn(missing_docs)] +#![warn(noop_method_call)] +#![warn(unreachable_pub)] +#![warn(clippy::all)] +#![deny(clippy::await_holding_lock)] +#![deny(clippy::cargo_common_metadata)] +#![deny(clippy::cast_lossless)] +#![deny(clippy::checked_conversions)] +#![warn(clippy::cognitive_complexity)] +#![deny(clippy::debug_assert_with_mut_call)] +#![deny(clippy::exhaustive_enums)] +#![deny(clippy::exhaustive_structs)] +#![deny(clippy::expl_impl_clone_on_copy)] +#![deny(clippy::fallible_impl_from)] +#![deny(clippy::implicit_clone)] +#![deny(clippy::large_stack_arrays)] +#![warn(clippy::manual_ok_or)] +#![deny(clippy::missing_docs_in_private_items)] +#![warn(clippy::needless_borrow)] +#![warn(clippy::needless_pass_by_value)] +#![warn(clippy::option_option)] +#![deny(clippy::print_stderr)] +#![deny(clippy::print_stdout)] +#![warn(clippy::rc_buffer)] +#![deny(clippy::ref_option_ref)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![warn(clippy::trait_duplication_in_bounds)] +#![deny(clippy::unchecked_time_subtraction)] +#![deny(clippy::unnecessary_wraps)] +#![warn(clippy::unseparated_literal_suffix)] +#![deny(clippy::unwrap_used)] +#![deny(clippy::mod_module_files)] +#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness +#![allow(clippy::uninlined_format_args)] +#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945 +#![allow(clippy::result_large_err)] // temporary workaround for arti#587 +#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best +#![allow(clippy::needless_lifetimes)] // See arti#1765 +#![allow(mismatched_lifetime_syntaxes)] // temporary workaround for arti#2060 +#![allow(clippy::collapsible_if)] // See arti#2342 +#![deny(clippy::unused_async)] +//! <!-- @@ end lint list maintained by maint/add_warning @@ --> + +// We always use `SystemTime` for our data representation outside of this crate. +// +// The only time that we touch `SystemTime` is when we are constructing it with +// `SystemTimeExt::get`. +pub use std::time::SystemTime; + +// "Duration" is the same type in web_time as it is in stdlib. +pub use std::time::Duration; + +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +mod stdlib; + +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +pub use stdlib::*; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +mod wasm; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +pub use wasm::*; + +/// Module to hide "Sealed" +mod seal { + /// Trait used to prevent implementing InstantExt or SystemTimeExt outside of this crate. + #[allow(unreachable_pub)] + pub trait Sealed {} +} + +/// Extension trait for [`std::time::SystemTime`] +/// +/// This trait adds a `get` method which works like `now`, +/// but also supports `wasm32-unknown-unknown` environments. +pub trait SystemTimeExt: seal::Sealed { + /// Return the current time. + fn get() -> std::time::SystemTime; +} + +/// Extension trait for [`Instant`]. +/// +/// This trait adds a `get` method which works like `now`, +/// so we can make sure we aren't calling [`std::time::Instant::now`] +/// on`wasm32-unknown-unknown` environments. +/// +/// ## Design note +/// +/// Since we already replace the `std::time::Instant` type with +/// `web_time::Instant` in this crate, why do we also provide +/// an extension trait to rename its "now" method? +/// +/// We do so for two reasons: +/// +/// 1. Consistency. With this approach, you don't have to remember +/// which type uses `get` and which uses `now`. +/// 2. Enforcement. This approach makes it possible to use Clippy +/// to disallow `std::time::Instant::now()` unconditionally, +/// to make sure that you don't forget to use +/// the appropriate `web_time_compat::Instant` type instead. +pub trait InstantExt: seal::Sealed { + /// Return the current time. + fn get() -> crate::Instant; +} + +impl seal::Sealed for std::time::SystemTime {} +impl seal::Sealed for crate::Instant {} diff --git a/crates/web-time-compat/src/stdlib.rs b/crates/web-time-compat/src/stdlib.rs new file mode 100644 index 000000000..891a0e0f7 --- /dev/null +++ b/crates/web-time-compat/src/stdlib.rs @@ -0,0 +1,21 @@ +//! Standard-library time functionality.. + +// If we've forbidden `now` elsewhere in our project, we enable it here. +// (And only here!) +#![allow(clippy::disallowed_methods)] + +pub use std::time::Instant; + +use std::time::SystemTime; + +impl crate::SystemTimeExt for SystemTime { + fn get() -> SystemTime { + SystemTime::now() + } +} + +impl crate::InstantExt for Instant { + fn get() -> crate::Instant { + Instant::now() + } +} diff --git a/crates/web-time-compat/src/wasm.rs b/crates/web-time-compat/src/wasm.rs new file mode 100644 index 000000000..37d2198ce --- /dev/null +++ b/crates/web-time-compat/src/wasm.rs @@ -0,0 +1,20 @@ +//! Wasm-specific time functionality. + +// If we've forbidden `now` elsewhere in our project, we enable it here. +#![allow(clippy::disallowed_methods)] + +pub use web_time::Instant; + +impl crate::SystemTimeExt for std::time::SystemTime { + fn get() -> std::time::SystemTime { + use web_time::web::SystemTimeExt as _; + let now = web_time::SystemTime::now(); + now.to_std() + } +} + +impl crate::InstantExt for Instant { + fn get() -> crate::Instant { + Instant::now() + } +} diff --git a/examples/gsoc2023/obfs4-checker/Cargo.toml b/examples/gsoc2023/obfs4-checker/Cargo.toml index be381a04d..f0073df82 100644 --- a/examples/gsoc2023/obfs4-checker/Cargo.toml +++ b/examples/gsoc2023/obfs4-checker/Cargo.toml @@ -21,6 +21,7 @@ tor-guardmgr = { path = "../../../crates/tor-guardmgr", version = "0.40", featur tor-proto = { path = "../../../crates/tor-proto", version = "0.40", features = [] } tor-rtcompat = { path = "../../../crates/tor-rtcompat", version = "0.40" } tracing-subscriber = "0.3.20" +web-time-compat = { path = "../../../crates/web-time-compat", version = "0.1.0" } [features] full = [ diff --git a/examples/gsoc2023/obfs4-checker/src/checking.rs b/examples/gsoc2023/obfs4-checker/src/checking.rs index ccf614be0..746cfc00b 100644 --- a/examples/gsoc2023/obfs4-checker/src/checking.rs +++ b/examples/gsoc2023/obfs4-checker/src/checking.rs @@ -4,7 +4,6 @@ use arti_client::config::{BridgeConfigBuilder, CfgPath, TorClientConfigBuilder}; use arti_client::{TorClient, TorClientConfig}; use std::collections::{HashMap, HashSet}; use std::sync::Arc; -use time::OffsetDateTime; use tokio::sync::broadcast; use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio::time::{Duration, timeout}; @@ -14,7 +13,7 @@ use tor_proto::channel::Channel; use tor_proto::memquota::{ChannelAccount, SpecificAccount as _}; use tor_rtcompat::PreferredRuntime; -use crate::BridgeResult; +use crate::{BridgeResult, now_utc}; /// The maximum number of open connections to relays at any given time const MAX_CONNECTIONS: usize = 10; @@ -101,7 +100,7 @@ async fn test_bridges( let bridge_config = bridge.build().unwrap(); let tor_client = common_tor_client.isolated_client(); tokio::spawn(async move { - let current_time = OffsetDateTime::now_utc(); + let current_time = now_utc(); match is_bridge_online(&bridge_config, &tor_client).await { Ok(functional) => { (rawbridgeline, Some(functional), current_time, None) @@ -120,7 +119,7 @@ async fn test_bridges( }) } Err(e) => tokio::spawn(async move { - let current_time = OffsetDateTime::now_utc(); + let current_time = now_utc(); // Build error here since we can't // represent the actual Arti-related errors // by `dyn ErrorReport` and we need the diff --git a/examples/gsoc2023/obfs4-checker/src/main.rs b/examples/gsoc2023/obfs4-checker/src/main.rs index 2fde754e8..8938d3551 100644 --- a/examples/gsoc2023/obfs4-checker/src/main.rs +++ b/examples/gsoc2023/obfs4-checker/src/main.rs @@ -70,9 +70,9 @@ async fn check_bridges( obfs4_path: String, new_bridges_rx: broadcast::Receiver<Vec<String>>, ) -> (StatusCode, Json<BridgesResult>) { - let commencement_time = OffsetDateTime::now_utc(); + let commencement_time = now_utc(); let mainop = crate::checking::main_test(bridge_lines.clone(), &obfs4_path).await; - let end_time = OffsetDateTime::now_utc(); + let end_time = now_utc(); let diff = (end_time - commencement_time).as_seconds_f64(); let (bridge_results, error) = match mainop { Ok((bridge_results, channels)) => { @@ -135,6 +135,14 @@ async fn add_new_bridges( } } +/// Helper: Return an OffsetDateTime equal to the current time in UTC. +/// +/// Uses web_time_compat to avoid panics on wasm environments. +fn now_utc() -> OffsetDateTime { + use web_time_compat::{SystemTime, SystemTimeExt}; + OffsetDateTime::from(SystemTime::get()) +} + /// Run the HTTP server and call the required methods to initialize the testing #[tokio::main] async fn main() { |
