client: run 'up' on all interfaces when none is specified
parent
2fd0049d1a
commit
2c31a4b6ec
|
@ -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(),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue