mod builder;
pub use builder::{HiddenServiceBuilder, HiddenServiceBuilderError, HsFlags};
mod controller;
pub use controller::{HiddenServiceController, HiddenServiceControllerError};
mod proxy_opts;
use std::fmt;
use derivative::Derivative;
pub use proxy_opts::TorProxyOpts;
use serde_derive::{Deserialize, Serialize};
use tari_shutdown::OptionalShutdownSignal;
use crate::{
multiaddr::Multiaddr,
tor::{PrivateKey, TorClientError},
};
#[derive(Clone)]
pub struct HiddenService {
pub(super) identity: TorIdentity,
pub(super) proxied_addr: Multiaddr,
pub(super) shutdown_signal: OptionalShutdownSignal,
}
impl HiddenService {
pub fn get_onion_address(&self) -> Multiaddr {
multiaddr_from_service_id_and_port(self.service_id(), self.identity.onion_port)
.expect("failed to create onion address from HiddenService service_id and onion_port")
}
pub fn service_id(&self) -> &str {
&self.identity.service_id
}
pub fn proxied_address(&self) -> &Multiaddr {
&self.proxied_addr
}
pub fn tor_identity(&self) -> &TorIdentity {
&self.identity
}
}
fn multiaddr_from_service_id_and_port(service_id: &str, onion_port: u16) -> Result<Multiaddr, TorClientError> {
const ONION_V2_LEN: usize = 16;
const ONION_V3_LEN: usize = 56;
match service_id.len() {
ONION_V2_LEN => format!("/onion/{service_id}:{onion_port}")
.parse()
.map_err(|_| TorClientError::InvalidServiceId),
ONION_V3_LEN => {
format!("/onion3/{service_id}:{onion_port}")
.parse()
.map_err(|_| TorClientError::InvalidServiceId)
},
_ => Err(TorClientError::InvalidServiceId),
}
}
#[derive(Clone, Derivative, Serialize, Deserialize)]
#[derivative(Debug)]
pub struct TorIdentity {
#[derivative(Debug = "ignore")]
pub private_key: PrivateKey,
pub service_id: String,
pub onion_port: u16,
}
impl TorIdentity {
pub fn try_get_onion_address(&self) -> Result<Multiaddr, TorClientError> {
multiaddr_from_service_id_and_port(&self.service_id, self.onion_port)
}
}
impl fmt::Display for TorIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Service ID: {}", self.service_id)?;
writeln!(f, "Port: {}", self.onion_port)?;
Ok(())
}
}