mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
switch to managers: wip
This commit is contained in:
committed by
Aiden McClelland
parent
e2b77b23f8
commit
34e4c12af3
@@ -1,24 +0,0 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use patch_db::DbHandle;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::{Error, HOST_IP};
|
||||
|
||||
pub const TLD: &'static str = "embassy";
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Hosts(pub IndexMap<PackageId, Ipv4Addr>);
|
||||
impl Hosts {
|
||||
pub fn docker_args(&self) -> Vec<OsString> {
|
||||
let mut res = Vec::with_capacity(self.0.len() + 1);
|
||||
res.push(format!("--add-host={}:{}", TLD, Ipv4Addr::from(HOST_IP)).into());
|
||||
for (id, ip) in &self.0 {
|
||||
res.push(format!("--add-host={}.{}:{}", id, TLD, ip).into());
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::Path;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
@@ -6,7 +5,7 @@ use serde::{Deserialize, Deserializer, Serialize};
|
||||
use sqlx::{Executor, Sqlite};
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
use crate::db::model::{InterfaceAddressMap, InterfaceAddresses, InterfaceInfo};
|
||||
use crate::db::model::{InterfaceAddressMap, InterfaceAddresses};
|
||||
use crate::id::Id;
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::util::Port;
|
||||
@@ -20,15 +19,11 @@ impl Interfaces {
|
||||
&self,
|
||||
secrets: &mut Ex,
|
||||
package_id: &PackageId,
|
||||
ip: Ipv4Addr,
|
||||
) -> Result<InterfaceInfo, Error>
|
||||
) -> Result<InterfaceAddressMap, Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
let mut interface_info = InterfaceInfo {
|
||||
ip,
|
||||
addresses: InterfaceAddressMap(IndexMap::new()),
|
||||
};
|
||||
let mut interface_addresses = InterfaceAddressMap(IndexMap::new());
|
||||
for (id, iface) in &self.0 {
|
||||
let mut addrs = InterfaceAddresses {
|
||||
tor_address: None,
|
||||
@@ -54,9 +49,9 @@ impl Interfaces {
|
||||
Some(format!("{}.local", onion.get_address_without_dot_onion()));
|
||||
}
|
||||
}
|
||||
interface_info.addresses.0.insert(id.clone(), addrs);
|
||||
interface_addresses.0.insert(id.clone(), addrs);
|
||||
}
|
||||
Ok(interface_info)
|
||||
Ok(interface_addresses)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,93 +1,77 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use avahi_sys::{
|
||||
self, avahi_client_free, avahi_entry_group_commit, avahi_entry_group_free,
|
||||
avahi_entry_group_reset, avahi_free, AvahiClient, AvahiEntryGroup,
|
||||
self, avahi_entry_group_commit, avahi_entry_group_free, avahi_entry_group_reset, avahi_free,
|
||||
AvahiEntryGroup,
|
||||
};
|
||||
use libc::c_void;
|
||||
use patch_db::{DbHandle, OptionModel};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::Mutex;
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
use super::interface::InterfaceId;
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::util::Apply;
|
||||
use crate::Error;
|
||||
|
||||
pub struct MdnsController(RwLock<MdnsControllerInner>);
|
||||
pub struct MdnsController(Mutex<MdnsControllerInner>);
|
||||
impl MdnsController {
|
||||
pub async fn init<Db: DbHandle>(db: &mut Db) -> Result<Self, Error> {
|
||||
Ok(MdnsController(RwLock::new(
|
||||
MdnsControllerInner::init(db).await?,
|
||||
)))
|
||||
pub fn init() -> Self {
|
||||
MdnsController(Mutex::new(MdnsControllerInner::init()))
|
||||
}
|
||||
pub async fn sync<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> {
|
||||
self.0.write().await.sync(db).await
|
||||
pub async fn add<'a, I: IntoIterator<Item = (InterfaceId, TorSecretKeyV3)>>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) {
|
||||
self.0.lock().await.add(pkg_id, interfaces)
|
||||
}
|
||||
pub async fn remove<I: IntoIterator<Item = InterfaceId>>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) {
|
||||
self.0.lock().await.remove(pkg_id, interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MdnsControllerInner {
|
||||
hostname: Vec<u8>,
|
||||
entry_group: *mut AvahiEntryGroup,
|
||||
services: HashMap<(PackageId, InterfaceId), TorSecretKeyV3>,
|
||||
}
|
||||
unsafe impl Send for MdnsControllerInner {}
|
||||
unsafe impl Sync for MdnsControllerInner {}
|
||||
|
||||
impl MdnsControllerInner {
|
||||
async fn load_services<Db: DbHandle>(&mut self, db: &mut Db) -> Result<(), Error> {
|
||||
fn load_services(&mut self) {
|
||||
unsafe {
|
||||
for app_id in crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.keys(db)
|
||||
.await?
|
||||
{
|
||||
let iface_model = if let Some(model) = crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&app_id)
|
||||
.expect(db)
|
||||
.await?
|
||||
.installed()
|
||||
.map(|i| i.interface_info().addresses())
|
||||
.apply(OptionModel::from)
|
||||
.check(db)
|
||||
.await?
|
||||
{
|
||||
model
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
for iface in iface_model.keys(db).await? {
|
||||
let lan_address = if let Some(addr) = iface_model
|
||||
.clone()
|
||||
.idx_model(&iface)
|
||||
.expect(db)
|
||||
.await?
|
||||
.lan_address()
|
||||
.get(db)
|
||||
.await?
|
||||
.to_owned()
|
||||
{
|
||||
addr
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let lan_address_ptr = std::ffi::CString::new(lan_address)
|
||||
.expect("Could not cast lan address to c string");
|
||||
let _ = avahi_sys::avahi_entry_group_add_record(
|
||||
self.entry_group,
|
||||
avahi_sys::AVAHI_IF_UNSPEC,
|
||||
avahi_sys::AVAHI_PROTO_UNSPEC,
|
||||
avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_USE_MULTICAST
|
||||
| avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_ALLOW_MULTIPLE,
|
||||
lan_address_ptr.as_ptr(),
|
||||
avahi_sys::AVAHI_DNS_CLASS_IN as u16,
|
||||
avahi_sys::AVAHI_DNS_TYPE_CNAME as u16,
|
||||
avahi_sys::AVAHI_DEFAULT_TTL,
|
||||
self.hostname.as_ptr().cast(),
|
||||
self.hostname.len(),
|
||||
);
|
||||
log::info!("Published {:?}", lan_address_ptr);
|
||||
}
|
||||
for key in self.services.values() {
|
||||
let lan_address = key
|
||||
.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion()
|
||||
+ ".local";
|
||||
let lan_address_ptr = std::ffi::CString::new(lan_address)
|
||||
.expect("Could not cast lan address to c string");
|
||||
let _ = avahi_sys::avahi_entry_group_add_record(
|
||||
self.entry_group,
|
||||
avahi_sys::AVAHI_IF_UNSPEC,
|
||||
avahi_sys::AVAHI_PROTO_UNSPEC,
|
||||
avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_USE_MULTICAST
|
||||
| avahi_sys::AvahiPublishFlags_AVAHI_PUBLISH_ALLOW_MULTIPLE,
|
||||
lan_address_ptr.as_ptr(),
|
||||
avahi_sys::AVAHI_DNS_CLASS_IN as u16,
|
||||
avahi_sys::AVAHI_DNS_TYPE_CNAME as u16,
|
||||
avahi_sys::AVAHI_DEFAULT_TTL,
|
||||
self.hostname.as_ptr().cast(),
|
||||
self.hostname.len(),
|
||||
);
|
||||
log::info!("Published {:?}", lan_address_ptr);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn init<Db: DbHandle>(db: &mut Db) -> Result<Self, Error> {
|
||||
fn init() -> Self {
|
||||
unsafe {
|
||||
// let app_list = crate::apps::list_info().await?;
|
||||
|
||||
@@ -118,22 +102,39 @@ impl MdnsControllerInner {
|
||||
hostname_buf[0] = (buflen - 8) as u8; // set the prefix length to len - 8 (leading byte, .local, nul) for the main address
|
||||
hostname_buf[buflen - 7] = 5; // set the prefix length to 5 for "local"
|
||||
|
||||
let mut ctrl = MdnsControllerInner {
|
||||
avahi_entry_group_commit(group);
|
||||
|
||||
MdnsControllerInner {
|
||||
hostname: hostname_buf,
|
||||
entry_group: group,
|
||||
};
|
||||
ctrl.load_services(db).await?;
|
||||
avahi_entry_group_commit(group);
|
||||
Ok(ctrl)
|
||||
services: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn sync<Db: DbHandle>(&mut self, db: &mut Db) -> Result<(), Error> {
|
||||
fn sync(&mut self) {
|
||||
unsafe {
|
||||
avahi_entry_group_reset(self.entry_group);
|
||||
self.load_services(db).await?;
|
||||
self.load_services();
|
||||
avahi_entry_group_commit(self.entry_group);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn add<'a, I: IntoIterator<Item = (InterfaceId, TorSecretKeyV3)>>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) {
|
||||
self.services.extend(
|
||||
interfaces
|
||||
.into_iter()
|
||||
.map(|(interface_id, key)| ((pkg_id.clone(), interface_id), key)),
|
||||
);
|
||||
self.sync();
|
||||
}
|
||||
fn remove<I: IntoIterator<Item = InterfaceId>>(&self, pkg_id: &PackageId, interfaces: I) {
|
||||
for interface_id in interfaces {
|
||||
self.services.remove(&(pkg_id.clone(), interface_id));
|
||||
}
|
||||
self.sync();
|
||||
}
|
||||
}
|
||||
impl Drop for MdnsControllerInner {
|
||||
|
||||
@@ -1,63 +1,72 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use id_pool::IdPool;
|
||||
use patch_db::HasModel;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
use self::host::Hosts;
|
||||
use self::interface::{Interface, InterfaceId};
|
||||
#[cfg(feature = "avahi")]
|
||||
use self::mdns::MdnsController;
|
||||
use self::tor::TorController;
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::{Error, ResultExt};
|
||||
|
||||
pub mod host;
|
||||
pub mod interface;
|
||||
#[cfg(feature = "avahi")]
|
||||
pub mod mdns;
|
||||
pub mod tor;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct IpPool(IdPool);
|
||||
impl IpPool {
|
||||
pub fn new() -> Self {
|
||||
let pool = IdPool::new();
|
||||
IpPool(pool)
|
||||
pub struct NetController {
|
||||
tor: TorController,
|
||||
#[cfg(feature = "avahi")]
|
||||
mdns: MdnsController,
|
||||
// nginx: NginxController, // TODO
|
||||
}
|
||||
impl NetController {
|
||||
pub async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
tor: TorController::init(tor_control).await?,
|
||||
#[cfg(feature = "avahi")]
|
||||
mdns: MdnsController::init(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get(&mut self) -> Option<Ipv4Addr> {
|
||||
let id = self.0.request_id()?;
|
||||
let ip = u32::from_be_bytes(crate::HOST_IP) + id as u32;
|
||||
Some(ip.into())
|
||||
pub async fn add<
|
||||
'a,
|
||||
I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)> + Clone,
|
||||
>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
ip: Ipv4Addr,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
let (tor_res, _) = tokio::join!(self.tor.add(pkg_id, ip, interfaces.clone()), {
|
||||
#[cfg(feature = "avahi")]
|
||||
let mdns_fut = self.mdns.add(
|
||||
pkg_id,
|
||||
interfaces
|
||||
.into_iter()
|
||||
.map(|(interface_id, _, key)| (interface_id, key)),
|
||||
);
|
||||
#[cfg(not(feature = "avahi"))]
|
||||
let mdns_fut = futures::future::ready(());
|
||||
mdns_fut
|
||||
},);
|
||||
tor_res?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn put(&mut self, ip: Ipv4Addr) {
|
||||
let ip = u32::from_be_bytes(ip.octets());
|
||||
let id = ip - u32::from_be_bytes(crate::HOST_IP);
|
||||
let _ = self.0.return_id(id as u16);
|
||||
}
|
||||
}
|
||||
impl Default for IpPool {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)]
|
||||
pub struct Network {
|
||||
pub ip_pool: IpPool,
|
||||
pub hosts: Hosts,
|
||||
}
|
||||
impl Network {
|
||||
pub fn register_host(&mut self, id: &PackageId) -> Result<Ipv4Addr, Error> {
|
||||
if let Some(exists) = self.hosts.0.get(id) {
|
||||
Ok(*exists)
|
||||
} else {
|
||||
let ip = self
|
||||
.ip_pool
|
||||
.get()
|
||||
.ok_or_else(|| anyhow!("No available IP addresses"))
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
self.hosts.0.insert(id.clone(), ip);
|
||||
Ok(ip)
|
||||
}
|
||||
pub async fn remove<I: IntoIterator<Item = InterfaceId> + Clone>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
let (tor_res, _) = tokio::join!(self.tor.remove(pkg_id, interfaces.clone()), {
|
||||
#[cfg(feature = "avahi")]
|
||||
let mdns_fut = self.mdns.remove(pkg_id, interfaces);
|
||||
#[cfg(not(feature = "avahi"))]
|
||||
let mdns_fut = futures::future::ready(());
|
||||
mdns_fut
|
||||
});
|
||||
tor_res?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
use std::collections::HashMap;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::FutureExt;
|
||||
use indexmap::IndexMap;
|
||||
use patch_db::DbHandle;
|
||||
use sqlx::{Executor, Sqlite};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::Mutex;
|
||||
use torut::control::{AsyncEvent, AuthenticatedConn, ConnError};
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
use super::interface::TorConfig;
|
||||
use super::interface::{Interface, InterfaceId, TorConfig};
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::{Error, ResultExt as _};
|
||||
|
||||
fn event_handler(event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>> {
|
||||
async move { Ok(()) }.boxed()
|
||||
}
|
||||
|
||||
pub struct TorController(RwLock<TorControllerInner>);
|
||||
pub struct TorController(Mutex<TorControllerInner>);
|
||||
impl TorController {
|
||||
pub async fn init<Db: DbHandle, Ex>(
|
||||
tor_cp: SocketAddr,
|
||||
db: &mut Db,
|
||||
secrets: &mut Ex,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
Ok(TorController(RwLock::new(
|
||||
TorControllerInner::init(tor_cp, db, secrets).await?,
|
||||
pub async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
|
||||
Ok(TorController(Mutex::new(
|
||||
TorControllerInner::init(tor_control).await?,
|
||||
)))
|
||||
}
|
||||
|
||||
pub async fn sync<Db: DbHandle, Ex>(&self, db: &mut Db, secrets: &mut Ex) -> Result<(), Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
let new = TorControllerInner::get_services(db, secrets).await?;
|
||||
if &new != &self.0.read().await.services {
|
||||
self.0.write().await.sync(new).await?;
|
||||
}
|
||||
Ok(())
|
||||
pub async fn add<
|
||||
'a,
|
||||
I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)> + Clone,
|
||||
>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
ip: Ipv4Addr,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
self.0.lock().await.add(pkg_id, ip, interfaces).await
|
||||
}
|
||||
|
||||
pub async fn remove<I: IntoIterator<Item = InterfaceId> + Clone>(
|
||||
&self,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
self.0.lock().await.remove(pkg_id, interfaces).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,149 +59,70 @@ struct HiddenServiceConfig {
|
||||
|
||||
pub struct TorControllerInner {
|
||||
connection: AuthenticatedConnection,
|
||||
services: IndexMap<[u8; 64], HiddenServiceConfig>,
|
||||
services: HashMap<(PackageId, InterfaceId), TorSecretKeyV3>,
|
||||
}
|
||||
impl TorControllerInner {
|
||||
async fn get_services<Db: DbHandle, Ex>(
|
||||
db: &mut Db,
|
||||
secrets: &mut Ex,
|
||||
) -> Result<IndexMap<[u8; 64], HiddenServiceConfig>, Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
let pkg_ids = crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.keys(db)
|
||||
.await?;
|
||||
let mut services = IndexMap::new();
|
||||
for pkg_id in pkg_ids {
|
||||
if let Some(installed) = crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&pkg_id)
|
||||
.expect(db)
|
||||
.await?
|
||||
.installed()
|
||||
.check(db)
|
||||
.await?
|
||||
{
|
||||
let ifaces = installed
|
||||
.clone()
|
||||
.manifest()
|
||||
.interfaces()
|
||||
.get(db)
|
||||
.await?
|
||||
.to_owned();
|
||||
for (iface_id, cfgs) in ifaces.0 {
|
||||
if let Some(tor_cfg) = cfgs.tor_config {
|
||||
if let Some(key) = sqlx::query!(
|
||||
"SELECT key FROM tor WHERE package = ? AND interface = ?",
|
||||
*pkg_id,
|
||||
*iface_id,
|
||||
)
|
||||
.fetch_optional(&mut *secrets)
|
||||
.await?
|
||||
{
|
||||
if key.key.len() != 64 {
|
||||
return Err(Error::new(
|
||||
anyhow!("Invalid key length"),
|
||||
crate::ErrorKind::Database,
|
||||
));
|
||||
}
|
||||
let mut buf = [0; 64];
|
||||
buf.clone_from_slice(&key.key);
|
||||
services.insert(
|
||||
buf,
|
||||
HiddenServiceConfig {
|
||||
ip: installed
|
||||
.clone()
|
||||
.interface_info()
|
||||
.ip()
|
||||
.get(db)
|
||||
.await?
|
||||
.to_owned(),
|
||||
cfg: tor_cfg,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(services)
|
||||
}
|
||||
|
||||
async fn add_svc(
|
||||
async fn add<'a, I: IntoIterator<Item = (InterfaceId, &'a Interface, TorSecretKeyV3)>>(
|
||||
&mut self,
|
||||
key: &TorSecretKeyV3,
|
||||
config: &HiddenServiceConfig,
|
||||
pkg_id: &PackageId,
|
||||
ip: Ipv4Addr,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
self.connection
|
||||
.add_onion_v3(
|
||||
key,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
&mut config
|
||||
.cfg
|
||||
.port_mapping
|
||||
.iter()
|
||||
.map(|(external, internal)| {
|
||||
(external.0, SocketAddr::from((config.ip, internal.0)))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.iter(),
|
||||
)
|
||||
.await?;
|
||||
for (interface_id, interface, key) in interfaces {
|
||||
let id = (pkg_id.clone(), interface_id);
|
||||
match self.services.get(&id) {
|
||||
Some(k) if k != &key => {
|
||||
self.remove(pkg_id, std::iter::once(id.1.clone())).await?;
|
||||
}
|
||||
Some(_) => return Ok(()),
|
||||
None => (),
|
||||
}
|
||||
if let Some(tor_cfg) = &interface.tor_config {
|
||||
self.connection
|
||||
.add_onion_v3(
|
||||
&key,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
&mut tor_cfg
|
||||
.port_mapping
|
||||
.iter()
|
||||
.map(|(external, internal)| {
|
||||
(external.0, SocketAddr::from((ip, internal.0)))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.iter(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
self.services.insert(id, key);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn sync(
|
||||
async fn remove<I: IntoIterator<Item = InterfaceId>>(
|
||||
&mut self,
|
||||
services: IndexMap<[u8; 64], HiddenServiceConfig>,
|
||||
pkg_id: &PackageId,
|
||||
interfaces: I,
|
||||
) -> Result<(), Error> {
|
||||
for (key, new) in &services {
|
||||
let tor_key = TorSecretKeyV3::from(key.clone());
|
||||
if let Some(old) = self.services.remove(&key[..]) {
|
||||
if new != &old {
|
||||
self.connection
|
||||
.del_onion(
|
||||
&tor_key
|
||||
.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion(),
|
||||
)
|
||||
.await?;
|
||||
self.add_svc(&tor_key, new).await?;
|
||||
}
|
||||
} else {
|
||||
self.add_svc(&tor_key, new).await?;
|
||||
for interface_id in interfaces {
|
||||
if let Some(key) = self.services.remove(&(pkg_id.clone(), interface_id)) {
|
||||
self.connection
|
||||
.del_onion(
|
||||
&key.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
for (key, _) in self.services.drain(..) {
|
||||
self.connection
|
||||
.del_onion(
|
||||
&TorSecretKeyV3::from(key)
|
||||
.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
self.services = services;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn init<Db: DbHandle, Ex>(
|
||||
tor_cp: SocketAddr,
|
||||
db: &mut Db,
|
||||
secrets: &mut Ex,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
async fn init(tor_control: SocketAddr) -> Result<Self, Error> {
|
||||
let mut conn = torut::control::UnauthenticatedConn::new(
|
||||
TcpStream::connect(tor_cp).await?, // TODO
|
||||
TcpStream::connect(tor_control).await?, // TODO
|
||||
);
|
||||
let auth = conn
|
||||
.load_protocol_info()
|
||||
@@ -212,12 +133,10 @@ impl TorControllerInner {
|
||||
conn.authenticate(&auth).await?;
|
||||
let mut connection: AuthenticatedConnection = conn.into_authenticated().await;
|
||||
connection.set_async_event_handler(Some(event_handler));
|
||||
let mut res = TorControllerInner {
|
||||
Ok(TorControllerInner {
|
||||
connection,
|
||||
services: IndexMap::new(),
|
||||
};
|
||||
res.sync(Self::get_services(db, secrets).await?).await?;
|
||||
Ok(res)
|
||||
services: HashMap::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user