refactoring, more config, packaging
This commit is contained in:
@@ -136,10 +136,10 @@ impl Log for ApiLogger {
|
||||
|
||||
let s = format!("{}{}{}", tgt, loc, record.args());
|
||||
|
||||
(inner.update_callback)(VeilidUpdate::Log {
|
||||
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
|
||||
log_level: ll,
|
||||
message: s,
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,15 +271,18 @@ impl AttachmentManager {
|
||||
let network_manager = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.update_callback = Some(update_callback.clone());
|
||||
let update_callback2 = update_callback.clone();
|
||||
inner.attachment_machine.set_state_change_callback(Arc::new(
|
||||
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
||||
update_callback(VeilidUpdate::Attachment { state: new_state })
|
||||
update_callback2(VeilidUpdate::Attachment(VeilidStateAttachment {
|
||||
state: new_state,
|
||||
}))
|
||||
},
|
||||
));
|
||||
inner.network_manager.clone()
|
||||
};
|
||||
|
||||
network_manager.init().await?;
|
||||
network_manager.init(update_callback).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -356,4 +359,10 @@ impl AttachmentManager {
|
||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
||||
attachment_machine.state()
|
||||
}
|
||||
|
||||
pub fn get_veilid_state(&self) -> VeilidStateAttachment {
|
||||
VeilidStateAttachment {
|
||||
state: self.get_state(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,14 @@ impl Network {
|
||||
.interfaces
|
||||
.best_addresses()
|
||||
.iter()
|
||||
.map(|a| SocketAddr::new(*a, from.port()))
|
||||
.filter_map(|a| {
|
||||
// We create sockets that are only ipv6 or ipv6 (not dual, so only translate matching unspecified address)
|
||||
if (a.is_ipv4() && from.is_ipv4()) || (a.is_ipv6() && from.is_ipv6()) {
|
||||
Some(SocketAddr::new(*a, from.port()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,6 +445,7 @@ impl Network {
|
||||
log_net!("updating network class");
|
||||
|
||||
let protocol_config = self.inner.lock().protocol_config.unwrap_or_default();
|
||||
let old_network_class = self.inner.lock().network_class;
|
||||
|
||||
let context = DiscoveryContext::new(self.routing_table(), self.clone());
|
||||
|
||||
@@ -470,9 +471,10 @@ impl Network {
|
||||
}
|
||||
|
||||
let network_class = context.inner.lock().network_class;
|
||||
self.inner.lock().network_class = network_class;
|
||||
|
||||
log_net!(debug "network class set to {:?}", network_class);
|
||||
if network_class != old_network_class {
|
||||
self.inner.lock().network_class = network_class;
|
||||
log_net!(debug "network class changed to {:?}", network_class);
|
||||
}
|
||||
|
||||
// send updates to everyone
|
||||
self.routing_table().send_node_info_updates();
|
||||
|
||||
@@ -291,6 +291,8 @@ impl Network {
|
||||
let local_dial_info_list = self.create_udp_inbound_sockets(ip_addrs, udp_port).await?;
|
||||
let mut static_public = false;
|
||||
|
||||
trace!("UDP: listener started on {:#?}", local_dial_info_list);
|
||||
|
||||
// Register local dial info
|
||||
for di in &local_dial_info_list {
|
||||
// If the local interface address is global, or we are enabling local peer scope
|
||||
@@ -397,7 +399,7 @@ impl Network {
|
||||
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
||||
)
|
||||
.await?;
|
||||
trace!("WS: listener started");
|
||||
trace!("WS: listener started on {:#?}", socket_addresses);
|
||||
|
||||
let mut static_public = false;
|
||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||
@@ -515,7 +517,7 @@ impl Network {
|
||||
wss_port,
|
||||
ip_addrs
|
||||
);
|
||||
let _socket_addresses = self
|
||||
let socket_addresses = self
|
||||
.start_tcp_listener(
|
||||
ip_addrs,
|
||||
wss_port,
|
||||
@@ -523,7 +525,7 @@ impl Network {
|
||||
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
||||
)
|
||||
.await?;
|
||||
trace!("WSS: listener started");
|
||||
trace!("WSS: listener started on {:#?}", socket_addresses);
|
||||
|
||||
// NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS
|
||||
// If the hostname is specified, it is the public dialinfo via the URL. If no hostname
|
||||
@@ -629,7 +631,7 @@ impl Network {
|
||||
Box::new(|_, _, a| Box::new(RawTcpProtocolHandler::new(a))),
|
||||
)
|
||||
.await?;
|
||||
trace!("TCP: listener started");
|
||||
trace!("TCP: listener started on {:#?}", socket_addresses);
|
||||
|
||||
let mut static_public = false;
|
||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||
|
||||
@@ -90,6 +90,7 @@ pub enum SendDataKind {
|
||||
struct NetworkManagerInner {
|
||||
routing_table: Option<RoutingTable>,
|
||||
components: Option<NetworkComponents>,
|
||||
update_callback: Option<UpdateCallback>,
|
||||
stats: NetworkManagerStats,
|
||||
client_whitelist: LruCache<key::DHTKey, ClientWhitelistEntry>,
|
||||
relay_node: Option<NodeRef>,
|
||||
@@ -116,6 +117,7 @@ impl NetworkManager {
|
||||
NetworkManagerInner {
|
||||
routing_table: None,
|
||||
components: None,
|
||||
update_callback: None,
|
||||
stats: NetworkManagerStats::default(),
|
||||
client_whitelist: LruCache::new_unbounded(),
|
||||
relay_node: None,
|
||||
@@ -205,10 +207,11 @@ impl NetworkManager {
|
||||
self.inner.lock().relay_node.clone()
|
||||
}
|
||||
|
||||
pub async fn init(&self) -> Result<(), String> {
|
||||
pub async fn init(&self, update_callback: UpdateCallback) -> Result<(), String> {
|
||||
let routing_table = RoutingTable::new(self.clone());
|
||||
routing_table.init().await?;
|
||||
self.inner.lock().routing_table = Some(routing_table.clone());
|
||||
self.inner.lock().update_callback = Some(update_callback);
|
||||
Ok(())
|
||||
}
|
||||
pub async fn terminate(&self) {
|
||||
@@ -219,6 +222,7 @@ impl NetworkManager {
|
||||
if let Some(routing_table) = routing_table {
|
||||
routing_table.terminate().await;
|
||||
}
|
||||
self.inner.lock().update_callback = None;
|
||||
}
|
||||
|
||||
pub async fn internal_startup(&self) -> Result<(), String> {
|
||||
@@ -256,9 +260,16 @@ impl NetworkManager {
|
||||
self.shutdown().await;
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
self.send_network_update();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().components.is_some()
|
||||
}
|
||||
|
||||
pub async fn shutdown(&self) {
|
||||
trace!("NetworkManager::shutdown begin");
|
||||
|
||||
@@ -272,8 +283,13 @@ impl NetworkManager {
|
||||
}
|
||||
|
||||
// reset the state
|
||||
let mut inner = self.inner.lock();
|
||||
inner.components = None;
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
inner.components = None;
|
||||
}
|
||||
|
||||
// send update
|
||||
self.send_network_update();
|
||||
|
||||
trace!("NetworkManager::shutdown end");
|
||||
}
|
||||
@@ -334,7 +350,9 @@ impl NetworkManager {
|
||||
// if things can't restart, then we fail out of the attachment manager
|
||||
if net.needs_restart() {
|
||||
net.shutdown().await;
|
||||
self.send_network_update();
|
||||
net.startup().await?;
|
||||
self.send_network_update();
|
||||
}
|
||||
|
||||
// Run the routing table tick
|
||||
@@ -1155,35 +1173,41 @@ impl NetworkManager {
|
||||
// Compute transfer statistics for the low level network
|
||||
async fn rolling_transfers_task_routine(self, last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
||||
log_net!("--- network manager rolling_transfers task");
|
||||
let inner = &mut *self.inner.lock();
|
||||
{
|
||||
let inner = &mut *self.inner.lock();
|
||||
|
||||
// Roll the low level network transfer stats for our address
|
||||
inner
|
||||
.stats
|
||||
.self_stats
|
||||
.transfer_stats_accounting
|
||||
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
||||
// Roll the low level network transfer stats for our address
|
||||
inner
|
||||
.stats
|
||||
.self_stats
|
||||
.transfer_stats_accounting
|
||||
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
||||
|
||||
// Roll all per-address transfers
|
||||
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
||||
for (addr, stats) in &mut inner.stats.per_address_stats {
|
||||
stats.transfer_stats_accounting.roll_transfers(
|
||||
last_ts,
|
||||
cur_ts,
|
||||
&mut stats.transfer_stats,
|
||||
);
|
||||
// Roll all per-address transfers
|
||||
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
||||
for (addr, stats) in &mut inner.stats.per_address_stats {
|
||||
stats.transfer_stats_accounting.roll_transfers(
|
||||
last_ts,
|
||||
cur_ts,
|
||||
&mut stats.transfer_stats,
|
||||
);
|
||||
|
||||
// While we're here, lets see if this address has timed out
|
||||
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
||||
// it's dead, put it in the dead list
|
||||
dead_addrs.insert(*addr);
|
||||
// While we're here, lets see if this address has timed out
|
||||
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
||||
// it's dead, put it in the dead list
|
||||
dead_addrs.insert(*addr);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the dead addresses from our tables
|
||||
for da in &dead_addrs {
|
||||
inner.stats.per_address_stats.remove(da);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the dead addresses from our tables
|
||||
for da in &dead_addrs {
|
||||
inner.stats.per_address_stats.remove(da);
|
||||
}
|
||||
// Send update
|
||||
self.send_network_update();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1220,6 +1244,45 @@ impl NetworkManager {
|
||||
.add_down(bytes);
|
||||
}
|
||||
|
||||
// Get stats
|
||||
pub fn get_stats(&self) -> NetworkManagerStats {
|
||||
let inner = self.inner.lock();
|
||||
inner.stats.clone()
|
||||
}
|
||||
|
||||
fn get_veilid_state_inner(inner: &NetworkManagerInner) -> VeilidStateNetwork {
|
||||
if inner.components.is_some() {
|
||||
VeilidStateNetwork {
|
||||
started: true,
|
||||
bps_down: inner.stats.self_stats.transfer_stats.down.average,
|
||||
bps_up: inner.stats.self_stats.transfer_stats.up.average,
|
||||
}
|
||||
} else {
|
||||
VeilidStateNetwork {
|
||||
started: false,
|
||||
bps_down: 0,
|
||||
bps_up: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn get_veilid_state(&self) -> VeilidStateNetwork {
|
||||
let inner = self.inner.lock();
|
||||
Self::get_veilid_state_inner(&*inner)
|
||||
}
|
||||
|
||||
fn send_network_update(&self) {
|
||||
let (update_cb, state) = {
|
||||
let inner = self.inner.lock();
|
||||
let update_cb = inner.update_callback.clone();
|
||||
if update_cb.is_none() {
|
||||
return;
|
||||
}
|
||||
let state = Self::get_veilid_state_inner(&*inner);
|
||||
(update_cb.unwrap(), state)
|
||||
};
|
||||
update_cb(VeilidUpdate::Network(state));
|
||||
}
|
||||
|
||||
// Determine if a local IP address has changed
|
||||
// this means we should restart the low level network and and recreate all of our dial info
|
||||
// Wait until we have received confirmation from N different peers
|
||||
|
||||
@@ -205,10 +205,6 @@ impl ReceiptManager {
|
||||
let config = self.core().config();
|
||||
let c = config.get();
|
||||
let mut inner = self.inner.lock();
|
||||
inner.max_server_signal_leases = c.network.leases.max_server_signal_leases as usize;
|
||||
inner.max_server_relay_leases = c.network.leases.max_server_relay_leases as usize;
|
||||
inner.max_client_signal_leases = c.network.leases.max_client_signal_leases as usize;
|
||||
inner.max_client_relay_leases = c.network.leases.max_client_relay_leases as usize;
|
||||
}
|
||||
*/
|
||||
Ok(())
|
||||
|
||||
@@ -22,20 +22,36 @@ impl RoutingTable {
|
||||
|
||||
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();
|
||||
pub fn debug_info_dialinfo(&self, txt_format: bool) -> String {
|
||||
if txt_format {
|
||||
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);
|
||||
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
|
||||
} else {
|
||||
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
|
||||
}
|
||||
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();
|
||||
|
||||
@@ -771,17 +771,36 @@ impl RoutingTable {
|
||||
}
|
||||
}
|
||||
|
||||
async fn resolve_bootstrap(&self, bootstrap: Vec<String>) -> Result<Vec<String>, String> {
|
||||
let mut out = Vec::<String>::new();
|
||||
for bh in bootstrap {
|
||||
//
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
async fn bootstrap_task_routine(self) -> Result<(), String> {
|
||||
let bootstrap = {
|
||||
let (bootstrap, bootstrap_nodes) = {
|
||||
let c = self.config.get();
|
||||
c.network.bootstrap.clone()
|
||||
(
|
||||
c.network.bootstrap.clone(),
|
||||
c.network.bootstrap_nodes.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
log_rtab!("--- bootstrap_task");
|
||||
|
||||
// If we aren't specifying a bootstrap node list explicitly, then pull from the bootstrap server(s)
|
||||
let bootstrap_nodes = if !bootstrap_nodes.is_empty() {
|
||||
bootstrap_nodes
|
||||
} else {
|
||||
// Resolve bootstrap servers and recurse their TXT entries
|
||||
self.resolve_bootstrap(bootstrap).await?
|
||||
};
|
||||
|
||||
// Map all bootstrap entries to a single key with multiple dialinfo
|
||||
let mut bsmap: BTreeMap<DHTKey, Vec<DialInfoDetail>> = BTreeMap::new();
|
||||
for b in bootstrap {
|
||||
for b in bootstrap_nodes {
|
||||
let ndis = NodeDialInfo::from_str(b.as_str())
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_rtab!("Invalid dial info in bootstrap entry: {}", b))?;
|
||||
@@ -794,7 +813,7 @@ impl RoutingTable {
|
||||
class: DialInfoClass::Direct, // Bootstraps are always directly reachable
|
||||
});
|
||||
}
|
||||
log_rtab!(" bootstrap list: {:?}", bsmap);
|
||||
log_rtab!(" bootstrap node dialinfo: {:?}", bsmap);
|
||||
|
||||
// Run all bootstrap operations concurrently
|
||||
let mut unord = FuturesUnordered::new();
|
||||
|
||||
@@ -192,9 +192,12 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
||||
"network.max_connections_per_ip6_prefix_size" => Ok(Box::new(56u32)),
|
||||
"network.max_connection_frequency_per_min" => Ok(Box::new(8u32)),
|
||||
"network.client_whitelist_timeout_ms" => Ok(Box::new(300_000u32)),
|
||||
"network.reverse_connection_receipt_time_ms" => Ok(Box::new(5_000u32)),
|
||||
"network.hole_punch_receipt_time_ms" => Ok(Box::new(5_000u32)),
|
||||
"network.node_id" => Ok(Box::new(dht::key::DHTKey::default())),
|
||||
"network.node_id_secret" => Ok(Box::new(dht::key::DHTKeySecret::default())),
|
||||
"network.bootstrap" => Ok(Box::new(Vec::<String>::new())),
|
||||
"network.bootstrap_nodes" => Ok(Box::new(Vec::<String>::new())),
|
||||
"network.routing_table.limit_over_attached" => Ok(Box::new(64u32)),
|
||||
"network.routing_table.limit_fully_attached" => Ok(Box::new(32u32)),
|
||||
"network.routing_table.limit_attached_strong" => Ok(Box::new(16u32)),
|
||||
@@ -255,10 +258,6 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
||||
"network.protocol.wss.listen_address" => Ok(Box::new("".to_owned())),
|
||||
"network.protocol.wss.path" => Ok(Box::new(String::from("ws"))),
|
||||
"network.protocol.wss.url" => Ok(Box::new(Option::<String>::None)),
|
||||
"network.leases.max_server_signal_leases" => Ok(Box::new(256u32)),
|
||||
"network.leases.max_server_relay_leases" => Ok(Box::new(8u32)),
|
||||
"network.leases.max_client_signal_leases" => Ok(Box::new(2u32)),
|
||||
"network.leases.max_client_relay_leases" => Ok(Box::new(2u32)),
|
||||
_ => {
|
||||
let err = format!("config key '{}' doesn't exist", key);
|
||||
debug!("{}", err);
|
||||
@@ -318,9 +317,12 @@ pub async fn test_config() {
|
||||
assert_eq!(inner.network.max_connections_per_ip6_prefix_size, 56u32);
|
||||
assert_eq!(inner.network.max_connection_frequency_per_min, 8u32);
|
||||
assert_eq!(inner.network.client_whitelist_timeout_ms, 300_000u32);
|
||||
assert_eq!(inner.network.reverse_connection_receipt_time_ms, 5_000u32);
|
||||
assert_eq!(inner.network.hole_punch_receipt_time_ms, 5_000u32);
|
||||
assert!(!inner.network.node_id.valid);
|
||||
assert!(!inner.network.node_id_secret.valid);
|
||||
assert_eq!(inner.network.bootstrap, Vec::<String>::new());
|
||||
assert_eq!(inner.network.bootstrap_nodes, Vec::<String>::new());
|
||||
assert_eq!(inner.network.rpc.concurrency, 2u32);
|
||||
assert_eq!(inner.network.rpc.queue_size, 128u32);
|
||||
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
||||
|
||||
@@ -79,10 +79,16 @@ impl VeilidAPI {
|
||||
Ok(routing_table.debug_info_buckets(min_state))
|
||||
}
|
||||
|
||||
async fn debug_dialinfo(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
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
|
||||
};
|
||||
// Dump routing table dialinfo
|
||||
let routing_table = self.network_manager()?.routing_table();
|
||||
Ok(routing_table.debug_info_dialinfo())
|
||||
Ok(routing_table.debug_info_dialinfo(is_txt))
|
||||
}
|
||||
|
||||
async fn debug_entries(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||
@@ -147,7 +153,7 @@ impl VeilidAPI {
|
||||
|
||||
// Must be detached
|
||||
if !matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@@ -168,7 +174,7 @@ impl VeilidAPI {
|
||||
if args[0] == "buckets" {
|
||||
// Must be detached
|
||||
if matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached | AttachmentState::Detaching
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@@ -194,7 +200,7 @@ impl VeilidAPI {
|
||||
|
||||
async fn debug_attach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
if !matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@@ -209,7 +215,7 @@ impl VeilidAPI {
|
||||
|
||||
async fn debug_detach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
if matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detaching
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
|
||||
@@ -167,22 +167,37 @@ impl VeilidLogLevel {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidStateLog {
|
||||
pub log_level: VeilidLogLevel,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidStateAttachment {
|
||||
pub state: AttachmentState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidStateNetwork {
|
||||
pub started: bool,
|
||||
pub bps_down: u64,
|
||||
pub bps_up: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum VeilidUpdate {
|
||||
Log {
|
||||
log_level: VeilidLogLevel,
|
||||
message: String,
|
||||
},
|
||||
Attachment {
|
||||
state: AttachmentState,
|
||||
},
|
||||
Log(VeilidStateLog),
|
||||
Attachment(VeilidStateAttachment),
|
||||
Network(VeilidStateNetwork),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidState {
|
||||
pub attachment: AttachmentState,
|
||||
pub attachment: VeilidStateAttachment,
|
||||
pub network: VeilidStateNetwork,
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -745,8 +760,37 @@ impl fmt::Display for DialInfo {
|
||||
match self {
|
||||
DialInfo::UDP(di) => write!(f, "udp|{}", di.socket_address),
|
||||
DialInfo::TCP(di) => write!(f, "tcp|{}", di.socket_address),
|
||||
DialInfo::WS(di) => write!(f, "ws|{}|{}", di.socket_address, di.request),
|
||||
DialInfo::WSS(di) => write!(f, "wss|{}|{}", di.socket_address, di.request),
|
||||
DialInfo::WS(di) => {
|
||||
let url = format!("ws://{}", di.request);
|
||||
let split_url = SplitUrl::from_str(&url).unwrap();
|
||||
match split_url.host {
|
||||
SplitUrlHost::Hostname(_) => {
|
||||
write!(f, "ws|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
||||
}
|
||||
SplitUrlHost::IpAddr(a) => {
|
||||
if di.socket_address.to_ip_addr() == a {
|
||||
write!(f, "ws|{}", di.request)
|
||||
} else {
|
||||
panic!("resolved address does not match url: {}", di.request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DialInfo::WSS(di) => {
|
||||
let url = format!("wss://{}", di.request);
|
||||
let split_url = SplitUrl::from_str(&url).unwrap();
|
||||
match split_url.host {
|
||||
SplitUrlHost::Hostname(_) => {
|
||||
write!(f, "wss|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
||||
}
|
||||
SplitUrlHost::IpAddr(_) => {
|
||||
panic!(
|
||||
"secure websockets can not use ip address in request: {}",
|
||||
di.request
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,18 +811,50 @@ impl FromStr for DialInfo {
|
||||
Ok(DialInfo::tcp(socket_address))
|
||||
}
|
||||
"ws" => {
|
||||
let (sa, rest) = rest.split_once('|').ok_or_else(|| {
|
||||
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||
})?;
|
||||
let socket_address = SocketAddress::from_str(sa)?;
|
||||
DialInfo::try_ws(socket_address, format!("ws://{}", rest))
|
||||
let url = format!("ws://{}", rest);
|
||||
let split_url = SplitUrl::from_str(&url)
|
||||
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?;
|
||||
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
||||
return Err(parse_error!("incorrect scheme for WS dialinfo", url));
|
||||
}
|
||||
let url_port = split_url.port.unwrap_or(80u16);
|
||||
|
||||
match rest.split_once('|') {
|
||||
Some((sa, rest)) => {
|
||||
let address = Address::from_str(sa)?;
|
||||
|
||||
DialInfo::try_ws(
|
||||
SocketAddress::new(address, url_port),
|
||||
format!("ws://{}", rest),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let address = Address::from_str(&split_url.host.to_string())?;
|
||||
DialInfo::try_ws(
|
||||
SocketAddress::new(address, url_port),
|
||||
format!("ws://{}", rest),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
"wss" => {
|
||||
let (sa, rest) = rest.split_once('|').ok_or_else(|| {
|
||||
let url = format!("wss://{}", rest);
|
||||
let split_url = SplitUrl::from_str(&url)
|
||||
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?;
|
||||
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
||||
return Err(parse_error!("incorrect scheme for WSS dialinfo", url));
|
||||
}
|
||||
let url_port = split_url.port.unwrap_or(443u16);
|
||||
|
||||
let (a, rest) = rest.split_once('|').ok_or_else(|| {
|
||||
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||
})?;
|
||||
let socket_address = SocketAddress::from_str(sa)?;
|
||||
DialInfo::try_wss(socket_address, format!("wss://{}", rest))
|
||||
|
||||
let address = Address::from_str(a)?;
|
||||
DialInfo::try_wss(
|
||||
SocketAddress::new(address, url_port),
|
||||
format!("wss://{}", rest),
|
||||
)
|
||||
}
|
||||
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)),
|
||||
}
|
||||
@@ -819,6 +895,14 @@ impl DialInfo {
|
||||
url
|
||||
));
|
||||
}
|
||||
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
||||
if socket_address.to_ip_addr() != a {
|
||||
return Err(parse_error!(
|
||||
format!("request address does not match socket address: {}", a),
|
||||
socket_address
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(Self::WS(DialInfoWS {
|
||||
socket_address: socket_address.to_canonical(),
|
||||
request: url[5..].to_string(),
|
||||
@@ -1497,11 +1581,19 @@ impl VeilidAPI {
|
||||
// get a full copy of the current state
|
||||
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
let network_manager = attachment_manager.network_manager();
|
||||
|
||||
let attachment = attachment_manager.get_veilid_state();
|
||||
let network = network_manager.get_veilid_state();
|
||||
|
||||
Ok(VeilidState {
|
||||
attachment: attachment_manager.get_state(),
|
||||
attachment,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
// get network connectedness
|
||||
|
||||
// connect to the network
|
||||
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
|
||||
@@ -104,7 +104,6 @@ pub struct VeilidConfigDHT {
|
||||
pub min_peer_count: u32,
|
||||
pub min_peer_refresh_time_ms: u32,
|
||||
pub validate_dial_info_receipt_time_ms: u32,
|
||||
pub nearby_node_percentage: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -117,13 +116,6 @@ pub struct VeilidConfigRPC {
|
||||
pub max_route_hop_count: u8,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidConfigLeases {
|
||||
pub max_server_signal_leases: u32,
|
||||
pub max_server_relay_leases: u32,
|
||||
pub max_client_signal_leases: u32,
|
||||
pub max_client_relay_leases: u32,
|
||||
}
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidConfigRoutingTable {
|
||||
pub limit_over_attached: u32,
|
||||
@@ -147,6 +139,7 @@ pub struct VeilidConfigNetwork {
|
||||
pub node_id: key::DHTKey,
|
||||
pub node_id_secret: key::DHTKeySecret,
|
||||
pub bootstrap: Vec<String>,
|
||||
pub bootstrap_nodes: Vec<String>,
|
||||
pub routing_table: VeilidConfigRoutingTable,
|
||||
pub rpc: VeilidConfigRPC,
|
||||
pub dht: VeilidConfigDHT,
|
||||
@@ -157,7 +150,6 @@ pub struct VeilidConfigNetwork {
|
||||
pub tls: VeilidConfigTLS,
|
||||
pub application: VeilidConfigApplication,
|
||||
pub protocol: VeilidConfigProtocol,
|
||||
pub leases: VeilidConfigLeases,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -305,6 +297,7 @@ impl VeilidConfig {
|
||||
get_config!(inner.network.max_connection_frequency_per_min);
|
||||
get_config!(inner.network.client_whitelist_timeout_ms);
|
||||
get_config!(inner.network.bootstrap);
|
||||
get_config!(inner.network.bootstrap_nodes);
|
||||
get_config!(inner.network.routing_table.limit_over_attached);
|
||||
get_config!(inner.network.routing_table.limit_fully_attached);
|
||||
get_config!(inner.network.routing_table.limit_attached_strong);
|
||||
@@ -365,10 +358,6 @@ impl VeilidConfig {
|
||||
get_config!(inner.network.protocol.wss.listen_address);
|
||||
get_config!(inner.network.protocol.wss.path);
|
||||
get_config!(inner.network.protocol.wss.url);
|
||||
get_config!(inner.network.leases.max_server_signal_leases);
|
||||
get_config!(inner.network.leases.max_server_relay_leases);
|
||||
get_config!(inner.network.leases.max_client_signal_leases);
|
||||
get_config!(inner.network.leases.max_client_relay_leases);
|
||||
}
|
||||
// Validate settings
|
||||
self.validate()?;
|
||||
|
||||
Reference in New Issue
Block a user