use std::sync::Arc;
use tor_chanmgr::Dormancy;
use tor_config_path::CfgPathResolver;
use tor_error::internal;
use tor_keymgr::{
ArtiEphemeralKeystore, ArtiNativeKeystore, KeyMgr, KeyMgrBuilder, KeystoreSelector,
};
use tor_memquota::ArcMemoryQuotaTrackerExt as _;
use tor_netdir::params::NetParameters;
use tor_proto::memquota::ToplevelAccount;
use tor_relay_crypto::pk::{RelayIdentityKeypair, RelayIdentityKeypairSpecifier};
use tor_rtcompat::Runtime;
use tracing::info;
use crate::config::TorRelayConfig;
use crate::err::ErrorDetail;
#[derive(Clone)]
pub(crate) struct TorRelay<R: Runtime> {
#[allow(unused)] runtime: R,
#[allow(unused)] path_resolver: CfgPathResolver,
#[allow(unused)] chanmgr: Arc<tor_chanmgr::ChanMgr<R>>,
#[allow(unused)] keymgr: Arc<KeyMgr>,
}
impl<R: Runtime> TorRelay<R> {
pub(crate) fn new(
runtime: R,
config: &TorRelayConfig,
path_resolver: CfgPathResolver,
) -> Result<Self, ErrorDetail> {
let keymgr = Self::create_keymgr(config, &path_resolver)?;
let chanmgr = Arc::new(tor_chanmgr::ChanMgr::new(
runtime.clone(),
&config.channel,
Dormancy::Active,
&NetParameters::default(),
ToplevelAccount::new_noop(), ));
Ok(Self {
runtime,
path_resolver,
chanmgr,
keymgr,
})
}
fn create_keymgr(
config: &TorRelayConfig,
path_resolver: &CfgPathResolver,
) -> Result<Arc<KeyMgr>, ErrorDetail> {
let key_store_dir = config.storage.keystore_dir(path_resolver)?;
let permissions = config.storage.permissions();
let ephemeral_store = ArtiEphemeralKeystore::new("relay-ephemeral".into());
let persistent_store =
ArtiNativeKeystore::from_path_and_mistrust(&key_store_dir, permissions)?;
info!("Using relay keystore from {key_store_dir:?}");
let keymgr = Arc::new(
KeyMgrBuilder::default()
.primary_store(Box::new(persistent_store))
.set_secondary_stores(vec![Box::new(ephemeral_store)])
.build()
.map_err(|e| internal!("Failed to build KeyMgr: {e}"))?,
);
Self::try_generate_keys(&keymgr)?;
Ok(keymgr)
}
fn try_generate_keys(keymgr: &KeyMgr) -> Result<(), ErrorDetail> {
let mut rng = tor_llcrypto::rng::CautiousRng;
let _kp_relay_id = keymgr.get_or_generate::<RelayIdentityKeypair>(
&RelayIdentityKeypairSpecifier::new(),
KeystoreSelector::default(),
&mut rng,
)?;
Ok(())
}
}