GuardMgr/DirMgr: Add APIs for bridge descriptor lists
This commit is contained in:
parent
571e7f9556
commit
1196e1b680
|
@ -15,6 +15,7 @@ repository = "https://gitlab.torproject.org/tpo/core/arti.git/"
|
|||
default = ["mmap"]
|
||||
full = ["routerdesc"]
|
||||
experimental = ["experimental-api", "dirfilter"]
|
||||
bridge-client = ["tor-guardmgr/bridge-client", "routerdesc"]
|
||||
|
||||
mmap = ["memmap2"]
|
||||
static = ["rusqlite/bundled"]
|
||||
|
|
|
@ -153,6 +153,7 @@ pub trait DirProvider: NetDirProvider {
|
|||
|
||||
// NOTE(eta): We can't implement this for Arc<DirMgr<R>> due to trait coherence rules, so instead
|
||||
// there's a blanket impl for Arc<T> in tor-netdir.
|
||||
// TODO pt-client: Also implement BridgeDescProvider for DirMgr.
|
||||
impl<R: Runtime> NetDirProvider for DirMgr<R> {
|
||||
fn netdir(&self, timeliness: Timeliness) -> tor_netdir::Result<Arc<NetDir>> {
|
||||
use tor_netdir::Error as NetDirError;
|
||||
|
|
|
@ -12,12 +12,12 @@ categories = ["network-programming", "cryptography"]
|
|||
repository = "https://gitlab.torproject.org/tpo/core/arti.git/"
|
||||
|
||||
[features]
|
||||
default = ["bridge-client"]
|
||||
default = []
|
||||
|
||||
# Support for using bridges as a client. Note that this is not the same as
|
||||
# other crates' pt-client feature, since here we are not concerned with
|
||||
# pluggable transports necessarily.
|
||||
bridge-client = []
|
||||
bridge-client = ["tor-netdoc/routerdesc"]
|
||||
|
||||
# Enable testing-only APIs. APIs under this feature are not
|
||||
# covered by semver.
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
//! When a client is configured to use bridges, it uses them in place of its
|
||||
//! regular set of guards in building the first hop of its circuits.
|
||||
//
|
||||
// TODO pt-client: Put this whole module behind a "bridge" feature?
|
||||
// TODO pt-client: Should this whole module be in another crate?
|
||||
|
||||
mod config;
|
||||
mod descs;
|
||||
|
||||
pub use config::Bridge;
|
||||
pub use descs::{BridgeDescEvent, BridgeDescList, BridgeDescProvider};
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
//! Code for working with bridge descriptors.
|
||||
//!
|
||||
//! Here we need to keep track of which bridge descriptors we need, and inform
|
||||
//! the directory manager of them.
|
||||
|
||||
// TODO pt-client: remove these "allow"s.
|
||||
#![allow(clippy::missing_panics_doc)]
|
||||
#![allow(dead_code, unused_variables, clippy::needless_pass_by_value)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::stream::BoxStream;
|
||||
use tor_linkspec::{OwnedChanTarget, RelayId, RelayIds};
|
||||
|
||||
// TODO pt-client: I think we may want another layer of abstraction between
|
||||
// RouterDesc and BridgeDesc, to implement e.g. CircTarget for RouterDesc.
|
||||
// Likely it should contain an Arc<RouterDesc>.
|
||||
use tor_netdoc::doc::routerdesc::RouterDesc as BridgeDesc;
|
||||
|
||||
/// This is analogous to NetDirProvider.
|
||||
///
|
||||
/// TODO pt-client: improve documentation.
|
||||
pub trait BridgeDescProvider {
|
||||
/// Return the current set of bridge descriptors.
|
||||
fn bridges(&self) -> Arc<BridgeDescList>;
|
||||
/// Return a stream that gets a notification when the set of bridge
|
||||
/// descriptors has changed.
|
||||
fn events(&self) -> BoxStream<'static, BridgeDescEvent>;
|
||||
|
||||
/// Change the set of bridges that we want to download descriptors for.
|
||||
///
|
||||
/// Bridges outside of this set will not have their descriptors updated,
|
||||
/// and will not be revealed in the BridgeDescList.
|
||||
fn set_bridges(&self, bridges: &[OwnedChanTarget]);
|
||||
}
|
||||
|
||||
/// An event describing a change in a `BridgeDescList`.
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum BridgeDescEvent {
|
||||
/// A new descriptor has arrived
|
||||
//
|
||||
// TODO: (Should we do anything to indicate which one? If so, we
|
||||
// won't be able to use a flag-based publisher.)
|
||||
NewDesc,
|
||||
}
|
||||
|
||||
/// A set of bridge descriptors, managed and modified by a BridgeDescProvider.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BridgeDescList {
|
||||
/// The known bridges.
|
||||
///
|
||||
/// TODO pt-client: This is almost certainly the wrong data structure; some
|
||||
/// kind of ID-based hashmap is likelier to be right.
|
||||
///
|
||||
/// TODO pt-client: Maybe we should have an intermediary struct between
|
||||
/// RouterDescriptors and "usable bridge", as we have for `Relay`.
|
||||
bridges: Vec<BridgeDesc>,
|
||||
}
|
||||
|
||||
impl BridgeDescList {
|
||||
/// Return the bridge descriptor, if any, for the given `RelayId`.
|
||||
pub fn by_id(&self, id: &RelayId) -> Option<&BridgeDesc> {
|
||||
todo!() // TODO pt-client: implement.
|
||||
}
|
||||
|
||||
/// Return the bridge descriptor, if any, that has all of the given `RelayIds`.
|
||||
pub fn by_ids(&self, id: &RelayIds) -> Option<&BridgeDesc> {
|
||||
todo!() // TODO pt-client: implement.
|
||||
}
|
||||
|
||||
/// Return an iterator over every bridge descriptor in this list.
|
||||
///
|
||||
/// No bridge descriptors will be returned more than once, and no more than
|
||||
/// one descriptor will be returned for any given `RelayId`.
|
||||
pub fn bridges(&self) -> impl Iterator<Item = &BridgeDesc> {
|
||||
todo!(); // TODO pt-client: implement.
|
||||
#[allow(unreachable_code)]
|
||||
[].iter()
|
||||
}
|
||||
|
||||
/// Insert `desc` into this list of bridges.
|
||||
///
|
||||
/// Replace every already-existing descriptor that shares any identity with
|
||||
/// `desc`.
|
||||
pub fn insert(&mut self, desc: BridgeDesc) {
|
||||
todo!() // TODO pt-client: implement.
|
||||
}
|
||||
|
||||
/// Drop every member of this list for which `func` returns false.
|
||||
pub fn retain<F>(&mut self, func: F)
|
||||
where
|
||||
F: FnMut(&BridgeDesc) -> bool,
|
||||
{
|
||||
todo!() // TODO pt-client: implement.
|
||||
}
|
||||
}
|
|
@ -416,6 +416,18 @@ impl<R: Runtime> GuardMgr<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Configure a new BridgeDescProvider.
|
||||
///
|
||||
/// TODO pt-client: give this more documentation, like install_netdir_provider has.
|
||||
#[cfg(feature = "bridge-client")]
|
||||
#[allow(clippy::needless_pass_by_value, clippy::missing_panics_doc)]
|
||||
pub fn install_bridge_desc_provider<T>(
|
||||
&self,
|
||||
_provider: Arc<dyn bridge::BridgeDescProvider>,
|
||||
) -> Result<(), GuardMgrError> {
|
||||
todo!() // TODO pt-client: Implement this and remove the clippy exceptions above.
|
||||
}
|
||||
|
||||
/// Flush our current guard state to the state manager, if there
|
||||
/// is any unsaved state.
|
||||
pub fn store_persistent_state(&self) -> Result<(), GuardMgrError> {
|
||||
|
|
Loading…
Reference in New Issue