client: run 'up' on all interfaces when none is specified

pull/178/head
Jake McGinty 2021-11-23 23:07:57 -07:00
parent 2fd0049d1a
commit 2c31a4b6ec
2 changed files with 45 additions and 9 deletions

View File

@ -32,6 +32,8 @@ use nat::NatTraverse;
use shared::{wg, Error}; use shared::{wg, Error};
use util::{human_duration, human_size, Api}; use util::{human_duration, human_size, Api};
use crate::util::all_installed;
struct PeerState<'a> { struct PeerState<'a> {
peer: &'a Peer, peer: &'a Peer,
info: Option<&'a PeerInfo>, info: Option<&'a PeerInfo>,
@ -131,7 +133,7 @@ enum Command {
#[structopt(flatten)] #[structopt(flatten)]
nat: NatOpts, nat: NatOpts,
interface: Interface, interface: Option<Interface>,
}, },
/// Fetch and update your local interface with the latest peer list /// Fetch and update your local interface with the latest peer list
@ -421,7 +423,7 @@ fn redeem_invite(
target_conf: PathBuf, target_conf: PathBuf,
network: NetworkOpts, network: NetworkOpts,
) -> Result<(), Error> { ) -> Result<(), Error> {
log::info!("bringing up the interface."); log::info!("bringing up interface {}.", iface.as_str_lossy().yellow());
let resolved_endpoint = config let resolved_endpoint = config
.server .server
.external_endpoint .external_endpoint
@ -474,14 +476,22 @@ fn redeem_invite(
} }
fn up( fn up(
interface: &InterfaceName, interface: Option<Interface>,
opts: &Opts, opts: &Opts,
loop_interval: Option<Duration>, loop_interval: Option<Duration>,
hosts_path: Option<PathBuf>, hosts_path: Option<PathBuf>,
nat: &NatOpts, nat: &NatOpts,
) -> Result<(), Error> { ) -> Result<(), Error> {
loop { loop {
fetch(interface, opts, true, hosts_path.clone(), nat)?; let interfaces = match &interface {
Some(iface) => vec![iface.clone()],
None => all_installed(&opts.config_dir)?,
};
for iface in interfaces {
fetch(&*iface, opts, true, hosts_path.clone(), nat)?;
}
match loop_interval { match loop_interval {
Some(interval) => thread::sleep(interval), Some(interval) => thread::sleep(interval),
None => break, None => break,
@ -512,7 +522,7 @@ fn fetch(
); );
} }
log::info!("bringing up the interface."); log::info!("bringing up interface {}.", interface.as_str_lossy().yellow());
let resolved_endpoint = config let resolved_endpoint = config
.server .server
.external_endpoint .external_endpoint
@ -533,7 +543,7 @@ fn fetch(
.with_str(interface.to_string())?; .with_str(interface.to_string())?;
} }
log::info!("fetching state from server..."); log::info!("fetching state for {} from server...", interface.as_str_lossy().yellow());
let mut store = DataStore::open_or_create(&opts.data_dir, interface)?; let mut store = DataStore::open_or_create(&opts.data_dir, interface)?;
let api = Api::new(&config.server); let api = Api::new(&config.server);
let State { peers, cidrs } = api.http("GET", "/user/state")?; let State { peers, cidrs } = api.http("GET", "/user/state")?;
@ -1158,7 +1168,7 @@ fn run(opts: &Opts) -> Result<(), Error> {
nat, nat,
interval, interval,
} => up( } => up(
&interface, interface,
opts, opts,
daemon.then(|| Duration::from_secs(interval)), daemon.then(|| Duration::from_secs(interval)),
hosts.into(), hosts.into(),

View File

@ -3,8 +3,8 @@ use colored::*;
use indoc::eprintdoc; use indoc::eprintdoc;
use log::{Level, LevelFilter}; use log::{Level, LevelFilter};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use shared::{interface_config::ServerInfo, PeerDiff, INNERNET_PUBKEY_HEADER}; use shared::{interface_config::ServerInfo, PeerDiff, INNERNET_PUBKEY_HEADER, Interface};
use std::{io, path::Path, time::Duration}; use std::{io, path::Path, time::Duration, ffi::OsStr};
use ureq::{Agent, AgentBuilder}; use ureq::{Agent, AgentBuilder};
static LOGGER: Logger = Logger; static LOGGER: Logger = Logger;
@ -170,6 +170,32 @@ pub fn print_peer_diff(store: &DataStore, diff: &PeerDiff) {
} }
} }
pub fn all_installed(config_dir: &Path) -> Result<Vec<Interface>, std::io::Error> {
// All errors are bubbled up when enumerating a directory
let entries: Vec<_> = std::fs::read_dir(config_dir)?
.into_iter()
.collect::<Result<_, _>>()?;
let installed: Vec<_> = entries.into_iter()
.filter(|entry| match entry.file_type() {
Ok(f) => f.is_file(),
_ => false
})
.filter_map(|entry| {
let path = entry.path();
match (path.extension(), path.file_stem()) {
(Some(extension), Some(stem)) if extension == OsStr::new("conf") => {
Some(stem.to_string_lossy().to_string())
}
_ => None
}
})
.map(|name| name.parse())
.collect::<Result<_, _>>()?;
Ok(installed)
}
pub struct Api<'a> { pub struct Api<'a> {
agent: Agent, agent: Agent,
server: &'a ServerInfo, server: &'a ServerInfo,