Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Period clock changes (WIP) #2

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/databases/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use r2d2_sqlite::SqliteConnectionManager;

use crate::databases::database;
use crate::databases::database::{Database, Error};
use crate::protocol::clock::clock::SinceUnixEpoch;
use crate::protocol::clock::clock::DurationSinceUnixEpoch;
use crate::tracker::key::AuthKey;
use crate::InfoHash;

Expand Down Expand Up @@ -86,7 +86,7 @@ impl Database for SqliteDatabase {

Ok(AuthKey {
key,
valid_until: Some(SinceUnixEpoch::from_secs(valid_until as u64)),
valid_until: Some(DurationSinceUnixEpoch::from_secs(valid_until as u64)),
})
})?;

Expand Down Expand Up @@ -193,7 +193,7 @@ impl Database for SqliteDatabase {

Ok(AuthKey {
key,
valid_until: Some(SinceUnixEpoch::from_secs(valid_until_i64 as u64)),
valid_until: Some(DurationSinceUnixEpoch::from_secs(valid_until_i64 as u64)),
})
} else {
Err(database::Error::QueryReturnedNoRows)
Expand Down
38 changes: 19 additions & 19 deletions src/protocol/clock/clock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::num::IntErrorKind;
pub use std::time::Duration;

pub type SinceUnixEpoch = Duration;
pub type DurationSinceUnixEpoch = Duration;

#[derive(Debug)]
pub enum ClockType {
Expand All @@ -22,14 +22,14 @@ pub type DefaultClock = WorkingClock;
pub type DefaultClock = StoppedClock;

pub trait Time: Sized {
fn now() -> SinceUnixEpoch;
fn now() -> DurationSinceUnixEpoch;
}

pub trait TimeNow: Time {
fn add(add_time: &Duration) -> Option<SinceUnixEpoch> {
fn add(add_time: &Duration) -> Option<DurationSinceUnixEpoch> {
Self::now().checked_add(*add_time)
}
fn sub(sub_time: &Duration) -> Option<SinceUnixEpoch> {
fn sub(sub_time: &Duration) -> Option<DurationSinceUnixEpoch> {
Self::now().checked_sub(*sub_time)
}
}
Expand Down Expand Up @@ -57,10 +57,10 @@ mod tests {
mod working_clock {
use std::time::SystemTime;

use super::{SinceUnixEpoch, Time, TimeNow, WorkingClock};
use super::{DurationSinceUnixEpoch, Time, TimeNow, WorkingClock};

impl Time for WorkingClock {
fn now() -> SinceUnixEpoch {
fn now() -> DurationSinceUnixEpoch {
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
}
}
Expand All @@ -69,9 +69,9 @@ mod working_clock {
}

pub trait StoppedTime: TimeNow {
fn local_set(unix_time: &SinceUnixEpoch);
fn local_set(unix_time: &DurationSinceUnixEpoch);
fn local_set_to_unix_epoch() {
Self::local_set(&SinceUnixEpoch::ZERO)
Self::local_set(&DurationSinceUnixEpoch::ZERO)
}
fn local_set_to_app_start_time();
fn local_set_to_system_time_now();
Expand All @@ -84,10 +84,10 @@ mod stopped_clock {
use std::num::IntErrorKind;
use std::time::Duration;

use super::{SinceUnixEpoch, StoppedClock, StoppedTime, Time, TimeNow};
use super::{DurationSinceUnixEpoch, StoppedClock, StoppedTime, Time, TimeNow};

impl Time for StoppedClock {
fn now() -> SinceUnixEpoch {
fn now() -> DurationSinceUnixEpoch {
detail::FIXED_TIME.with(|time| {
return *time.borrow();
})
Expand All @@ -97,7 +97,7 @@ mod stopped_clock {
impl TimeNow for StoppedClock {}

impl StoppedTime for StoppedClock {
fn local_set(unix_time: &SinceUnixEpoch) {
fn local_set(unix_time: &DurationSinceUnixEpoch) {
detail::FIXED_TIME.with(|time| {
*time.borrow_mut() = *unix_time;
})
Expand Down Expand Up @@ -147,11 +147,11 @@ mod stopped_clock {
use std::thread;
use std::time::Duration;

use crate::protocol::clock::clock::{SinceUnixEpoch, StoppedClock, StoppedTime, Time, TimeNow, WorkingClock};
use crate::protocol::clock::clock::{DurationSinceUnixEpoch, StoppedClock, StoppedTime, Time, TimeNow, WorkingClock};

#[test]
fn it_should_default_to_zero_when_testing() {
assert_eq!(StoppedClock::now(), SinceUnixEpoch::ZERO)
assert_eq!(StoppedClock::now(), DurationSinceUnixEpoch::ZERO)
}

#[test]
Expand Down Expand Up @@ -206,26 +206,26 @@ mod stopped_clock {
use std::cell::RefCell;
use std::time::SystemTime;

use crate::protocol::clock::clock::SinceUnixEpoch;
use crate::protocol::clock::clock::DurationSinceUnixEpoch;
use crate::static_time;

pub fn get_app_start_time() -> SinceUnixEpoch {
pub fn get_app_start_time() -> DurationSinceUnixEpoch {
(*static_time::TIME_AT_APP_START)
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
}

#[cfg(not(test))]
pub fn get_default_fixed_time() -> SinceUnixEpoch {
pub fn get_default_fixed_time() -> DurationSinceUnixEpoch {
get_app_start_time()
}

#[cfg(test)]
pub fn get_default_fixed_time() -> SinceUnixEpoch {
SinceUnixEpoch::ZERO
pub fn get_default_fixed_time() -> DurationSinceUnixEpoch {
DurationSinceUnixEpoch::ZERO
}

thread_local!(pub static FIXED_TIME: RefCell<SinceUnixEpoch> = RefCell::new(get_default_fixed_time()));
thread_local!(pub static FIXED_TIME: RefCell<DurationSinceUnixEpoch> = RefCell::new(get_default_fixed_time()));

#[cfg(test)]
mod tests {
Expand Down
86 changes: 86 additions & 0 deletions src/protocol/clock/clockperiod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use std::num::TryFromIntError;
use std::time::Duration;

use super::clock::{ClockType, StoppedClock, TimeNow, WorkingClock};
use super::period::{self, Periods};

pub trait ClockPeriods<T>: Sized
where
T: TimeNow,
{
fn now(length: &period::PeriodLength) -> Option<Result<period::PeriodSinceUnixEpoch, TryFromIntError>> {
T::now().as_nanos().checked_div(length.as_nanos())
.map(|count| match period::PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(period::PeriodSinceUnixEpoch::new(length, &count)),
})
}

fn now_add(
length: &period::PeriodLength,
add_time: &Duration,
) -> Option<Result<period::PeriodSinceUnixEpoch, TryFromIntError>> {
match T::add(add_time) {
None => None,
Some(time) => time.as_nanos().checked_div(length.as_nanos())
.map(|count| match period::PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(period::PeriodSinceUnixEpoch::new(length, &count)),
}),
}
}
fn now_sub(
length: &period::PeriodLength,
sub_time: &Duration,
) -> Option<Result<period::PeriodSinceUnixEpoch, TryFromIntError>> {
match T::sub(sub_time) {
None => None,
Some(time) => time.as_nanos().checked_div(length.as_nanos())
.map(|count| match period::PeriodCount::try_from(count) {
Err(error) => Err(error),
Ok(count) => Ok(period::PeriodSinceUnixEpoch::new(length, &count)),
}),
}
}
}

#[derive(Debug)]
pub struct PeriodClock<const T: usize> {}

pub type ClockPeriodWorking = PeriodClock<{ ClockType::WorkingClock as usize }>;

pub type StoppedPeriodClock = PeriodClock<{ ClockType::StoppedClock as usize }>;

impl ClockPeriods<WorkingClock> for ClockPeriodWorking {}

impl ClockPeriods<StoppedClock> for StoppedPeriodClock {}

#[cfg(not(test))]
pub type DefaultPeriodClock = ClockPeriodWorking;

#[cfg(test)]
pub type DefaultPeriodClock = StoppedPeriodClock;

#[cfg(test)]
mod tests {
use std::time::Duration;

use crate::protocol::clock::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime};
use crate::protocol::clock::clockperiod::{ClockPeriods, DefaultPeriodClock};
use crate::protocol::clock::period::Period;

#[test]
fn it_should_get_the_current_period() {
assert_eq!(
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
Period::from_secs(2, 0)
);

DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(12387687123));

assert_eq!(
DefaultPeriodClock::now(&Duration::from_secs(2)).unwrap().unwrap(),
Period::from_secs(2, 6193843561)
);
}
}
2 changes: 2 additions & 0 deletions src/protocol/clock/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod clock;
pub mod clockperiod;
pub mod period;
99 changes: 99 additions & 0 deletions src/protocol/clock/period.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::num::{IntErrorKind, TryFromIntError};
use std::time::Duration;

pub type PeriodLength = Duration;
pub type PeriodCount = u64;
pub type PeriodTotalTime = Duration;
pub type PeriodSinceUnixEpoch = Period;

/// A `Period` type with a `length` as `Duration` and a `count` as `u64`,
/// to represent a time duration and how many times that duration will occur or has occurred.
#[derive(Debug, Default, Hash, PartialEq)]
pub struct Period {
pub length: PeriodLength,
pub count: PeriodCount,
}

impl Period {
/// Returns a new `Period`.
pub fn new(length: &PeriodLength, count: PeriodCount) -> Self {
Self {
length: *length,
count,
}
}

/// Returns a new `Period` from seconds.
pub const fn from_secs(seconds: u64, count: PeriodCount) -> Self {
Self {
length: Duration::from_secs(seconds),
count,
}
}

/// Return `Self.length` * `Self.count` as `Duration`.
pub fn total_time(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
match u32::try_from(self.count) {
Err(error) => Err(error),
Ok(count) => Ok(self.length.checked_mul(count)),
}
}

/// Return `Self.length` * (`Self.count` + 1) as `Duration`.
pub fn total_time_end(&self) -> Result<Option<PeriodTotalTime>, TryFromIntError> {
match u32::try_from(self.count) {
Err(e) => Err(e),
Ok(count) => match count.checked_add(1) {
None => Ok(None),
Some(count) => match self.length.checked_mul(count) {
None => Ok(None),
Some(time) => Ok(Some(time)),
},
},
}
}

/// Increase `Self.count` by `u64`.
pub fn add_count(&self, add: PeriodCount) -> Result<Period, IntErrorKind> {
match self.count.checked_add(add) {
None => Err(IntErrorKind::PosOverflow),
Some(count) => Ok(Self {
length: self.length,
count,
}),
}
}

/// Decrease `Self.count` by `u64`.
pub fn sub_count(&self, sub: PeriodCount) -> Result<Period, IntErrorKind> {
match self.count.checked_sub(sub) {
None => Err(IntErrorKind::NegOverflow),
Some(count) => Ok(Self {
length: self.length,
count,
}),
}
}
}

#[cfg(test)]
mod test {

use std::time::Duration;

use crate::protocol::clock::period::Period;

#[test]
fn it_should_get_the_total_time_of_a_period() {
assert_eq!(Period::default().total_time().unwrap().unwrap(), Duration::ZERO);

assert_eq!(
Period::from_secs(12, 12).total_time().unwrap().unwrap(),
Duration::from_secs(144)
);
assert_eq!(
Period::from_secs(12, 12).total_time_end().unwrap().unwrap(),
Duration::from_secs(156)
);
}
}
4 changes: 2 additions & 2 deletions src/protocol/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::net::SocketAddr;

use aquatic_udp_protocol::ConnectionId;

use super::clock::clock::{DefaultClock, SinceUnixEpoch, Time};
use super::clock::clock::{DefaultClock, DurationSinceUnixEpoch, Time};

pub fn get_connection_id(remote_address: &SocketAddr) -> ConnectionId {
ConnectionId(((current_time() / 3600) | ((remote_address.port() as u64) << 36)) as i64)
Expand All @@ -12,6 +12,6 @@ pub fn current_time() -> u64 {
DefaultClock::now().as_secs()
}

pub fn ser_unix_time_value<S: serde::Serializer>(unix_time_value: &SinceUnixEpoch, ser: S) -> Result<S::Ok, S::Error> {
pub fn ser_unix_time_value<S: serde::Serializer>(unix_time_value: &DurationSinceUnixEpoch, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_u64(unix_time_value.as_millis() as u64)
}
6 changes: 3 additions & 3 deletions src/tracker/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use serde::Serialize;

use crate::protocol::clock::clock::{DefaultClock, SinceUnixEpoch, Time, TimeNow};
use crate::protocol::clock::clock::{DefaultClock, DurationSinceUnixEpoch, Time, TimeNow};
use crate::AUTH_KEY_LENGTH;

pub fn generate_auth_key(lifetime: Duration) -> AuthKey {
Expand All @@ -25,7 +25,7 @@ pub fn generate_auth_key(lifetime: Duration) -> AuthKey {
}

pub fn verify_auth_key(auth_key: &AuthKey) -> Result<(), Error> {
let current_time: SinceUnixEpoch = DefaultClock::now();
let current_time: DurationSinceUnixEpoch = DefaultClock::now();
if auth_key.valid_until.is_none() {
return Err(Error::KeyInvalid);
}
Expand All @@ -39,7 +39,7 @@ pub fn verify_auth_key(auth_key: &AuthKey) -> Result<(), Error> {
#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
pub struct AuthKey {
pub key: String,
pub valid_until: Option<SinceUnixEpoch>,
pub valid_until: Option<DurationSinceUnixEpoch>,
}

impl AuthKey {
Expand Down
Loading