mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
wip refactor
This commit is contained in:
@@ -3,19 +3,23 @@ use std::future::Future;
|
||||
use std::panic::RefUnwindSafe;
|
||||
|
||||
use clap::Parser;
|
||||
use imbl::OrdMap;
|
||||
use imbl_value::InternedString;
|
||||
use itertools::Itertools;
|
||||
use patch_db::DestructureMut;
|
||||
use rpc_toolkit::{Context, Empty, HandlerExt, OrEmpty, ParentHandler, from_fn_async};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::context::RpcContext;
|
||||
use crate::db::model::DatabaseModel;
|
||||
use crate::db::model::public::NetworkInterfaceInfo;
|
||||
use crate::net::forward::AvailablePorts;
|
||||
use crate::net::host::address::{HostAddress, PublicDomainConfig, address_api};
|
||||
use crate::net::host::binding::{BindInfo, BindOptions, Bindings, binding};
|
||||
use crate::net::service_interface::{HostnameInfo, HostnameMetadata};
|
||||
use crate::prelude::*;
|
||||
use crate::{HostId, PackageId};
|
||||
use crate::{GatewayId, HostId, PackageId};
|
||||
|
||||
pub mod address;
|
||||
pub mod binding;
|
||||
@@ -27,7 +31,7 @@ pub mod binding;
|
||||
pub struct Host {
|
||||
pub bindings: Bindings,
|
||||
pub public_domains: BTreeMap<InternedString, PublicDomainConfig>,
|
||||
pub private_domains: BTreeSet<InternedString>,
|
||||
pub private_domains: BTreeMap<InternedString, BTreeSet<GatewayId>>,
|
||||
}
|
||||
|
||||
impl AsRef<Host> for Host {
|
||||
@@ -45,20 +49,183 @@ impl Host {
|
||||
.map(|(address, config)| HostAddress {
|
||||
address: address.clone(),
|
||||
public: Some(config.clone()),
|
||||
private: self.private_domains.contains(address),
|
||||
private: self.private_domains.get(address).cloned(),
|
||||
})
|
||||
.chain(
|
||||
self.private_domains
|
||||
.iter()
|
||||
.filter(|a| !self.public_domains.contains_key(*a))
|
||||
.map(|address| HostAddress {
|
||||
address: address.clone(),
|
||||
.filter(|(domain, _)| !self.public_domains.contains_key(*domain))
|
||||
.map(|(domain, gateways)| HostAddress {
|
||||
address: domain.clone(),
|
||||
public: None,
|
||||
private: true,
|
||||
private: Some(gateways.clone()),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Model<Host> {
|
||||
pub fn update_addresses(
|
||||
&mut self,
|
||||
gateways: &OrdMap<GatewayId, NetworkInterfaceInfo>,
|
||||
available_ports: &AvailablePorts,
|
||||
) -> Result<(), Error> {
|
||||
let this = self.destructure_mut();
|
||||
for (_, bind) in this.bindings.as_entries_mut()? {
|
||||
let net = bind.as_net().de()?;
|
||||
let opt = bind.as_options().de()?;
|
||||
let mut available = BTreeSet::new();
|
||||
for (gid, g) in gateways {
|
||||
let Some(ip_info) = &g.ip_info else {
|
||||
continue;
|
||||
};
|
||||
let gateway_secure = g.secure();
|
||||
for subnet in &ip_info.subnets {
|
||||
let host = InternedString::from_display(&subnet.addr());
|
||||
let metadata = if subnet.addr().is_ipv4() {
|
||||
HostnameMetadata::Ipv4 {
|
||||
gateway: gid.clone(),
|
||||
}
|
||||
} else {
|
||||
HostnameMetadata::Ipv6 {
|
||||
gateway: gid.clone(),
|
||||
scope_id: ip_info.scope_id,
|
||||
}
|
||||
};
|
||||
if let Some(port) = net.assigned_port.filter(|_| {
|
||||
opt.secure
|
||||
.map_or(gateway_secure, |s| !(s.ssl && opt.add_ssl.is_some()))
|
||||
}) {
|
||||
available.insert(HostnameInfo {
|
||||
ssl: opt.secure.map_or(false, |s| s.ssl),
|
||||
public: false,
|
||||
host: host.clone(),
|
||||
port: Some(port),
|
||||
metadata: metadata.clone(),
|
||||
});
|
||||
}
|
||||
if let Some(port) = net.assigned_ssl_port {
|
||||
available.insert(HostnameInfo {
|
||||
ssl: true,
|
||||
public: false,
|
||||
host: host.clone(),
|
||||
port: Some(port),
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(wan_ip) = &ip_info.wan_ip {
|
||||
let host = InternedString::from_display(&wan_ip);
|
||||
let metadata = HostnameMetadata::Ipv4 {
|
||||
gateway: gid.clone(),
|
||||
};
|
||||
if let Some(port) = net.assigned_port.filter(|_| {
|
||||
opt.secure.map_or(
|
||||
false, // the public internet is never secure
|
||||
|s| !(s.ssl && opt.add_ssl.is_some()),
|
||||
)
|
||||
}) {
|
||||
available.insert(HostnameInfo {
|
||||
ssl: opt.secure.map_or(false, |s| s.ssl),
|
||||
public: true,
|
||||
host: host.clone(),
|
||||
port: Some(port),
|
||||
metadata: metadata.clone(),
|
||||
});
|
||||
}
|
||||
if let Some(port) = net.assigned_ssl_port {
|
||||
available.insert(HostnameInfo {
|
||||
ssl: true,
|
||||
public: true,
|
||||
host: host.clone(),
|
||||
port: Some(port),
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
for (domain, info) in this.public_domains.de()? {
|
||||
let metadata = HostnameMetadata::PublicDomain {
|
||||
gateway: info.gateway.clone(),
|
||||
};
|
||||
if let Some(port) = net.assigned_port.filter(|_| {
|
||||
opt.secure.map_or(
|
||||
false, // the public internet is never secure
|
||||
|s| !(s.ssl && opt.add_ssl.is_some()),
|
||||
)
|
||||
}) {
|
||||
available.insert(HostnameInfo {
|
||||
ssl: opt.secure.map_or(false, |s| s.ssl),
|
||||
public: true,
|
||||
host: domain.clone(),
|
||||
port: Some(port),
|
||||
metadata: metadata.clone(),
|
||||
});
|
||||
}
|
||||
if let Some(mut port) = net.assigned_ssl_port {
|
||||
if let Some(preferred) = opt
|
||||
.add_ssl
|
||||
.as_ref()
|
||||
.map(|s| s.preferred_external_port)
|
||||
.filter(|p| available_ports.is_ssl(*p))
|
||||
{
|
||||
port = preferred;
|
||||
}
|
||||
available.insert(HostnameInfo {
|
||||
ssl: true,
|
||||
public: true,
|
||||
host: domain.clone(),
|
||||
port: Some(port),
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
}
|
||||
for (domain, domain_gateways) in this.private_domains.de()? {
|
||||
if let Some(port) = net.assigned_port.filter(|_| {
|
||||
opt.secure
|
||||
.map_or(true, |s| !(s.ssl && opt.add_ssl.is_some()))
|
||||
}) {
|
||||
let gateways = if opt.secure.is_some() {
|
||||
domain_gateways.clone()
|
||||
} else {
|
||||
domain_gateways
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|g| gateways.get(g).map_or(false, |g| g.secure()))
|
||||
.collect()
|
||||
};
|
||||
available.insert(HostnameInfo {
|
||||
ssl: opt.secure.map_or(false, |s| s.ssl),
|
||||
public: true,
|
||||
host: domain.clone(),
|
||||
port: Some(port),
|
||||
metadata: HostnameMetadata::PrivateDomain { gateways },
|
||||
});
|
||||
}
|
||||
if let Some(mut port) = net.assigned_ssl_port {
|
||||
if let Some(preferred) = opt
|
||||
.add_ssl
|
||||
.as_ref()
|
||||
.map(|s| s.preferred_external_port)
|
||||
.filter(|p| available_ports.is_ssl(*p))
|
||||
{
|
||||
port = preferred;
|
||||
}
|
||||
available.insert(HostnameInfo {
|
||||
ssl: true,
|
||||
public: true,
|
||||
host: domain.clone(),
|
||||
port: Some(port),
|
||||
metadata: HostnameMetadata::PrivateDomain {
|
||||
gateways: domain_gateways,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
bind.as_addresses_mut().as_available_mut().ser(&available)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
|
||||
#[model = "Model<Self>"]
|
||||
|
||||
Reference in New Issue
Block a user