Loading crates/arti-client/src/client.rs +65 −0 Viewed Changes for crates/arti-client/src/client.rs: 65 added lines, 0 removed lines. Original line number Original line Diff line number Diff line Loading @@ -12,6 +12,8 @@ use tor_basic_utils::futures::{DropNotifyWatchSender, PostageWatchSenderExt}; use tor_circmgr::isolation::Isolation; use tor_circmgr::isolation::Isolation; use tor_circmgr::{isolation::StreamIsolationBuilder, IsolationToken, TargetPort}; use tor_circmgr::{isolation::StreamIsolationBuilder, IsolationToken, TargetPort}; use tor_config::MutCfg; use tor_config::MutCfg; #[cfg(feature = "bridge-client")] use tor_dirmgr::bridgedesc::BridgeDescMgr; use tor_dirmgr::{DirMgrStore, Timeliness}; use tor_dirmgr::{DirMgrStore, Timeliness}; use tor_error::{internal, Bug}; use tor_error::{internal, Bug}; use tor_guardmgr::GuardMgr; use tor_guardmgr::GuardMgr; Loading Loading @@ -70,10 +72,23 @@ pub struct TorClient<R: Runtime> { /// them on-demand. /// them on-demand. circmgr: Arc<tor_circmgr::CircMgr<R>>, circmgr: Arc<tor_circmgr::CircMgr<R>>, /// Directory manager persistent storage. /// Directory manager persistent storage. #[cfg_attr(not(feature = "bridge-client"), allow(dead_code))] dirmgr_store: DirMgrStore<R>, dirmgr_store: DirMgrStore<R>, /// Directory manager for keeping our directory material up to date. /// Directory manager for keeping our directory material up to date. dirmgr: Arc<dyn tor_dirmgr::DirProvider>, dirmgr: Arc<dyn tor_dirmgr::DirProvider>, /// Bridge descriptor manager /// /// None until we have bootstrapped. /// /// Lock hierarchy: don't acquire this before dormant // // TODO: after or as part of https://gitlab.torproject.org/tpo/core/arti/-/issues/634 // this can be bridge_desc_mgr: BridgeDescMgr<R>> // since BridgeDescMgr is Clone and all its methods take `&self` (it has a lock inside) #[cfg(feature = "bridge-client")] bridge_desc_mgr: Arc<Mutex<Option<BridgeDescMgr<R>>>>, /// Guard manager /// Guard manager #[cfg_attr(not(feature = "bridge-client"), allow(dead_code))] guardmgr: GuardMgr<R>, guardmgr: GuardMgr<R>, /// Location on disk where we store persistent data. /// Location on disk where we store persistent data. statemgr: FsStateMgr, statemgr: FsStateMgr, Loading Loading @@ -168,6 +183,15 @@ impl From<DormantMode> for tor_chanmgr::Dormancy { } } } } } } #[cfg(feature = "bridge-client")] impl From<DormantMode> for tor_dirmgr::bridgedesc::Dormancy { fn from(dormant: DormantMode) -> tor_dirmgr::bridgedesc::Dormancy { match dormant { DormantMode::Normal => tor_dirmgr::bridgedesc::Dormancy::Active, DormantMode::Soft => tor_dirmgr::bridgedesc::Dormancy::Dormant, } } } impl StreamPrefs { impl StreamPrefs { /// Construct a new StreamPrefs. /// Construct a new StreamPrefs. Loading Loading @@ -452,12 +476,16 @@ impl<R: Runtime> TorClient<R> { let (dormant_send, dormant_recv) = postage::watch::channel_with(dormant); let (dormant_send, dormant_recv) = postage::watch::channel_with(dormant); let dormant_send = DropNotifyWatchSender::new(dormant_send); let dormant_send = DropNotifyWatchSender::new(dormant_send); #[cfg(feature = "bridge-client")] let bridge_desc_mgr = Arc::new(Mutex::new(None)); runtime runtime .spawn(tasks_monitor_dormant( .spawn(tasks_monitor_dormant( dormant_recv, dormant_recv, dirmgr.clone().upcast_arc(), dirmgr.clone().upcast_arc(), chanmgr.clone(), chanmgr.clone(), #[cfg(feature = "bridge-client")] bridge_desc_mgr.clone(), periodic_task_handles, periodic_task_handles, )) )) .map_err(|e| ErrorDetail::from_spawn("periodic task dormant monitor", e))?; .map_err(|e| ErrorDetail::from_spawn("periodic task dormant monitor", e))?; Loading @@ -484,6 +512,8 @@ impl<R: Runtime> TorClient<R> { circmgr, circmgr, dirmgr_store, dirmgr_store, dirmgr, dirmgr, #[cfg(feature = "bridge-client")] bridge_desc_mgr, guardmgr, guardmgr, statemgr, statemgr, addrcfg: Arc::new(addr_cfg.into()), addrcfg: Arc::new(addr_cfg.into()), Loading Loading @@ -521,6 +551,31 @@ impl<R: Runtime> TorClient<R> { /// Implementation of `bootstrap`, split out in order to avoid manually specifying /// Implementation of `bootstrap`, split out in order to avoid manually specifying /// double error conversions. /// double error conversions. async fn bootstrap_inner(&self) -> StdResult<(), ErrorDetail> { async fn bootstrap_inner(&self) -> StdResult<(), ErrorDetail> { // Make sure we have a bridge descriptor manager, which is active iff required #[cfg(feature = "bridge-client")] { let mut dormant = self.dormant.lock().expect("dormant lock poisoned"); let dormant = dormant.borrow(); let dormant = dormant.ok_or_else(|| internal!("dormant dropped"))?.into(); let mut bdm = self.bridge_desc_mgr.lock().expect("bdm lock poisoned"); if bdm.is_none() { let new_bdm = BridgeDescMgr::new( &Default::default(), self.runtime.clone(), self.dirmgr_store.clone(), self.circmgr.clone(), dormant, )?; self.guardmgr .install_bridge_desc_provider(&(Arc::new(new_bdm.clone()) as _)) .map_err(ErrorDetail::GuardMgrSetup)?; // If ^ that fails, we drop the BridgeDescMgr again. It may do some // work but will hopefully eventually quit. *bdm = Some(new_bdm); } } // Wait for an existing bootstrap attempt to finish first. // Wait for an existing bootstrap attempt to finish first. // // // This is a futures::lock::Mutex, so it's okay to await while we hold it. // This is a futures::lock::Mutex, so it's okay to await while we hold it. Loading Loading @@ -999,6 +1054,7 @@ async fn tasks_monitor_dormant<R: Runtime>( mut dormant_rx: postage::watch::Receiver<DormantMode>, mut dormant_rx: postage::watch::Receiver<DormantMode>, netdir: Arc<dyn NetDirProvider>, netdir: Arc<dyn NetDirProvider>, chanmgr: Arc<tor_chanmgr::ChanMgr<R>>, chanmgr: Arc<tor_chanmgr::ChanMgr<R>>, #[cfg(feature = "bridge-client")] bridge_desc_mgr: Arc<Mutex<Option<BridgeDescMgr<R>>>>, periodic_task_handles: Vec<TaskHandle>, periodic_task_handles: Vec<TaskHandle>, ) { ) { while let Some(mode) = dormant_rx.next().await { while let Some(mode) = dormant_rx.next().await { Loading @@ -1008,6 +1064,15 @@ async fn tasks_monitor_dormant<R: Runtime>( .set_dormancy(mode.into(), netparams) .set_dormancy(mode.into(), netparams) .unwrap_or_else(|e| error!("set dormancy: {}", e)); .unwrap_or_else(|e| error!("set dormancy: {}", e)); // IEFI simplifies handling of exceptional cases, as "never mind, then". #[cfg(feature = "bridge-client")] (|| { let mut bdm = bridge_desc_mgr.lock().ok()?; let bdm = bdm.as_mut()?; bdm.set_dormancy(mode.into()); Some(()) })(); let is_dormant = matches!(mode, DormantMode::Soft); let is_dormant = matches!(mode, DormantMode::Soft); for task in periodic_task_handles.iter() { for task in periodic_task_handles.iter() { Loading crates/arti-client/src/err.rs +7 −0 Viewed Changes for crates/arti-client/src/err.rs: 7 added lines, 0 removed lines. Original line number Original line Diff line number Diff line Loading @@ -125,6 +125,11 @@ enum ErrorDetail { #[error("Error setting up the circuit manager")] #[error("Error setting up the circuit manager")] CircMgrSetup(#[source] tor_circmgr::Error), CircMgrSetup(#[source] tor_circmgr::Error), /// Error setting up the bridge descriptor manager #[error("Error setting up the bridge descriptor managerr")] #[cfg(feature = "bridge-client")] BridgeDescMgrSetup(#[from] tor_dirmgr::bridgedesc::StartupError), /// Error setting up the directory manager /// Error setting up the directory manager // TODO: should "dirmgr setup error" be its own type in tor-dirmgr? // TODO: should "dirmgr setup error" be its own type in tor-dirmgr? #[error("Error setting up the directory manager")] #[error("Error setting up the directory manager")] Loading Loading @@ -289,6 +294,8 @@ impl tor_error::HasKind for ErrorDetail { E::ExitTimeout => EK::RemoteNetworkTimeout, E::ExitTimeout => EK::RemoteNetworkTimeout, E::BootstrapRequired { .. } => EK::BootstrapRequired, E::BootstrapRequired { .. } => EK::BootstrapRequired, E::GuardMgrSetup(e) => e.kind(), E::GuardMgrSetup(e) => e.kind(), #[cfg(feature = "bridge-client")] E::BridgeDescMgrSetup(e) => e.kind(), E::CircMgrSetup(e) => e.kind(), E::CircMgrSetup(e) => e.kind(), E::DirMgrSetup(e) => e.kind(), E::DirMgrSetup(e) => e.kind(), E::StateMgrSetup(e) => e.kind(), E::StateMgrSetup(e) => e.kind(), Loading Loading
crates/arti-client/src/client.rs +65 −0 Viewed Changes for crates/arti-client/src/client.rs: 65 added lines, 0 removed lines. Original line number Original line Diff line number Diff line Loading @@ -12,6 +12,8 @@ use tor_basic_utils::futures::{DropNotifyWatchSender, PostageWatchSenderExt}; use tor_circmgr::isolation::Isolation; use tor_circmgr::isolation::Isolation; use tor_circmgr::{isolation::StreamIsolationBuilder, IsolationToken, TargetPort}; use tor_circmgr::{isolation::StreamIsolationBuilder, IsolationToken, TargetPort}; use tor_config::MutCfg; use tor_config::MutCfg; #[cfg(feature = "bridge-client")] use tor_dirmgr::bridgedesc::BridgeDescMgr; use tor_dirmgr::{DirMgrStore, Timeliness}; use tor_dirmgr::{DirMgrStore, Timeliness}; use tor_error::{internal, Bug}; use tor_error::{internal, Bug}; use tor_guardmgr::GuardMgr; use tor_guardmgr::GuardMgr; Loading Loading @@ -70,10 +72,23 @@ pub struct TorClient<R: Runtime> { /// them on-demand. /// them on-demand. circmgr: Arc<tor_circmgr::CircMgr<R>>, circmgr: Arc<tor_circmgr::CircMgr<R>>, /// Directory manager persistent storage. /// Directory manager persistent storage. #[cfg_attr(not(feature = "bridge-client"), allow(dead_code))] dirmgr_store: DirMgrStore<R>, dirmgr_store: DirMgrStore<R>, /// Directory manager for keeping our directory material up to date. /// Directory manager for keeping our directory material up to date. dirmgr: Arc<dyn tor_dirmgr::DirProvider>, dirmgr: Arc<dyn tor_dirmgr::DirProvider>, /// Bridge descriptor manager /// /// None until we have bootstrapped. /// /// Lock hierarchy: don't acquire this before dormant // // TODO: after or as part of https://gitlab.torproject.org/tpo/core/arti/-/issues/634 // this can be bridge_desc_mgr: BridgeDescMgr<R>> // since BridgeDescMgr is Clone and all its methods take `&self` (it has a lock inside) #[cfg(feature = "bridge-client")] bridge_desc_mgr: Arc<Mutex<Option<BridgeDescMgr<R>>>>, /// Guard manager /// Guard manager #[cfg_attr(not(feature = "bridge-client"), allow(dead_code))] guardmgr: GuardMgr<R>, guardmgr: GuardMgr<R>, /// Location on disk where we store persistent data. /// Location on disk where we store persistent data. statemgr: FsStateMgr, statemgr: FsStateMgr, Loading Loading @@ -168,6 +183,15 @@ impl From<DormantMode> for tor_chanmgr::Dormancy { } } } } } } #[cfg(feature = "bridge-client")] impl From<DormantMode> for tor_dirmgr::bridgedesc::Dormancy { fn from(dormant: DormantMode) -> tor_dirmgr::bridgedesc::Dormancy { match dormant { DormantMode::Normal => tor_dirmgr::bridgedesc::Dormancy::Active, DormantMode::Soft => tor_dirmgr::bridgedesc::Dormancy::Dormant, } } } impl StreamPrefs { impl StreamPrefs { /// Construct a new StreamPrefs. /// Construct a new StreamPrefs. Loading Loading @@ -452,12 +476,16 @@ impl<R: Runtime> TorClient<R> { let (dormant_send, dormant_recv) = postage::watch::channel_with(dormant); let (dormant_send, dormant_recv) = postage::watch::channel_with(dormant); let dormant_send = DropNotifyWatchSender::new(dormant_send); let dormant_send = DropNotifyWatchSender::new(dormant_send); #[cfg(feature = "bridge-client")] let bridge_desc_mgr = Arc::new(Mutex::new(None)); runtime runtime .spawn(tasks_monitor_dormant( .spawn(tasks_monitor_dormant( dormant_recv, dormant_recv, dirmgr.clone().upcast_arc(), dirmgr.clone().upcast_arc(), chanmgr.clone(), chanmgr.clone(), #[cfg(feature = "bridge-client")] bridge_desc_mgr.clone(), periodic_task_handles, periodic_task_handles, )) )) .map_err(|e| ErrorDetail::from_spawn("periodic task dormant monitor", e))?; .map_err(|e| ErrorDetail::from_spawn("periodic task dormant monitor", e))?; Loading @@ -484,6 +512,8 @@ impl<R: Runtime> TorClient<R> { circmgr, circmgr, dirmgr_store, dirmgr_store, dirmgr, dirmgr, #[cfg(feature = "bridge-client")] bridge_desc_mgr, guardmgr, guardmgr, statemgr, statemgr, addrcfg: Arc::new(addr_cfg.into()), addrcfg: Arc::new(addr_cfg.into()), Loading Loading @@ -521,6 +551,31 @@ impl<R: Runtime> TorClient<R> { /// Implementation of `bootstrap`, split out in order to avoid manually specifying /// Implementation of `bootstrap`, split out in order to avoid manually specifying /// double error conversions. /// double error conversions. async fn bootstrap_inner(&self) -> StdResult<(), ErrorDetail> { async fn bootstrap_inner(&self) -> StdResult<(), ErrorDetail> { // Make sure we have a bridge descriptor manager, which is active iff required #[cfg(feature = "bridge-client")] { let mut dormant = self.dormant.lock().expect("dormant lock poisoned"); let dormant = dormant.borrow(); let dormant = dormant.ok_or_else(|| internal!("dormant dropped"))?.into(); let mut bdm = self.bridge_desc_mgr.lock().expect("bdm lock poisoned"); if bdm.is_none() { let new_bdm = BridgeDescMgr::new( &Default::default(), self.runtime.clone(), self.dirmgr_store.clone(), self.circmgr.clone(), dormant, )?; self.guardmgr .install_bridge_desc_provider(&(Arc::new(new_bdm.clone()) as _)) .map_err(ErrorDetail::GuardMgrSetup)?; // If ^ that fails, we drop the BridgeDescMgr again. It may do some // work but will hopefully eventually quit. *bdm = Some(new_bdm); } } // Wait for an existing bootstrap attempt to finish first. // Wait for an existing bootstrap attempt to finish first. // // // This is a futures::lock::Mutex, so it's okay to await while we hold it. // This is a futures::lock::Mutex, so it's okay to await while we hold it. Loading Loading @@ -999,6 +1054,7 @@ async fn tasks_monitor_dormant<R: Runtime>( mut dormant_rx: postage::watch::Receiver<DormantMode>, mut dormant_rx: postage::watch::Receiver<DormantMode>, netdir: Arc<dyn NetDirProvider>, netdir: Arc<dyn NetDirProvider>, chanmgr: Arc<tor_chanmgr::ChanMgr<R>>, chanmgr: Arc<tor_chanmgr::ChanMgr<R>>, #[cfg(feature = "bridge-client")] bridge_desc_mgr: Arc<Mutex<Option<BridgeDescMgr<R>>>>, periodic_task_handles: Vec<TaskHandle>, periodic_task_handles: Vec<TaskHandle>, ) { ) { while let Some(mode) = dormant_rx.next().await { while let Some(mode) = dormant_rx.next().await { Loading @@ -1008,6 +1064,15 @@ async fn tasks_monitor_dormant<R: Runtime>( .set_dormancy(mode.into(), netparams) .set_dormancy(mode.into(), netparams) .unwrap_or_else(|e| error!("set dormancy: {}", e)); .unwrap_or_else(|e| error!("set dormancy: {}", e)); // IEFI simplifies handling of exceptional cases, as "never mind, then". #[cfg(feature = "bridge-client")] (|| { let mut bdm = bridge_desc_mgr.lock().ok()?; let bdm = bdm.as_mut()?; bdm.set_dormancy(mode.into()); Some(()) })(); let is_dormant = matches!(mode, DormantMode::Soft); let is_dormant = matches!(mode, DormantMode::Soft); for task in periodic_task_handles.iter() { for task in periodic_task_handles.iter() { Loading
crates/arti-client/src/err.rs +7 −0 Viewed Changes for crates/arti-client/src/err.rs: 7 added lines, 0 removed lines. Original line number Original line Diff line number Diff line Loading @@ -125,6 +125,11 @@ enum ErrorDetail { #[error("Error setting up the circuit manager")] #[error("Error setting up the circuit manager")] CircMgrSetup(#[source] tor_circmgr::Error), CircMgrSetup(#[source] tor_circmgr::Error), /// Error setting up the bridge descriptor manager #[error("Error setting up the bridge descriptor managerr")] #[cfg(feature = "bridge-client")] BridgeDescMgrSetup(#[from] tor_dirmgr::bridgedesc::StartupError), /// Error setting up the directory manager /// Error setting up the directory manager // TODO: should "dirmgr setup error" be its own type in tor-dirmgr? // TODO: should "dirmgr setup error" be its own type in tor-dirmgr? #[error("Error setting up the directory manager")] #[error("Error setting up the directory manager")] Loading Loading @@ -289,6 +294,8 @@ impl tor_error::HasKind for ErrorDetail { E::ExitTimeout => EK::RemoteNetworkTimeout, E::ExitTimeout => EK::RemoteNetworkTimeout, E::BootstrapRequired { .. } => EK::BootstrapRequired, E::BootstrapRequired { .. } => EK::BootstrapRequired, E::GuardMgrSetup(e) => e.kind(), E::GuardMgrSetup(e) => e.kind(), #[cfg(feature = "bridge-client")] E::BridgeDescMgrSetup(e) => e.kind(), E::CircMgrSetup(e) => e.kind(), E::CircMgrSetup(e) => e.kind(), E::DirMgrSetup(e) => e.kind(), E::DirMgrSetup(e) => e.kind(), E::StateMgrSetup(e) => e.kind(), E::StateMgrSetup(e) => e.kind(), Loading