mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-11-22 08:56:58 -06: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",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "curve25519-dalek"
|
||||
version = "3.2.1"
|
||||
@ -5087,6 +5096,7 @@ dependencies = [
|
||||
"cursive",
|
||||
"cursive-flexi-logger-view",
|
||||
"cursive_buffered_backend",
|
||||
"cursive_table_view",
|
||||
"directories",
|
||||
"flexi_logger",
|
||||
"futures",
|
||||
@ -5155,6 +5165,7 @@ dependencies = [
|
||||
"nix 0.25.0",
|
||||
"no-std-net",
|
||||
"once_cell",
|
||||
"owning_ref",
|
||||
"owo-colors",
|
||||
"parking_lot 0.12.1",
|
||||
"rand 0.7.3",
|
||||
|
@ -23,9 +23,9 @@ tokio-util = { version = "^0", features = ["compat"], optional = true}
|
||||
async-tungstenite = { version = "^0.8" }
|
||||
cursive-flexi-logger-view = { path = "../external/cursive-flexi-logger-view" }
|
||||
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_table_view = "0.12.0"
|
||||
cursive_table_view = "0.14.0"
|
||||
# cursive-tabs = "0.5.0"
|
||||
clap = "^3"
|
||||
directories = "^4"
|
||||
|
@ -8,7 +8,7 @@ use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
use veilid_core::xx::{Eventual, EventualCommon};
|
||||
use veilid_core::VeilidConfigLogLevel;
|
||||
use veilid_core::*;
|
||||
|
||||
pub fn convert_loglevel(s: &str) -> Result<VeilidConfigLogLevel, String> {
|
||||
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) {
|
||||
self.inner_mut()
|
||||
.ui
|
||||
.set_network_status(network.started, network.bps_down, network.bps_up);
|
||||
self.inner_mut().ui.set_network_status(
|
||||
network.started,
|
||||
network.bps_down,
|
||||
network.bps_up,
|
||||
network.peers,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_log(&mut self, log: veilid_core::VeilidStateLog) {
|
||||
|
@ -12,6 +12,7 @@ use tools::*;
|
||||
|
||||
mod client_api_connection;
|
||||
mod command_processor;
|
||||
mod peers_table_view;
|
||||
mod settings;
|
||||
mod tools;
|
||||
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::peers_table_view::*;
|
||||
use crate::settings::Settings;
|
||||
use crossbeam_channel::Sender;
|
||||
use cursive::align::*;
|
||||
@ -10,6 +11,7 @@ use cursive::views::*;
|
||||
use cursive::Cursive;
|
||||
use cursive::CursiveRunnable;
|
||||
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
||||
//use cursive_multiplex::*;
|
||||
use log::*;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
@ -20,7 +22,7 @@ use veilid_core::*;
|
||||
//////////////////////////////////////////////////////////////
|
||||
///
|
||||
struct Dirty<T> {
|
||||
pub value: T,
|
||||
value: T,
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
@ -52,6 +54,7 @@ struct UIState {
|
||||
network_started: Dirty<bool>,
|
||||
network_down_up: Dirty<(f32, f32)>,
|
||||
connection_state: Dirty<ConnectionState>,
|
||||
peers_state: Dirty<Vec<PeerTableData>>,
|
||||
}
|
||||
|
||||
impl UIState {
|
||||
@ -61,6 +64,7 @@ impl UIState {
|
||||
network_started: Dirty::new(false),
|
||||
network_down_up: Dirty::new((0.0, 0.0)),
|
||||
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> {
|
||||
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 {
|
||||
match inner.ui_state.attachment_state.get() {
|
||||
AttachmentState::Detached => " Detached [----]",
|
||||
@ -607,15 +614,23 @@ impl UI {
|
||||
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) {
|
||||
let mut inner = Self::inner_mut(s);
|
||||
|
||||
let mut refresh_statusbar = false;
|
||||
let mut refresh_button_attach = false;
|
||||
let mut refresh_connection_dialog = false;
|
||||
let mut refresh_peers = false;
|
||||
if inner.ui_state.attachment_state.take_dirty() {
|
||||
refresh_statusbar = true;
|
||||
refresh_button_attach = true;
|
||||
refresh_peers = true;
|
||||
}
|
||||
if inner.ui_state.network_started.take_dirty() {
|
||||
refresh_statusbar = true;
|
||||
@ -627,6 +642,10 @@ impl UI {
|
||||
refresh_statusbar = true;
|
||||
refresh_button_attach = true;
|
||||
refresh_connection_dialog = true;
|
||||
refresh_peers = true;
|
||||
}
|
||||
if inner.ui_state.peers_state.take_dirty() {
|
||||
refresh_peers = true;
|
||||
}
|
||||
|
||||
drop(inner);
|
||||
@ -640,6 +659,9 @@ impl UI {
|
||||
if refresh_connection_dialog {
|
||||
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());
|
||||
|
||||
// Create layouts
|
||||
let mut mainlayout = LinearLayout::vertical().with_name("main-layout");
|
||||
mainlayout.get_mut().add_child(
|
||||
Panel::new(
|
||||
FlexiLoggerView::new_scrollable()
|
||||
.with_name("node-events")
|
||||
.full_screen(),
|
||||
)
|
||||
.title_position(HAlign::Left)
|
||||
.title("Node Events"),
|
||||
);
|
||||
mainlayout.get_mut().add_child(
|
||||
Panel::new(ScrollView::new(
|
||||
TextView::new("Peer Table")
|
||||
.with_name("peers")
|
||||
.fixed_height(8)
|
||||
.scrollable(),
|
||||
))
|
||||
.title_position(HAlign::Left)
|
||||
.title("Peers"),
|
||||
);
|
||||
|
||||
let node_events_view = Panel::new(
|
||||
FlexiLoggerView::new_scrollable()
|
||||
.with_name("node-events")
|
||||
.full_screen(),
|
||||
)
|
||||
.title_position(HAlign::Left)
|
||||
.title("Node Events");
|
||||
|
||||
let peers_table_view = PeersTableView::new()
|
||||
.column(PeerTableColumn::NodeId, "Node Id", |c| c.width(43))
|
||||
.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")
|
||||
.full_width()
|
||||
.min_height(8);
|
||||
|
||||
// attempt at using Mux. Mux has bugs, like resizing problems.
|
||||
// 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();
|
||||
command.append_styled("Command> ", ColorStyle::title_primary());
|
||||
//
|
||||
mainlayout.get_mut().add_child(
|
||||
mainlayout.add_child(
|
||||
LinearLayout::horizontal()
|
||||
.child(TextView::new(command))
|
||||
.child(
|
||||
@ -738,7 +778,7 @@ impl UI {
|
||||
ColorStyle::highlight_inactive(),
|
||||
);
|
||||
|
||||
mainlayout.get_mut().add_child(
|
||||
mainlayout.add_child(
|
||||
LinearLayout::horizontal()
|
||||
.color(Some(ColorStyle::highlight_inactive()))
|
||||
.child(
|
||||
@ -776,13 +816,20 @@ impl UI {
|
||||
inner.ui_state.attachment_state.set(state);
|
||||
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();
|
||||
inner.ui_state.network_started.set(started);
|
||||
inner.ui_state.network_down_up.set((
|
||||
((bps_down 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));
|
||||
}
|
||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||
@ -790,6 +837,7 @@ impl UI {
|
||||
inner.ui_state.connection_state.set(state);
|
||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||
}
|
||||
|
||||
pub fn add_node_event(&self, event: String) {
|
||||
let inner = self.inner.borrow();
|
||||
let color = *inner.log_colors.get(&Level::Info).unwrap();
|
||||
|
@ -41,6 +41,7 @@ lazy_static = "^1"
|
||||
directories = "^4"
|
||||
once_cell = "^1"
|
||||
json = "^0"
|
||||
owning_ref = "^0"
|
||||
flume = { version = "^0", features = ["async"] }
|
||||
enumset = { version= "^1", features = ["serde"] }
|
||||
backtrace = { version = "^0", optional = true }
|
||||
|
@ -1680,12 +1680,30 @@ impl NetworkManager {
|
||||
started: true,
|
||||
bps_down: inner.stats.self_stats.transfer_stats.down.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 {
|
||||
VeilidStateNetwork {
|
||||
started: false,
|
||||
bps_down: 0,
|
||||
bps_up: 0,
|
||||
peers: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ const RECENT_PEERS_TABLE_SIZE: usize = 64;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RecentPeersEntry {
|
||||
last_connection: ConnectionDescriptor,
|
||||
pub last_connection: ConnectionDescriptor,
|
||||
}
|
||||
|
||||
/// RoutingTable rwlock-internal data
|
||||
@ -776,13 +776,15 @@ impl RoutingTable {
|
||||
descriptor: ConnectionDescriptor,
|
||||
timestamp: u64,
|
||||
) -> Option<NodeRef> {
|
||||
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);
|
||||
|
||||
let out = self.create_node_ref(node_id, |e| {
|
||||
// this node is live because it literally just connected to us
|
||||
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
|
||||
@ -834,11 +836,8 @@ impl RoutingTable {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn touch_recent_peer(
|
||||
inner: &mut RoutingTableInner,
|
||||
node_id: DHTKey,
|
||||
last_connection: ConnectionDescriptor,
|
||||
) {
|
||||
pub fn touch_recent_peer(&self, node_id: DHTKey, last_connection: ConnectionDescriptor) {
|
||||
let mut inner = self.inner.write();
|
||||
inner
|
||||
.recent_peers
|
||||
.insert(node_id, RecentPeersEntry { last_connection });
|
||||
|
@ -200,6 +200,9 @@ impl NodeRef {
|
||||
pub fn state(&self, cur_ts: u64) -> BucketEntryState {
|
||||
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
|
||||
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) {
|
||||
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 {
|
||||
|
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 log_level: VeilidLogLevel,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct VeilidStateAttachment {
|
||||
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 started: bool,
|
||||
#[serde(with = "json_as_string")]
|
||||
pub bps_down: u64,
|
||||
#[serde(with = "json_as_string")]
|
||||
pub bps_up: u64,
|
||||
pub peers: Vec<PeerTableData>,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
type Err = 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)]
|
||||
pub struct PeerAddress {
|
||||
protocol_type: ProtocolType,
|
||||
#[serde(with = "json_as_string")]
|
||||
socket_address: SocketAddress,
|
||||
}
|
||||
|
||||
@ -1565,42 +1585,53 @@ impl FromStr for NodeDialInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct LatencyStats {
|
||||
#[serde(with = "json_as_string")]
|
||||
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
|
||||
#[serde(with = "json_as_string")]
|
||||
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 total: u64, // total amount transferred ever
|
||||
#[serde(with = "json_as_string")]
|
||||
pub total: u64, // total amount transferred ever
|
||||
#[serde(with = "json_as_string")]
|
||||
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
|
||||
#[serde(with = "json_as_string")]
|
||||
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 down: TransferStats,
|
||||
pub up: TransferStats,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct RPCStats {
|
||||
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 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
|
||||
#[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
|
||||
#[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 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
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct PeerStats {
|
||||
pub time_added: u64, // when the peer was added to the routing table
|
||||
#[serde(with = "json_as_string")]
|
||||
pub time_added: u64, // when the peer was added to the routing table
|
||||
pub rpc_stats: RPCStats, // information about RPCs
|
||||
pub latency: Option<LatencyStats>, // latencies for communications with the peer
|
||||
pub transfer: TransferStatsDownUp, // Stats 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 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:veilid/veilid.dart';
|
||||
import 'package:flutter_loggy/flutter_loggy.dart';
|
||||
@ -188,7 +187,7 @@ class _MyAppState extends State<MyApp> with UiLoggy {
|
||||
if (update is VeilidUpdateLog) {
|
||||
await processUpdateLog(update);
|
||||
} else {
|
||||
loggy.trace("Update: " + update.json.toString());
|
||||
loggy.trace("Update: ${update.json}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
version: "2.9.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -28,21 +28,14 @@ packages:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.2.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -63,21 +56,21 @@ packages:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
version: "6.1.4"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -134,30 +127,30 @@ packages:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
version: "0.12.12"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
version: "1.8.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
@ -169,14 +162,14 @@ packages:
|
||||
name: path_provider_android
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.14"
|
||||
version: "2.0.20"
|
||||
path_provider_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_ios
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.10"
|
||||
version: "2.0.11"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -204,7 +197,7 @@ packages:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.3"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -232,7 +225,7 @@ packages:
|
||||
name: rxdart
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.27.4"
|
||||
version: "0.27.5"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -244,7 +237,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.9.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -265,21 +258,21 @@ packages:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.9"
|
||||
version: "0.4.12"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -300,14 +293,14 @@ packages:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
version: "3.0.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0+1"
|
||||
version: "0.2.0+2"
|
||||
sdks:
|
||||
dart: ">=2.17.0 <3.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
@ -34,6 +34,8 @@ dependencies:
|
||||
cupertino_icons: ^1.0.2
|
||||
loggy: ^2.0.1+1
|
||||
flutter_loggy: ^2.0.1
|
||||
path_provider: ^2.0.11
|
||||
path: ^1.8.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -987,6 +987,243 @@ class VeilidConfig {
|
||||
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
|
||||
|
||||
@ -996,16 +1233,17 @@ abstract class VeilidUpdate {
|
||||
case "Log":
|
||||
{
|
||||
return VeilidUpdateLog(
|
||||
veilidLogLevelFromJson(json["log_level"]), json["message"]);
|
||||
logLevel: veilidLogLevelFromJson(json["log_level"]),
|
||||
message: json["message"]);
|
||||
}
|
||||
case "Attachment":
|
||||
{
|
||||
return VeilidUpdateAttachment(attachmentStateFromJson(json["state"]));
|
||||
return VeilidUpdateAttachment(
|
||||
state: VeilidStateAttachment.fromJson(json));
|
||||
}
|
||||
case "Network":
|
||||
{
|
||||
return VeilidUpdateNetwork(
|
||||
json["started"], json["bps_up"], json["bps_down"]);
|
||||
return VeilidUpdateNetwork(state: VeilidStateNetwork.fromJson(json));
|
||||
}
|
||||
default:
|
||||
{
|
||||
@ -1021,7 +1259,10 @@ class VeilidUpdateLog implements VeilidUpdate {
|
||||
final VeilidLogLevel logLevel;
|
||||
final String message;
|
||||
//
|
||||
VeilidUpdateLog(this.logLevel, this.message);
|
||||
VeilidUpdateLog({
|
||||
required this.logLevel,
|
||||
required this.message,
|
||||
});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get json {
|
||||
@ -1034,34 +1275,28 @@ class VeilidUpdateLog implements VeilidUpdate {
|
||||
}
|
||||
|
||||
class VeilidUpdateAttachment implements VeilidUpdate {
|
||||
final AttachmentState state;
|
||||
final VeilidStateAttachment state;
|
||||
//
|
||||
VeilidUpdateAttachment(this.state);
|
||||
VeilidUpdateAttachment({required this.state});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'kind': "Attachment",
|
||||
'state': state.json,
|
||||
};
|
||||
var jsonRep = state.json;
|
||||
jsonRep['kind'] = "Attachment";
|
||||
return jsonRep;
|
||||
}
|
||||
}
|
||||
|
||||
class VeilidUpdateNetwork implements VeilidUpdate {
|
||||
final bool started;
|
||||
final int bpsDown;
|
||||
final int bpsUp;
|
||||
final VeilidStateNetwork state;
|
||||
//
|
||||
VeilidUpdateNetwork(this.started, this.bpsDown, this.bpsUp);
|
||||
VeilidUpdateNetwork({required this.state});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'kind': "Network",
|
||||
'started': started,
|
||||
'bps_down': bpsDown,
|
||||
'bps_up': bpsUp
|
||||
};
|
||||
var jsonRep = state.json;
|
||||
jsonRep['kind'] = "Network";
|
||||
return jsonRep;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1075,6 +1310,12 @@ class VeilidStateAttachment {
|
||||
|
||||
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
||||
: state = attachmentStateFromJson(json['state']);
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
return {
|
||||
'state': state.json,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
@ -1082,11 +1323,30 @@ class VeilidStateAttachment {
|
||||
|
||||
class VeilidStateNetwork {
|
||||
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)
|
||||
: 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 VeilidStateNetwork network;
|
||||
|
||||
VeilidState(this.attachment, this.network);
|
||||
|
||||
VeilidState.fromJson(Map<String, dynamic> json)
|
||||
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
||||
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