refactor attachment
This commit is contained in:
parent
525baea32c
commit
f49e4f0892
@ -388,7 +388,11 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
pub fn update_attachment(&mut self, attachment: veilid_core::VeilidStateAttachment) {
|
pub fn update_attachment(&mut self, attachment: veilid_core::VeilidStateAttachment) {
|
||||||
self.inner_mut().ui.set_attachment_state(attachment.state);
|
self.inner_mut().ui.set_attachment_state(
|
||||||
|
attachment.state,
|
||||||
|
attachment.public_internet_ready,
|
||||||
|
attachment.local_network_ready,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_network_status(&mut self, network: veilid_core::VeilidStateNetwork) {
|
pub fn update_network_status(&mut self, network: veilid_core::VeilidStateNetwork) {
|
||||||
|
@ -51,6 +51,8 @@ pub type UICallback = Box<dyn Fn(&mut Cursive) + Send>;
|
|||||||
|
|
||||||
struct UIState {
|
struct UIState {
|
||||||
attachment_state: Dirty<AttachmentState>,
|
attachment_state: Dirty<AttachmentState>,
|
||||||
|
public_internet_ready: Dirty<bool>,
|
||||||
|
local_network_ready: Dirty<bool>,
|
||||||
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>,
|
||||||
@ -62,6 +64,8 @@ impl UIState {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
attachment_state: Dirty::new(AttachmentState::Detached),
|
attachment_state: Dirty::new(AttachmentState::Detached),
|
||||||
|
public_internet_ready: Dirty::new(false),
|
||||||
|
local_network_ready: Dirty::new(false),
|
||||||
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),
|
||||||
@ -234,17 +238,28 @@ impl UI {
|
|||||||
fn peers(s: &mut Cursive) -> ViewRef<PeersTableView> {
|
fn peers(s: &mut Cursive) -> ViewRef<PeersTableView> {
|
||||||
s.find_name("peers").unwrap()
|
s.find_name("peers").unwrap()
|
||||||
}
|
}
|
||||||
fn render_attachment_state<'a>(inner: &mut UIInner) -> &'a str {
|
fn render_attachment_state(inner: &mut UIInner) -> String {
|
||||||
match inner.ui_state.attachment_state.get() {
|
let att = match inner.ui_state.attachment_state.get() {
|
||||||
AttachmentState::Detached => " Detached [----]",
|
AttachmentState::Detached => "[----]",
|
||||||
AttachmentState::Attaching => "Attaching [/ ]",
|
AttachmentState::Attaching => "[/ ]",
|
||||||
AttachmentState::AttachedWeak => " Attached [| ]",
|
AttachmentState::AttachedWeak => "[| ]",
|
||||||
AttachmentState::AttachedGood => " Attached [|| ]",
|
AttachmentState::AttachedGood => "[|| ]",
|
||||||
AttachmentState::AttachedStrong => " Attached [||| ]",
|
AttachmentState::AttachedStrong => "[||| ]",
|
||||||
AttachmentState::FullyAttached => " Attached [||||]",
|
AttachmentState::FullyAttached => "[||||]",
|
||||||
AttachmentState::OverAttached => " Attached [++++]",
|
AttachmentState::OverAttached => "[++++]",
|
||||||
AttachmentState::Detaching => "Detaching [////]",
|
AttachmentState::Detaching => "[////]",
|
||||||
}
|
};
|
||||||
|
let pi = if *inner.ui_state.public_internet_ready.get() {
|
||||||
|
"+P"
|
||||||
|
} else {
|
||||||
|
"-p"
|
||||||
|
};
|
||||||
|
let ln = if *inner.ui_state.local_network_ready.get() {
|
||||||
|
"+L"
|
||||||
|
} else {
|
||||||
|
"-l"
|
||||||
|
};
|
||||||
|
format!("{}{}{}", att, pi, ln)
|
||||||
}
|
}
|
||||||
fn render_network_status(inner: &mut UIInner) -> String {
|
fn render_network_status(inner: &mut UIInner) -> String {
|
||||||
match inner.ui_state.network_started.get() {
|
match inner.ui_state.network_started.get() {
|
||||||
@ -832,9 +847,20 @@ impl UI {
|
|||||||
inner.cmdproc = Some(cmdproc);
|
inner.cmdproc = Some(cmdproc);
|
||||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
pub fn set_attachment_state(&mut self, state: AttachmentState) {
|
pub fn set_attachment_state(
|
||||||
|
&mut self,
|
||||||
|
state: AttachmentState,
|
||||||
|
public_internet_ready: bool,
|
||||||
|
local_network_ready: bool,
|
||||||
|
) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.ui_state.attachment_state.set(state);
|
inner.ui_state.attachment_state.set(state);
|
||||||
|
inner
|
||||||
|
.ui_state
|
||||||
|
.public_internet_ready
|
||||||
|
.set(public_internet_ready);
|
||||||
|
inner.ui_state.local_network_ready.set(local_network_ready);
|
||||||
|
|
||||||
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(
|
pub fn set_network_status(
|
||||||
|
@ -2,106 +2,10 @@ use crate::crypto::Crypto;
|
|||||||
use crate::network_manager::*;
|
use crate::network_manager::*;
|
||||||
use crate::routing_table::*;
|
use crate::routing_table::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use core::convert::TryFrom;
|
|
||||||
use core::fmt;
|
|
||||||
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
|
||||||
use serde::*;
|
|
||||||
|
|
||||||
state_machine! {
|
|
||||||
derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,)
|
|
||||||
pub Attachment(Detached)
|
|
||||||
//---
|
|
||||||
Detached(AttachRequested) => Attaching [StartAttachment],
|
|
||||||
Attaching => {
|
|
||||||
AttachmentStopped => Detached,
|
|
||||||
WeakPeers => AttachedWeak,
|
|
||||||
GoodPeers => AttachedGood,
|
|
||||||
StrongPeers => AttachedStrong,
|
|
||||||
FullPeers => FullyAttached,
|
|
||||||
TooManyPeers => OverAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
AttachedWeak => {
|
|
||||||
NoPeers => Attaching,
|
|
||||||
GoodPeers => AttachedGood,
|
|
||||||
StrongPeers => AttachedStrong,
|
|
||||||
FullPeers => FullyAttached,
|
|
||||||
TooManyPeers => OverAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
AttachedGood => {
|
|
||||||
NoPeers => Attaching,
|
|
||||||
WeakPeers => AttachedWeak,
|
|
||||||
StrongPeers => AttachedStrong,
|
|
||||||
FullPeers => FullyAttached,
|
|
||||||
TooManyPeers => OverAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
AttachedStrong => {
|
|
||||||
NoPeers => Attaching,
|
|
||||||
WeakPeers => AttachedWeak,
|
|
||||||
GoodPeers => AttachedGood,
|
|
||||||
FullPeers => FullyAttached,
|
|
||||||
TooManyPeers => OverAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
FullyAttached => {
|
|
||||||
NoPeers => Attaching,
|
|
||||||
WeakPeers => AttachedWeak,
|
|
||||||
GoodPeers => AttachedGood,
|
|
||||||
StrongPeers => AttachedStrong,
|
|
||||||
TooManyPeers => OverAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
OverAttached => {
|
|
||||||
NoPeers => Attaching,
|
|
||||||
WeakPeers => AttachedWeak,
|
|
||||||
GoodPeers => AttachedGood,
|
|
||||||
StrongPeers => AttachedStrong,
|
|
||||||
FullPeers => FullyAttached,
|
|
||||||
DetachRequested => Detaching [StopAttachment]
|
|
||||||
},
|
|
||||||
Detaching => {
|
|
||||||
AttachmentStopped => Detached,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for AttachmentState {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
let out = match self {
|
|
||||||
AttachmentState::Attaching => "attaching".to_owned(),
|
|
||||||
AttachmentState::AttachedWeak => "attached_weak".to_owned(),
|
|
||||||
AttachmentState::AttachedGood => "attached_good".to_owned(),
|
|
||||||
AttachmentState::AttachedStrong => "attached_strong".to_owned(),
|
|
||||||
AttachmentState::FullyAttached => "fully_attached".to_owned(),
|
|
||||||
AttachmentState::OverAttached => "over_attached".to_owned(),
|
|
||||||
AttachmentState::Detaching => "detaching".to_owned(),
|
|
||||||
AttachmentState::Detached => "detached".to_owned(),
|
|
||||||
};
|
|
||||||
write!(f, "{}", out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<String> for AttachmentState {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
|
||||||
Ok(match s.as_str() {
|
|
||||||
"attaching" => AttachmentState::Attaching,
|
|
||||||
"attached_weak" => AttachmentState::AttachedWeak,
|
|
||||||
"attached_good" => AttachmentState::AttachedGood,
|
|
||||||
"attached_strong" => AttachmentState::AttachedStrong,
|
|
||||||
"fully_attached" => AttachmentState::FullyAttached,
|
|
||||||
"over_attached" => AttachmentState::OverAttached,
|
|
||||||
"detaching" => AttachmentState::Detaching,
|
|
||||||
"detached" => AttachmentState::Detached,
|
|
||||||
_ => return Err(()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AttachmentManagerInner {
|
pub struct AttachmentManagerInner {
|
||||||
attachment_machine: CallbackStateMachine<Attachment>,
|
last_attachment_state: AttachmentState,
|
||||||
|
last_routing_table_health: Option<RoutingTableHealth>,
|
||||||
maintain_peers: bool,
|
maintain_peers: bool,
|
||||||
attach_ts: Option<Timestamp>,
|
attach_ts: Option<Timestamp>,
|
||||||
update_callback: Option<UpdateCallback>,
|
update_callback: Option<UpdateCallback>,
|
||||||
@ -140,7 +44,8 @@ impl AttachmentManager {
|
|||||||
}
|
}
|
||||||
fn new_inner() -> AttachmentManagerInner {
|
fn new_inner() -> AttachmentManagerInner {
|
||||||
AttachmentManagerInner {
|
AttachmentManagerInner {
|
||||||
attachment_machine: CallbackStateMachine::new(),
|
last_attachment_state: AttachmentState::Detached,
|
||||||
|
last_routing_table_health: None,
|
||||||
maintain_peers: false,
|
maintain_peers: false,
|
||||||
attach_ts: None,
|
attach_ts: None,
|
||||||
update_callback: None,
|
update_callback: None,
|
||||||
@ -175,11 +80,11 @@ impl AttachmentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_attached(&self) -> bool {
|
pub fn is_attached(&self) -> bool {
|
||||||
let s = self.inner.lock().attachment_machine.state();
|
let s = self.inner.lock().last_attachment_state;
|
||||||
!matches!(s, AttachmentState::Detached | AttachmentState::Detaching)
|
!matches!(s, AttachmentState::Detached | AttachmentState::Detaching)
|
||||||
}
|
}
|
||||||
pub fn is_detached(&self) -> bool {
|
pub fn is_detached(&self) -> bool {
|
||||||
let s = self.inner.lock().attachment_machine.state();
|
let s = self.inner.lock().last_attachment_state;
|
||||||
matches!(s, AttachmentState::Detached)
|
matches!(s, AttachmentState::Detached)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,71 +93,94 @@ impl AttachmentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn translate_routing_table_health(
|
fn translate_routing_table_health(
|
||||||
health: RoutingTableHealth,
|
health: &RoutingTableHealth,
|
||||||
config: &VeilidConfigRoutingTable,
|
config: &VeilidConfigRoutingTable,
|
||||||
) -> AttachmentInput {
|
) -> AttachmentState {
|
||||||
if health.reliable_entry_count >= config.limit_over_attached.try_into().unwrap() {
|
if health.reliable_entry_count >= config.limit_over_attached.try_into().unwrap() {
|
||||||
return AttachmentInput::TooManyPeers;
|
return AttachmentState::OverAttached;
|
||||||
}
|
}
|
||||||
if health.reliable_entry_count >= config.limit_fully_attached.try_into().unwrap() {
|
if health.reliable_entry_count >= config.limit_fully_attached.try_into().unwrap() {
|
||||||
return AttachmentInput::FullPeers;
|
return AttachmentState::FullyAttached;
|
||||||
}
|
}
|
||||||
if health.reliable_entry_count >= config.limit_attached_strong.try_into().unwrap() {
|
if health.reliable_entry_count >= config.limit_attached_strong.try_into().unwrap() {
|
||||||
return AttachmentInput::StrongPeers;
|
return AttachmentState::AttachedStrong;
|
||||||
}
|
}
|
||||||
if health.reliable_entry_count >= config.limit_attached_good.try_into().unwrap() {
|
if health.reliable_entry_count >= config.limit_attached_good.try_into().unwrap() {
|
||||||
return AttachmentInput::GoodPeers;
|
return AttachmentState::AttachedGood;
|
||||||
}
|
}
|
||||||
if health.reliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
|
if health.reliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
|
||||||
|| health.unreliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
|
|| health.unreliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
|
||||||
{
|
{
|
||||||
return AttachmentInput::WeakPeers;
|
return AttachmentState::AttachedWeak;
|
||||||
}
|
|
||||||
AttachmentInput::NoPeers
|
|
||||||
}
|
|
||||||
fn translate_attachment_state(state: &AttachmentState) -> AttachmentInput {
|
|
||||||
match state {
|
|
||||||
AttachmentState::OverAttached => AttachmentInput::TooManyPeers,
|
|
||||||
AttachmentState::FullyAttached => AttachmentInput::FullPeers,
|
|
||||||
AttachmentState::AttachedStrong => AttachmentInput::StrongPeers,
|
|
||||||
AttachmentState::AttachedGood => AttachmentInput::GoodPeers,
|
|
||||||
AttachmentState::AttachedWeak => AttachmentInput::WeakPeers,
|
|
||||||
AttachmentState::Attaching => AttachmentInput::NoPeers,
|
|
||||||
_ => panic!("Invalid state"),
|
|
||||||
}
|
}
|
||||||
|
AttachmentState::Attaching
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_attachment(&self) {
|
/// Update attachment and network readiness state
|
||||||
let new_peer_state_input = {
|
/// and possibly send a VeilidUpdate::Attachment
|
||||||
let inner = self.inner.lock();
|
fn update_attachment(&self) {
|
||||||
|
// update the routing table health
|
||||||
|
let routing_table = self.network_manager().routing_table();
|
||||||
|
let health = routing_table.get_routing_table_health();
|
||||||
|
let opt_update = {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
let old_peer_state_input =
|
// Check if the routing table health is different
|
||||||
AttachmentManager::translate_attachment_state(&inner.attachment_machine.state());
|
if let Some(last_routing_table_health) = &inner.last_routing_table_health {
|
||||||
|
// If things are the same, just return
|
||||||
|
if last_routing_table_health == &health {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get reliable peer count from routing table
|
// Swap in new health numbers
|
||||||
let routing_table = self.network_manager().routing_table();
|
let opt_previous_health = inner.last_routing_table_health.take();
|
||||||
let health = routing_table.get_routing_table_health();
|
inner.last_routing_table_health = Some(health.clone());
|
||||||
|
|
||||||
|
// Calculate new attachment state
|
||||||
let config = self.config();
|
let config = self.config();
|
||||||
let routing_table_config = &config.get().network.routing_table;
|
let routing_table_config = &config.get().network.routing_table;
|
||||||
|
let previous_attachment_state = inner.last_attachment_state;
|
||||||
|
inner.last_attachment_state =
|
||||||
|
AttachmentManager::translate_routing_table_health(&health, routing_table_config);
|
||||||
|
|
||||||
let new_peer_state_input =
|
// If we don't have an update callback yet for some reason, just return now
|
||||||
AttachmentManager::translate_routing_table_health(health, routing_table_config);
|
let Some(update_callback) = inner.update_callback.clone() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if old_peer_state_input == new_peer_state_input {
|
// Send update if one of:
|
||||||
None
|
// * the attachment state has changed
|
||||||
|
// * routing domain readiness has changed
|
||||||
|
// * this is our first routing table health check
|
||||||
|
let send_update = previous_attachment_state != inner.last_attachment_state
|
||||||
|
|| opt_previous_health
|
||||||
|
.map(|x| {
|
||||||
|
x.public_internet_ready != health.public_internet_ready
|
||||||
|
|| x.local_network_ready != health.local_network_ready
|
||||||
|
})
|
||||||
|
.unwrap_or(true);
|
||||||
|
if send_update {
|
||||||
|
Some((update_callback, Self::get_veilid_state_inner(&*inner)))
|
||||||
} else {
|
} else {
|
||||||
Some(new_peer_state_input)
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(next_input) = new_peer_state_input {
|
|
||||||
let _ = self.process_input(&next_input).await;
|
// Send the update outside of the lock
|
||||||
|
if let Some(update) = opt_update {
|
||||||
|
(update.0)(VeilidUpdate::Attachment(update.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn attachment_maintainer(self) {
|
async fn attachment_maintainer(self) {
|
||||||
debug!("attachment starting");
|
{
|
||||||
self.inner.lock().attach_ts = Some(get_aligned_timestamp());
|
let mut inner = self.inner.lock();
|
||||||
|
inner.last_attachment_state = AttachmentState::Attaching;
|
||||||
|
self.inner.lock().attach_ts = Some(get_aligned_timestamp());
|
||||||
|
debug!("attachment starting");
|
||||||
|
}
|
||||||
let netman = self.network_manager();
|
let netman = self.network_manager();
|
||||||
|
|
||||||
let mut restart;
|
let mut restart;
|
||||||
@ -281,13 +209,21 @@ impl AttachmentManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_attachment().await;
|
// Update attachment and network readiness state
|
||||||
|
// and possibly send a VeilidUpdate::Attachment
|
||||||
|
self.update_attachment();
|
||||||
|
|
||||||
// sleep should be at the end in case maintain_peers changes state
|
// sleep should be at the end in case maintain_peers changes state
|
||||||
sleep(1000).await;
|
sleep(1000).await;
|
||||||
}
|
}
|
||||||
debug!("stopped maintaining peers");
|
debug!("stopped maintaining peers");
|
||||||
|
|
||||||
|
if !restart {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
inner.last_attachment_state = AttachmentState::Detaching;
|
||||||
|
debug!("attachment stopping");
|
||||||
|
}
|
||||||
|
|
||||||
debug!("stopping network");
|
debug!("stopping network");
|
||||||
netman.shutdown().await;
|
netman.shutdown().await;
|
||||||
|
|
||||||
@ -300,13 +236,12 @@ impl AttachmentManager {
|
|||||||
sleep(1000).await;
|
sleep(1000).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("stopping attachment");
|
{
|
||||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
let mut inner = self.inner.lock();
|
||||||
let _output = attachment_machine
|
inner.last_attachment_state = AttachmentState::Detached;
|
||||||
.consume(&AttachmentInput::AttachmentStopped)
|
inner.attach_ts = None;
|
||||||
.await;
|
debug!("attachment stopped");
|
||||||
debug!("attachment stopped");
|
}
|
||||||
self.inner.lock().attach_ts = None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all, err)]
|
#[instrument(level = "debug", skip_all, err)]
|
||||||
@ -315,15 +250,7 @@ impl AttachmentManager {
|
|||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.update_callback = Some(update_callback.clone());
|
inner.update_callback = Some(update_callback.clone());
|
||||||
let update_callback2 = update_callback.clone();
|
}
|
||||||
inner.attachment_machine.set_state_change_callback(Arc::new(
|
|
||||||
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
|
||||||
update_callback2(VeilidUpdate::Attachment(VeilidStateAttachment {
|
|
||||||
state: new_state,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
self.network_manager().init(update_callback).await?;
|
self.network_manager().init(update_callback).await?;
|
||||||
|
|
||||||
@ -339,18 +266,20 @@ impl AttachmentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn attach(&self) {
|
pub async fn attach(&self) -> bool {
|
||||||
// Create long-running connection maintenance routine
|
// Create long-running connection maintenance routine
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
if inner.attachment_maintainer_jh.is_some() {
|
if inner.attachment_maintainer_jh.is_some() {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
inner.maintain_peers = true;
|
inner.maintain_peers = true;
|
||||||
inner.attachment_maintainer_jh = Some(spawn(self.clone().attachment_maintainer()));
|
inner.attachment_maintainer_jh = Some(spawn(self.clone().attachment_maintainer()));
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
async fn detach(&self) {
|
pub async fn detach(&self) -> bool {
|
||||||
let attachment_maintainer_jh = {
|
let attachment_maintainer_jh = {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let attachment_maintainer_jh = inner.attachment_maintainer_jh.take();
|
let attachment_maintainer_jh = inner.attachment_maintainer_jh.take();
|
||||||
@ -362,57 +291,34 @@ impl AttachmentManager {
|
|||||||
};
|
};
|
||||||
if let Some(jh) = attachment_maintainer_jh {
|
if let Some(jh) = attachment_maintainer_jh {
|
||||||
jh.await;
|
jh.await;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_output(&self, output: &AttachmentOutput) {
|
pub fn get_attachment_state(&self) -> AttachmentState {
|
||||||
match output {
|
self.inner.lock().last_attachment_state
|
||||||
AttachmentOutput::StartAttachment => self.attach(),
|
}
|
||||||
AttachmentOutput::StopAttachment => self.detach().await,
|
|
||||||
|
fn get_veilid_state_inner(inner: &AttachmentManagerInner) -> VeilidStateAttachment {
|
||||||
|
VeilidStateAttachment {
|
||||||
|
state: inner.last_attachment_state,
|
||||||
|
public_internet_ready: inner
|
||||||
|
.last_routing_table_health
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| x.public_internet_ready)
|
||||||
|
.unwrap_or(false),
|
||||||
|
local_network_ready: inner
|
||||||
|
.last_routing_table_health
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| x.local_network_ready)
|
||||||
|
.unwrap_or(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_input(&self, input: &AttachmentInput) -> EyreResult<()> {
|
|
||||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
|
||||||
let output = attachment_machine.consume(input).await;
|
|
||||||
match output {
|
|
||||||
Err(e) => Err(eyre!(
|
|
||||||
"invalid input '{:?}' for state machine in state '{:?}': {:?}",
|
|
||||||
input,
|
|
||||||
attachment_machine.state(),
|
|
||||||
e
|
|
||||||
)),
|
|
||||||
Ok(v) => {
|
|
||||||
if let Some(o) = v {
|
|
||||||
self.handle_output(&o).await;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
|
||||||
pub async fn request_attach(&self) -> EyreResult<()> {
|
|
||||||
self.process_input(&AttachmentInput::AttachRequested)
|
|
||||||
.await
|
|
||||||
.map_err(|e| eyre!("Attach request failed: {}", e))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
|
||||||
pub async fn request_detach(&self) -> EyreResult<()> {
|
|
||||||
self.process_input(&AttachmentInput::DetachRequested)
|
|
||||||
.await
|
|
||||||
.map_err(|e| eyre!("Detach request failed: {}", e))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_state(&self) -> AttachmentState {
|
|
||||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
|
||||||
attachment_machine.state()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_veilid_state(&self) -> VeilidStateAttachment {
|
pub fn get_veilid_state(&self) -> VeilidStateAttachment {
|
||||||
VeilidStateAttachment {
|
let inner = self.inner.lock();
|
||||||
state: self.get_state(),
|
Self::get_veilid_state_inner(&*inner)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ mod veilid_config;
|
|||||||
mod veilid_layer_filter;
|
mod veilid_layer_filter;
|
||||||
|
|
||||||
pub use self::api_tracing_layer::ApiTracingLayer;
|
pub use self::api_tracing_layer::ApiTracingLayer;
|
||||||
pub use self::attachment_manager::AttachmentState;
|
|
||||||
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
||||||
pub use self::veilid_api::*;
|
pub use self::veilid_api::*;
|
||||||
pub use self::veilid_config::*;
|
pub use self::veilid_config::*;
|
||||||
|
@ -51,7 +51,7 @@ pub struct LowLevelPortInfo {
|
|||||||
pub type RoutingTableEntryFilter<'t> =
|
pub type RoutingTableEntryFilter<'t> =
|
||||||
Box<dyn FnMut(&RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> bool + Send + 't>;
|
Box<dyn FnMut(&RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> bool + Send + 't>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct RoutingTableHealth {
|
pub struct RoutingTableHealth {
|
||||||
/// Number of reliable (responsive) entries in the routing table
|
/// Number of reliable (responsive) entries in the routing table
|
||||||
pub reliable_entry_count: usize,
|
pub reliable_entry_count: usize,
|
||||||
@ -60,9 +60,9 @@ pub struct RoutingTableHealth {
|
|||||||
/// Number of dead (always unresponsive) entries in the routing table
|
/// Number of dead (always unresponsive) entries in the routing table
|
||||||
pub dead_entry_count: usize,
|
pub dead_entry_count: usize,
|
||||||
/// If PublicInternet network class is valid yet
|
/// If PublicInternet network class is valid yet
|
||||||
pub public_internet_network_class_valid: bool, xxx do this and add to attachment calculation
|
pub public_internet_ready: bool,
|
||||||
/// If LocalNetwork network class is valid yet
|
/// If LocalNetwork network class is valid yet
|
||||||
pub local_network_network_class_valid: bool,
|
pub local_network_ready: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct RoutingTableUnlockedInner {
|
pub(super) struct RoutingTableUnlockedInner {
|
||||||
@ -78,7 +78,7 @@ pub(super) struct RoutingTableUnlockedInner {
|
|||||||
kick_queue: Mutex<BTreeSet<usize>>,
|
kick_queue: Mutex<BTreeSet<usize>>,
|
||||||
/// Background process for computing statistics
|
/// Background process for computing statistics
|
||||||
rolling_transfers_task: TickTask<EyreReport>,
|
rolling_transfers_task: TickTask<EyreReport>,
|
||||||
/// Backgroup process to purge dead routing table entries when necessary
|
/// Background process to purge dead routing table entries when necessary
|
||||||
kick_buckets_task: TickTask<EyreReport>,
|
kick_buckets_task: TickTask<EyreReport>,
|
||||||
/// Background process to get our initial routing table
|
/// Background process to get our initial routing table
|
||||||
bootstrap_task: TickTask<EyreReport>,
|
bootstrap_task: TickTask<EyreReport>,
|
||||||
|
@ -318,10 +318,8 @@ impl RoutingTableInner {
|
|||||||
4 => 16,
|
4 => 16,
|
||||||
5 => 8,
|
5 => 8,
|
||||||
6 => 4,
|
6 => 4,
|
||||||
7 => 4,
|
7 => 2,
|
||||||
8 => 4,
|
_ => 1,
|
||||||
9 => 4,
|
|
||||||
_ => 4,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,24 +716,45 @@ impl RoutingTableInner {
|
|||||||
// Routing Table Health Metrics
|
// Routing Table Health Metrics
|
||||||
|
|
||||||
pub fn get_routing_table_health(&self) -> RoutingTableHealth {
|
pub fn get_routing_table_health(&self) -> RoutingTableHealth {
|
||||||
let mut health = RoutingTableHealth::default();
|
let mut reliable_entry_count: usize = 0;
|
||||||
|
let mut unreliable_entry_count: usize = 0;
|
||||||
|
let mut dead_entry_count: usize = 0;
|
||||||
|
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
for bucket in &self.buckets {
|
for bucket in &self.buckets {
|
||||||
for (_, v) in bucket.entries() {
|
for (_, v) in bucket.entries() {
|
||||||
match v.with(self, |_rti, e| e.state(cur_ts)) {
|
match v.with(self, |_rti, e| e.state(cur_ts)) {
|
||||||
BucketEntryState::Reliable => {
|
BucketEntryState::Reliable => {
|
||||||
health.reliable_entry_count += 1;
|
reliable_entry_count += 1;
|
||||||
}
|
}
|
||||||
BucketEntryState::Unreliable => {
|
BucketEntryState::Unreliable => {
|
||||||
health.unreliable_entry_count += 1;
|
unreliable_entry_count += 1;
|
||||||
}
|
}
|
||||||
BucketEntryState::Dead => {
|
BucketEntryState::Dead => {
|
||||||
health.dead_entry_count += 1;
|
dead_entry_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
health
|
|
||||||
|
let public_internet_ready = matches!(
|
||||||
|
self.get_network_class(RoutingDomain::PublicInternet)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
NetworkClass::Invalid
|
||||||
|
);
|
||||||
|
let local_network_ready = matches!(
|
||||||
|
self.get_network_class(RoutingDomain::LocalNetwork)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
NetworkClass::Invalid
|
||||||
|
);
|
||||||
|
|
||||||
|
RoutingTableHealth {
|
||||||
|
reliable_entry_count,
|
||||||
|
unreliable_entry_count,
|
||||||
|
dead_entry_count,
|
||||||
|
public_internet_ready,
|
||||||
|
local_network_ready,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn touch_recent_peer(&mut self, node_id: DHTKey, last_connection: ConnectionDescriptor) {
|
pub fn touch_recent_peer(&mut self, node_id: DHTKey, last_connection: ConnectionDescriptor) {
|
||||||
|
@ -139,20 +139,20 @@ impl VeilidAPI {
|
|||||||
#[instrument(level = "debug", err, skip_all)]
|
#[instrument(level = "debug", err, skip_all)]
|
||||||
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
||||||
let attachment_manager = self.attachment_manager()?;
|
let attachment_manager = self.attachment_manager()?;
|
||||||
attachment_manager
|
if !attachment_manager.attach().await {
|
||||||
.request_attach()
|
apibail_generic!("Already attached");
|
||||||
.await
|
}
|
||||||
.map_err(|e| VeilidAPIError::internal(e))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// disconnect from the network
|
// disconnect from the network
|
||||||
#[instrument(level = "debug", err, skip_all)]
|
#[instrument(level = "debug", err, skip_all)]
|
||||||
pub async fn detach(&self) -> Result<(), VeilidAPIError> {
|
pub async fn detach(&self) -> Result<(), VeilidAPIError> {
|
||||||
let attachment_manager = self.attachment_manager()?;
|
let attachment_manager = self.attachment_manager()?;
|
||||||
attachment_manager
|
if !attachment_manager.detach().await {
|
||||||
.request_detach()
|
apibail_generic!("Already detached");
|
||||||
.await
|
}
|
||||||
.map_err(|e| VeilidAPIError::internal(e))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
@ -130,12 +130,72 @@ pub struct VeilidAppCall {
|
|||||||
pub id: OperationId,
|
pub id: OperationId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
RkyvArchive,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(repr(u8), derive(CheckBytes))]
|
||||||
|
pub enum AttachmentState {
|
||||||
|
Detached,
|
||||||
|
Attaching,
|
||||||
|
AttachedWeak,
|
||||||
|
AttachedGood,
|
||||||
|
AttachedStrong,
|
||||||
|
FullyAttached,
|
||||||
|
OverAttached,
|
||||||
|
Detaching,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AttachmentState {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
let out = match self {
|
||||||
|
AttachmentState::Attaching => "attaching".to_owned(),
|
||||||
|
AttachmentState::AttachedWeak => "attached_weak".to_owned(),
|
||||||
|
AttachmentState::AttachedGood => "attached_good".to_owned(),
|
||||||
|
AttachmentState::AttachedStrong => "attached_strong".to_owned(),
|
||||||
|
AttachmentState::FullyAttached => "fully_attached".to_owned(),
|
||||||
|
AttachmentState::OverAttached => "over_attached".to_owned(),
|
||||||
|
AttachmentState::Detaching => "detaching".to_owned(),
|
||||||
|
AttachmentState::Detached => "detached".to_owned(),
|
||||||
|
};
|
||||||
|
write!(f, "{}", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for AttachmentState {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||||
|
Ok(match s.as_str() {
|
||||||
|
"attaching" => AttachmentState::Attaching,
|
||||||
|
"attached_weak" => AttachmentState::AttachedWeak,
|
||||||
|
"attached_good" => AttachmentState::AttachedGood,
|
||||||
|
"attached_strong" => AttachmentState::AttachedStrong,
|
||||||
|
"fully_attached" => AttachmentState::FullyAttached,
|
||||||
|
"over_attached" => AttachmentState::OverAttached,
|
||||||
|
"detaching" => AttachmentState::Detaching,
|
||||||
|
"detached" => AttachmentState::Detached,
|
||||||
|
_ => return Err(()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||||
pub struct VeilidStateAttachment {
|
pub struct VeilidStateAttachment {
|
||||||
pub state: AttachmentState,
|
pub state: AttachmentState,
|
||||||
|
pub public_internet_ready: bool,
|
||||||
|
pub local_network_ready: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -336,6 +336,8 @@ pub struct VeilidConfigRoutingTable {
|
|||||||
pub limit_attached_strong: u32,
|
pub limit_attached_strong: u32,
|
||||||
pub limit_attached_good: u32,
|
pub limit_attached_good: u32,
|
||||||
pub limit_attached_weak: u32,
|
pub limit_attached_weak: u32,
|
||||||
|
// xxx pub enable_public_internet: bool,
|
||||||
|
// xxx pub enable_local_network: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
140
veilid-flutter/lib/default_config.dart
Normal file
140
veilid-flutter/lib/default_config.dart
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'veilid.dart';
|
||||||
|
|
||||||
|
Future<VeilidConfig> getDefaultVeilidConfig(String programName) async {
|
||||||
|
return VeilidConfig(
|
||||||
|
programName: programName,
|
||||||
|
namespace: "",
|
||||||
|
capabilities: VeilidConfigCapabilities(
|
||||||
|
protocolUDP: !kIsWeb,
|
||||||
|
protocolConnectTCP: !kIsWeb,
|
||||||
|
protocolAcceptTCP: !kIsWeb,
|
||||||
|
protocolConnectWS: true,
|
||||||
|
protocolAcceptWS: !kIsWeb,
|
||||||
|
protocolConnectWSS: true,
|
||||||
|
protocolAcceptWSS: false,
|
||||||
|
),
|
||||||
|
protectedStore: VeilidConfigProtectedStore(
|
||||||
|
allowInsecureFallback: false,
|
||||||
|
alwaysUseInsecureStorage: false,
|
||||||
|
insecureFallbackDirectory: "",
|
||||||
|
delete: false,
|
||||||
|
),
|
||||||
|
tableStore: VeilidConfigTableStore(
|
||||||
|
directory: kIsWeb
|
||||||
|
? ""
|
||||||
|
: p.join((await getApplicationSupportDirectory()).absolute.path,
|
||||||
|
"table_store"),
|
||||||
|
delete: false,
|
||||||
|
),
|
||||||
|
blockStore: VeilidConfigBlockStore(
|
||||||
|
directory: kIsWeb
|
||||||
|
? ""
|
||||||
|
: p.join((await getApplicationSupportDirectory()).absolute.path,
|
||||||
|
"block_store"),
|
||||||
|
delete: false,
|
||||||
|
),
|
||||||
|
network: VeilidConfigNetwork(
|
||||||
|
connectionInitialTimeoutMs: 2000,
|
||||||
|
connectionInactivityTimeoutMs: 60000,
|
||||||
|
maxConnectionsPerIp4: 32,
|
||||||
|
maxConnectionsPerIp6Prefix: 32,
|
||||||
|
maxConnectionsPerIp6PrefixSize: 56,
|
||||||
|
maxConnectionFrequencyPerMin: 128,
|
||||||
|
clientWhitelistTimeoutMs: 300000,
|
||||||
|
reverseConnectionReceiptTimeMs: 5000,
|
||||||
|
holePunchReceiptTimeMs: 5000,
|
||||||
|
nodeId: null,
|
||||||
|
nodeIdSecret: null,
|
||||||
|
bootstrap: kIsWeb
|
||||||
|
? ["ws://bootstrap.dev.veilid.net:5150/ws"]
|
||||||
|
: ["bootstrap.dev.veilid.net"],
|
||||||
|
bootstrapNodes: [],
|
||||||
|
routingTable: VeilidConfigRoutingTable(
|
||||||
|
limitOverAttached: 64,
|
||||||
|
limitFullyAttached: 32,
|
||||||
|
limitAttachedStrong: 16,
|
||||||
|
limitAttachedGood: 8,
|
||||||
|
limitAttachedWeak: 4,
|
||||||
|
),
|
||||||
|
rpc: VeilidConfigRPC(
|
||||||
|
concurrency: 0,
|
||||||
|
queueSize: 1024,
|
||||||
|
maxTimestampBehindMs: 10000,
|
||||||
|
maxTimestampAheadMs: 10000,
|
||||||
|
timeoutMs: 10000,
|
||||||
|
maxRouteHopCount: 4,
|
||||||
|
defaultRouteHopCount: 1,
|
||||||
|
),
|
||||||
|
dht: VeilidConfigDHT(
|
||||||
|
resolveNodeTimeoutMs: null,
|
||||||
|
resolveNodeCount: 20,
|
||||||
|
resolveNodeFanout: 3,
|
||||||
|
maxFindNodeCount: 20,
|
||||||
|
getValueTimeoutMs: null,
|
||||||
|
getValueCount: 20,
|
||||||
|
getValueFanout: 3,
|
||||||
|
setValueTimeoutMs: null,
|
||||||
|
setValueCount: 20,
|
||||||
|
setValueFanout: 5,
|
||||||
|
minPeerCount: 20,
|
||||||
|
minPeerRefreshTimeMs: 2000,
|
||||||
|
validateDialInfoReceiptTimeMs: 2000,
|
||||||
|
),
|
||||||
|
upnp: true,
|
||||||
|
detectAddressChanges: true,
|
||||||
|
restrictedNatRetries: 0,
|
||||||
|
tls: VeilidConfigTLS(
|
||||||
|
certificatePath: "",
|
||||||
|
privateKeyPath: "",
|
||||||
|
connectionInitialTimeoutMs: 2000,
|
||||||
|
),
|
||||||
|
application: VeilidConfigApplication(
|
||||||
|
https: VeilidConfigHTTPS(
|
||||||
|
enabled: false,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "",
|
||||||
|
url: null,
|
||||||
|
),
|
||||||
|
http: VeilidConfigHTTP(
|
||||||
|
enabled: false,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "",
|
||||||
|
url: null,
|
||||||
|
)),
|
||||||
|
protocol: VeilidConfigProtocol(
|
||||||
|
udp: VeilidConfigUDP(
|
||||||
|
enabled: !kIsWeb,
|
||||||
|
socketPoolSize: 0,
|
||||||
|
listenAddress: "",
|
||||||
|
publicAddress: null,
|
||||||
|
),
|
||||||
|
tcp: VeilidConfigTCP(
|
||||||
|
connect: !kIsWeb,
|
||||||
|
listen: !kIsWeb,
|
||||||
|
maxConnections: 32,
|
||||||
|
listenAddress: "",
|
||||||
|
publicAddress: null,
|
||||||
|
),
|
||||||
|
ws: VeilidConfigWS(
|
||||||
|
connect: true,
|
||||||
|
listen: !kIsWeb,
|
||||||
|
maxConnections: 16,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "ws",
|
||||||
|
url: null,
|
||||||
|
),
|
||||||
|
wss: VeilidConfigWSS(
|
||||||
|
connect: true,
|
||||||
|
listen: false,
|
||||||
|
maxConnections: 16,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "ws",
|
||||||
|
url: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -1400,15 +1400,22 @@ class VeilidUpdateRoute implements VeilidUpdate {
|
|||||||
|
|
||||||
class VeilidStateAttachment {
|
class VeilidStateAttachment {
|
||||||
final AttachmentState state;
|
final AttachmentState state;
|
||||||
|
final bool publicInternetReady;
|
||||||
|
final bool localNetworkReady;
|
||||||
|
|
||||||
VeilidStateAttachment(this.state);
|
VeilidStateAttachment(
|
||||||
|
this.state, this.publicInternetReady, this.localNetworkReady);
|
||||||
|
|
||||||
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
||||||
: state = attachmentStateFromJson(json['state']);
|
: state = attachmentStateFromJson(json['state']),
|
||||||
|
publicInternetReady = json['public_internet_ready'],
|
||||||
|
localNetworkReady = json['local_network_ready'];
|
||||||
|
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
return {
|
return {
|
||||||
'state': state.json,
|
'state': state.json,
|
||||||
|
'public_internet_ready': publicInternetReady,
|
||||||
|
'local_network_ready': localNetworkReady,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user