mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
feat: add mdns hostname metadata variant and fix vhost routing
- Add HostnameMetadata::Mdns variant to distinguish mDNS from private domains - Mark mDNS addresses as private (public: false) since mDNS is local-only - Fall back to null SNI entry when hostname not found in vhost mapping - Simplify public detection in ProxyTarget filter - Pass hostname to update_addresses for mDNS domain name generation
This commit is contained in:
@@ -16,16 +16,16 @@ The container runtime communicates with the host via JSON-RPC over Unix socket.
|
|||||||
|
|
||||||
## `/media/startos/` Directory (mounted by host into container)
|
## `/media/startos/` Directory (mounted by host into container)
|
||||||
|
|
||||||
| Path | Description |
|
| Path | Description |
|
||||||
|------|-------------|
|
| -------------------- | ----------------------------------------------------- |
|
||||||
| `volumes/<name>/` | Package data volumes (id-mapped, persistent) |
|
| `volumes/<name>/` | Package data volumes (id-mapped, persistent) |
|
||||||
| `assets/` | Read-only assets from s9pk `assets.squashfs` |
|
| `assets/` | Read-only assets from s9pk `assets.squashfs` |
|
||||||
| `images/<name>/` | Container images (squashfs, used for subcontainers) |
|
| `images/<name>/` | Container images (squashfs, used for subcontainers) |
|
||||||
| `images/<name>.env` | Environment variables for image |
|
| `images/<name>.env` | Environment variables for image |
|
||||||
| `images/<name>.json` | Image metadata |
|
| `images/<name>.json` | Image metadata |
|
||||||
| `backup/` | Backup mount point (mounted during backup operations) |
|
| `backup/` | Backup mount point (mounted during backup operations) |
|
||||||
| `rpc/service.sock` | RPC socket (container runtime listens here) |
|
| `rpc/service.sock` | RPC socket (container runtime listens here) |
|
||||||
| `rpc/host.sock` | Host RPC socket (for effects callbacks to host) |
|
| `rpc/host.sock` | Host RPC socket (for effects callbacks to host) |
|
||||||
|
|
||||||
## S9PK Structure
|
## S9PK Structure
|
||||||
|
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ export class DockerProcedureContainer extends Drop {
|
|||||||
`${packageId}.embassy`,
|
`${packageId}.embassy`,
|
||||||
...new Set(
|
...new Set(
|
||||||
Object.values(hostInfo?.bindings || {})
|
Object.values(hostInfo?.bindings || {})
|
||||||
.flatMap((b) => b.addresses.possible)
|
.flatMap((b) => b.addresses.available)
|
||||||
.map((h) => h.hostname.value),
|
.map((h) => h.host),
|
||||||
).values(),
|
).values(),
|
||||||
]
|
]
|
||||||
const certChain = await effects.getSslCertificate({
|
const certChain = await effects.getSslCertificate({
|
||||||
|
|||||||
@@ -1245,7 +1245,7 @@ async function updateConfig(
|
|||||||
: catchFn(
|
: catchFn(
|
||||||
() =>
|
() =>
|
||||||
filled.addressInfo!.filter({ kind: "mdns" })!.hostnames[0]
|
filled.addressInfo!.filter({ kind: "mdns" })!.hostnames[0]
|
||||||
.hostname.value,
|
.host,
|
||||||
) || ""
|
) || ""
|
||||||
mutConfigValue[key] = url
|
mutConfigValue[key] = url
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1005,9 +1005,10 @@ impl NetworkInterfaceController {
|
|||||||
.as_network_mut()
|
.as_network_mut()
|
||||||
.as_gateways_mut()
|
.as_gateways_mut()
|
||||||
.ser(info)?;
|
.ser(info)?;
|
||||||
|
let hostname = crate::hostname::Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
for host in all_hosts(db) {
|
for host in all_hosts(db) {
|
||||||
host?.update_addresses(info, &ports)?;
|
host?.update_addresses(&hostname, info, &ports)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use ts_rs::TS;
|
|||||||
use crate::GatewayId;
|
use crate::GatewayId;
|
||||||
use crate::context::{CliContext, RpcContext};
|
use crate::context::{CliContext, RpcContext};
|
||||||
use crate::db::model::DatabaseModel;
|
use crate::db::model::DatabaseModel;
|
||||||
|
use crate::hostname::Hostname;
|
||||||
use crate::net::acme::AcmeProvider;
|
use crate::net::acme::AcmeProvider;
|
||||||
use crate::net::host::{HostApiKind, all_hosts};
|
use crate::net::host::{HostApiKind, all_hosts};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@@ -194,9 +195,10 @@ pub async fn add_public_domain<Kind: HostApiKind>(
|
|||||||
.as_public_domains_mut()
|
.as_public_domains_mut()
|
||||||
.insert(&fqdn, &PublicDomainConfig { acme, gateway })?;
|
.insert(&fqdn, &PublicDomainConfig { acme, gateway })?;
|
||||||
handle_duplicates(db)?;
|
handle_duplicates(db)?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
Kind::host_for(&inheritance, db)?.update_addresses(&gateways, &ports)
|
Kind::host_for(&inheritance, db)?.update_addresses(&hostname, &gateways, &ports)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.result?;
|
.result?;
|
||||||
@@ -225,9 +227,10 @@ pub async fn remove_public_domain<Kind: HostApiKind>(
|
|||||||
Kind::host_for(&inheritance, db)?
|
Kind::host_for(&inheritance, db)?
|
||||||
.as_public_domains_mut()
|
.as_public_domains_mut()
|
||||||
.remove(&fqdn)?;
|
.remove(&fqdn)?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
Kind::host_for(&inheritance, db)?.update_addresses(&gateways, &ports)
|
Kind::host_for(&inheritance, db)?.update_addresses(&hostname, &gateways, &ports)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.result?;
|
.result?;
|
||||||
@@ -255,9 +258,10 @@ pub async fn add_private_domain<Kind: HostApiKind>(
|
|||||||
.upsert(&fqdn, || Ok(BTreeSet::new()))?
|
.upsert(&fqdn, || Ok(BTreeSet::new()))?
|
||||||
.mutate(|d| Ok(d.insert(gateway)))?;
|
.mutate(|d| Ok(d.insert(gateway)))?;
|
||||||
handle_duplicates(db)?;
|
handle_duplicates(db)?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
Kind::host_for(&inheritance, db)?.update_addresses(&gateways, &ports)
|
Kind::host_for(&inheritance, db)?.update_addresses(&hostname, &gateways, &ports)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.result?;
|
.result?;
|
||||||
@@ -276,9 +280,10 @@ pub async fn remove_private_domain<Kind: HostApiKind>(
|
|||||||
Kind::host_for(&inheritance, db)?
|
Kind::host_for(&inheritance, db)?
|
||||||
.as_private_domains_mut()
|
.as_private_domains_mut()
|
||||||
.mutate(|d| Ok(d.remove(&domain)))?;
|
.mutate(|d| Ok(d.remove(&domain)))?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
Kind::host_for(&inheritance, db)?.update_addresses(&gateways, &ports)
|
Kind::host_for(&inheritance, db)?.update_addresses(&hostname, &gateways, &ports)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.result?;
|
.result?;
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ use ts_rs::TS;
|
|||||||
|
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
use crate::db::model::DatabaseModel;
|
use crate::db::model::DatabaseModel;
|
||||||
use crate::db::model::public::NetworkInterfaceInfo;
|
use crate::db::model::public::{NetworkInterfaceInfo, NetworkInterfaceType};
|
||||||
|
use crate::hostname::Hostname;
|
||||||
use crate::net::forward::AvailablePorts;
|
use crate::net::forward::AvailablePorts;
|
||||||
use crate::net::host::address::{HostAddress, PublicDomainConfig, address_api};
|
use crate::net::host::address::{HostAddress, PublicDomainConfig, address_api};
|
||||||
use crate::net::host::binding::{BindInfo, BindOptions, Bindings, binding};
|
use crate::net::host::binding::{BindInfo, BindOptions, Bindings, binding};
|
||||||
@@ -66,10 +67,13 @@ impl Host {
|
|||||||
impl Model<Host> {
|
impl Model<Host> {
|
||||||
pub fn update_addresses(
|
pub fn update_addresses(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
mdns: &Hostname,
|
||||||
gateways: &OrdMap<GatewayId, NetworkInterfaceInfo>,
|
gateways: &OrdMap<GatewayId, NetworkInterfaceInfo>,
|
||||||
available_ports: &AvailablePorts,
|
available_ports: &AvailablePorts,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let this = self.destructure_mut();
|
let this = self.destructure_mut();
|
||||||
|
|
||||||
|
// ips
|
||||||
for (_, bind) in this.bindings.as_entries_mut()? {
|
for (_, bind) in this.bindings.as_entries_mut()? {
|
||||||
let net = bind.as_net().de()?;
|
let net = bind.as_net().de()?;
|
||||||
let opt = bind.as_options().de()?;
|
let opt = bind.as_options().de()?;
|
||||||
@@ -143,6 +147,46 @@ impl Model<Host> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mdns
|
||||||
|
let mdns_host = mdns.local_domain_name();
|
||||||
|
let mdns_gateways: BTreeSet<GatewayId> = gateways
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, g)| {
|
||||||
|
matches!(
|
||||||
|
g.ip_info.as_ref().and_then(|i| i.device_type),
|
||||||
|
Some(NetworkInterfaceType::Ethernet | NetworkInterfaceType::Wireless)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(id, _)| id.clone())
|
||||||
|
.collect();
|
||||||
|
if let Some(port) = net.assigned_port.filter(|_| {
|
||||||
|
opt.secure
|
||||||
|
.map_or(true, |s| !(s.ssl && opt.add_ssl.is_some()))
|
||||||
|
}) {
|
||||||
|
available.insert(HostnameInfo {
|
||||||
|
ssl: opt.secure.map_or(false, |s| s.ssl),
|
||||||
|
public: false,
|
||||||
|
host: mdns_host.clone(),
|
||||||
|
port: Some(port),
|
||||||
|
metadata: HostnameMetadata::Mdns {
|
||||||
|
gateways: mdns_gateways.clone(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(mut port) = net.assigned_ssl_port {
|
||||||
|
available.insert(HostnameInfo {
|
||||||
|
ssl: true,
|
||||||
|
public: false,
|
||||||
|
host: mdns_host,
|
||||||
|
port: Some(port),
|
||||||
|
metadata: HostnameMetadata::Mdns {
|
||||||
|
gateways: mdns_gateways,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// public domains
|
||||||
for (domain, info) in this.public_domains.de()? {
|
for (domain, info) in this.public_domains.de()? {
|
||||||
let metadata = HostnameMetadata::PublicDomain {
|
let metadata = HostnameMetadata::PublicDomain {
|
||||||
gateway: info.gateway.clone(),
|
gateway: info.gateway.clone(),
|
||||||
@@ -173,12 +217,14 @@ impl Model<Host> {
|
|||||||
available.insert(HostnameInfo {
|
available.insert(HostnameInfo {
|
||||||
ssl: true,
|
ssl: true,
|
||||||
public: true,
|
public: true,
|
||||||
host: domain.clone(),
|
host: domain,
|
||||||
port: Some(port),
|
port: Some(port),
|
||||||
metadata,
|
metadata,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private domains
|
||||||
for (domain, domain_gateways) in this.private_domains.de()? {
|
for (domain, domain_gateways) in this.private_domains.de()? {
|
||||||
if let Some(port) = net.assigned_port.filter(|_| {
|
if let Some(port) = net.assigned_port.filter(|_| {
|
||||||
opt.secure
|
opt.secure
|
||||||
@@ -213,7 +259,7 @@ impl Model<Host> {
|
|||||||
available.insert(HostnameInfo {
|
available.insert(HostnameInfo {
|
||||||
ssl: true,
|
ssl: true,
|
||||||
public: true,
|
public: true,
|
||||||
host: domain.clone(),
|
host: domain,
|
||||||
port: Some(port),
|
port: Some(port),
|
||||||
metadata: HostnameMetadata::PrivateDomain {
|
metadata: HostnameMetadata::PrivateDomain {
|
||||||
gateways: domain_gateways,
|
gateways: domain_gateways,
|
||||||
|
|||||||
@@ -539,10 +539,11 @@ impl NetService {
|
|||||||
.as_network()
|
.as_network()
|
||||||
.as_gateways()
|
.as_gateways()
|
||||||
.de()?;
|
.de()?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let mut ports = db.as_private().as_available_ports().de()?;
|
let mut ports = db.as_private().as_available_ports().de()?;
|
||||||
let host = host_for(db, pkg_id.as_ref(), &id)?;
|
let host = host_for(db, pkg_id.as_ref(), &id)?;
|
||||||
host.add_binding(&mut ports, internal_port, options)?;
|
host.add_binding(&mut ports, internal_port, options)?;
|
||||||
host.update_addresses(&gateways, &ports)?;
|
host.update_addresses(&hostname, &gateways, &ports)?;
|
||||||
db.as_private_mut().as_available_ports_mut().ser(&ports)?;
|
db.as_private_mut().as_available_ports_mut().ser(&ports)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@@ -563,6 +564,7 @@ impl NetService {
|
|||||||
.as_network()
|
.as_network()
|
||||||
.as_gateways()
|
.as_gateways()
|
||||||
.de()?;
|
.de()?;
|
||||||
|
let hostname = Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
if let Some(ref pkg_id) = pkg_id {
|
if let Some(ref pkg_id) = pkg_id {
|
||||||
for (host_id, host) in db
|
for (host_id, host) in db
|
||||||
@@ -584,7 +586,7 @@ impl NetService {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
host.update_addresses(&gateways, &ports)?;
|
host.update_addresses(&hostname, &gateways, &ports)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let host = db
|
let host = db
|
||||||
@@ -603,7 +605,7 @@ impl NetService {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
host.update_addresses(&gateways, &ports)?;
|
host.update_addresses(&hostname, &gateways, &ports)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ pub enum HostnameMetadata {
|
|||||||
gateway: GatewayId,
|
gateway: GatewayId,
|
||||||
scope_id: u32,
|
scope_id: u32,
|
||||||
},
|
},
|
||||||
|
Mdns {
|
||||||
|
gateways: BTreeSet<GatewayId>,
|
||||||
|
},
|
||||||
PrivateDomain {
|
PrivateDomain {
|
||||||
gateways: BTreeSet<GatewayId>,
|
gateways: BTreeSet<GatewayId>,
|
||||||
},
|
},
|
||||||
@@ -67,7 +70,9 @@ impl HostnameMetadata {
|
|||||||
Self::Ipv4 { gateway }
|
Self::Ipv4 { gateway }
|
||||||
| Self::Ipv6 { gateway, .. }
|
| Self::Ipv6 { gateway, .. }
|
||||||
| Self::PublicDomain { gateway } => Box::new(std::iter::once(gateway)),
|
| Self::PublicDomain { gateway } => Box::new(std::iter::once(gateway)),
|
||||||
Self::PrivateDomain { gateways } => Box::new(gateways.iter()),
|
Self::PrivateDomain { gateways } | Self::Mdns { gateways } => {
|
||||||
|
Box::new(gateways.iter())
|
||||||
|
}
|
||||||
Self::Plugin { .. } => Box::new(std::iter::empty()),
|
Self::Plugin { .. } => Box::new(std::iter::empty()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,13 +175,14 @@ pub async fn remove_tunnel(
|
|||||||
|
|
||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| {
|
.mutate(|db| {
|
||||||
|
let hostname = crate::hostname::Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
for host in all_hosts(db) {
|
for host in all_hosts(db) {
|
||||||
let host = host?;
|
let host = host?;
|
||||||
host.as_public_domains_mut()
|
host.as_public_domains_mut()
|
||||||
.mutate(|p| Ok(p.retain(|_, v| v.gateway != id)))?;
|
.mutate(|p| Ok(p.retain(|_, v| v.gateway != id)))?;
|
||||||
host.update_addresses(&gateways, &ports)?;
|
host.update_addresses(&hostname, &gateways, &ports)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -193,6 +194,7 @@ pub async fn remove_tunnel(
|
|||||||
|
|
||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| {
|
.mutate(|db| {
|
||||||
|
let hostname = crate::hostname::Hostname(db.as_public().as_server_info().as_hostname().de()?);
|
||||||
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
let gateways = db.as_public().as_server_info().as_network().as_gateways().de()?;
|
||||||
let ports = db.as_private().as_available_ports().de()?;
|
let ports = db.as_private().as_available_ports().de()?;
|
||||||
for host in all_hosts(db) {
|
for host in all_hosts(db) {
|
||||||
@@ -204,7 +206,7 @@ pub async fn remove_tunnel(
|
|||||||
d.retain(|_, gateways| !gateways.is_empty());
|
d.retain(|_, gateways| !gateways.is_empty());
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
host.update_addresses(&gateways, &ports)?;
|
host.update_addresses(&hostname, &gateways, &ports)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -278,8 +278,7 @@ impl Accept for VHostBindListener {
|
|||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> Poll<Result<(Self::Metadata, AcceptStream), Error>> {
|
) -> Poll<Result<(Self::Metadata, AcceptStream), Error>> {
|
||||||
// Update listeners when ip_info or bind_reqs change
|
// Update listeners when ip_info or bind_reqs change
|
||||||
while self.ip_info.poll_changed(cx).is_ready()
|
while self.ip_info.poll_changed(cx).is_ready() || self.bind_reqs.poll_changed(cx).is_ready()
|
||||||
|| self.bind_reqs.poll_changed(cx).is_ready()
|
|
||||||
{
|
{
|
||||||
let reqs = self.bind_reqs.read_and_mark_seen();
|
let reqs = self.bind_reqs.read_and_mark_seen();
|
||||||
let listeners = &mut self.listeners;
|
let listeners = &mut self.listeners;
|
||||||
@@ -506,10 +505,8 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let src = tcp.peer_addr.ip();
|
let src = tcp.peer_addr.ip();
|
||||||
// Public if: source is a gateway/router IP (NAT'd internet),
|
// Public: source is outside all known subnets (direct internet)
|
||||||
// or source is outside all known subnets (direct internet)
|
let is_public = !ip_info.subnets.iter().any(|s| s.contains(&src));
|
||||||
let is_public = ip_info.lan_ip.contains(&src)
|
|
||||||
|| !ip_info.subnets.iter().any(|s| s.contains(&src));
|
|
||||||
|
|
||||||
if is_public {
|
if is_public {
|
||||||
self.public.contains(&gw.id)
|
self.public.contains(&gw.id)
|
||||||
@@ -695,6 +692,7 @@ where
|
|||||||
|
|
||||||
let (target, rc) = self.0.peek(|m| {
|
let (target, rc) = self.0.peek(|m| {
|
||||||
m.get(&hello.server_name().map(InternedString::from))
|
m.get(&hello.server_name().map(InternedString::from))
|
||||||
|
.or_else(|| m.get(&None))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.filter(|(_, rc)| rc.strong_count() > 0)
|
.filter(|(_, rc)| rc.strong_count() > 0)
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ impl LocaleString {
|
|||||||
pub fn localize(&mut self) {
|
pub fn localize(&mut self) {
|
||||||
self.localize_for(&*rust_i18n::locale());
|
self.localize_for(&*rust_i18n::locale());
|
||||||
}
|
}
|
||||||
pub fn localized(mut self) -> String {
|
pub fn localized(self) -> String {
|
||||||
self.localized_for(&*rust_i18n::locale())
|
self.localized_for(&*rust_i18n::locale())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type { PackageId } from './PackageId'
|
|||||||
export type HostnameMetadata =
|
export type HostnameMetadata =
|
||||||
| { kind: 'ipv4'; gateway: GatewayId }
|
| { kind: 'ipv4'; gateway: GatewayId }
|
||||||
| { kind: 'ipv6'; gateway: GatewayId; scopeId: number }
|
| { kind: 'ipv6'; gateway: GatewayId; scopeId: number }
|
||||||
|
| { kind: 'mdns'; gateways: Array<GatewayId> }
|
||||||
| { kind: 'private-domain'; gateways: Array<GatewayId> }
|
| { kind: 'private-domain'; gateways: Array<GatewayId> }
|
||||||
| { kind: 'public-domain'; gateway: GatewayId }
|
| { kind: 'public-domain'; gateway: GatewayId }
|
||||||
| { kind: 'plugin'; package: PackageId }
|
| { kind: 'plugin'; package: PackageId }
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ type VisibilityFilter<V extends 'public' | 'private'> = V extends 'public'
|
|||||||
: never
|
: never
|
||||||
type KindFilter<K extends FilterKinds> = K extends 'mdns'
|
type KindFilter<K extends FilterKinds> = K extends 'mdns'
|
||||||
?
|
?
|
||||||
| (HostnameInfo & { metadata: { kind: 'private-domain' } })
|
| (HostnameInfo & { metadata: { kind: 'mdns' } })
|
||||||
| KindFilter<Exclude<K, 'mdns'>>
|
| KindFilter<Exclude<K, 'mdns'>>
|
||||||
: K extends 'domain'
|
: K extends 'domain'
|
||||||
?
|
?
|
||||||
@@ -199,9 +199,7 @@ function filterRec(
|
|||||||
hostnames = hostnames.filter(
|
hostnames = hostnames.filter(
|
||||||
(h) =>
|
(h) =>
|
||||||
invert !==
|
invert !==
|
||||||
((kind.has('mdns') &&
|
((kind.has('mdns') && h.metadata.kind === 'mdns') ||
|
||||||
h.metadata.kind === 'private-domain' &&
|
|
||||||
h.host.endsWith('.local')) ||
|
|
||||||
(kind.has('domain') &&
|
(kind.has('domain') &&
|
||||||
(h.metadata.kind === 'private-domain' ||
|
(h.metadata.kind === 'private-domain' ||
|
||||||
h.metadata.kind === 'public-domain')) ||
|
h.metadata.kind === 'public-domain')) ||
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ function getGatewayIds(h: T.HostnameInfo): string[] {
|
|||||||
case 'ipv6':
|
case 'ipv6':
|
||||||
case 'public-domain':
|
case 'public-domain':
|
||||||
return [h.metadata.gateway]
|
return [h.metadata.gateway]
|
||||||
|
case 'mdns':
|
||||||
case 'private-domain':
|
case 'private-domain':
|
||||||
return h.metadata.gateways
|
return h.metadata.gateways
|
||||||
case 'plugin':
|
case 'plugin':
|
||||||
@@ -45,8 +46,10 @@ function getAddressType(h: T.HostnameInfo): string {
|
|||||||
return 'IPv6'
|
return 'IPv6'
|
||||||
case 'public-domain':
|
case 'public-domain':
|
||||||
return 'Public Domain'
|
return 'Public Domain'
|
||||||
|
case 'mdns':
|
||||||
|
return 'mDNS'
|
||||||
case 'private-domain':
|
case 'private-domain':
|
||||||
return h.host.endsWith('.local') ? 'mDNS' : 'Private Domain'
|
return 'Private Domain'
|
||||||
case 'plugin':
|
case 'plugin':
|
||||||
return 'Plugin'
|
return 'Plugin'
|
||||||
}
|
}
|
||||||
@@ -84,8 +87,7 @@ export class InterfaceService {
|
|||||||
const isDomain =
|
const isDomain =
|
||||||
h.metadata.kind === 'private-domain' ||
|
h.metadata.kind === 'private-domain' ||
|
||||||
h.metadata.kind === 'public-domain'
|
h.metadata.kind === 'public-domain'
|
||||||
const isMdns =
|
const isMdns = h.metadata.kind === 'mdns'
|
||||||
h.metadata.kind === 'private-domain' && h.host.endsWith('.local')
|
|
||||||
|
|
||||||
const address: GatewayAddress = {
|
const address: GatewayAddress = {
|
||||||
enabled,
|
enabled,
|
||||||
|
|||||||
@@ -2137,7 +2137,7 @@ export namespace Mock {
|
|||||||
host: 'adjective-noun.local',
|
host: 'adjective-noun.local',
|
||||||
port: 1234,
|
port: 1234,
|
||||||
metadata: {
|
metadata: {
|
||||||
kind: 'private-domain',
|
kind: 'mdns',
|
||||||
gateways: ['eth0', 'wlan0'],
|
gateways: ['eth0', 'wlan0'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const mockPatchData: DataModel = {
|
|||||||
host: 'adjective-noun.local',
|
host: 'adjective-noun.local',
|
||||||
port: 443,
|
port: 443,
|
||||||
metadata: {
|
metadata: {
|
||||||
kind: 'private-domain',
|
kind: 'mdns',
|
||||||
gateways: ['eth0', 'wlan0'],
|
gateways: ['eth0', 'wlan0'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -515,7 +515,7 @@ export const mockPatchData: DataModel = {
|
|||||||
host: 'adjective-noun.local',
|
host: 'adjective-noun.local',
|
||||||
port: 443,
|
port: 443,
|
||||||
metadata: {
|
metadata: {
|
||||||
kind: 'private-domain',
|
kind: 'mdns',
|
||||||
gateways: ['eth0'],
|
gateways: ['eth0'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -622,7 +622,7 @@ export const mockPatchData: DataModel = {
|
|||||||
host: 'adjective-noun.local',
|
host: 'adjective-noun.local',
|
||||||
port: 8332,
|
port: 8332,
|
||||||
metadata: {
|
metadata: {
|
||||||
kind: 'private-domain',
|
kind: 'mdns',
|
||||||
gateways: ['eth0'],
|
gateways: ['eth0'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user