Commit 8a998337 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Implement the guard side of shared state directories.

parent fdddb74d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ pub enum Error {

    /// Problem creating or updating a guard manager.
    #[error("Problem creating or updating guards list: {0}")]
    GuardMgr(#[from] tor_guardmgr::GuardMgrError),
    GuardMgr(#[source] tor_guardmgr::GuardMgrError),

    /// Problem selecting a guard relay.
    #[error("Unable to select a guard relay: {0}")]
@@ -84,3 +84,12 @@ impl From<tor_rtcompat::TimeoutError> for Error {
        Error::CircTimeout
    }
}

impl From<tor_guardmgr::GuardMgrError> for Error {
    fn from(err: tor_guardmgr::GuardMgrError) -> Error {
        match err {
            tor_guardmgr::GuardMgrError::State(e) => Error::State(e),
            _ => Error::GuardMgr(err),
        }
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -201,6 +201,20 @@ impl Guard {
        self.reachable
    }

    /// Copy all _non-persistent_ status from `other` to self.
    ///
    /// Requires that the two `Guard`s have the same ID.
    pub(crate) fn copy_status_from(&mut self, other: &Guard) {
        debug_assert_eq!(self.id, other.id);

        self.last_tried_to_connect_at = other.last_tried_to_connect_at;
        self.retry_at = other.retry_at;
        self.reachable = other.reachable;
        self.failing_since = other.failing_since;
        self.is_dir_cache = other.is_dir_cache;
        self.exploratory_circ_pending = other.exploratory_circ_pending;
    }

    /// Change the reachability status for this guard.
    fn set_reachable(&mut self, r: Reachable) {
        if self.reachable != r {
+18 −2
Original line number Diff line number Diff line
@@ -288,7 +288,11 @@ impl<R: Runtime> GuardMgr<R> {
    /// We only call this method if we _don't_ have the lock on the state
    /// files.  If we have the lock, we only want to save.
    pub fn reload_persistent_state(&self) -> Result<(), GuardMgrError> {
        warn!("Not yet implemented");
        let mut inner = self.inner.lock().expect("Poisoned lock");
        if let Some(new_guards) = inner.default_storage.load()? {
            let now = self.runtime.wallclock();
            inner.replace_guards_with(new_guards, now);
        }
        Ok(())
    }

@@ -296,7 +300,11 @@ impl<R: Runtime> GuardMgr<R> {
    ///
    /// Requires that we hold the lock on the state files.
    pub fn upgrade_to_owned_persistent_state(&self) -> Result<(), GuardMgrError> {
        warn!("Not yet implemented");
        let mut inner = self.inner.lock().expect("Poisoned lock");
        debug_assert!(inner.default_storage.can_store());
        let new_guards = inner.default_storage.load()?.unwrap_or_else(GuardSet::new);
        let now = self.runtime.wallclock();
        inner.replace_guards_with(new_guards, now);
        Ok(())
    }

@@ -492,6 +500,14 @@ impl GuardMgrInner {
        self.active_guards.select_primary_guards(&self.params);
    }

    /// Replace the active guard set with `new_guards`, preserving
    /// non-persistent state for any guards that are retained.
    fn replace_guards_with(&mut self, mut new_guards: GuardSet, now: SystemTime) {
        new_guards.copy_status_from(&self.active_guards);
        self.active_guards = new_guards;
        self.update(now, None);
    }

    /// Called when the circuit manager reports (via [`GuardMonitor`]) that
    /// a guard succeeded or failed.
    ///
+9 −0
Original line number Diff line number Diff line
@@ -163,6 +163,15 @@ impl GuardSet {
        self.primary_guards_invalidated = true;
    }

    /// Copy non-persistent status from every guard shared with `other`.
    pub(crate) fn copy_status_from(&mut self, other: &GuardSet) {
        for (id, guard) in self.guards.iter_mut() {
            if let Some(other_guard) = other.get(id) {
                guard.copy_status_from(other_guard);
            }
        }
    }

    /// Return a serializable state object that can be stored to disk
    /// to capture the current state of this GuardSet.
    fn get_state(&self) -> GuardSample<'_> {