{client,server}: allow hostnames in endpoints (#56)
use new Endpoint type instead of SocketAddr in appropriate placespull/59/head
parent
e2ea2ddded
commit
0a26bdedce
|
@ -1138,6 +1138,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"ureq",
|
"ureq",
|
||||||
|
"url",
|
||||||
"warp",
|
"warp",
|
||||||
"wgctrl",
|
"wgctrl",
|
||||||
]
|
]
|
||||||
|
@ -1169,6 +1170,7 @@ dependencies = [
|
||||||
"structopt",
|
"structopt",
|
||||||
"toml",
|
"toml",
|
||||||
"ureq",
|
"ureq",
|
||||||
|
"url",
|
||||||
"wgctrl",
|
"wgctrl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,7 @@ fn redeem_invite(
|
||||||
target_conf: PathBuf,
|
target_conf: PathBuf,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
println!("{} bringing up the interface.", "[*]".dimmed());
|
println!("{} bringing up the interface.", "[*]".dimmed());
|
||||||
|
let resolved_endpoint = config.server.external_endpoint.resolve()?;
|
||||||
wg::up(
|
wg::up(
|
||||||
&iface,
|
&iface,
|
||||||
&config.interface.private_key,
|
&config.interface.private_key,
|
||||||
|
@ -291,7 +292,7 @@ fn redeem_invite(
|
||||||
Some((
|
Some((
|
||||||
&config.server.public_key,
|
&config.server.public_key,
|
||||||
config.server.internal_endpoint.ip(),
|
config.server.internal_endpoint.ip(),
|
||||||
config.server.external_endpoint,
|
resolved_endpoint,
|
||||||
)),
|
)),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -369,6 +370,7 @@ fn fetch(
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{} bringing up the interface.", "[*]".dimmed());
|
println!("{} bringing up the interface.", "[*]".dimmed());
|
||||||
|
let resolved_endpoint = config.server.external_endpoint.resolve()?;
|
||||||
wg::up(
|
wg::up(
|
||||||
interface,
|
interface,
|
||||||
&config.interface.private_key,
|
&config.interface.private_key,
|
||||||
|
@ -377,7 +379,7 @@ fn fetch(
|
||||||
Some((
|
Some((
|
||||||
&config.server.public_key,
|
&config.server.public_key,
|
||||||
config.server.internal_endpoint.ip(),
|
config.server.internal_endpoint.ip(),
|
||||||
config.server.external_endpoint,
|
resolved_endpoint,
|
||||||
)),
|
)),
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
|
@ -821,7 +823,7 @@ fn print_peer(our_peer: &Peer, peer: &PeerInfo, short: bool) -> Result<(), Error
|
||||||
&our_peer.public_key[..10].yellow()
|
&our_peer.public_key[..10].yellow()
|
||||||
);
|
);
|
||||||
println!(" {}: {}", "ip".bold(), our_peer.ip);
|
println!(" {}: {}", "ip".bold(), our_peer.ip);
|
||||||
if let Some(endpoint) = our_peer.endpoint {
|
if let Some(ref endpoint) = our_peer.endpoint {
|
||||||
println!(" {}: {}", "endpoint".bold(), endpoint);
|
println!(" {}: {}", "endpoint".bold(), endpoint);
|
||||||
}
|
}
|
||||||
if let Some(last_handshake) = peer.stats.last_handshake_time {
|
if let Some(last_handshake) = peer.stats.last_handshake_time {
|
||||||
|
|
|
@ -34,6 +34,7 @@ subtle = "2"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
ureq = { version = "2", default-features = false }
|
ureq = { version = "2", default-features = false }
|
||||||
|
url = "2"
|
||||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
warp = { git = "https://github.com/tonarino/warp", default-features = false } # pending https://github.com/seanmonstar/warp/issues/830
|
warp = { git = "https://github.com/tonarino/warp", default-features = false } # pending https://github.com/seanmonstar/warp/issues/830
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub fn inject_endpoints(session: &Session, peers: &mut Vec<Peer>) {
|
||||||
for mut peer in peers {
|
for mut peer in peers {
|
||||||
if peer.contents.endpoint.is_none() {
|
if peer.contents.endpoint.is_none() {
|
||||||
if let Some(endpoint) = session.context.endpoints.get(&peer.public_key) {
|
if let Some(endpoint) = session.context.endpoints.get(&peer.public_key) {
|
||||||
peer.contents.endpoint = Some(endpoint.to_owned());
|
peer.contents.endpoint = Some(endpoint.to_owned().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ mod tests {
|
||||||
.put_request_from_ip(test::DEVELOPER1_PEER_IP)
|
.put_request_from_ip(test::DEVELOPER1_PEER_IP)
|
||||||
.path("/v1/user/endpoint")
|
.path("/v1/user/endpoint")
|
||||||
.body(serde_json::to_string(&EndpointContents::Set(
|
.body(serde_json::to_string(&EndpointContents::Set(
|
||||||
"1.1.1.1:51820".parse()?
|
"1.1.1.1:51820".parse().unwrap()
|
||||||
))?)
|
))?)
|
||||||
.reply(&filter)
|
.reply(&filter)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl DatabasePeer {
|
||||||
ip.to_string(),
|
ip.to_string(),
|
||||||
cidr_id,
|
cidr_id,
|
||||||
&public_key,
|
&public_key,
|
||||||
endpoint.map(|endpoint| endpoint.to_string()),
|
endpoint.as_ref().map(|endpoint| endpoint.to_string()),
|
||||||
is_admin,
|
is_admin,
|
||||||
is_disabled,
|
is_disabled,
|
||||||
is_redeemed,
|
is_redeemed,
|
||||||
|
@ -138,7 +138,10 @@ impl DatabasePeer {
|
||||||
WHERE id = ?5",
|
WHERE id = ?5",
|
||||||
params![
|
params![
|
||||||
new_contents.name,
|
new_contents.name,
|
||||||
new_contents.endpoint.map(|endpoint| endpoint.to_string()),
|
new_contents
|
||||||
|
.endpoint
|
||||||
|
.as_ref()
|
||||||
|
.map(|endpoint| endpoint.to_string()),
|
||||||
new_contents.is_admin,
|
new_contents.is_admin,
|
||||||
new_contents.is_disabled,
|
new_contents.is_disabled,
|
||||||
self.id,
|
self.id,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use indoc::printdoc;
|
||||||
use rusqlite::{params, Connection};
|
use rusqlite::{params, Connection};
|
||||||
use shared::{
|
use shared::{
|
||||||
prompts::{self, hostname_validator},
|
prompts::{self, hostname_validator},
|
||||||
CidrContents, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
CidrContents, Endpoint, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
||||||
};
|
};
|
||||||
use wgctrl::KeyPair;
|
use wgctrl::KeyPair;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub struct InitializeOpts {
|
||||||
|
|
||||||
/// This server's external endpoint (ex: 100.100.100.100:51820)
|
/// This server's external endpoint (ex: 100.100.100.100:51820)
|
||||||
#[structopt(long, conflicts_with = "auto-external-endpoint")]
|
#[structopt(long, conflicts_with = "auto-external-endpoint")]
|
||||||
pub external_endpoint: Option<SocketAddr>,
|
pub external_endpoint: Option<Endpoint>,
|
||||||
|
|
||||||
/// Auto-resolve external endpoint
|
/// Auto-resolve external endpoint
|
||||||
#[structopt(long = "auto-external-endpoint")]
|
#[structopt(long = "auto-external-endpoint")]
|
||||||
|
@ -49,7 +49,7 @@ struct DbInitData {
|
||||||
server_cidr: IpNetwork,
|
server_cidr: IpNetwork,
|
||||||
our_ip: IpAddr,
|
our_ip: IpAddr,
|
||||||
public_key_base64: String,
|
public_key_base64: String,
|
||||||
endpoint: SocketAddr,
|
endpoint: Endpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_database(conn: &Connection, db_init_data: DbInitData) -> Result<(), Error> {
|
fn populate_database(conn: &Connection, db_init_data: DbInitData) -> Result<(), Error> {
|
||||||
|
@ -126,7 +126,7 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
|
||||||
// This probably won't error because of the `hostname_validator` regex.
|
// This probably won't error because of the `hostname_validator` regex.
|
||||||
let name = name.parse()?;
|
let name = name.parse()?;
|
||||||
|
|
||||||
let endpoint: SocketAddr = if let Some(endpoint) = opts.external_endpoint {
|
let endpoint: Endpoint = if let Some(endpoint) = opts.external_endpoint {
|
||||||
endpoint.clone()
|
endpoint.clone()
|
||||||
} else {
|
} else {
|
||||||
let external_ip: Option<IpAddr> = ureq::get("http://4.icanhazip.com")
|
let external_ip: Option<IpAddr> = ureq::get("http://4.icanhazip.com")
|
||||||
|
@ -139,7 +139,7 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
|
||||||
|
|
||||||
if opts.auto_external_endpoint {
|
if opts.auto_external_endpoint {
|
||||||
let ip = external_ip.ok_or("couldn't get external IP")?;
|
let ip = external_ip.ok_or("couldn't get external IP")?;
|
||||||
(ip, 51820).into()
|
SocketAddr::new(ip, 51820).into()
|
||||||
} else {
|
} else {
|
||||||
prompts::ask_endpoint(external_ip)?
|
prompts::ask_endpoint(external_ip)?
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl Server {
|
||||||
let opts = InitializeOpts {
|
let opts = InitializeOpts {
|
||||||
network_name: Some(interface.clone()),
|
network_name: Some(interface.clone()),
|
||||||
network_cidr: Some(ROOT_CIDR.parse()?),
|
network_cidr: Some(ROOT_CIDR.parse()?),
|
||||||
external_endpoint: Some("155.155.155.155:54321".parse()?),
|
external_endpoint: Some("155.155.155.155:54321".parse().unwrap()),
|
||||||
listen_port: Some(54321),
|
listen_port: Some(54321),
|
||||||
auto_external_endpoint: false,
|
auto_external_endpoint: false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,4 +17,5 @@ serde = { version = "1", features = ["derive"] }
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
ureq = { version = "2", default-features = false }
|
ureq = { version = "2", default-features = false }
|
||||||
|
url = "2"
|
||||||
wgctrl = { path = "../wgctrl-rs" }
|
wgctrl = { path = "../wgctrl-rs" }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{ensure_dirs_exist, Error, IoErrorContext, CLIENT_CONFIG_PATH};
|
use crate::{ensure_dirs_exist, Endpoint, Error, IoErrorContext, CLIENT_CONFIG_PATH};
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
|
@ -46,7 +46,7 @@ pub struct ServerInfo {
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
|
|
||||||
/// The external internet endpoint to reach the server.
|
/// The external internet endpoint to reach the server.
|
||||||
pub external_endpoint: SocketAddr,
|
pub external_endpoint: Endpoint,
|
||||||
|
|
||||||
/// An internal endpoint in the WireGuard network that hosts the coordination API.
|
/// An internal endpoint in the WireGuard network that hosts the coordination API.
|
||||||
pub internal_endpoint: SocketAddr,
|
pub internal_endpoint: SocketAddr,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
|
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
|
||||||
AddCidrOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, Error, Peer, PeerContents,
|
AddCidrOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, Endpoint, Error, Peer,
|
||||||
PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
||||||
};
|
};
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
|
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
|
||||||
|
@ -299,6 +299,7 @@ pub fn save_peer_invitation(
|
||||||
server: ServerInfo {
|
server: ServerInfo {
|
||||||
external_endpoint: server_peer
|
external_endpoint: server_peer
|
||||||
.endpoint
|
.endpoint
|
||||||
|
.clone()
|
||||||
.expect("The innernet server should have a WireGuard endpoint"),
|
.expect("The innernet server should have a WireGuard endpoint"),
|
||||||
internal_endpoint: *server_api_addr,
|
internal_endpoint: *server_api_addr,
|
||||||
public_key: server_peer.public_key.clone(),
|
public_key: server_peer.public_key.clone(),
|
||||||
|
@ -362,7 +363,7 @@ pub fn set_listen_port(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<SocketAddr, Error> {
|
pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<Endpoint, Error> {
|
||||||
println!("getting external IP address.");
|
println!("getting external IP address.");
|
||||||
|
|
||||||
let external_ip = if external_ip.is_some() {
|
let external_ip = if external_ip.is_some() {
|
||||||
|
@ -379,7 +380,7 @@ pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<SocketAddr, Error> {
|
||||||
|
|
||||||
let mut endpoint_builder = Input::with_theme(&*THEME);
|
let mut endpoint_builder = Input::with_theme(&*THEME);
|
||||||
if let Some(ip) = external_ip {
|
if let Some(ip) = external_ip {
|
||||||
endpoint_builder.default(SocketAddr::new(ip, 51820));
|
endpoint_builder.default(SocketAddr::new(ip, 51820).into());
|
||||||
} else {
|
} else {
|
||||||
println!("failed to get external IP.");
|
println!("failed to get external IP.");
|
||||||
}
|
}
|
||||||
|
@ -389,7 +390,7 @@ pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<SocketAddr, Error> {
|
||||||
.map_err(|e| Error::from(e))
|
.map_err(|e| Error::from(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn override_endpoint(unset: bool) -> Result<Option<Option<SocketAddr>>, Error> {
|
pub fn override_endpoint(unset: bool) -> Result<Option<Option<Endpoint>>, Error> {
|
||||||
let endpoint = if !unset {
|
let endpoint = if !unset {
|
||||||
Some(ask_endpoint(None)?)
|
Some(ask_endpoint(None)?)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,13 +2,15 @@ use crate::prompts::hostname_validator;
|
||||||
use ipnetwork::IpNetwork;
|
use ipnetwork::IpNetwork;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr, ToSocketAddrs},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
path::Path,
|
path::Path,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
vec,
|
||||||
};
|
};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
use url::Host;
|
||||||
use wgctrl::{InterfaceName, InvalidInterfaceName, Key, PeerConfig, PeerConfigBuilder};
|
use wgctrl::{InterfaceName, InvalidInterfaceName, Key, PeerConfig, PeerConfigBuilder};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -37,15 +39,105 @@ impl Deref for Interface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
/// An external endpoint that supports both IP and domain name hosts.
|
||||||
|
pub struct Endpoint {
|
||||||
|
host: Host,
|
||||||
|
port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SocketAddr> for Endpoint {
|
||||||
|
fn from(addr: SocketAddr) -> Self {
|
||||||
|
match addr {
|
||||||
|
SocketAddr::V4(v4addr) => Self {
|
||||||
|
host: Host::Ipv4(*v4addr.ip()),
|
||||||
|
port: v4addr.port(),
|
||||||
|
},
|
||||||
|
SocketAddr::V6(v6addr) => Self {
|
||||||
|
host: Host::Ipv6(*v6addr.ip()),
|
||||||
|
port: v6addr.port(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Endpoint {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s.rsplitn(2, ':').collect::<Vec<&str>>().as_slice() {
|
||||||
|
[port, host] => {
|
||||||
|
let port = port.parse().map_err(|_| "couldn't parse port")?;
|
||||||
|
let host = Host::parse(host).map_err(|_| "couldn't parse host")?;
|
||||||
|
Ok(Endpoint { host, port })
|
||||||
|
},
|
||||||
|
_ => Err("couldn't parse in form of 'host:port'"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Endpoint {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Endpoint {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct EndpointVisitor;
|
||||||
|
impl<'de> serde::de::Visitor<'de> for EndpointVisitor {
|
||||||
|
type Value = Endpoint;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a valid host:port endpoint")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
s.parse().map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deserializer.deserialize_str(EndpointVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Endpoint {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
self.host.fmt(f)?;
|
||||||
|
f.write_str(":")?;
|
||||||
|
self.port.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Endpoint {
|
||||||
|
pub fn resolve(&self) -> Result<SocketAddr, String> {
|
||||||
|
let mut addrs = self
|
||||||
|
.to_string()
|
||||||
|
.to_socket_addrs()
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
addrs
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "failed to resolve address".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(tag = "option", content = "content")]
|
#[serde(tag = "option", content = "content")]
|
||||||
pub enum EndpointContents {
|
pub enum EndpointContents {
|
||||||
Set(SocketAddr),
|
Set(Endpoint),
|
||||||
Unset,
|
Unset,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<Option<SocketAddr>> for EndpointContents {
|
impl Into<Option<Endpoint>> for EndpointContents {
|
||||||
fn into(self) -> Option<SocketAddr> {
|
fn into(self) -> Option<Endpoint> {
|
||||||
match self {
|
match self {
|
||||||
Self::Set(addr) => Some(addr),
|
Self::Set(addr) => Some(addr),
|
||||||
Self::Unset => None,
|
Self::Unset => None,
|
||||||
|
@ -53,8 +145,8 @@ impl Into<Option<SocketAddr>> for EndpointContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<SocketAddr>> for EndpointContents {
|
impl From<Option<Endpoint>> for EndpointContents {
|
||||||
fn from(option: Option<SocketAddr>) -> Self {
|
fn from(option: Option<Endpoint>) -> Self {
|
||||||
match option {
|
match option {
|
||||||
Some(addr) => Self::Set(addr),
|
Some(addr) => Self::Set(addr),
|
||||||
None => Self::Unset,
|
None => Self::Unset,
|
||||||
|
@ -246,7 +338,7 @@ pub struct PeerContents {
|
||||||
pub ip: IpAddr,
|
pub ip: IpAddr,
|
||||||
pub cidr_id: i64,
|
pub cidr_id: i64,
|
||||||
pub public_key: String,
|
pub public_key: String,
|
||||||
pub endpoint: Option<SocketAddr>,
|
pub endpoint: Option<Endpoint>,
|
||||||
pub persistent_keepalive_interval: Option<u16>,
|
pub persistent_keepalive_interval: Option<u16>,
|
||||||
pub is_admin: bool,
|
pub is_admin: bool,
|
||||||
pub is_disabled: bool,
|
pub is_disabled: bool,
|
||||||
|
@ -287,8 +379,11 @@ impl Peer {
|
||||||
pub fn diff(&self, peer: &PeerConfig) -> Option<PeerDiff> {
|
pub fn diff(&self, peer: &PeerConfig) -> Option<PeerDiff> {
|
||||||
assert_eq!(self.public_key, peer.public_key.to_base64());
|
assert_eq!(self.public_key, peer.public_key.to_base64());
|
||||||
|
|
||||||
let endpoint_diff = if peer.endpoint != self.endpoint {
|
let endpoint_diff = if let Some(ref endpoint) = self.endpoint {
|
||||||
self.endpoint
|
match endpoint.resolve() {
|
||||||
|
Ok(resolved) if Some(resolved) != peer.endpoint => Some(resolved),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -331,7 +426,9 @@ impl<'a> From<&'a Peer> for PeerConfigBuilder {
|
||||||
builder
|
builder
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(endpoint) = peer.endpoint {
|
let resolved = peer.endpoint.as_ref().map(|e| e.resolve().ok()).flatten();
|
||||||
|
|
||||||
|
if let Some(endpoint) = resolved {
|
||||||
builder.set_endpoint(endpoint)
|
builder.set_endpoint(endpoint)
|
||||||
} else {
|
} else {
|
||||||
builder
|
builder
|
||||||
|
|
Loading…
Reference in New Issue