refactor done for native
This commit is contained in:
parent
922470365a
commit
23abaa3c99
@ -18,13 +18,11 @@ use utils::network_interfaces::*;
|
|||||||
use async_std::io;
|
use async_std::io;
|
||||||
use async_std::net::*;
|
use async_std::net::*;
|
||||||
use async_tls::TlsAcceptor;
|
use async_tls::TlsAcceptor;
|
||||||
use cfg_if::*;
|
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
// xxx: rustls ^0.20
|
// xxx: rustls ^0.20
|
||||||
//use rustls::{server::NoClientAuth, Certificate, PrivateKey, ServerConfig};
|
//use rustls::{server::NoClientAuth, Certificate, PrivateKey, ServerConfig};
|
||||||
use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};
|
use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};
|
||||||
use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
|
use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
|
||||||
use socket2::{Domain, Protocol, Socket, Type};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -44,6 +42,7 @@ struct NetworkInner {
|
|||||||
protocol_config: Option<ProtocolConfig>,
|
protocol_config: Option<ProtocolConfig>,
|
||||||
udp_static_public_dialinfo: bool,
|
udp_static_public_dialinfo: bool,
|
||||||
tcp_static_public_dialinfo: bool,
|
tcp_static_public_dialinfo: bool,
|
||||||
|
ws_static_public_dialinfo: bool,
|
||||||
network_class: Option<NetworkClass>,
|
network_class: Option<NetworkClass>,
|
||||||
join_handles: Vec<JoinHandle<()>>,
|
join_handles: Vec<JoinHandle<()>>,
|
||||||
listener_states: BTreeMap<SocketAddr, Arc<RwLock<ListenerState>>>,
|
listener_states: BTreeMap<SocketAddr, Arc<RwLock<ListenerState>>>,
|
||||||
@ -55,9 +54,6 @@ struct NetworkInner {
|
|||||||
wss_port: u16,
|
wss_port: u16,
|
||||||
outbound_udpv4_protocol_handler: Option<RawUdpProtocolHandler>,
|
outbound_udpv4_protocol_handler: Option<RawUdpProtocolHandler>,
|
||||||
outbound_udpv6_protocol_handler: Option<RawUdpProtocolHandler>,
|
outbound_udpv6_protocol_handler: Option<RawUdpProtocolHandler>,
|
||||||
outbound_tcp_protocol_handler: Option<RawTcpProtocolHandler>,
|
|
||||||
outbound_ws_protocol_handler: Option<WebsocketProtocolHandler>,
|
|
||||||
outbound_wss_protocol_handler: Option<WebsocketProtocolHandler>,
|
|
||||||
interfaces: NetworkInterfaces,
|
interfaces: NetworkInterfaces,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +80,7 @@ impl Network {
|
|||||||
protocol_config: None,
|
protocol_config: None,
|
||||||
udp_static_public_dialinfo: false,
|
udp_static_public_dialinfo: false,
|
||||||
tcp_static_public_dialinfo: false,
|
tcp_static_public_dialinfo: false,
|
||||||
|
ws_static_public_dialinfo: false,
|
||||||
network_class: None,
|
network_class: None,
|
||||||
join_handles: Vec::new(),
|
join_handles: Vec::new(),
|
||||||
listener_states: BTreeMap::new(),
|
listener_states: BTreeMap::new(),
|
||||||
@ -95,9 +92,6 @@ impl Network {
|
|||||||
wss_port: 0u16,
|
wss_port: 0u16,
|
||||||
outbound_udpv4_protocol_handler: None,
|
outbound_udpv4_protocol_handler: None,
|
||||||
outbound_udpv6_protocol_handler: None,
|
outbound_udpv6_protocol_handler: None,
|
||||||
outbound_tcp_protocol_handler: None,
|
|
||||||
outbound_ws_protocol_handler: None,
|
|
||||||
outbound_wss_protocol_handler: None,
|
|
||||||
interfaces: NetworkInterfaces::new(),
|
interfaces: NetworkInterfaces::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,7 +458,7 @@ impl Network {
|
|||||||
.local_addr()
|
.local_addr()
|
||||||
.map_err(map_to_string)?
|
.map_err(map_to_string)?
|
||||||
.as_socket_ipv4()
|
.as_socket_ipv4()
|
||||||
.ok_or("expected ipv4 address type".to_owned())?
|
.ok_or_else(|| "expected ipv4 address type".to_owned())?
|
||||||
.port();
|
.port();
|
||||||
|
|
||||||
// Make an async UdpSocket from the socket2 socket
|
// Make an async UdpSocket from the socket2 socket
|
||||||
@ -639,7 +633,6 @@ impl Network {
|
|||||||
local_port: u16,
|
local_port: u16,
|
||||||
peer_socket_addr: &SocketAddr,
|
peer_socket_addr: &SocketAddr,
|
||||||
) -> SocketAddr {
|
) -> SocketAddr {
|
||||||
let inner = self.inner.lock();
|
|
||||||
match peer_socket_addr {
|
match peer_socket_addr {
|
||||||
SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), local_port),
|
SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), local_port),
|
||||||
SocketAddr::V6(_) => SocketAddr::new(
|
SocketAddr::V6(_) => SocketAddr::new(
|
||||||
@ -807,15 +800,27 @@ impl Network {
|
|||||||
};
|
};
|
||||||
info!("UDP: starting listener at {:?}", listen_address);
|
info!("UDP: starting listener at {:?}", listen_address);
|
||||||
let dial_infos = self.start_udp_handler(listen_address.clone()).await?;
|
let dial_infos = self.start_udp_handler(listen_address.clone()).await?;
|
||||||
for x in &dial_infos {
|
let mut static_public = false;
|
||||||
|
for di in &dial_infos {
|
||||||
// Pick out UDP port for outbound connections (they will all be the same)
|
// Pick out UDP port for outbound connections (they will all be the same)
|
||||||
self.inner.lock().udp_port = x.port();
|
self.inner.lock().udp_port = di.port();
|
||||||
|
|
||||||
|
// Register local dial info only here if we specify a public address
|
||||||
|
if public_address.is_none() && di.is_global() {
|
||||||
|
// Register global dial info if no public address is specified
|
||||||
|
routing_table.register_dial_info(
|
||||||
|
di.clone(),
|
||||||
|
DialInfoOrigin::Static,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
|
);
|
||||||
|
static_public = true;
|
||||||
|
} else if di.is_local() {
|
||||||
// Register local dial info
|
// Register local dial info
|
||||||
routing_table.register_local_dial_info(x.clone(), DialInfoOrigin::Static);
|
routing_table.register_dial_info(di.clone(), DialInfoOrigin::Static, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add static public dialinfo if it's configured
|
// Add static public dialinfo if it's configured
|
||||||
let mut static_public = false;
|
|
||||||
if let Some(public_address) = public_address.as_ref() {
|
if let Some(public_address) = public_address.as_ref() {
|
||||||
// Resolve statically configured public dialinfo
|
// Resolve statically configured public dialinfo
|
||||||
let mut public_sockaddrs = public_address
|
let mut public_sockaddrs = public_address
|
||||||
@ -825,26 +830,15 @@ impl Network {
|
|||||||
|
|
||||||
// Add all resolved addresses as public dialinfo
|
// Add all resolved addresses as public dialinfo
|
||||||
for pdi_addr in &mut public_sockaddrs {
|
for pdi_addr in &mut public_sockaddrs {
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
DialInfo::udp_from_socketaddr(pdi_addr),
|
DialInfo::udp_from_socketaddr(pdi_addr),
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
);
|
|
||||||
static_public = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Register local dial info as public if it is publicly routable
|
|
||||||
for x in &dial_infos {
|
|
||||||
if x.is_global() {
|
|
||||||
routing_table.register_global_dial_info(
|
|
||||||
x.clone(),
|
|
||||||
Some(NetworkClass::Server),
|
Some(NetworkClass::Server),
|
||||||
DialInfoOrigin::Static,
|
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.inner.lock().udp_static_public_dialinfo = static_public;
|
self.inner.lock().udp_static_public_dialinfo = static_public;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -869,18 +863,35 @@ impl Network {
|
|||||||
.await?;
|
.await?;
|
||||||
trace!("WS: listener started");
|
trace!("WS: listener started");
|
||||||
|
|
||||||
let mut dial_infos: Vec<DialInfo> = Vec::new();
|
let mut static_public = false;
|
||||||
for socket_address in socket_addresses {
|
for socket_address in socket_addresses {
|
||||||
// Pick out WS port for outbound connections (they will all be the same)
|
// Pick out WS port for outbound connections (they will all be the same)
|
||||||
self.inner.lock().ws_port = socket_address.port();
|
self.inner.lock().ws_port = socket_address.port();
|
||||||
|
|
||||||
|
if url.is_none() && socket_address.address().is_global() {
|
||||||
|
// Build global dial info request url
|
||||||
|
let global_url = format!("ws://{}/{}", socket_address, path);
|
||||||
|
|
||||||
|
// Create global dial info
|
||||||
|
let di = DialInfo::try_ws(socket_address, global_url)
|
||||||
|
.map_err(map_to_string)
|
||||||
|
.map_err(logthru_net!(error))?;
|
||||||
|
routing_table.register_dial_info(
|
||||||
|
di,
|
||||||
|
DialInfoOrigin::Static,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
|
);
|
||||||
|
static_public = true;
|
||||||
|
} else if socket_address.address().is_local() {
|
||||||
// Build local dial info request url
|
// Build local dial info request url
|
||||||
let local_url = format!("ws://{}/{}", socket_address, path);
|
let local_url = format!("ws://{}/{}", socket_address, path);
|
||||||
|
|
||||||
// Create local dial info
|
// Create local dial info
|
||||||
let di = DialInfo::try_ws(socket_address, local_url)
|
let di = DialInfo::try_ws(socket_address, local_url)
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?;
|
.map_err(logthru_net!(error))?;
|
||||||
dial_infos.push(di.clone());
|
routing_table.register_dial_info(di, DialInfoOrigin::Static, None);
|
||||||
routing_table.register_local_dial_info(di, DialInfoOrigin::Static);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add static public dialinfo if it's configured
|
// Add static public dialinfo if it's configured
|
||||||
@ -900,15 +911,17 @@ impl Network {
|
|||||||
.map_err(logthru_net!(error))?;
|
.map_err(logthru_net!(error))?;
|
||||||
|
|
||||||
for gsa in global_socket_addrs {
|
for gsa in global_socket_addrs {
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
DialInfo::try_ws(SocketAddress::from_socket_addr(gsa), url.clone())
|
DialInfo::try_ws(SocketAddress::from_socket_addr(gsa), url.clone())
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?,
|
.map_err(logthru_net!(error))?,
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
static_public = true;
|
||||||
}
|
}
|
||||||
|
self.inner.lock().ws_static_public_dialinfo = static_public;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -937,13 +950,9 @@ impl Network {
|
|||||||
// is specified, then TLS won't validate, so no local dialinfo is possible.
|
// is specified, then TLS won't validate, so no local dialinfo is possible.
|
||||||
// This is not the case with unencrypted websockets, which can be specified solely by an IP address
|
// This is not the case with unencrypted websockets, which can be specified solely by an IP address
|
||||||
//
|
//
|
||||||
// let mut dial_infos: Vec<DialInfo> = Vec::new();
|
if let Some(socket_address) = socket_addresses.first() {
|
||||||
for socket_address in socket_addresses {
|
|
||||||
// Pick out WSS port for outbound connections (they will all be the same)
|
// Pick out WSS port for outbound connections (they will all be the same)
|
||||||
self.inner.lock().wss_port = socket_address.port();
|
self.inner.lock().wss_port = socket_address.port();
|
||||||
|
|
||||||
// Don't register local dial info because TLS won't allow that anyway without a local CA
|
|
||||||
// and we aren't doing that yet at all today.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add static public dialinfo if it's configured
|
// Add static public dialinfo if it's configured
|
||||||
@ -964,12 +973,12 @@ impl Network {
|
|||||||
.map_err(logthru_net!(error))?;
|
.map_err(logthru_net!(error))?;
|
||||||
|
|
||||||
for gsa in global_socket_addrs {
|
for gsa in global_socket_addrs {
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
DialInfo::try_wss(SocketAddress::from_socket_addr(gsa), url.clone())
|
DialInfo::try_wss(SocketAddress::from_socket_addr(gsa), url.clone())
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_net!(error))?,
|
.map_err(logthru_net!(error))?,
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Static,
|
DialInfoOrigin::Static,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -998,18 +1007,29 @@ impl Network {
|
|||||||
.await?;
|
.await?;
|
||||||
trace!("TCP: listener started");
|
trace!("TCP: listener started");
|
||||||
|
|
||||||
let mut dial_infos: Vec<DialInfo> = Vec::new();
|
let mut static_public = false;
|
||||||
for socket_address in socket_addresses {
|
for socket_address in socket_addresses {
|
||||||
// Pick out TCP port for outbound connections (they will all be the same)
|
// Pick out TCP port for outbound connections (they will all be the same)
|
||||||
self.inner.lock().tcp_port = socket_address.port();
|
self.inner.lock().tcp_port = socket_address.port();
|
||||||
|
|
||||||
let di = DialInfo::tcp(socket_address);
|
let di = DialInfo::tcp(socket_address);
|
||||||
dial_infos.push(di.clone());
|
|
||||||
routing_table.register_local_dial_info(di, DialInfoOrigin::Static);
|
// Register local dial info only here if we specify a public address
|
||||||
|
if public_address.is_none() && di.is_global() {
|
||||||
|
// Register global dial info if no public address is specified
|
||||||
|
routing_table.register_dial_info(
|
||||||
|
di.clone(),
|
||||||
|
DialInfoOrigin::Static,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
|
);
|
||||||
|
static_public = true;
|
||||||
|
} else if di.is_local() {
|
||||||
|
// Register local dial info
|
||||||
|
routing_table.register_dial_info(di.clone(), DialInfoOrigin::Static, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add static public dialinfo if it's configured
|
// Add static public dialinfo if it's configured
|
||||||
let mut static_public = false;
|
|
||||||
if let Some(public_address) = public_address.as_ref() {
|
if let Some(public_address) = public_address.as_ref() {
|
||||||
// Resolve statically configured public dialinfo
|
// Resolve statically configured public dialinfo
|
||||||
let mut public_sockaddrs = public_address
|
let mut public_sockaddrs = public_address
|
||||||
@ -1019,25 +1039,13 @@ impl Network {
|
|||||||
|
|
||||||
// Add all resolved addresses as public dialinfo
|
// Add all resolved addresses as public dialinfo
|
||||||
for pdi_addr in &mut public_sockaddrs {
|
for pdi_addr in &mut public_sockaddrs {
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
DialInfo::tcp_from_socketaddr(pdi_addr),
|
DialInfo::tcp_from_socketaddr(pdi_addr),
|
||||||
|
DialInfoOrigin::Static,
|
||||||
None,
|
None,
|
||||||
DialInfoOrigin::Static,
|
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Register local dial info as public if it is publicly routable
|
|
||||||
for x in &dial_infos {
|
|
||||||
if x.is_global() {
|
|
||||||
routing_table.register_global_dial_info(
|
|
||||||
x.clone(),
|
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Static,
|
|
||||||
);
|
|
||||||
static_public = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.lock().tcp_static_public_dialinfo = static_public;
|
self.inner.lock().tcp_static_public_dialinfo = static_public;
|
||||||
@ -1046,12 +1054,11 @@ impl Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
|
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
|
||||||
self.inner.lock().protocol_config.clone()
|
self.inner.lock().protocol_config
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn startup(&self) -> Result<(), String> {
|
pub async fn startup(&self) -> Result<(), String> {
|
||||||
info!("starting network");
|
info!("starting network");
|
||||||
let network_manager = self.inner.lock().network_manager.clone();
|
|
||||||
|
|
||||||
// initialize interfaces
|
// initialize interfaces
|
||||||
self.inner.lock().interfaces.refresh()?;
|
self.inner.lock().interfaces.refresh()?;
|
||||||
@ -1103,8 +1110,7 @@ impl Network {
|
|||||||
let routing_table = network_manager.routing_table();
|
let routing_table = network_manager.routing_table();
|
||||||
|
|
||||||
// Drop all dial info
|
// Drop all dial info
|
||||||
routing_table.clear_local_dial_info();
|
routing_table.clear_dial_info_details();
|
||||||
routing_table.clear_global_dial_info();
|
|
||||||
|
|
||||||
// Cancels all async background tasks by dropping join handles
|
// Cancels all async background tasks by dropping join handles
|
||||||
*self.inner.lock() = Self::new_inner(network_manager);
|
*self.inner.lock() = Self::new_inner(network_manager);
|
||||||
@ -1151,10 +1157,7 @@ impl Network {
|
|||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
(
|
(
|
||||||
inner.network_manager.routing_table(),
|
inner.network_manager.routing_table(),
|
||||||
inner
|
inner.protocol_config.unwrap_or_default(),
|
||||||
.protocol_config
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| ProtocolConfig::default()),
|
|
||||||
inner.udp_static_public_dialinfo,
|
inner.udp_static_public_dialinfo,
|
||||||
inner.tcp_static_public_dialinfo,
|
inner.tcp_static_public_dialinfo,
|
||||||
inner.network_class.unwrap_or(NetworkClass::Invalid),
|
inner.network_class.unwrap_or(NetworkClass::Invalid),
|
||||||
@ -1170,12 +1173,11 @@ impl Network {
|
|||||||
&& !udp_static_public_dialinfo
|
&& !udp_static_public_dialinfo
|
||||||
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
||||||
{
|
{
|
||||||
let filter = DialInfoFilter::with_protocol_type_and_address_type(
|
let filter = DialInfoFilter::global()
|
||||||
ProtocolType::UDP,
|
.with_protocol_type(ProtocolType::UDP)
|
||||||
AddressType::IPV4,
|
.with_address_type(AddressType::IPV4);
|
||||||
);
|
|
||||||
let need_udpv4_dialinfo = routing_table
|
let need_udpv4_dialinfo = routing_table
|
||||||
.first_filtered_global_dial_info_details(|d| d.dial_info.matches_filter(&filter))
|
.first_filtered_dial_info_detail(&filter)
|
||||||
.is_none();
|
.is_none();
|
||||||
if need_udpv4_dialinfo {
|
if need_udpv4_dialinfo {
|
||||||
// If we have no public UDPv4 dialinfo, then we need to run a NAT check
|
// If we have no public UDPv4 dialinfo, then we need to run a NAT check
|
||||||
@ -1192,12 +1194,11 @@ impl Network {
|
|||||||
&& !tcp_static_public_dialinfo
|
&& !tcp_static_public_dialinfo
|
||||||
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
&& (network_class.inbound_capable() || network_class == NetworkClass::Invalid)
|
||||||
{
|
{
|
||||||
let filter = DialInfoFilter::with_protocol_type_and_address_type(
|
let filter = DialInfoFilter::global()
|
||||||
ProtocolType::TCP,
|
.with_protocol_type(ProtocolType::TCP)
|
||||||
AddressType::IPV4,
|
.with_address_type(AddressType::IPV4);
|
||||||
);
|
|
||||||
let need_tcpv4_dialinfo = routing_table
|
let need_tcpv4_dialinfo = routing_table
|
||||||
.first_filtered_global_dial_info_details(|d| d.dial_info.matches_filter(&filter))
|
.first_filtered_dial_info_detail(&filter)
|
||||||
.is_none();
|
.is_none();
|
||||||
if need_tcpv4_dialinfo {
|
if need_tcpv4_dialinfo {
|
||||||
// If we have no public TCPv4 dialinfo, then we need to run a NAT check
|
// If we have no public TCPv4 dialinfo, then we need to run a NAT check
|
||||||
|
@ -4,17 +4,14 @@ pub mod wrtc;
|
|||||||
pub mod ws;
|
pub mod ws;
|
||||||
|
|
||||||
use super::listener_state::*;
|
use super::listener_state::*;
|
||||||
use crate::veilid_api::ProtocolType;
|
|
||||||
use crate::xx::*;
|
use crate::xx::*;
|
||||||
|
use crate::*;
|
||||||
use socket2::{Domain, Protocol, Socket, Type};
|
use socket2::{Domain, Protocol, Socket, Type};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct DummyNetworkConnection {}
|
pub struct DummyNetworkConnection {}
|
||||||
|
|
||||||
impl DummyNetworkConnection {
|
impl DummyNetworkConnection {
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
ProtocolType::UDP
|
|
||||||
}
|
|
||||||
pub fn send(&self, _message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, _message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
Box::pin(async { Ok(()) })
|
Box::pin(async { Ok(()) })
|
||||||
}
|
}
|
||||||
@ -34,15 +31,6 @@ pub enum NetworkConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkConnection {
|
impl NetworkConnection {
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
match self {
|
|
||||||
Self::Dummy(d) => d.protocol_type(),
|
|
||||||
Self::RawTcp(t) => t.protocol_type(),
|
|
||||||
Self::WsAccepted(w) => w.protocol_type(),
|
|
||||||
Self::Ws(w) => w.protocol_type(),
|
|
||||||
Self::Wss(w) => w.protocol_type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Dummy(d) => d.send(message),
|
Self::Dummy(d) => d.send(message),
|
||||||
|
@ -44,10 +44,6 @@ impl RawTcpNetworkConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RawTcpNetworkConnection {
|
impl RawTcpNetworkConnection {
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
ProtocolType::TCP
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
|
|
||||||
|
@ -80,14 +80,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
if self.tls {
|
|
||||||
ProtocolType::WSS
|
|
||||||
} else {
|
|
||||||
ProtocolType::WS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
|
|
||||||
@ -248,9 +240,9 @@ impl WebsocketProtocolHandler {
|
|||||||
dial_info: &DialInfo,
|
dial_info: &DialInfo,
|
||||||
) -> Result<NetworkConnection, String> {
|
) -> Result<NetworkConnection, String> {
|
||||||
// Split dial info up
|
// Split dial info up
|
||||||
let (tls, protocol_type, scheme) = match &dial_info {
|
let (tls, scheme) = match &dial_info {
|
||||||
DialInfo::WS(_) => (false, ProtocolType::WS, "ws"),
|
DialInfo::WS(_) => (false, "ws"),
|
||||||
DialInfo::WSS(_) => (true, ProtocolType::WSS, "wss"),
|
DialInfo::WSS(_) => (true, "wss"),
|
||||||
_ => panic!("invalid dialinfo for WS/WSS protocol"),
|
_ => panic!("invalid dialinfo for WS/WSS protocol"),
|
||||||
};
|
};
|
||||||
let request = dial_info.request().unwrap();
|
let request = dial_info.request().unwrap();
|
||||||
|
@ -5,8 +5,6 @@ use crate::network_manager::*;
|
|||||||
use crate::routing_table::*;
|
use crate::routing_table::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
use async_std::net::*;
|
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
// Ask for a public address check from a particular noderef
|
// Ask for a public address check from a particular noderef
|
||||||
async fn request_public_address(&self, node_ref: NodeRef) -> Option<SocketAddress> {
|
async fn request_public_address(&self, node_ref: NodeRef) -> Option<SocketAddress> {
|
||||||
@ -22,17 +20,20 @@ impl Network {
|
|||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
xxx convert to filter
|
|
||||||
// find fast peers with a particular address type, and ask them to tell us what our external address is
|
// find fast peers with a particular address type, and ask them to tell us what our external address is
|
||||||
async fn discover_external_address(
|
async fn discover_external_address(
|
||||||
&self,
|
&self,
|
||||||
protocol_address_type: ProtocolAddressType,
|
protocol_type: ProtocolType,
|
||||||
|
address_type: AddressType,
|
||||||
ignore_node: Option<DHTKey>,
|
ignore_node: Option<DHTKey>,
|
||||||
) -> Option<(SocketAddr, NodeRef)> {
|
) -> Option<(SocketAddress, NodeRef)> {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let peers = routing_table.get_fast_nodes_of_type(protocol_address_type);
|
let filter = DialInfoFilter::global()
|
||||||
|
.with_protocol_type(protocol_type)
|
||||||
|
.with_address_type(address_type);
|
||||||
|
let peers = routing_table.find_fast_nodes_filtered(&filter);
|
||||||
if peers.is_empty() {
|
if peers.is_empty() {
|
||||||
log_net!("no peers of type '{:?}'", protocol_address_type);
|
log_net!("no peers of type '{:?}'", filter);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
@ -49,24 +50,20 @@ impl Network {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_interface_addresses(
|
fn get_local_addresses(
|
||||||
&self,
|
&self,
|
||||||
protocol_address_type: ProtocolAddressType,
|
protocol_type: ProtocolType,
|
||||||
) -> Vec<SocketAddr> {
|
address_type: AddressType,
|
||||||
|
) -> Vec<SocketAddress> {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
|
let filter = DialInfoFilter::local()
|
||||||
|
.with_protocol_type(protocol_type)
|
||||||
|
.with_address_type(address_type);
|
||||||
routing_table
|
routing_table
|
||||||
.get_own_peer_info(PeerScope::Local)
|
.all_filtered_dial_info_details(&filter)
|
||||||
.dial_infos
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|di| {
|
.map(|did| did.dial_info.socket_address())
|
||||||
if di.protocol_address_type() == protocol_address_type {
|
|
||||||
if let Ok(addr) = di.to_socket_addr() {
|
|
||||||
return Some(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +85,12 @@ impl Network {
|
|||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_port_mapping<I: AsRef<[SocketAddr]>>(
|
async fn try_port_mapping<I: AsRef<[SocketAddress]>>(
|
||||||
&self,
|
&self,
|
||||||
_intf_addrs: I,
|
_intf_addrs: I,
|
||||||
_protocol_address_type: ProtocolAddressType,
|
_protocol_type: ProtocolType,
|
||||||
) -> Option<SocketAddr> {
|
_address_type: AddressType,
|
||||||
|
) -> Option<SocketAddress> {
|
||||||
//xxx
|
//xxx
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -107,13 +105,13 @@ impl Network {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get our interface addresses
|
// Get our interface addresses
|
||||||
let intf_addrs = self.get_interface_addresses(ProtocolAddressType::UDPv4);
|
let intf_addrs = self.get_local_addresses(ProtocolType::UDP, AddressType::IPV4);
|
||||||
|
|
||||||
// Loop for restricted NAT retries
|
// Loop for restricted NAT retries
|
||||||
loop {
|
loop {
|
||||||
// Get our external address from some fast node, call it node B
|
// Get our external address from some fast node, call it node B
|
||||||
let (external1, node_b) = match self
|
let (external1, node_b) = match self
|
||||||
.discover_external_address(ProtocolAddressType::UDPv4, None)
|
.discover_external_address(ProtocolType::UDP, AddressType::IPV4, None)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
None => {
|
None => {
|
||||||
@ -122,7 +120,7 @@ impl Network {
|
|||||||
}
|
}
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
};
|
};
|
||||||
let external1_dial_info = DialInfo::udp_from_socketaddr(external1);
|
let external1_dial_info = DialInfo::udp(external1);
|
||||||
|
|
||||||
// If our local interface list contains external1 then there is no NAT in place
|
// If our local interface list contains external1 then there is no NAT in place
|
||||||
if intf_addrs.contains(&external1) {
|
if intf_addrs.contains(&external1) {
|
||||||
@ -133,10 +131,10 @@ impl Network {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Add public dial info with Server network class
|
// Add public dial info with Server network class
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
|
Some(NetworkClass::Server),
|
||||||
);
|
);
|
||||||
|
|
||||||
// No more retries
|
// No more retries
|
||||||
@ -149,15 +147,15 @@ impl Network {
|
|||||||
// There is -some NAT-
|
// There is -some NAT-
|
||||||
// Attempt a UDP port mapping via all available and enabled mechanisms
|
// Attempt a UDP port mapping via all available and enabled mechanisms
|
||||||
if let Some(external_mapped) = self
|
if let Some(external_mapped) = self
|
||||||
.try_port_mapping(&intf_addrs, ProtocolAddressType::UDPv4)
|
.try_port_mapping(&intf_addrs, ProtocolType::UDP, AddressType::IPV4)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Got a port mapping, let's use it
|
// Got a port mapping, let's use it
|
||||||
let external_mapped_dial_info = DialInfo::udp_from_socketaddr(external_mapped);
|
let external_mapped_dial_info = DialInfo::udp(external_mapped);
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
external_mapped_dial_info,
|
external_mapped_dial_info,
|
||||||
Some(NetworkClass::Mapped),
|
|
||||||
DialInfoOrigin::Mapped,
|
DialInfoOrigin::Mapped,
|
||||||
|
Some(NetworkClass::Mapped),
|
||||||
);
|
);
|
||||||
|
|
||||||
// No more retries
|
// No more retries
|
||||||
@ -177,10 +175,10 @@ impl Network {
|
|||||||
{
|
{
|
||||||
// Yes, another machine can use the dial info directly, so Full Cone
|
// Yes, another machine can use the dial info directly, so Full Cone
|
||||||
// Add public dial info with full cone NAT network class
|
// Add public dial info with full cone NAT network class
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
Some(NetworkClass::FullNAT),
|
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
|
Some(NetworkClass::FullNAT),
|
||||||
);
|
);
|
||||||
|
|
||||||
// No more retries
|
// No more retries
|
||||||
@ -191,7 +189,8 @@ impl Network {
|
|||||||
// Get our external address from some fast node, that is not node B, call it node D
|
// Get our external address from some fast node, that is not node B, call it node D
|
||||||
let (external2, node_d) = match self
|
let (external2, node_d) = match self
|
||||||
.discover_external_address(
|
.discover_external_address(
|
||||||
ProtocolAddressType::UDPv4,
|
ProtocolType::UDP,
|
||||||
|
AddressType::IPV4,
|
||||||
Some(node_b.node_id()),
|
Some(node_b.node_id()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -214,7 +213,7 @@ impl Network {
|
|||||||
// we should go through our retries before we assign a dial info
|
// we should go through our retries before we assign a dial info
|
||||||
if retry_count == 0 {
|
if retry_count == 0 {
|
||||||
// Address is the same, so it's address or port restricted
|
// Address is the same, so it's address or port restricted
|
||||||
let external2_dial_info = DialInfo::udp_from_socketaddr(external2);
|
let external2_dial_info = DialInfo::udp(external2);
|
||||||
// Do a validate_dial_info on the external address from a routed node
|
// Do a validate_dial_info on the external address from a routed node
|
||||||
if self
|
if self
|
||||||
.validate_dial_info(
|
.validate_dial_info(
|
||||||
@ -226,17 +225,17 @@ impl Network {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Got a reply from a non-default port, which means we're only address restricted
|
// Got a reply from a non-default port, which means we're only address restricted
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
Some(NetworkClass::AddressRestrictedNAT),
|
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
|
Some(NetworkClass::AddressRestrictedNAT),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Didn't get a reply from a non-default port, which means we are also port restricted
|
// Didn't get a reply from a non-default port, which means we are also port restricted
|
||||||
routing_table.register_global_dial_info(
|
routing_table.register_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
Some(NetworkClass::PortRestrictedNAT),
|
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
|
Some(NetworkClass::PortRestrictedNAT),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,8 +185,7 @@ impl Network {
|
|||||||
let routing_table = network_manager.routing_table();
|
let routing_table = network_manager.routing_table();
|
||||||
|
|
||||||
// Drop all dial info
|
// Drop all dial info
|
||||||
routing_table.clear_local_dial_info();
|
routing_table.clear_dial_info_details();
|
||||||
routing_table.clear_global_dial_info();
|
|
||||||
|
|
||||||
// Cancels all async background tasks by dropping join handles
|
// Cancels all async background tasks by dropping join handles
|
||||||
*self.inner.lock() = Self::new_inner(network_manager);
|
*self.inner.lock() = Self::new_inner(network_manager);
|
||||||
|
@ -27,12 +27,6 @@ pub enum NetworkConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkConnection {
|
impl NetworkConnection {
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
match self {
|
|
||||||
Self::Dummy(d) => d.protocol_type(),
|
|
||||||
Self::WS(w) => w.protocol_type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Dummy(d) => d.send(message),
|
Self::Dummy(d) => d.send(message),
|
||||||
|
@ -45,13 +45,6 @@ impl WebsocketNetworkConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WebsocketNetworkConnection {
|
impl WebsocketNetworkConnection {
|
||||||
pub fn protocol_type(&self) -> ProtocolType {
|
|
||||||
if self.tls {
|
|
||||||
ProtocolType::WSS
|
|
||||||
} else {
|
|
||||||
ProtocolType::WS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), String>> {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
@ -76,7 +76,7 @@ impl BucketEntry {
|
|||||||
where
|
where
|
||||||
F: Fn(&DialInfo) -> bool,
|
F: Fn(&DialInfo) -> bool,
|
||||||
{
|
{
|
||||||
let ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
for di in &self.dial_infos {
|
for di in &self.dial_infos {
|
||||||
if filter(di) {
|
if filter(di) {
|
||||||
ret.push(di.clone());
|
ret.push(di.clone());
|
||||||
@ -86,7 +86,7 @@ impl BucketEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dial_infos(&self) -> &[DialInfo] {
|
pub fn dial_infos(&self) -> &[DialInfo] {
|
||||||
&self.dial_infos.clone()
|
&self.dial_infos
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo {
|
pub fn get_peer_info(&self, key: DHTKey, scope: PeerScope) -> PeerInfo {
|
||||||
|
@ -8,10 +8,11 @@ use crate::*;
|
|||||||
pub type FilterType = Box<dyn Fn(&(&DHTKey, Option<&mut BucketEntry>)) -> bool>;
|
pub type FilterType = Box<dyn Fn(&(&DHTKey, Option<&mut BucketEntry>)) -> bool>;
|
||||||
|
|
||||||
impl RoutingTable {
|
impl RoutingTable {
|
||||||
// Retrieve the fastest nodes in the routing table with a particular kind of protocol address type
|
// Retrieve the fastest nodes in the routing table with a particular kind of protocol and address type
|
||||||
// Returns noderefs are are scoped to that address type only
|
// Returns noderefs are are scoped to that address type only
|
||||||
pub fn get_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
|
pub fn find_fast_nodes_filtered(&self, dial_info_filter: &DialInfoFilter) -> Vec<NodeRef> {
|
||||||
let dial_info_filter = dial_info_filter.clone();
|
let dial_info_filter1 = dial_info_filter.clone();
|
||||||
|
let dial_info_filter2 = dial_info_filter.clone();
|
||||||
self.find_fastest_nodes(
|
self.find_fastest_nodes(
|
||||||
// filter
|
// filter
|
||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
@ -20,7 +21,7 @@ impl RoutingTable {
|
|||||||
.1
|
.1
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter))
|
.first_filtered_dial_info(|di| di.matches_filter(&dial_info_filter1))
|
||||||
.is_some()
|
.is_some()
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
@ -30,27 +31,22 @@ impl RoutingTable {
|
|||||||
self.clone(),
|
self.clone(),
|
||||||
*e.0,
|
*e.0,
|
||||||
e.1.as_mut().unwrap(),
|
e.1.as_mut().unwrap(),
|
||||||
dial_info_filter.clone(),
|
dial_info_filter2.clone(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo {
|
pub fn get_own_peer_info(&self, scope: PeerScope) -> PeerInfo {
|
||||||
let dial_infos = match scope {
|
let filter = DialInfoFilter::scoped(scope);
|
||||||
PeerScope::All => {
|
|
||||||
let mut divec = self.global_dial_info_details();
|
|
||||||
divec.append(&mut self.local_dial_info_details());
|
|
||||||
divec.dedup();
|
|
||||||
divec
|
|
||||||
}
|
|
||||||
PeerScope::Global => self.global_dial_info_details(),
|
|
||||||
PeerScope::Local => self.local_dial_info_details(),
|
|
||||||
};
|
|
||||||
|
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
node_id: NodeId::new(self.node_id()),
|
node_id: NodeId::new(self.node_id()),
|
||||||
dial_infos: dial_infos.iter().map(|x| x.dial_info.clone()).collect(),
|
dial_infos: self
|
||||||
|
.all_filtered_dial_info_details(&filter)
|
||||||
|
.iter()
|
||||||
|
.map(|did| did.dial_info.clone())
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +37,18 @@ pub struct DialInfoDetail {
|
|||||||
pub timestamp: u64,
|
pub timestamp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MatchesDialInfoFilter for DialInfoDetail {
|
||||||
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
||||||
|
self.dial_info.matches_filter(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct RoutingTableInner {
|
struct RoutingTableInner {
|
||||||
network_manager: NetworkManager,
|
network_manager: NetworkManager,
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
node_id_secret: DHTKeySecret,
|
node_id_secret: DHTKeySecret,
|
||||||
buckets: Vec<Bucket>,
|
buckets: Vec<Bucket>,
|
||||||
local_dial_info: Vec<DialInfoDetail>,
|
dial_info_details: Vec<DialInfoDetail>,
|
||||||
global_dial_info: Vec<DialInfoDetail>,
|
|
||||||
bucket_entry_count: usize,
|
bucket_entry_count: usize,
|
||||||
// Waiters
|
// Waiters
|
||||||
eventual_changed_dial_info: Eventual,
|
eventual_changed_dial_info: Eventual,
|
||||||
@ -75,8 +80,7 @@ impl RoutingTable {
|
|||||||
node_id: DHTKey::default(),
|
node_id: DHTKey::default(),
|
||||||
node_id_secret: DHTKeySecret::default(),
|
node_id_secret: DHTKeySecret::default(),
|
||||||
buckets: Vec::new(),
|
buckets: Vec::new(),
|
||||||
local_dial_info: Vec::new(),
|
dial_info_details: Vec::new(),
|
||||||
global_dial_info: Vec::new(),
|
|
||||||
bucket_entry_count: 0,
|
bucket_entry_count: 0,
|
||||||
eventual_changed_dial_info: Eventual::new(),
|
eventual_changed_dial_info: Eventual::new(),
|
||||||
stats_accounting: StatsAccounting::new(),
|
stats_accounting: StatsAccounting::new(),
|
||||||
@ -150,125 +154,71 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_local_dial_info(&self) -> bool {
|
pub fn has_local_dial_info(&self) -> bool {
|
||||||
let inner = self.inner.lock();
|
self.first_filtered_dial_info_detail(&DialInfoFilter::local())
|
||||||
!inner.local_dial_info.is_empty()
|
.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_global_dial_info(&self) -> bool {
|
||||||
|
self.first_filtered_dial_info_detail(&DialInfoFilter::global())
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn global_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||||
|
self.all_filtered_dial_info_details(&DialInfoFilter::global())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
pub fn local_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
||||||
let inner = self.inner.lock();
|
self.all_filtered_dial_info_details(&DialInfoFilter::local())
|
||||||
inner.local_dial_info.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_filtered_local_dial_info_details<F>(&self, filter: F) -> Option<DialInfoDetail>
|
pub fn first_filtered_dial_info_detail(
|
||||||
where
|
&self,
|
||||||
F: Fn(&DialInfoDetail) -> bool,
|
filter: &DialInfoFilter,
|
||||||
{
|
) -> Option<DialInfoDetail> {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
for did in &inner.local_dial_info {
|
for did in &inner.dial_info_details {
|
||||||
if filter(did) {
|
if did.matches_filter(filter) {
|
||||||
return Some(did.clone());
|
return Some(did.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
pub fn all_filtered_local_dial_info_details<F>(&self, filter: F) -> Vec<DialInfoDetail>
|
pub fn all_filtered_dial_info_details(&self, filter: &DialInfoFilter) -> Vec<DialInfoDetail> {
|
||||||
where
|
|
||||||
F: Fn(&DialInfoDetail) -> bool,
|
|
||||||
{
|
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
let ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
for did in &inner.local_dial_info {
|
for did in &inner.dial_info_details {
|
||||||
if filter(did) {
|
if did.matches_filter(filter) {
|
||||||
ret.push(did.clone());
|
ret.push(did.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_local_dial_info(&self, dial_info: DialInfo, origin: DialInfoOrigin) {
|
pub fn register_dial_info(
|
||||||
|
&self,
|
||||||
|
dial_info: DialInfo,
|
||||||
|
origin: DialInfoOrigin,
|
||||||
|
network_class: Option<NetworkClass>,
|
||||||
|
) {
|
||||||
let timestamp = get_timestamp();
|
let timestamp = get_timestamp();
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
inner.local_dial_info.push(DialInfoDetail {
|
inner.dial_info_details.push(DialInfoDetail {
|
||||||
dial_info: dial_info.clone(),
|
dial_info: dial_info.clone(),
|
||||||
origin,
|
origin,
|
||||||
network_class: None,
|
network_class,
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Local Dial Info: {}",
|
"{}Dial Info: {}",
|
||||||
NodeDialInfoSingle {
|
if dial_info.is_local() {
|
||||||
node_id: NodeId::new(inner.node_id),
|
"Local "
|
||||||
dial_info
|
} else if dial_info.is_global() {
|
||||||
}
|
"Global "
|
||||||
.to_string(),
|
} else {
|
||||||
);
|
"Other "
|
||||||
debug!(" Origin: {:?}", origin);
|
},
|
||||||
|
|
||||||
Self::trigger_changed_dial_info(&mut *inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_local_dial_info(&self) {
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
inner.local_dial_info.clear();
|
|
||||||
Self::trigger_changed_dial_info(&mut *inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_global_dial_info(&self) -> bool {
|
|
||||||
let inner = self.inner.lock();
|
|
||||||
!inner.global_dial_info.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global_dial_info_details(&self) -> Vec<DialInfoDetail> {
|
|
||||||
let inner = self.inner.lock();
|
|
||||||
inner.global_dial_info.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn first_filtered_global_dial_info_details<F>(&self, filter: F) -> Option<DialInfoDetail>
|
|
||||||
where
|
|
||||||
F: Fn(&DialInfoDetail) -> bool,
|
|
||||||
{
|
|
||||||
let inner = self.inner.lock();
|
|
||||||
for did in &inner.global_dial_info {
|
|
||||||
if filter(did) {
|
|
||||||
return Some(did.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub fn all_filtered_global_dial_info_details<F>(&self, filter: F) -> Vec<DialInfoDetail>
|
|
||||||
where
|
|
||||||
F: Fn(&DialInfoDetail) -> bool,
|
|
||||||
{
|
|
||||||
let inner = self.inner.lock();
|
|
||||||
let ret = Vec::new();
|
|
||||||
for did in &inner.global_dial_info {
|
|
||||||
if filter(did) {
|
|
||||||
ret.push(did.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_global_dial_info(
|
|
||||||
&self,
|
|
||||||
dial_info: DialInfo,
|
|
||||||
network_class: Option<NetworkClass>,
|
|
||||||
origin: DialInfoOrigin,
|
|
||||||
) {
|
|
||||||
let ts = get_timestamp();
|
|
||||||
let mut inner = self.inner.lock();
|
|
||||||
|
|
||||||
inner.global_dial_info.push(DialInfoDetail {
|
|
||||||
dial_info: dial_info.clone(),
|
|
||||||
origin,
|
|
||||||
network_class,
|
|
||||||
timestamp: ts,
|
|
||||||
});
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"Global Dial Info: {}",
|
|
||||||
NodeDialInfoSingle {
|
NodeDialInfoSingle {
|
||||||
node_id: NodeId::new(inner.node_id),
|
node_id: NodeId::new(inner.node_id),
|
||||||
dial_info
|
dial_info
|
||||||
@ -277,12 +227,13 @@ impl RoutingTable {
|
|||||||
);
|
);
|
||||||
debug!(" Origin: {:?}", origin);
|
debug!(" Origin: {:?}", origin);
|
||||||
debug!(" Network Class: {:?}", network_class);
|
debug!(" Network Class: {:?}", network_class);
|
||||||
|
|
||||||
Self::trigger_changed_dial_info(&mut *inner);
|
Self::trigger_changed_dial_info(&mut *inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_global_dial_info(&self) {
|
pub fn clear_dial_info_details(&self) {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.global_dial_info.clear();
|
inner.dial_info_details.clear();
|
||||||
Self::trigger_changed_dial_info(&mut *inner);
|
Self::trigger_changed_dial_info(&mut *inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,12 +49,7 @@ impl NodeRef {
|
|||||||
// Returns the best dial info to attempt a connection to this node
|
// Returns the best dial info to attempt a connection to this node
|
||||||
pub fn best_dial_info(&self) -> Option<DialInfo> {
|
pub fn best_dial_info(&self) -> Option<DialInfo> {
|
||||||
let nm = self.routing_table.network_manager();
|
let nm = self.routing_table.network_manager();
|
||||||
let protocol_config = nm.get_protocol_config();
|
let protocol_config = nm.get_protocol_config()?;
|
||||||
if protocol_config.is_none() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let protocol_config = protocol_config.unwrap();
|
|
||||||
|
|
||||||
self.operate(|e| {
|
self.operate(|e| {
|
||||||
e.first_filtered_dial_info(|di| {
|
e.first_filtered_dial_info(|di| {
|
||||||
// Does it match the dial info filter
|
// Does it match the dial info filter
|
||||||
@ -99,7 +94,7 @@ impl Clone for NodeRef {
|
|||||||
|
|
||||||
impl fmt::Debug for NodeRef {
|
impl fmt::Debug for NodeRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let out = format!("{}", self.node_id.encode());
|
let mut out = self.node_id.encode();
|
||||||
if !self.dial_info_filter.is_empty() {
|
if !self.dial_info_filter.is_empty() {
|
||||||
out += &format!("{:?}", self.dial_info_filter);
|
out += &format!("{:?}", self.dial_info_filter);
|
||||||
}
|
}
|
||||||
|
@ -867,23 +867,23 @@ impl RPCProcessor {
|
|||||||
if redirect {
|
if redirect {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let filter = dial_info.make_filter(true);
|
let filter = dial_info.make_filter(true);
|
||||||
let peers = routing_table.get_fast_nodes_filtered(&filter);
|
let peers = routing_table.find_fast_nodes_filtered(&filter);
|
||||||
if peers.is_empty() {
|
if peers.is_empty() {
|
||||||
return Err(rpc_error_internal(format!(
|
return Err(rpc_error_internal(format!(
|
||||||
"no peers matching filter '{:?}'",
|
"no peers matching filter '{:?}'",
|
||||||
filter
|
filter
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
// See if this peer will validate dial info
|
// See if this peer will validate dial info
|
||||||
if !peer.operate(|e| {
|
let will_validate_dial_info = peer.operate(|e: &mut BucketEntry| {
|
||||||
if let Some(ni) = &e.peer_stats().node_info {
|
if let Some(ni) = &e.peer_stats().node_info {
|
||||||
ni.will_validate_dial_info
|
ni.will_validate_dial_info
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}) {
|
});
|
||||||
|
if !will_validate_dial_info {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Make a copy of the request, without the redirect flag
|
// Make a copy of the request, without the redirect flag
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod debug;
|
mod debug;
|
||||||
pub use debug::*;
|
pub use debug::*;
|
||||||
|
|
||||||
@ -209,8 +211,8 @@ impl Address {
|
|||||||
}
|
}
|
||||||
pub fn address_type(&self) -> AddressType {
|
pub fn address_type(&self) -> AddressType {
|
||||||
match self {
|
match self {
|
||||||
Address::IPV4(v4) => AddressType::IPV4,
|
Address::IPV4(_) => AddressType::IPV4,
|
||||||
Address::IPV6(v6) => AddressType::IPV6,
|
Address::IPV6(_) => AddressType::IPV6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn address_string(&self) -> String {
|
pub fn address_string(&self) -> String {
|
||||||
@ -227,14 +229,14 @@ impl Address {
|
|||||||
}
|
}
|
||||||
pub fn is_global(&self) -> bool {
|
pub fn is_global(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Address::IPV4(v4) => ipv4addr_is_global(&v4),
|
Address::IPV4(v4) => ipv4addr_is_global(v4),
|
||||||
Address::IPV6(v6) => ipv6addr_is_global(&v6),
|
Address::IPV6(v6) => ipv6addr_is_global(v6),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn is_local(&self) -> bool {
|
pub fn is_local(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Address::IPV4(v4) => ipv4addr_is_private(&v4),
|
Address::IPV4(v4) => ipv4addr_is_private(v4),
|
||||||
Address::IPV6(v6) => ipv6addr_is_unicast_site_local(&v6),
|
Address::IPV6(v6) => ipv6addr_is_unicast_site_local(v6),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_ip_addr(&self) -> IpAddr {
|
pub fn to_ip_addr(&self) -> IpAddr {
|
||||||
@ -334,30 +336,42 @@ pub struct DialInfoFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DialInfoFilter {
|
impl DialInfoFilter {
|
||||||
pub fn new_empty() -> Self {
|
pub fn all() -> Self {
|
||||||
Self {
|
Self {
|
||||||
peer_scope: PeerScope::All,
|
peer_scope: PeerScope::All,
|
||||||
protocol_type: None,
|
protocol_type: None,
|
||||||
address_type: None,
|
address_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn with_protocol_type(protocol_type: ProtocolType) -> Self {
|
pub fn global() -> Self {
|
||||||
Self {
|
Self {
|
||||||
peer_scope: PeerScope::All,
|
peer_scope: PeerScope::Global,
|
||||||
protocol_type: Some(protocol_type),
|
protocol_type: None,
|
||||||
address_type: None,
|
address_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn with_protocol_type_and_address_type(
|
pub fn local() -> Self {
|
||||||
protocol_type: ProtocolType,
|
|
||||||
address_type: AddressType,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
peer_scope: PeerScope::All,
|
peer_scope: PeerScope::Local,
|
||||||
protocol_type: Some(protocol_type),
|
protocol_type: None,
|
||||||
address_type: Some(address_type),
|
address_type: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn scoped(peer_scope: PeerScope) -> Self {
|
||||||
|
Self {
|
||||||
|
peer_scope,
|
||||||
|
protocol_type: None,
|
||||||
|
address_type: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_protocol_type(mut self, protocol_type: ProtocolType) -> Self {
|
||||||
|
self.protocol_type = Some(protocol_type);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
|
||||||
|
self.address_type = Some(address_type);
|
||||||
|
self
|
||||||
|
}
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.peer_scope == PeerScope::All
|
self.peer_scope == PeerScope::All
|
||||||
&& self.protocol_type.is_none()
|
&& self.protocol_type.is_none()
|
||||||
@ -379,6 +393,10 @@ impl fmt::Debug for DialInfoFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MatchesDialInfoFilter {
|
||||||
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
||||||
pub struct DialInfoUDP {
|
pub struct DialInfoUDP {
|
||||||
pub socket_address: SocketAddress,
|
pub socket_address: SocketAddress,
|
||||||
@ -430,9 +448,9 @@ impl fmt::Display for DialInfo {
|
|||||||
impl FromStr for DialInfo {
|
impl FromStr for DialInfo {
|
||||||
type Err = VeilidAPIError;
|
type Err = VeilidAPIError;
|
||||||
fn from_str(s: &str) -> Result<DialInfo, VeilidAPIError> {
|
fn from_str(s: &str) -> Result<DialInfo, VeilidAPIError> {
|
||||||
let (proto, rest) = s.split_once('|').ok_or_else(|| {
|
let (proto, rest) = s
|
||||||
parse_error!("SocketAddress::from_str missing protocol '|' separator", s)
|
.split_once('|')
|
||||||
})?;
|
.ok_or_else(|| parse_error!("DialInfo::from_str missing protocol '|' separator", s))?;
|
||||||
match proto {
|
match proto {
|
||||||
"udp" => {
|
"udp" => {
|
||||||
let socket_address = SocketAddress::from_str(rest)?;
|
let socket_address = SocketAddress::from_str(rest)?;
|
||||||
@ -444,24 +462,19 @@ impl FromStr for DialInfo {
|
|||||||
}
|
}
|
||||||
"ws" => {
|
"ws" => {
|
||||||
let (sa, rest) = s.split_once('|').ok_or_else(|| {
|
let (sa, rest) = s.split_once('|').ok_or_else(|| {
|
||||||
parse_error!(
|
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||||
"SocketAddress::from_str missing socket address '|' separator",
|
|
||||||
s
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
let socket_address = SocketAddress::from_str(sa)?;
|
let socket_address = SocketAddress::from_str(sa)?;
|
||||||
DialInfo::try_ws(socket_address, rest.to_string())
|
DialInfo::try_ws(socket_address, rest.to_string())
|
||||||
}
|
}
|
||||||
"wss" => {
|
"wss" => {
|
||||||
let (sa, rest) = s.split_once('|').ok_or_else(|| {
|
let (sa, rest) = s.split_once('|').ok_or_else(|| {
|
||||||
parse_error!(
|
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||||
"SocketAddress::from_str missing socket address '|' separator",
|
|
||||||
s
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
let socket_address = SocketAddress::from_str(sa)?;
|
let socket_address = SocketAddress::from_str(sa)?;
|
||||||
DialInfo::try_wss(socket_address, rest.to_string())
|
DialInfo::try_wss(socket_address, rest.to_string())
|
||||||
}
|
}
|
||||||
|
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,7 +531,7 @@ impl DialInfo {
|
|||||||
url
|
url
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !Address::from_str(&split_url.host).is_err() {
|
if Address::from_str(&split_url.host).is_ok() {
|
||||||
return Err(parse_error!(
|
return Err(parse_error!(
|
||||||
"WSS url can not use address format, only hostname format",
|
"WSS url can not use address format, only hostname format",
|
||||||
url
|
url
|
||||||
@ -599,22 +612,6 @@ impl DialInfo {
|
|||||||
PeerScope::Local => self.is_local(),
|
PeerScope::Local => self.is_local(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
|
||||||
if !self.matches_peer_scope(filter.peer_scope) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if let Some(pt) = filter.protocol_type {
|
|
||||||
if self.protocol_type() != pt {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(at) = filter.address_type {
|
|
||||||
if self.address_type() != at {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
pub fn make_filter(&self, scoped: bool) -> DialInfoFilter {
|
pub fn make_filter(&self, scoped: bool) -> DialInfoFilter {
|
||||||
DialInfoFilter {
|
DialInfoFilter {
|
||||||
peer_scope: if scoped {
|
peer_scope: if scoped {
|
||||||
@ -634,6 +631,25 @@ impl DialInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MatchesDialInfoFilter for DialInfo {
|
||||||
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
||||||
|
if !self.matches_peer_scope(filter.peer_scope) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Some(pt) = filter.protocol_type {
|
||||||
|
if self.protocol_type() != pt {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(at) = filter.address_type {
|
||||||
|
if self.address_type() != at {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@ -709,7 +725,10 @@ impl ConnectionDescriptor {
|
|||||||
PeerScope::Local => self.remote.socket_address.address().is_local(),
|
PeerScope::Local => self.remote.socket_address.address().is_local(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
}
|
||||||
|
|
||||||
|
impl MatchesDialInfoFilter for ConnectionDescriptor {
|
||||||
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
||||||
if !self.matches_peer_scope(filter.peer_scope) {
|
if !self.matches_peer_scope(filter.peer_scope) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1093,18 +1112,11 @@ impl VeilidAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait for state change
|
// wait for state change
|
||||||
// xxx: this should not use 'sleep', perhaps this function should be eliminated anyway
|
// xxx: should have optional timeout
|
||||||
// xxx: it should really only be used for test anyway, and there is probably a better way to do this regardless
|
|
||||||
// xxx: that doesn't wait forever and can time out
|
|
||||||
pub async fn wait_for_state(&self, state: VeilidState) -> Result<(), VeilidAPIError> {
|
pub async fn wait_for_state(&self, state: VeilidState) -> Result<(), VeilidAPIError> {
|
||||||
loop {
|
|
||||||
intf::sleep(500).await;
|
|
||||||
match state {
|
match state {
|
||||||
VeilidState::Attachment(cs) => {
|
VeilidState::Attachment(cs) => {
|
||||||
if self.attachment_manager()?.get_state() == cs {
|
self.attachment_manager()?.wait_for_state(cs).await;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user