use std::sync::Arc;
use anyhow::Context;
use tor_chanmgr::ChanMgr;
use tor_circmgr::{CircMgr, CircMgrConfig};
use tor_dirmgr::{DirMgr, DirMgrConfig, DirMgrStore, DirProvider};
use tor_guardmgr::{GuardMgr, GuardMgrConfig};
use tor_persist::FsStateMgr;
use tor_rtcompat::Runtime;
use tor_rtcompat::scheduler::TaskHandle;
pub(crate) struct RelayClient<R: Runtime> {
runtime: R,
state_mgr: FsStateMgr,
#[expect(unused)] chanmgr: Arc<ChanMgr<R>>,
#[expect(unused)] guardmgr: GuardMgr<R>,
circmgr: Arc<CircMgr<R>>,
dirmgr: Arc<dyn DirProvider>,
}
impl<R: Runtime> RelayClient<R> {
pub(crate) fn new(
runtime: R,
chanmgr: Arc<ChanMgr<R>>,
guardmgr_config: &impl GuardMgrConfig,
circmgr_config: &impl CircMgrConfig,
dirmgr_config: DirMgrConfig,
state_mgr: FsStateMgr,
) -> anyhow::Result<Self> {
let guardmgr = GuardMgr::new(runtime.clone(), state_mgr.clone(), guardmgr_config)
.context("Failed to initialize the guard manager")?;
let circmgr = Arc::new(
CircMgr::new(
circmgr_config,
state_mgr.clone(),
&runtime,
Arc::clone(&chanmgr),
&guardmgr,
)
.context("Failed to initialize the circuit manager")?,
);
let dirmgr_store =
DirMgrStore::new(&dirmgr_config, runtime.clone(), false)
.context("Failed to initialize directory store")?;
let dirmgr = Arc::new(
DirMgr::create_unbootstrapped(
dirmgr_config,
runtime.clone(),
dirmgr_store,
Arc::clone(&circmgr),
)
.context("Failed to initialize the directory manager")?,
);
Ok(Self {
runtime,
state_mgr,
chanmgr,
guardmgr,
circmgr,
dirmgr,
})
}
pub(crate) fn launch_background_tasks(&self) -> anyhow::Result<Vec<TaskHandle>> {
self.circmgr
.launch_background_tasks(&self.runtime, &self.dirmgr, self.state_mgr.clone())
.context("Failed to launch circuit manager background tasks")
}
pub(crate) async fn bootstrap(&self) -> anyhow::Result<()> {
self.dirmgr
.bootstrap()
.await
.context("Failed to bootstrap the directory manager")?;
Ok(())
}
pub(crate) fn dirmgr(&self) -> &Arc<dyn DirProvider> {
&self.dirmgr
}
}