prevent gateways from getting stuck empty

This commit is contained in:
Aiden McClelland
2025-11-13 15:19:30 -07:00
parent aeaad3c833
commit 60ee836d44

View File

@@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::future::Future; use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV6}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV6};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::task::{Poll, ready}; use std::task::{ready, Poll};
use std::time::Duration; use std::time::Duration;
use clap::Parser; use clap::Parser;
@@ -17,7 +17,7 @@ use itertools::Itertools;
use models::GatewayId; use models::GatewayId;
use nix::net::if_::if_nametoindex; use nix::net::if_::if_nametoindex;
use patch_db::json_ptr::JsonPointer; use patch_db::json_ptr::JsonPointer;
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async}; use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::net::TcpListener; use tokio::net::TcpListener;
@@ -29,29 +29,29 @@ use zbus::proxy::{PropertyChanged, PropertyStream, SignalStream};
use zbus::zvariant::{ use zbus::zvariant::{
DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue, DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue,
}; };
use zbus::{Connection, proxy}; use zbus::{proxy, Connection};
use crate::context::{CliContext, RpcContext}; use crate::context::{CliContext, RpcContext};
use crate::db::model::Database;
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType}; use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::db::model::Database;
use crate::net::forward::START9_BRIDGE_IFACE; use crate::net::forward::START9_BRIDGE_IFACE;
use crate::net::gateway::device::DeviceProxy; use crate::net::gateway::device::DeviceProxy;
use crate::net::utils::ipv6_is_link_local; use crate::net::utils::ipv6_is_link_local;
use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor}; use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor};
use crate::prelude::*; use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::OrdMapIterMut; use crate::util::collections::OrdMapIterMut;
use crate::util::future::Until; use crate::util::future::Until;
use crate::util::io::open_file; use crate::util::io::open_file;
use crate::util::serde::{HandlerExtSerde, display_serializable}; use crate::util::serde::{display_serializable, HandlerExtSerde};
use crate::util::sync::{SyncMutex, Watch}; use crate::util::sync::{SyncMutex, Watch};
use crate::util::Invoke;
pub fn gateway_api<C: Context>() -> ParentHandler<C> { pub fn gateway_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new() ParentHandler::new()
.subcommand( .subcommand(
"list", "list",
from_fn_async(list_interfaces) from_fn_async(list_interfaces)
.custom_ts("{}".into(), BTreeMap::<GatewayId, NetworkInterfaceInfo>::inline()) .custom_ts("{}".into(), BTreeMap::<GatewayId, NetworkInterfaceInfo>::inline_flattened())
.with_display_serializable() .with_display_serializable()
.with_custom_display_fn(|HandlerArgs { params, .. }, res| { .with_custom_display_fn(|HandlerArgs { params, .. }, res| {
use prettytable::*; use prettytable::*;
@@ -131,7 +131,6 @@ async fn list_interfaces(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct NetworkInterfaceSetPublicParams { struct NetworkInterfaceSetPublicParams {
gateway: GatewayId, gateway: GatewayId,
public: Option<bool>, public: Option<bool>,
@@ -148,7 +147,6 @@ async fn set_public(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct UnsetPublicParams { struct UnsetPublicParams {
gateway: GatewayId, gateway: GatewayId,
} }
@@ -164,7 +162,6 @@ async fn unset_public(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct ForgetGatewayParams { struct ForgetGatewayParams {
gateway: GatewayId, gateway: GatewayId,
} }
@@ -177,7 +174,6 @@ async fn forget_iface(
} }
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)] #[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
struct RenameGatewayParams { struct RenameGatewayParams {
id: GatewayId, id: GatewayId,
name: InternedString, name: InternedString,
@@ -405,6 +401,12 @@ async fn watcher(
) { ) {
loop { loop {
let res: Result<(), Error> = async { let res: Result<(), Error> = async {
Command::new("systemctl")
.arg("start")
.arg("NetworkManager")
.invoke(ErrorKind::Network)
.await?;
let connection = Connection::system().await?; let connection = Connection::system().await?;
let netman_proxy = NetworkManagerProxy::new(&connection).await?; let netman_proxy = NetworkManagerProxy::new(&connection).await?;
@@ -436,7 +438,15 @@ async fn watcher(
loop { loop {
until until
.run(async { .run(async {
loop {
let devices = netman_proxy.all_devices().await?; let devices = netman_proxy.all_devices().await?;
if devices.is_empty() {
tracing::warn!(
"NetworkManager returned no devices. Trying again..."
);
tokio::time::sleep(Duration::from_secs(1)).await;
continue;
}
let mut ifaces = BTreeSet::new(); let mut ifaces = BTreeSet::new();
let mut jobs = Vec::new(); let mut jobs = Vec::new();
for device in devices { for device in devices {
@@ -444,7 +454,8 @@ async fn watcher(
let device_proxy = let device_proxy =
device::DeviceProxy::new(&connection, device.clone()).await?; device::DeviceProxy::new(&connection, device.clone()).await?;
let iface = InternedString::intern(device_proxy.ip_interface().await?); let iface =
InternedString::intern(device_proxy.ip_interface().await?);
if iface.is_empty() { if iface.is_empty() {
continue; continue;
} }
@@ -479,6 +490,8 @@ async fn watcher(
}); });
futures::future::try_join_all(jobs).await?; futures::future::try_join_all(jobs).await?;
break;
}
Ok::<_, Error>(()) Ok::<_, Error>(())
}) })
.await?; .await?;