mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-12-24 23:09:25 -05:00
veilid-cli cleanup
This commit is contained in:
parent
4d65903ee4
commit
ca6c616d66
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -1209,6 +1209,15 @@ dependencies = [
|
|||||||
"xi-unicode",
|
"xi-unicode",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cursive_table_view"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8935dd87d19c54b7506b245bc988a7b4e65b1058e1d0d64c0ad9b3188e48060"
|
||||||
|
dependencies = [
|
||||||
|
"cursive_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "3.2.1"
|
version = "3.2.1"
|
||||||
@ -5087,6 +5096,7 @@ dependencies = [
|
|||||||
"cursive",
|
"cursive",
|
||||||
"cursive-flexi-logger-view",
|
"cursive-flexi-logger-view",
|
||||||
"cursive_buffered_backend",
|
"cursive_buffered_backend",
|
||||||
|
"cursive_table_view",
|
||||||
"directories",
|
"directories",
|
||||||
"flexi_logger",
|
"flexi_logger",
|
||||||
"futures",
|
"futures",
|
||||||
@ -5155,6 +5165,7 @@ dependencies = [
|
|||||||
"nix 0.25.0",
|
"nix 0.25.0",
|
||||||
"no-std-net",
|
"no-std-net",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"owning_ref",
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
|
@ -23,9 +23,9 @@ tokio-util = { version = "^0", features = ["compat"], optional = true}
|
|||||||
async-tungstenite = { version = "^0.8" }
|
async-tungstenite = { version = "^0.8" }
|
||||||
cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" }
|
cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" }
|
||||||
cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
|
cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
|
||||||
# cursive-multiplex = "0.4.0"
|
# cursive-multiplex = "0.6.0"
|
||||||
# cursive_tree_view = "0.6.0"
|
# cursive_tree_view = "0.6.0"
|
||||||
# cursive_table_view = "0.12.0"
|
cursive_table_view = "0.14.0"
|
||||||
# cursive-tabs = "0.5.0"
|
# cursive-tabs = "0.5.0"
|
||||||
clap = "^3"
|
clap = "^3"
|
||||||
directories = "^4"
|
directories = "^4"
|
||||||
|
@ -8,7 +8,7 @@ use std::net::SocketAddr;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use veilid_core::xx::{Eventual, EventualCommon};
|
use veilid_core::xx::{Eventual, EventualCommon};
|
||||||
use veilid_core::VeilidConfigLogLevel;
|
use veilid_core::*;
|
||||||
|
|
||||||
pub fn convert_loglevel(s: &str) -> Result<VeilidConfigLogLevel, String> {
|
pub fn convert_loglevel(s: &str) -> Result<VeilidConfigLogLevel, String> {
|
||||||
match s.to_ascii_lowercase().as_str() {
|
match s.to_ascii_lowercase().as_str() {
|
||||||
@ -323,9 +323,12 @@ change_log_level - change the log level for a tracing layer
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_network_status(&mut self, network: veilid_core::VeilidStateNetwork) {
|
pub fn update_network_status(&mut self, network: veilid_core::VeilidStateNetwork) {
|
||||||
self.inner_mut()
|
self.inner_mut().ui.set_network_status(
|
||||||
.ui
|
network.started,
|
||||||
.set_network_status(network.started, network.bps_down, network.bps_up);
|
network.bps_down,
|
||||||
|
network.bps_up,
|
||||||
|
network.peers,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_log(&mut self, log: veilid_core::VeilidStateLog) {
|
pub fn update_log(&mut self, log: veilid_core::VeilidStateLog) {
|
||||||
|
@ -12,6 +12,7 @@ use tools::*;
|
|||||||
|
|
||||||
mod client_api_connection;
|
mod client_api_connection;
|
||||||
mod command_processor;
|
mod command_processor;
|
||||||
|
mod peers_table_view;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod tools;
|
mod tools;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
99
veilid-cli/src/peers_table_view.rs
Normal file
99
veilid-cli/src/peers_table_view.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
use super::*;
|
||||||
|
use cursive_table_view::*;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use veilid_core::PeerTableData;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum PeerTableColumn {
|
||||||
|
NodeId,
|
||||||
|
Address,
|
||||||
|
LatencyAvg,
|
||||||
|
TransferDownAvg,
|
||||||
|
TransferUpAvg,
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl PeerTableColumn {
|
||||||
|
// fn as_str(&self) -> &str {
|
||||||
|
// match self {
|
||||||
|
// PeerTableColumn::NodeId => "Node Id",
|
||||||
|
// PeerTableColumn::Address => "Address",
|
||||||
|
// PeerTableColumn::LatencyAvg => "Latency",
|
||||||
|
// PeerTableColumn::TransferDownAvg => "Down",
|
||||||
|
// PeerTableColumn::TransferUpAvg => "Up",
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn format_ts(ts: u64) -> String {
|
||||||
|
let secs = timestamp_to_secs(ts);
|
||||||
|
if secs >= 1.0 {
|
||||||
|
format!("{:.2}s", timestamp_to_secs(ts))
|
||||||
|
} else {
|
||||||
|
format!("{:.2}ms", timestamp_to_secs(ts) * 1000.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_bps(bps: u64) -> String {
|
||||||
|
if bps >= 1024u64 * 1024u64 * 1024u64 {
|
||||||
|
format!("{:.2}GB/s", (bps / (1024u64 * 1024u64)) as f64 / 1024.0)
|
||||||
|
} else if bps >= 1024u64 * 1024u64 {
|
||||||
|
format!("{:.2}MB/s", (bps / 1024u64) as f64 / 1024.0)
|
||||||
|
} else if bps >= 1024u64 {
|
||||||
|
format!("{:.2}KB/s", bps as f64 / 1024.0)
|
||||||
|
} else {
|
||||||
|
format!("{:.2}B/s", bps as f64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableViewItem<PeerTableColumn> for PeerTableData {
|
||||||
|
fn to_column(&self, column: PeerTableColumn) -> String {
|
||||||
|
match column {
|
||||||
|
PeerTableColumn::NodeId => self.node_id.encode(),
|
||||||
|
PeerTableColumn::Address => format!(
|
||||||
|
"{:?}:{}",
|
||||||
|
self.peer_address.protocol_type(),
|
||||||
|
self.peer_address.to_socket_addr()
|
||||||
|
),
|
||||||
|
PeerTableColumn::LatencyAvg => format!(
|
||||||
|
"{}",
|
||||||
|
self.peer_stats
|
||||||
|
.latency
|
||||||
|
.as_ref()
|
||||||
|
.map(|l| format_ts(l.average))
|
||||||
|
.unwrap_or("---".to_owned())
|
||||||
|
),
|
||||||
|
PeerTableColumn::TransferDownAvg => format_bps(self.peer_stats.transfer.down.average),
|
||||||
|
PeerTableColumn::TransferUpAvg => format_bps(self.peer_stats.transfer.up.average),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmp(&self, other: &Self, column: PeerTableColumn) -> Ordering
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
match column {
|
||||||
|
PeerTableColumn::NodeId => self.node_id.cmp(&other.node_id),
|
||||||
|
PeerTableColumn::Address => self.to_column(column).cmp(&other.to_column(column)),
|
||||||
|
PeerTableColumn::LatencyAvg => self
|
||||||
|
.peer_stats
|
||||||
|
.latency
|
||||||
|
.as_ref()
|
||||||
|
.map(|l| l.average)
|
||||||
|
.cmp(&other.peer_stats.latency.as_ref().map(|l| l.average)),
|
||||||
|
PeerTableColumn::TransferDownAvg => self
|
||||||
|
.peer_stats
|
||||||
|
.transfer
|
||||||
|
.down
|
||||||
|
.average
|
||||||
|
.cmp(&other.peer_stats.transfer.down.average),
|
||||||
|
PeerTableColumn::TransferUpAvg => self
|
||||||
|
.peer_stats
|
||||||
|
.transfer
|
||||||
|
.up
|
||||||
|
.average
|
||||||
|
.cmp(&other.peer_stats.transfer.up.average),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PeersTableView = TableView<PeerTableData, PeerTableColumn>;
|
@ -1,4 +1,5 @@
|
|||||||
use crate::command_processor::*;
|
use crate::command_processor::*;
|
||||||
|
use crate::peers_table_view::*;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use cursive::align::*;
|
use cursive::align::*;
|
||||||
@ -10,6 +11,7 @@ use cursive::views::*;
|
|||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
use cursive::CursiveRunnable;
|
use cursive::CursiveRunnable;
|
||||||
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
||||||
|
//use cursive_multiplex::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
@ -20,7 +22,7 @@ use veilid_core::*;
|
|||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
///
|
///
|
||||||
struct Dirty<T> {
|
struct Dirty<T> {
|
||||||
pub value: T,
|
value: T,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +54,7 @@ struct UIState {
|
|||||||
network_started: Dirty<bool>,
|
network_started: Dirty<bool>,
|
||||||
network_down_up: Dirty<(f32, f32)>,
|
network_down_up: Dirty<(f32, f32)>,
|
||||||
connection_state: Dirty<ConnectionState>,
|
connection_state: Dirty<ConnectionState>,
|
||||||
|
peers_state: Dirty<Vec<PeerTableData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UIState {
|
impl UIState {
|
||||||
@ -61,6 +64,7 @@ impl UIState {
|
|||||||
network_started: Dirty::new(false),
|
network_started: Dirty::new(false),
|
||||||
network_down_up: Dirty::new((0.0, 0.0)),
|
network_down_up: Dirty::new((0.0, 0.0)),
|
||||||
connection_state: Dirty::new(ConnectionState::Disconnected),
|
connection_state: Dirty::new(ConnectionState::Disconnected),
|
||||||
|
peers_state: Dirty::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,6 +223,9 @@ impl UI {
|
|||||||
fn status_bar(s: &mut Cursive) -> ViewRef<TextView> {
|
fn status_bar(s: &mut Cursive) -> ViewRef<TextView> {
|
||||||
s.find_name("status-bar").unwrap()
|
s.find_name("status-bar").unwrap()
|
||||||
}
|
}
|
||||||
|
fn peers(s: &mut Cursive) -> ViewRef<PeersTableView> {
|
||||||
|
s.find_name("peers").unwrap()
|
||||||
|
}
|
||||||
fn render_attachment_state<'a>(inner: &mut UIInner) -> &'a str {
|
fn render_attachment_state<'a>(inner: &mut UIInner) -> &'a str {
|
||||||
match inner.ui_state.attachment_state.get() {
|
match inner.ui_state.attachment_state.get() {
|
||||||
AttachmentState::Detached => " Detached [----]",
|
AttachmentState::Detached => " Detached [----]",
|
||||||
@ -607,15 +614,23 @@ impl UI {
|
|||||||
statusbar.set_content(status);
|
statusbar.set_content(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn refresh_peers(s: &mut Cursive) {
|
||||||
|
let mut peers = UI::peers(s);
|
||||||
|
let inner = Self::inner_mut(s);
|
||||||
|
peers.set_items_stable(inner.ui_state.peers_state.get().clone());
|
||||||
|
}
|
||||||
|
|
||||||
fn update_cb(s: &mut Cursive) {
|
fn update_cb(s: &mut Cursive) {
|
||||||
let mut inner = Self::inner_mut(s);
|
let mut inner = Self::inner_mut(s);
|
||||||
|
|
||||||
let mut refresh_statusbar = false;
|
let mut refresh_statusbar = false;
|
||||||
let mut refresh_button_attach = false;
|
let mut refresh_button_attach = false;
|
||||||
let mut refresh_connection_dialog = false;
|
let mut refresh_connection_dialog = false;
|
||||||
|
let mut refresh_peers = false;
|
||||||
if inner.ui_state.attachment_state.take_dirty() {
|
if inner.ui_state.attachment_state.take_dirty() {
|
||||||
refresh_statusbar = true;
|
refresh_statusbar = true;
|
||||||
refresh_button_attach = true;
|
refresh_button_attach = true;
|
||||||
|
refresh_peers = true;
|
||||||
}
|
}
|
||||||
if inner.ui_state.network_started.take_dirty() {
|
if inner.ui_state.network_started.take_dirty() {
|
||||||
refresh_statusbar = true;
|
refresh_statusbar = true;
|
||||||
@ -627,6 +642,10 @@ impl UI {
|
|||||||
refresh_statusbar = true;
|
refresh_statusbar = true;
|
||||||
refresh_button_attach = true;
|
refresh_button_attach = true;
|
||||||
refresh_connection_dialog = true;
|
refresh_connection_dialog = true;
|
||||||
|
refresh_peers = true;
|
||||||
|
}
|
||||||
|
if inner.ui_state.peers_state.take_dirty() {
|
||||||
|
refresh_peers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(inner);
|
drop(inner);
|
||||||
@ -640,6 +659,9 @@ impl UI {
|
|||||||
if refresh_connection_dialog {
|
if refresh_connection_dialog {
|
||||||
Self::refresh_connection_dialog(s);
|
Self::refresh_connection_dialog(s);
|
||||||
}
|
}
|
||||||
|
if refresh_peers {
|
||||||
|
Self::refresh_peers(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -686,30 +708,48 @@ impl UI {
|
|||||||
siv.set_user_data(this.inner.clone());
|
siv.set_user_data(this.inner.clone());
|
||||||
|
|
||||||
// Create layouts
|
// Create layouts
|
||||||
let mut mainlayout = LinearLayout::vertical().with_name("main-layout");
|
|
||||||
mainlayout.get_mut().add_child(
|
let node_events_view = Panel::new(
|
||||||
Panel::new(
|
|
||||||
FlexiLoggerView::new_scrollable()
|
FlexiLoggerView::new_scrollable()
|
||||||
.with_name("node-events")
|
.with_name("node-events")
|
||||||
.full_screen(),
|
.full_screen(),
|
||||||
)
|
)
|
||||||
.title_position(HAlign::Left)
|
.title_position(HAlign::Left)
|
||||||
.title("Node Events"),
|
.title("Node Events");
|
||||||
);
|
|
||||||
mainlayout.get_mut().add_child(
|
let peers_table_view = PeersTableView::new()
|
||||||
Panel::new(ScrollView::new(
|
.column(PeerTableColumn::NodeId, "Node Id", |c| c.width(43))
|
||||||
TextView::new("Peer Table")
|
.column(PeerTableColumn::Address, "Address", |c| c)
|
||||||
|
.column(PeerTableColumn::LatencyAvg, "Ping", |c| c.width(8))
|
||||||
|
.column(PeerTableColumn::TransferDownAvg, "Down", |c| c.width(8))
|
||||||
|
.column(PeerTableColumn::TransferUpAvg, "Up", |c| c.width(8))
|
||||||
.with_name("peers")
|
.with_name("peers")
|
||||||
.fixed_height(8)
|
.full_width()
|
||||||
.scrollable(),
|
.min_height(8);
|
||||||
))
|
|
||||||
.title_position(HAlign::Left)
|
// attempt at using Mux. Mux has bugs, like resizing problems.
|
||||||
.title("Peers"),
|
// let mut mux = Mux::new();
|
||||||
);
|
// let node_node_events_view = mux
|
||||||
|
// .add_below(node_events_view, mux.root().build().unwrap())
|
||||||
|
// .unwrap();
|
||||||
|
// let node_peers_table_view = mux
|
||||||
|
// .add_below(peers_table_view, node_node_events_view)
|
||||||
|
// .unwrap();
|
||||||
|
// mux.set_container_split_ratio(node_peers_table_view, 0.75)
|
||||||
|
// .unwrap();
|
||||||
|
// let mut mainlayout = LinearLayout::vertical();
|
||||||
|
// mainlayout.add_child(mux);
|
||||||
|
|
||||||
|
// Back to fixed layout
|
||||||
|
let mut mainlayout = LinearLayout::vertical();
|
||||||
|
mainlayout.add_child(node_events_view);
|
||||||
|
mainlayout.add_child(peers_table_view);
|
||||||
|
// ^^^ fixed layout
|
||||||
|
|
||||||
let mut command = StyledString::new();
|
let mut command = StyledString::new();
|
||||||
command.append_styled("Command> ", ColorStyle::title_primary());
|
command.append_styled("Command> ", ColorStyle::title_primary());
|
||||||
//
|
//
|
||||||
mainlayout.get_mut().add_child(
|
mainlayout.add_child(
|
||||||
LinearLayout::horizontal()
|
LinearLayout::horizontal()
|
||||||
.child(TextView::new(command))
|
.child(TextView::new(command))
|
||||||
.child(
|
.child(
|
||||||
@ -738,7 +778,7 @@ impl UI {
|
|||||||
ColorStyle::highlight_inactive(),
|
ColorStyle::highlight_inactive(),
|
||||||
);
|
);
|
||||||
|
|
||||||
mainlayout.get_mut().add_child(
|
mainlayout.add_child(
|
||||||
LinearLayout::horizontal()
|
LinearLayout::horizontal()
|
||||||
.color(Some(ColorStyle::highlight_inactive()))
|
.color(Some(ColorStyle::highlight_inactive()))
|
||||||
.child(
|
.child(
|
||||||
@ -776,13 +816,20 @@ impl UI {
|
|||||||
inner.ui_state.attachment_state.set(state);
|
inner.ui_state.attachment_state.set(state);
|
||||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
pub fn set_network_status(&mut self, started: bool, bps_down: u64, bps_up: u64) {
|
pub fn set_network_status(
|
||||||
|
&mut self,
|
||||||
|
started: bool,
|
||||||
|
bps_down: u64,
|
||||||
|
bps_up: u64,
|
||||||
|
peers: Vec<PeerTableData>,
|
||||||
|
) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.ui_state.network_started.set(started);
|
inner.ui_state.network_started.set(started);
|
||||||
inner.ui_state.network_down_up.set((
|
inner.ui_state.network_down_up.set((
|
||||||
((bps_down as f64) / 1000.0f64) as f32,
|
((bps_down as f64) / 1000.0f64) as f32,
|
||||||
((bps_up as f64) / 1000.0f64) as f32,
|
((bps_up as f64) / 1000.0f64) as f32,
|
||||||
));
|
));
|
||||||
|
inner.ui_state.peers_state.set(peers);
|
||||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
@ -790,6 +837,7 @@ impl UI {
|
|||||||
inner.ui_state.connection_state.set(state);
|
inner.ui_state.connection_state.set(state);
|
||||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_node_event(&self, event: String) {
|
pub fn add_node_event(&self, event: String) {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.borrow();
|
||||||
let color = *inner.log_colors.get(&Level::Info).unwrap();
|
let color = *inner.log_colors.get(&Level::Info).unwrap();
|
||||||
|
@ -41,6 +41,7 @@ lazy_static = "^1"
|
|||||||
directories = "^4"
|
directories = "^4"
|
||||||
once_cell = "^1"
|
once_cell = "^1"
|
||||||
json = "^0"
|
json = "^0"
|
||||||
|
owning_ref = "^0"
|
||||||
flume = { version = "^0", features = ["async"] }
|
flume = { version = "^0", features = ["async"] }
|
||||||
enumset = { version= "^1", features = ["serde"] }
|
enumset = { version= "^1", features = ["serde"] }
|
||||||
backtrace = { version = "^0", optional = true }
|
backtrace = { version = "^0", optional = true }
|
||||||
|
@ -1680,12 +1680,30 @@ impl NetworkManager {
|
|||||||
started: true,
|
started: true,
|
||||||
bps_down: inner.stats.self_stats.transfer_stats.down.average,
|
bps_down: inner.stats.self_stats.transfer_stats.down.average,
|
||||||
bps_up: inner.stats.self_stats.transfer_stats.up.average,
|
bps_up: inner.stats.self_stats.transfer_stats.up.average,
|
||||||
|
peers: {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
let routing_table = inner.routing_table.as_ref().unwrap();
|
||||||
|
for (k, v) in routing_table.get_recent_peers() {
|
||||||
|
if let Some(nr) = routing_table.lookup_node_ref(k) {
|
||||||
|
let peer_stats = nr.peer_stats();
|
||||||
|
let peer = PeerTableData {
|
||||||
|
node_id: k,
|
||||||
|
peer_address: v.last_connection.remote(),
|
||||||
|
peer_stats,
|
||||||
|
};
|
||||||
|
out.push(peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VeilidStateNetwork {
|
VeilidStateNetwork {
|
||||||
started: false,
|
started: false,
|
||||||
bps_down: 0,
|
bps_down: 0,
|
||||||
bps_up: 0,
|
bps_up: 0,
|
||||||
|
peers: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ const RECENT_PEERS_TABLE_SIZE: usize = 64;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct RecentPeersEntry {
|
pub struct RecentPeersEntry {
|
||||||
last_connection: ConnectionDescriptor,
|
pub last_connection: ConnectionDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RoutingTable rwlock-internal data
|
/// RoutingTable rwlock-internal data
|
||||||
@ -776,13 +776,15 @@ impl RoutingTable {
|
|||||||
descriptor: ConnectionDescriptor,
|
descriptor: ConnectionDescriptor,
|
||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
) -> Option<NodeRef> {
|
) -> Option<NodeRef> {
|
||||||
self.create_node_ref(node_id, |e| {
|
let out = self.create_node_ref(node_id, |e| {
|
||||||
// set the most recent node address for connection finding and udp replies
|
|
||||||
e.set_last_connection(descriptor, timestamp);
|
|
||||||
|
|
||||||
// this node is live because it literally just connected to us
|
// this node is live because it literally just connected to us
|
||||||
e.touch_last_seen(timestamp);
|
e.touch_last_seen(timestamp);
|
||||||
})
|
});
|
||||||
|
if let Some(nr) = &out {
|
||||||
|
// set the most recent node address for connection finding and udp replies
|
||||||
|
nr.set_last_connection(descriptor, timestamp);
|
||||||
|
}
|
||||||
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ticks about once per second
|
// Ticks about once per second
|
||||||
@ -834,11 +836,8 @@ impl RoutingTable {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn touch_recent_peer(
|
pub fn touch_recent_peer(&self, node_id: DHTKey, last_connection: ConnectionDescriptor) {
|
||||||
inner: &mut RoutingTableInner,
|
let mut inner = self.inner.write();
|
||||||
node_id: DHTKey,
|
|
||||||
last_connection: ConnectionDescriptor,
|
|
||||||
) {
|
|
||||||
inner
|
inner
|
||||||
.recent_peers
|
.recent_peers
|
||||||
.insert(node_id, RecentPeersEntry { last_connection });
|
.insert(node_id, RecentPeersEntry { last_connection });
|
||||||
|
@ -200,6 +200,9 @@ impl NodeRef {
|
|||||||
pub fn state(&self, cur_ts: u64) -> BucketEntryState {
|
pub fn state(&self, cur_ts: u64) -> BucketEntryState {
|
||||||
self.operate(|_rti, e| e.state(cur_ts))
|
self.operate(|_rti, e| e.state(cur_ts))
|
||||||
}
|
}
|
||||||
|
pub fn peer_stats(&self) -> PeerStats {
|
||||||
|
self.operate(|_rti, e| e.peer_stats().clone())
|
||||||
|
}
|
||||||
|
|
||||||
// Per-RoutingDomain accessors
|
// Per-RoutingDomain accessors
|
||||||
pub fn make_peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
pub fn make_peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||||
@ -322,7 +325,9 @@ impl NodeRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_last_connection(&self, connection_descriptor: ConnectionDescriptor, ts: u64) {
|
pub fn set_last_connection(&self, connection_descriptor: ConnectionDescriptor, ts: u64) {
|
||||||
self.operate_mut(|_rti, e| e.set_last_connection(connection_descriptor, ts))
|
self.operate_mut(|_rti, e| e.set_last_connection(connection_descriptor, ts));
|
||||||
|
self.routing_table
|
||||||
|
.touch_recent_peer(self.node_id(), connection_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_any_dial_info(&self) -> bool {
|
pub fn has_any_dial_info(&self) -> bool {
|
||||||
|
53
veilid-core/src/rpc_processor/origin.rs
Normal file
53
veilid-core/src/rpc_processor/origin.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Origin {
|
||||||
|
Sender,
|
||||||
|
PrivateRoute(PrivateRoute),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Origin {
|
||||||
|
pub fn sender() -> Self {
|
||||||
|
Self::Sender
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_route(private_route: PrivateRoute) -> Self {
|
||||||
|
Self::PrivateRoute(private_route)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_respond_to(self, destination: &Destination) -> Result<RespondTo, RPCError> {
|
||||||
|
match self {
|
||||||
|
Self::Sender => {
|
||||||
|
let peer = match destination {
|
||||||
|
Destination::Direct {
|
||||||
|
target,
|
||||||
|
safety_route_spec,
|
||||||
|
} => todo!(),
|
||||||
|
Destination::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec,
|
||||||
|
} => todo!(),
|
||||||
|
Destination::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec,
|
||||||
|
} => todo!(),
|
||||||
|
};
|
||||||
|
let routing_table = peer.routing_table();
|
||||||
|
let routing_domain = peer.best_routing_domain();
|
||||||
|
// Send some signed node info along with the question if this node needs to be replied to
|
||||||
|
if routing_table.has_valid_own_node_info()
|
||||||
|
&& !peer.has_seen_our_node_info(routing_domain)
|
||||||
|
{
|
||||||
|
let our_sni = self
|
||||||
|
.routing_table()
|
||||||
|
.get_own_signed_node_info(routing_domain);
|
||||||
|
RespondTo::Sender(Some(our_sni))
|
||||||
|
} else {
|
||||||
|
RespondTo::Sender(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::PrivateRoute(pr) => RespondTo::PrivateRoute(pr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -215,22 +215,32 @@ impl fmt::Display for VeilidLogLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct VeilidStateLog {
|
pub struct VeilidStateLog {
|
||||||
pub log_level: VeilidLogLevel,
|
pub log_level: VeilidLogLevel,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct VeilidStateAttachment {
|
pub struct VeilidStateAttachment {
|
||||||
pub state: AttachmentState,
|
pub state: AttachmentState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct PeerTableData {
|
||||||
|
pub node_id: DHTKey,
|
||||||
|
pub peer_address: PeerAddress,
|
||||||
|
pub peer_stats: PeerStats,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct VeilidStateNetwork {
|
pub struct VeilidStateNetwork {
|
||||||
pub started: bool,
|
pub started: bool,
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub bps_down: u64,
|
pub bps_down: u64,
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub bps_up: u64,
|
pub bps_up: u64,
|
||||||
|
pub peers: Vec<PeerTableData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -706,6 +716,15 @@ impl Address {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Address {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Address::IPV4(v4) => write!(f, "{}", v4),
|
||||||
|
Address::IPV6(v6) => write!(f, "{}", v6),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for Address {
|
impl FromStr for Address {
|
||||||
type Err = VeilidAPIError;
|
type Err = VeilidAPIError;
|
||||||
fn from_str(host: &str) -> Result<Address, VeilidAPIError> {
|
fn from_str(host: &str) -> Result<Address, VeilidAPIError> {
|
||||||
@ -1447,6 +1466,7 @@ impl PeerInfo {
|
|||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct PeerAddress {
|
pub struct PeerAddress {
|
||||||
protocol_type: ProtocolType,
|
protocol_type: ProtocolType,
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
socket_address: SocketAddress,
|
socket_address: SocketAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1565,41 +1585,52 @@ impl FromStr for NodeDialInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct LatencyStats {
|
pub struct LatencyStats {
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub fastest: u64, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
pub fastest: u64, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub average: u64, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
pub average: u64, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub slowest: u64, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
pub slowest: u64, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct TransferStats {
|
pub struct TransferStats {
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub total: u64, // total amount transferred ever
|
pub total: u64, // total amount transferred ever
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub maximum: u64, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub maximum: u64, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub average: u64, // average rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub average: u64, // average rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub minimum: u64, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
pub minimum: u64, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct TransferStatsDownUp {
|
pub struct TransferStatsDownUp {
|
||||||
pub down: TransferStats,
|
pub down: TransferStats,
|
||||||
pub up: TransferStats,
|
pub up: TransferStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct RPCStats {
|
pub struct RPCStats {
|
||||||
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
||||||
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
||||||
pub questions_in_flight: u32, // number of questions issued that have yet to be answered
|
pub questions_in_flight: u32, // number of questions issued that have yet to be answered
|
||||||
|
#[serde(with = "opt_json_as_string")]
|
||||||
pub last_question: Option<u64>, // when the peer was last questioned (either successfully or not) and we wanted an answer
|
pub last_question: Option<u64>, // when the peer was last questioned (either successfully or not) and we wanted an answer
|
||||||
|
#[serde(with = "opt_json_as_string")]
|
||||||
pub last_seen_ts: Option<u64>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
pub last_seen_ts: Option<u64>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
||||||
|
#[serde(with = "opt_json_as_string")]
|
||||||
pub first_consecutive_seen_ts: Option<u64>, // the timestamp of the first consecutive proof-of-life for this node (an answer or received question)
|
pub first_consecutive_seen_ts: Option<u64>, // the timestamp of the first consecutive proof-of-life for this node (an answer or received question)
|
||||||
pub recent_lost_answers: u32, // number of answers that have been lost since we lost reliability
|
pub recent_lost_answers: u32, // number of answers that have been lost since we lost reliability
|
||||||
pub failed_to_send: u32, // number of messages that have failed to send since we last successfully sent one
|
pub failed_to_send: u32, // number of messages that have failed to send since we last successfully sent one
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct PeerStats {
|
pub struct PeerStats {
|
||||||
|
#[serde(with = "json_as_string")]
|
||||||
pub time_added: u64, // when the peer was added to the routing table
|
pub time_added: u64, // when the peer was added to the routing table
|
||||||
pub rpc_stats: RPCStats, // information about RPCs
|
pub rpc_stats: RPCStats, // information about RPCs
|
||||||
pub latency: Option<LatencyStats>, // latencies for communications with the peer
|
pub latency: Option<LatencyStats>, // latencies for communications with the peer
|
||||||
|
@ -40,3 +40,59 @@ pub fn serialize_json<T: Serialize + Debug>(val: T) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod json_as_string {
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||||
|
|
||||||
|
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.collect_str(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
T::Err: Display,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
String::deserialize(deserializer)?
|
||||||
|
.parse()
|
||||||
|
.map_err(de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod opt_json_as_string {
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||||
|
|
||||||
|
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
Some(v) => serializer.collect_str(v),
|
||||||
|
None => serializer.serialize_none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
T::Err: Display,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
match Option::<String>::deserialize(deserializer)? {
|
||||||
|
None => Ok(None),
|
||||||
|
Some(v) => Ok(Some(v.parse::<T>().map_err(de::Error::custom)?)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,6 @@ import 'dart:typed_data';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'package:veilid/veilid.dart';
|
import 'package:veilid/veilid.dart';
|
||||||
import 'package:flutter_loggy/flutter_loggy.dart';
|
import 'package:flutter_loggy/flutter_loggy.dart';
|
||||||
@ -188,7 +187,7 @@ class _MyAppState extends State<MyApp> with UiLoggy {
|
|||||||
if (update is VeilidUpdateLog) {
|
if (update is VeilidUpdateLog) {
|
||||||
await processUpdateLog(update);
|
await processUpdateLog(update);
|
||||||
} else {
|
} else {
|
||||||
loggy.trace("Update: " + update.json.toString());
|
loggy.trace("Update: ${update.json}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ packages:
|
|||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.9.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -28,21 +28,14 @@ packages:
|
|||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.1"
|
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -63,21 +56,21 @@ packages:
|
|||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.1"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.1"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file
|
name: file
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.2"
|
version: "6.1.4"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -134,30 +127,30 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.12"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.4"
|
version: "0.1.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.8.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
@ -169,14 +162,14 @@ packages:
|
|||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.14"
|
version: "2.0.20"
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_ios
|
name: path_provider_ios
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.10"
|
version: "2.0.11"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -204,7 +197,7 @@ packages:
|
|||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.3"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -232,7 +225,7 @@ packages:
|
|||||||
name: rxdart
|
name: rxdart
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.27.4"
|
version: "0.27.5"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -244,7 +237,7 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.2"
|
version: "1.9.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -265,21 +258,21 @@ packages:
|
|||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.12"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -300,14 +293,14 @@ packages:
|
|||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.0"
|
version: "3.0.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0+1"
|
version: "0.2.0+2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.17.0 <3.0.0"
|
dart: ">=2.17.0 <3.0.0"
|
||||||
flutter: ">=3.0.0"
|
flutter: ">=3.0.0"
|
||||||
|
@ -34,6 +34,8 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
loggy: ^2.0.1+1
|
loggy: ^2.0.1+1
|
||||||
flutter_loggy: ^2.0.1
|
flutter_loggy: ^2.0.1
|
||||||
|
path_provider: ^2.0.11
|
||||||
|
path: ^1.8.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -987,6 +987,243 @@ class VeilidConfig {
|
|||||||
network = VeilidConfigNetwork.fromJson(json['network']);
|
network = VeilidConfigNetwork.fromJson(json['network']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class LatencyStats {
|
||||||
|
BigInt fastest;
|
||||||
|
BigInt average;
|
||||||
|
BigInt slowest;
|
||||||
|
|
||||||
|
LatencyStats({
|
||||||
|
required this.fastest,
|
||||||
|
required this.average,
|
||||||
|
required this.slowest,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'fastest': fastest.toString(),
|
||||||
|
'average': average.toString(),
|
||||||
|
'slowest': slowest.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
LatencyStats.fromJson(Map<String, dynamic> json)
|
||||||
|
: fastest = BigInt.parse(json['fastest']),
|
||||||
|
average = BigInt.parse(json['average']),
|
||||||
|
slowest = BigInt.parse(json['slowest']);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class TransferStats {
|
||||||
|
BigInt total;
|
||||||
|
BigInt fastest;
|
||||||
|
BigInt average;
|
||||||
|
BigInt slowest;
|
||||||
|
|
||||||
|
TransferStats({
|
||||||
|
required this.total,
|
||||||
|
required this.fastest,
|
||||||
|
required this.average,
|
||||||
|
required this.slowest,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'total': total.toString(),
|
||||||
|
'fastest': fastest.toString(),
|
||||||
|
'average': average.toString(),
|
||||||
|
'slowest': slowest.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferStats.fromJson(Map<String, dynamic> json)
|
||||||
|
: total = BigInt.parse(json['fastest']),
|
||||||
|
fastest = BigInt.parse(json['fastest']),
|
||||||
|
average = BigInt.parse(json['average']),
|
||||||
|
slowest = BigInt.parse(json['slowest']);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class TransferStatsDownUp {
|
||||||
|
TransferStats down;
|
||||||
|
TransferStats up;
|
||||||
|
|
||||||
|
TransferStatsDownUp({
|
||||||
|
required this.down,
|
||||||
|
required this.up,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'down': down.toString(),
|
||||||
|
'up': up.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferStatsDownUp.fromJson(Map<String, dynamic> json)
|
||||||
|
: down = TransferStats.fromJson(json['down']),
|
||||||
|
up = TransferStats.fromJson(json['up']);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class RPCStats {
|
||||||
|
int messagesSent;
|
||||||
|
int messagesRcvd;
|
||||||
|
int questionsInFlight;
|
||||||
|
BigInt? lastQuestion;
|
||||||
|
BigInt? lastSeenTs;
|
||||||
|
BigInt? firstConsecutiveSeenTs;
|
||||||
|
int recentLostAnswers;
|
||||||
|
int failedToSend;
|
||||||
|
|
||||||
|
RPCStats({
|
||||||
|
required this.messagesSent,
|
||||||
|
required this.messagesRcvd,
|
||||||
|
required this.questionsInFlight,
|
||||||
|
required this.lastQuestion,
|
||||||
|
required this.lastSeenTs,
|
||||||
|
required this.firstConsecutiveSeenTs,
|
||||||
|
required this.recentLostAnswers,
|
||||||
|
required this.failedToSend,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'messages_sent': messagesSent,
|
||||||
|
'messages_rcvd': messagesRcvd,
|
||||||
|
'questions_in_flight': questionsInFlight,
|
||||||
|
'last_question': lastQuestion?.toString(),
|
||||||
|
'last_seen_ts': lastSeenTs?.toString(),
|
||||||
|
'first_consecutive_seen_ts': firstConsecutiveSeenTs?.toString(),
|
||||||
|
'recent_lost_answers': recentLostAnswers,
|
||||||
|
'failed_to_send': failedToSend,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
RPCStats.fromJson(Map<String, dynamic> json)
|
||||||
|
: messagesSent = json['messages_sent'],
|
||||||
|
messagesRcvd = json['messages_rcvd'],
|
||||||
|
questionsInFlight = json['questions_in_flight'],
|
||||||
|
lastQuestion = json['last_question'] != null
|
||||||
|
? BigInt.parse(json['last_question'])
|
||||||
|
: null,
|
||||||
|
lastSeenTs = json['last_seen_ts'] != null
|
||||||
|
? BigInt.parse(json['last_seen_ts'])
|
||||||
|
: null,
|
||||||
|
firstConsecutiveSeenTs = json['first_consecutive_seen_ts'] != null
|
||||||
|
? BigInt.parse(json['first_consecutive_seen_ts'])
|
||||||
|
: null,
|
||||||
|
recentLostAnswers = json['recent_lost_answers'],
|
||||||
|
failedToSend = json['failed_to_send'];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class PeerStats {
|
||||||
|
BigInt timeAdded;
|
||||||
|
RPCStats rpcStats;
|
||||||
|
LatencyStats? latency;
|
||||||
|
TransferStatsDownUp transfer;
|
||||||
|
|
||||||
|
PeerStats({
|
||||||
|
required this.timeAdded,
|
||||||
|
required this.rpcStats,
|
||||||
|
required this.latency,
|
||||||
|
required this.transfer,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'time_added': timeAdded.toString(),
|
||||||
|
'rpc_stats': rpcStats.json,
|
||||||
|
'latency': latency?.json,
|
||||||
|
'transfer': transfer.json,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerStats.fromJson(Map<String, dynamic> json)
|
||||||
|
: timeAdded = BigInt.parse(json['time_added']),
|
||||||
|
rpcStats = RPCStats.fromJson(json['rpc_stats']),
|
||||||
|
latency = json['latency'] != null
|
||||||
|
? LatencyStats.fromJson(json['latency'])
|
||||||
|
: null,
|
||||||
|
transfer = TransferStatsDownUp.fromJson(json['transfer']);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class PeerTableData {
|
||||||
|
String nodeId;
|
||||||
|
PeerAddress peerAddress;
|
||||||
|
PeerStats peerStats;
|
||||||
|
|
||||||
|
PeerTableData({
|
||||||
|
required this.nodeId,
|
||||||
|
required this.peerAddress,
|
||||||
|
required this.peerStats,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'node_id': nodeId,
|
||||||
|
'peer_address': peerAddress.json,
|
||||||
|
'peer_stats': peerStats.json,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerTableData.fromJson(Map<String, dynamic> json)
|
||||||
|
: nodeId = json['node_id'],
|
||||||
|
peerAddress = PeerAddress.fromJson(json['peer_address']),
|
||||||
|
peerStats = PeerStats.fromJson(json['peer_stats']);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// AttachmentState
|
||||||
|
|
||||||
|
enum ProtocolType {
|
||||||
|
udp,
|
||||||
|
tcp,
|
||||||
|
ws,
|
||||||
|
wss,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ProtocolTypeExt on ProtocolType {
|
||||||
|
String get json {
|
||||||
|
return name.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolType protocolTypeFromJson(String j) {
|
||||||
|
return ProtocolType.values.byName(j.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
|
||||||
|
class PeerAddress {
|
||||||
|
ProtocolType protocolType;
|
||||||
|
String socketAddress;
|
||||||
|
|
||||||
|
PeerAddress({
|
||||||
|
required this.protocolType,
|
||||||
|
required this.socketAddress,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'protocol_type': protocolType.json,
|
||||||
|
'socket_address': socketAddress,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerAddress.fromJson(Map<String, dynamic> json)
|
||||||
|
: protocolType = protocolTypeFromJson(json['protocol_type']),
|
||||||
|
socketAddress = json['socket_address'];
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
/// VeilidUpdate
|
/// VeilidUpdate
|
||||||
|
|
||||||
@ -996,16 +1233,17 @@ abstract class VeilidUpdate {
|
|||||||
case "Log":
|
case "Log":
|
||||||
{
|
{
|
||||||
return VeilidUpdateLog(
|
return VeilidUpdateLog(
|
||||||
veilidLogLevelFromJson(json["log_level"]), json["message"]);
|
logLevel: veilidLogLevelFromJson(json["log_level"]),
|
||||||
|
message: json["message"]);
|
||||||
}
|
}
|
||||||
case "Attachment":
|
case "Attachment":
|
||||||
{
|
{
|
||||||
return VeilidUpdateAttachment(attachmentStateFromJson(json["state"]));
|
return VeilidUpdateAttachment(
|
||||||
|
state: VeilidStateAttachment.fromJson(json));
|
||||||
}
|
}
|
||||||
case "Network":
|
case "Network":
|
||||||
{
|
{
|
||||||
return VeilidUpdateNetwork(
|
return VeilidUpdateNetwork(state: VeilidStateNetwork.fromJson(json));
|
||||||
json["started"], json["bps_up"], json["bps_down"]);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -1021,7 +1259,10 @@ class VeilidUpdateLog implements VeilidUpdate {
|
|||||||
final VeilidLogLevel logLevel;
|
final VeilidLogLevel logLevel;
|
||||||
final String message;
|
final String message;
|
||||||
//
|
//
|
||||||
VeilidUpdateLog(this.logLevel, this.message);
|
VeilidUpdateLog({
|
||||||
|
required this.logLevel,
|
||||||
|
required this.message,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
@ -1034,34 +1275,28 @@ class VeilidUpdateLog implements VeilidUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VeilidUpdateAttachment implements VeilidUpdate {
|
class VeilidUpdateAttachment implements VeilidUpdate {
|
||||||
final AttachmentState state;
|
final VeilidStateAttachment state;
|
||||||
//
|
//
|
||||||
VeilidUpdateAttachment(this.state);
|
VeilidUpdateAttachment({required this.state});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
return {
|
var jsonRep = state.json;
|
||||||
'kind': "Attachment",
|
jsonRep['kind'] = "Attachment";
|
||||||
'state': state.json,
|
return jsonRep;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidUpdateNetwork implements VeilidUpdate {
|
class VeilidUpdateNetwork implements VeilidUpdate {
|
||||||
final bool started;
|
final VeilidStateNetwork state;
|
||||||
final int bpsDown;
|
|
||||||
final int bpsUp;
|
|
||||||
//
|
//
|
||||||
VeilidUpdateNetwork(this.started, this.bpsDown, this.bpsUp);
|
VeilidUpdateNetwork({required this.state});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
return {
|
var jsonRep = state.json;
|
||||||
'kind': "Network",
|
jsonRep['kind'] = "Network";
|
||||||
'started': started,
|
return jsonRep;
|
||||||
'bps_down': bpsDown,
|
|
||||||
'bps_up': bpsUp
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,6 +1310,12 @@ class VeilidStateAttachment {
|
|||||||
|
|
||||||
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
||||||
: state = attachmentStateFromJson(json['state']);
|
: state = attachmentStateFromJson(json['state']);
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'state': state.json,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -1082,11 +1323,30 @@ class VeilidStateAttachment {
|
|||||||
|
|
||||||
class VeilidStateNetwork {
|
class VeilidStateNetwork {
|
||||||
final bool started;
|
final bool started;
|
||||||
|
final int bpsDown;
|
||||||
|
final int bpsUp;
|
||||||
|
final List<PeerTableData> peers;
|
||||||
|
|
||||||
VeilidStateNetwork(this.started);
|
VeilidStateNetwork(
|
||||||
|
{required this.started,
|
||||||
|
required this.bpsDown,
|
||||||
|
required this.bpsUp,
|
||||||
|
required this.peers});
|
||||||
|
|
||||||
VeilidStateNetwork.fromJson(Map<String, dynamic> json)
|
VeilidStateNetwork.fromJson(Map<String, dynamic> json)
|
||||||
: started = json['started'];
|
: started = json['started'],
|
||||||
|
bpsDown = json['bps_down'],
|
||||||
|
bpsUp = json['bps_up'],
|
||||||
|
peers = json['peers'].map((j) => PeerTableData.fromJson(j)).toList();
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {
|
||||||
|
'started': started,
|
||||||
|
'bps_down': bpsDown,
|
||||||
|
'bps_up': bpsUp,
|
||||||
|
'peers': peers.map((p) => p.json).toList(),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -1096,11 +1356,13 @@ class VeilidState {
|
|||||||
final VeilidStateAttachment attachment;
|
final VeilidStateAttachment attachment;
|
||||||
final VeilidStateNetwork network;
|
final VeilidStateNetwork network;
|
||||||
|
|
||||||
VeilidState(this.attachment, this.network);
|
|
||||||
|
|
||||||
VeilidState.fromJson(Map<String, dynamic> json)
|
VeilidState.fromJson(Map<String, dynamic> json)
|
||||||
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
||||||
network = VeilidStateNetwork.fromJson(json['network']);
|
network = VeilidStateNetwork.fromJson(json['network']);
|
||||||
|
|
||||||
|
Map<String, dynamic> get json {
|
||||||
|
return {'attachment': attachment.json, 'network': network.json};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user