packaging and bootstrap work
This commit is contained in:
@@ -51,6 +51,7 @@ digest = "0.9.0"
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
async-std = { version = "^1", features = ["unstable"] }
|
||||
async-tungstenite = { version = "^0", features = ["async-std-runtime", "async-tls"] }
|
||||
async-std-resolver = { version = "^0" }
|
||||
maplit = "^1"
|
||||
config = { version = "^0", features = ["yaml"] }
|
||||
keyring-manager = { path = "../external/keyring-manager" }
|
||||
|
||||
@@ -482,6 +482,10 @@ impl Network {
|
||||
self.inner.lock().network_needs_restart
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().network_started
|
||||
}
|
||||
|
||||
pub fn restart_network(&self) {
|
||||
self.inner.lock().network_needs_restart = true;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,14 @@
|
||||
use crate::xx::*;
|
||||
pub use async_executors::JoinHandle;
|
||||
use async_executors::{AsyncStd, LocalSpawnHandleExt, SpawnHandleExt};
|
||||
use async_std_resolver::{config, resolver, AsyncStdResolver};
|
||||
use rand::prelude::*;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref RESOLVER: Arc<AsyncMutex<Option<AsyncStdResolver>>> = Arc::new(AsyncMutex::new(None));
|
||||
}
|
||||
|
||||
pub fn get_timestamp() -> u64 {
|
||||
match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(n) => n.as_micros() as u64,
|
||||
@@ -111,3 +116,48 @@ where
|
||||
}));
|
||||
}
|
||||
*/
|
||||
|
||||
async fn get_resolver() -> Result<AsyncStdResolver, String> {
|
||||
let mut resolver_lock = RESOLVER.lock().await;
|
||||
if let Some(r) = &*resolver_lock {
|
||||
Ok(r.clone())
|
||||
} else {
|
||||
let resolver = resolver(
|
||||
config::ResolverConfig::default(),
|
||||
config::ResolverOpts::default(),
|
||||
)
|
||||
.await
|
||||
.expect("failed to connect resolver");
|
||||
|
||||
*resolver_lock = Some(resolver.clone());
|
||||
Ok(resolver)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
|
||||
let resolver = get_resolver().await?;
|
||||
let txt_result = resolver
|
||||
.txt_lookup(host.as_ref())
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let mut out = Vec::new();
|
||||
for x in txt_result.iter() {
|
||||
for s in x.txt_data() {
|
||||
out.push(String::from_utf8(s.to_vec()).map_err(|e| e.to_string())?);
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn ptr_lookup(ip_addr: IpAddr) -> Result<String, String> {
|
||||
let resolver = get_resolver().await?;
|
||||
let ptr_result = resolver
|
||||
.reverse_lookup(ip_addr)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
if let Some(r) = ptr_result.iter().next() {
|
||||
Ok(r.to_string().trim_end_matches('.').to_string())
|
||||
} else {
|
||||
Err("PTR lookup returned an empty string".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,9 @@ fn veilid_core_setup_internal<'a>(
|
||||
let mut logs: Vec<Box<dyn SharedLogger>> = Vec::new();
|
||||
|
||||
let mut cb = ConfigBuilder::new();
|
||||
cb.add_filter_ignore_str("async_std");
|
||||
cb.add_filter_ignore_str("async_io");
|
||||
cb.add_filter_ignore_str("polling");
|
||||
cb.add_filter_ignore_str("rustls");
|
||||
cb.add_filter_ignore_str("async_tungstenite");
|
||||
cb.add_filter_ignore_str("tungstenite");
|
||||
for ig in veilid_core::DEFAULT_LOG_IGNORE_LIST {
|
||||
cb.add_filter_ignore_str(ig);
|
||||
}
|
||||
|
||||
if let Some(level) = terminal_log {
|
||||
logs.push(TermLogger::new(
|
||||
|
||||
@@ -172,6 +172,10 @@ impl Network {
|
||||
self.inner.lock().network_needs_restart
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().network_started
|
||||
}
|
||||
|
||||
pub fn restart_network(&self) {
|
||||
self.inner.lock().network_needs_restart = true;
|
||||
}
|
||||
|
||||
@@ -200,4 +200,13 @@ pub async fn get_outbound_relay_peer() -> Option<crate::veilid_api::PeerInfo> {
|
||||
// } else {
|
||||
// panic!("WASM requires browser or nodejs environment");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
pub async fn txt_lookup<S: AsRef<str>>(host: S) -> Result<Vec<String>, String> {
|
||||
Err("wasm does not support txt lookup".to_owned())
|
||||
}
|
||||
|
||||
pub async fn ptr_lookup(ip_addr: IpAddr) -> Result<String, String> {
|
||||
Err("wasm does not support ptr lookup".to_owned())
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ pub fn veilid_version() -> (u32, u32, u32) {
|
||||
#[cfg(target_os = "android")]
|
||||
pub use intf::utils::android::{veilid_core_setup_android, veilid_core_setup_android_no_log};
|
||||
|
||||
pub static DEFAULT_LOG_IGNORE_LIST: [&str; 8] = [
|
||||
pub static DEFAULT_LOG_IGNORE_LIST: [&str; 10] = [
|
||||
"async_std",
|
||||
"async_io",
|
||||
"polling",
|
||||
@@ -59,4 +59,6 @@ pub static DEFAULT_LOG_IGNORE_LIST: [&str; 8] = [
|
||||
"tungstenite",
|
||||
"netlink_proto",
|
||||
"netlink_sys",
|
||||
"trust_dns_resolver",
|
||||
"trust_dns_proto",
|
||||
];
|
||||
|
||||
@@ -266,10 +266,6 @@ impl NetworkManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().components.is_some()
|
||||
}
|
||||
|
||||
pub async fn shutdown(&self) {
|
||||
trace!("NetworkManager::shutdown begin");
|
||||
|
||||
@@ -1251,7 +1247,7 @@ impl NetworkManager {
|
||||
}
|
||||
|
||||
fn get_veilid_state_inner(inner: &NetworkManagerInner) -> VeilidStateNetwork {
|
||||
if inner.components.is_some() {
|
||||
if inner.components.is_some() && inner.components.as_ref().unwrap().net.is_started() {
|
||||
VeilidStateNetwork {
|
||||
started: true,
|
||||
bps_down: inner.stats.self_stats.transfer_stats.down.average,
|
||||
|
||||
@@ -22,37 +22,48 @@ impl RoutingTable {
|
||||
|
||||
out
|
||||
}
|
||||
pub fn debug_info_dialinfo(&self, txt_format: bool) -> String {
|
||||
if txt_format {
|
||||
let mut out = String::new();
|
||||
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
if gdis.is_empty() {
|
||||
out += "No TXT Record DialInfo\n";
|
||||
} else {
|
||||
out += "TXT Record DialInfo:\n";
|
||||
out += &format!("{}\n", self.node_id().encode());
|
||||
for gdi in gdis {
|
||||
out += &format!("{}\n", gdi.dial_info);
|
||||
}
|
||||
}
|
||||
out
|
||||
pub async fn debug_info_txtrecord(&self) -> String {
|
||||
let mut out = String::new();
|
||||
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
if gdis.is_empty() {
|
||||
out += "No TXT Record\n";
|
||||
} else {
|
||||
let ldis = self.dial_info_details(RoutingDomain::LocalNetwork);
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
let mut out = String::new();
|
||||
out += "TXT Record:\n";
|
||||
out += &self.node_id().encode();
|
||||
|
||||
out += "Local Network Dial Info Details:\n";
|
||||
for (n, ldi) in ldis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
||||
let mut urls = Vec::new();
|
||||
for gdi in gdis {
|
||||
urls.push(gdi.dial_info.to_url().await);
|
||||
}
|
||||
out += "Public Internet Dial Info Details:\n";
|
||||
for (n, gdi) in gdis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
||||
urls.sort();
|
||||
urls.dedup();
|
||||
|
||||
for url in urls {
|
||||
out += &format!(",{}", url);
|
||||
}
|
||||
out
|
||||
out += "\n";
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn debug_info_dialinfo(&self) -> String {
|
||||
let ldis = self.dial_info_details(RoutingDomain::LocalNetwork);
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
let mut out = String::new();
|
||||
|
||||
out += "Local Network Dial Info Details:\n";
|
||||
for (n, ldi) in ldis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
||||
}
|
||||
out += "Public Internet Dial Info Details:\n";
|
||||
for (n, gdi) in gdis.iter().enumerate() {
|
||||
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn debug_info_entries(&self, limit: usize, min_state: BucketEntryState) -> String {
|
||||
let inner = self.inner.lock();
|
||||
let cur_ts = get_timestamp();
|
||||
|
||||
@@ -129,11 +129,9 @@ cfg_if! {
|
||||
pub fn setup() {
|
||||
SETUP_ONCE.call_once(|| {
|
||||
let mut cb = ConfigBuilder::new();
|
||||
cb.add_filter_ignore_str("async_std");
|
||||
cb.add_filter_ignore_str("async_io");
|
||||
cb.add_filter_ignore_str("polling");
|
||||
cb.add_filter_ignore_str("netlink_proto");
|
||||
cb.add_filter_ignore_str("netlink_sys");
|
||||
for ig in crate::DEFAULT_LOG_IGNORE_LIST {
|
||||
cb.add_filter_ignore_str(ig);
|
||||
}
|
||||
TestLogger::init(LevelFilter::Trace, cb.build()).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,16 +79,16 @@ impl VeilidAPI {
|
||||
Ok(routing_table.debug_info_buckets(min_state))
|
||||
}
|
||||
|
||||
async fn debug_dialinfo(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||
let is_txt = if args.len() == 1 {
|
||||
args[0] == "txt"
|
||||
} else {
|
||||
false
|
||||
};
|
||||
async fn debug_dialinfo(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
// Dump routing table dialinfo
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_dialinfo(is_txt))
|
||||
Ok(routing_table.debug_info_dialinfo())
|
||||
}
|
||||
|
||||
async fn debug_txtrecord(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
// Dump routing table txt record
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_txtrecord().await)
|
||||
}
|
||||
|
||||
async fn debug_entries(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
@@ -259,6 +259,8 @@ impl VeilidAPI {
|
||||
self.debug_buckets(rest).await
|
||||
} else if arg == "dialinfo" {
|
||||
self.debug_dialinfo(rest).await
|
||||
} else if arg == "txtrecord" {
|
||||
self.debug_txtrecord(rest).await
|
||||
} else if arg == "entries" {
|
||||
self.debug_entries(rest).await
|
||||
} else if arg == "entry" {
|
||||
|
||||
@@ -1035,6 +1035,85 @@ impl DialInfo {
|
||||
address_type: Some(self.address_type()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_vec_from_url(url: String) -> Result<Vec<Self>, VeilidAPIError> {
|
||||
let split_url = SplitUrl::from_str(&url)
|
||||
.map_err(|e| parse_error!(format!("unable to split url: {}", e), url))?;
|
||||
|
||||
let port = match split_url.scheme.as_str() {
|
||||
"udp" | "tcp" => split_url
|
||||
.port
|
||||
.ok_or_else(|| parse_error!("Missing port in udp url", url))?,
|
||||
"ws" => split_url.port.unwrap_or(80u16),
|
||||
"wss" => split_url.port.unwrap_or(443u16),
|
||||
_ => {
|
||||
return Err(parse_error!(
|
||||
"Invalid dial info url scheme",
|
||||
split_url.scheme
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let socket_addrs = match split_url.host {
|
||||
SplitUrlHost::Hostname(_) => split_url
|
||||
.host_port(port)
|
||||
.to_socket_addrs()
|
||||
.map_err(|_| parse_error!("couldn't resolve hostname in url", url))?
|
||||
.collect(),
|
||||
SplitUrlHost::IpAddr(a) => vec![SocketAddr::new(a, port)],
|
||||
};
|
||||
|
||||
let mut out = Vec::new();
|
||||
for sa in socket_addrs {
|
||||
out.push(match split_url.scheme.as_str() {
|
||||
"udp" => Self::udp_from_socketaddr(sa),
|
||||
"tcp" => Self::tcp_from_socketaddr(sa),
|
||||
"ws" => Self::try_ws(
|
||||
SocketAddress::from_socket_addr(sa).to_canonical(),
|
||||
url.clone(),
|
||||
)?,
|
||||
"wss" => Self::try_wss(
|
||||
SocketAddress::from_socket_addr(sa).to_canonical(),
|
||||
url.clone(),
|
||||
)?,
|
||||
_ => {
|
||||
unreachable!("Invalid dial info url scheme")
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn to_url(&self) -> String {
|
||||
match self {
|
||||
DialInfo::UDP(di) => intf::ptr_lookup(di.socket_address.to_ip_addr())
|
||||
.await
|
||||
.map(|h| format!("udp://{}:{}", h, di.socket_address.port()))
|
||||
.unwrap_or_else(|_| format!("udp://{}", di.socket_address)),
|
||||
DialInfo::TCP(di) => intf::ptr_lookup(di.socket_address.to_ip_addr())
|
||||
.await
|
||||
.map(|h| format!("tcp://{}:{}", h, di.socket_address.port()))
|
||||
.unwrap_or_else(|_| format!("tcp://{}", di.socket_address)),
|
||||
DialInfo::WS(di) => {
|
||||
let mut split_url = SplitUrl::from_str(&format!("ws://{}", di.request)).unwrap();
|
||||
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
||||
if let Ok(host) = intf::ptr_lookup(a).await {
|
||||
split_url.host = SplitUrlHost::Hostname(host);
|
||||
}
|
||||
}
|
||||
split_url.to_string()
|
||||
}
|
||||
DialInfo::WSS(di) => {
|
||||
let mut split_url = SplitUrl::from_str(&format!("wss://{}", di.request)).unwrap();
|
||||
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
||||
if let Ok(host) = intf::ptr_lookup(a).await {
|
||||
split_url.host = SplitUrlHost::Hostname(host);
|
||||
}
|
||||
}
|
||||
split_url.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MatchesDialInfoFilter for DialInfo {
|
||||
|
||||
@@ -365,8 +365,10 @@ impl fmt::Display for SplitUrl {
|
||||
} else {
|
||||
format!("{}@{}", userinfo, self.host)
|
||||
}
|
||||
} else if let Some(port) = self.port {
|
||||
format!("{}:{}", self.host, port)
|
||||
} else {
|
||||
self.host.to_string()
|
||||
format!("{}", self.host)
|
||||
}
|
||||
};
|
||||
if let Some(path) = &self.path {
|
||||
|
||||
Reference in New Issue
Block a user