veilid/veilid-core/src/attachment_manager.rs

395 lines
14 KiB
Rust
Raw Normal View History

2021-11-22 11:28:30 -05:00
use crate::*;
2023-05-29 19:24:57 +00:00
use crypto::Crypto;
use network_manager::*;
use routing_table::*;
use storage_manager::*;
2021-11-22 11:28:30 -05:00
2023-10-25 22:32:06 -04:00
struct AttachmentManagerInner {
2022-12-26 16:33:48 -05:00
last_attachment_state: AttachmentState,
last_routing_table_health: Option<RoutingTableHealth>,
2021-11-22 11:28:30 -05:00
maintain_peers: bool,
2024-10-19 15:18:26 +00:00
started_ts: Timestamp,
2022-12-16 20:07:28 -05:00
attach_ts: Option<Timestamp>,
2022-03-24 10:14:50 -04:00
update_callback: Option<UpdateCallback>,
2022-06-12 20:58:02 -04:00
attachment_maintainer_jh: Option<MustJoinHandle<()>>,
2021-11-22 11:28:30 -05:00
}
2023-10-25 22:32:06 -04:00
struct AttachmentManagerUnlockedInner {
2022-10-09 22:07:15 -04:00
config: VeilidConfig,
network_manager: NetworkManager,
}
2021-11-22 11:28:30 -05:00
#[derive(Clone)]
2023-10-25 22:32:06 -04:00
pub(crate) struct AttachmentManager {
2021-11-22 11:28:30 -05:00
inner: Arc<Mutex<AttachmentManagerInner>>,
2022-10-09 22:07:15 -04:00
unlocked_inner: Arc<AttachmentManagerUnlockedInner>,
2021-11-22 11:28:30 -05:00
}
impl AttachmentManager {
2022-10-09 22:07:15 -04:00
fn new_unlocked_inner(
2021-11-22 11:28:30 -05:00
config: VeilidConfig,
2023-05-29 19:24:57 +00:00
storage_manager: StorageManager,
2021-11-22 11:28:30 -05:00
table_store: TableStore,
2023-06-04 21:22:55 -04:00
#[cfg(feature = "unstable-blockstore")] block_store: BlockStore,
2021-11-22 11:28:30 -05:00
crypto: Crypto,
2022-10-09 22:07:15 -04:00
) -> AttachmentManagerUnlockedInner {
AttachmentManagerUnlockedInner {
2021-11-22 11:28:30 -05:00
config: config.clone(),
2022-10-09 22:07:15 -04:00
network_manager: NetworkManager::new(
config,
2023-05-29 19:24:57 +00:00
storage_manager,
2022-10-09 22:07:15 -04:00
table_store,
2023-06-04 21:22:55 -04:00
#[cfg(feature = "unstable-blockstore")]
2022-10-09 22:07:15 -04:00
block_store,
crypto,
),
}
}
fn new_inner() -> AttachmentManagerInner {
AttachmentManagerInner {
2022-12-26 16:33:48 -05:00
last_attachment_state: AttachmentState::Detached,
last_routing_table_health: None,
2021-11-22 11:28:30 -05:00
maintain_peers: false,
2024-10-19 15:18:26 +00:00
started_ts: Timestamp::now(),
2022-12-16 20:07:28 -05:00
attach_ts: None,
2022-03-24 10:14:50 -04:00
update_callback: None,
2021-11-22 11:28:30 -05:00
attachment_maintainer_jh: None,
}
}
2022-10-09 22:07:15 -04:00
pub fn new(
config: VeilidConfig,
2023-05-29 19:24:57 +00:00
storage_manager: StorageManager,
2022-10-09 22:07:15 -04:00
table_store: TableStore,
2023-06-04 21:22:55 -04:00
#[cfg(feature = "unstable-blockstore")] block_store: BlockStore,
2022-10-09 22:07:15 -04:00
crypto: Crypto,
) -> Self {
2021-11-22 11:28:30 -05:00
Self {
2022-10-09 22:07:15 -04:00
inner: Arc::new(Mutex::new(Self::new_inner())),
unlocked_inner: Arc::new(Self::new_unlocked_inner(
config,
2023-05-29 19:24:57 +00:00
storage_manager,
2022-10-09 22:07:15 -04:00
table_store,
2023-06-04 21:22:55 -04:00
#[cfg(feature = "unstable-blockstore")]
2022-10-09 22:07:15 -04:00
block_store,
crypto,
)),
2021-11-22 11:28:30 -05:00
}
}
pub fn config(&self) -> VeilidConfig {
2022-10-09 22:07:15 -04:00
self.unlocked_inner.config.clone()
2021-11-22 11:28:30 -05:00
}
pub fn network_manager(&self) -> NetworkManager {
2022-10-09 22:07:15 -04:00
self.unlocked_inner.network_manager.clone()
2021-11-22 11:28:30 -05:00
}
2023-09-01 21:13:05 -04:00
// pub fn is_attached(&self) -> bool {
// let s = self.inner.lock().last_attachment_state;
// !matches!(s, AttachmentState::Detached | AttachmentState::Detaching)
// }
// pub fn is_detached(&self) -> bool {
// let s = self.inner.lock().last_attachment_state;
// matches!(s, AttachmentState::Detached)
// }
// pub fn get_attach_timestamp(&self) -> Option<Timestamp> {
// self.inner.lock().attach_ts
// }
2021-11-22 11:28:30 -05:00
2022-03-24 10:14:50 -04:00
fn translate_routing_table_health(
2022-12-26 16:33:48 -05:00
health: &RoutingTableHealth,
2022-03-24 10:14:50 -04:00
config: &VeilidConfigRoutingTable,
2022-12-26 16:33:48 -05:00
) -> AttachmentState {
2022-03-24 10:14:50 -04:00
if health.reliable_entry_count >= config.limit_over_attached.try_into().unwrap() {
2022-12-26 16:33:48 -05:00
return AttachmentState::OverAttached;
2021-11-22 11:28:30 -05:00
}
2022-03-24 10:14:50 -04:00
if health.reliable_entry_count >= config.limit_fully_attached.try_into().unwrap() {
2022-12-26 16:33:48 -05:00
return AttachmentState::FullyAttached;
2022-03-24 10:14:50 -04:00
}
if health.reliable_entry_count >= config.limit_attached_strong.try_into().unwrap() {
2022-12-26 16:33:48 -05:00
return AttachmentState::AttachedStrong;
2022-03-24 10:14:50 -04:00
}
if health.reliable_entry_count >= config.limit_attached_good.try_into().unwrap() {
2022-12-26 16:33:48 -05:00
return AttachmentState::AttachedGood;
2021-11-22 11:28:30 -05:00
}
2022-03-24 10:14:50 -04:00
if health.reliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
|| health.unreliable_entry_count >= config.limit_attached_weak.try_into().unwrap()
{
2022-12-26 16:33:48 -05:00
return AttachmentState::AttachedWeak;
2021-11-22 11:28:30 -05:00
}
2022-12-26 16:33:48 -05:00
AttachmentState::Attaching
2021-11-22 11:28:30 -05:00
}
2022-12-26 16:33:48 -05:00
/// Update attachment and network readiness state
/// and possibly send a VeilidUpdate::Attachment.
2022-12-26 16:33:48 -05:00
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();
// Check if the routing table health is different
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;
}
}
2021-11-22 11:28:30 -05:00
2022-12-26 16:33:48 -05:00
// Swap in new health numbers
let opt_previous_health = inner.last_routing_table_health.take();
inner.last_routing_table_health = Some(health.clone());
2021-11-22 11:28:30 -05:00
2022-12-26 16:33:48 -05:00
// Calculate new attachment state
2022-10-09 22:07:15 -04:00
let config = self.config();
let routing_table_config = &config.get().network.routing_table;
2022-12-26 16:33:48 -05:00
let previous_attachment_state = inner.last_attachment_state;
inner.last_attachment_state =
AttachmentManager::translate_routing_table_health(&health, routing_table_config);
// If we don't have an update callback yet for some reason, just return now
let Some(update_callback) = inner.update_callback.clone() else {
return;
};
// Send update if one of:
// * 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 {
2023-09-18 15:22:40 -04:00
Some((update_callback, Self::get_veilid_state_inner(&inner)))
2021-11-22 11:28:30 -05:00
} else {
2022-12-26 16:33:48 -05:00
None
2021-11-22 11:28:30 -05:00
}
};
2022-12-26 16:33:48 -05:00
// Send the update outside of the lock
if let Some(update) = opt_update {
(update.0)(VeilidUpdate::Attachment(update.1));
2021-11-22 11:28:30 -05:00
}
}
2023-06-28 23:46:29 -04:00
fn update_attaching_detaching_state(&self, state: AttachmentState) {
2024-10-19 15:18:26 +00:00
let uptime;
let attached_uptime;
2023-06-28 23:46:29 -04:00
let update_callback = {
2022-12-26 16:33:48 -05:00
let mut inner = self.inner.lock();
// Clear routing table health so when we start measuring it we start from scratch
inner.last_routing_table_health = None;
// Set attachment state directly
2023-06-28 23:46:29 -04:00
inner.last_attachment_state = state;
// Set timestamps
2023-06-28 23:46:29 -04:00
if state == AttachmentState::Attaching {
inner.attach_ts = Some(Timestamp::now());
2023-06-28 23:46:29 -04:00
} else if state == AttachmentState::Detached {
inner.attach_ts = None;
} else if state == AttachmentState::Detaching {
// ok
} else {
unreachable!("don't use this for attached states, use update_attachment()");
}
2024-10-19 15:18:26 +00:00
let now = Timestamp::now();
uptime = now - inner.started_ts;
attached_uptime = inner.attach_ts.map(|ts| now - ts);
// Get callback
2023-06-28 23:46:29 -04:00
inner.update_callback.clone()
};
// Send update
2023-06-28 23:46:29 -04:00
if let Some(update_callback) = update_callback {
2023-09-18 15:22:40 -04:00
update_callback(VeilidUpdate::Attachment(Box::new(VeilidStateAttachment {
2023-06-28 23:46:29 -04:00
state,
public_internet_ready: false,
local_network_ready: false,
2024-10-19 15:18:26 +00:00
uptime,
attached_uptime,
2023-09-18 15:22:40 -04:00
})))
2022-12-26 16:33:48 -05:00
}
2023-06-28 23:46:29 -04:00
}
#[instrument(parent = None, level = "debug", skip_all)]
2023-06-28 23:46:29 -04:00
async fn attachment_maintainer(self) {
2024-03-07 16:49:59 -05:00
log_net!(debug "attachment starting");
2023-06-28 23:46:29 -04:00
self.update_attaching_detaching_state(AttachmentState::Attaching);
2022-10-09 22:07:15 -04:00
let netman = self.network_manager();
2021-11-22 11:28:30 -05:00
2022-07-06 23:15:51 -04:00
let mut restart;
let mut restart_delay;
while self.inner.lock().maintain_peers {
2022-07-06 23:15:51 -04:00
restart = false;
restart_delay = 1;
2024-05-04 16:34:13 -04:00
match netman.startup().await {
Err(err) => {
error!("network startup failed: {}", err);
restart = true;
}
Ok(StartupDisposition::BindRetry) => {
info!("waiting for network to bind...");
restart = true;
restart_delay = 10;
}
Ok(StartupDisposition::Success) => {
log_net!(debug "started maintaining peers");
while self.inner.lock().maintain_peers {
// tick network manager
let next_tick_ts = get_timestamp() + 1_000_000u64;
if let Err(err) = netman.tick().await {
error!("Error in network manager: {}", err);
self.inner.lock().maintain_peers = false;
restart = true;
break;
}
// see if we need to restart the network
if netman.network_needs_restart() {
info!("Restarting network");
restart = true;
break;
}
// 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
let wait_duration = next_tick_ts
.saturating_sub(get_timestamp())
.clamp(0, 1_000_000u64);
sleep((wait_duration / 1_000) as u32).await;
2024-05-04 16:34:13 -04:00
}
log_net!(debug "stopped maintaining peers");
2024-05-04 16:34:13 -04:00
if !restart {
self.update_attaching_detaching_state(AttachmentState::Detaching);
log_net!(debug "attachment stopping");
}
2021-11-22 11:28:30 -05:00
log_net!(debug "stopping network");
netman.shutdown().await;
2022-07-22 13:05:28 -04:00
}
2022-12-26 16:33:48 -05:00
}
2022-07-06 23:15:51 -04:00
if !restart {
break;
}
2024-03-07 16:49:59 -05:00
log_net!(debug "completely restarting attachment");
2022-07-06 23:15:51 -04:00
// chill out for a second first, give network stack time to settle out
for _ in 0..restart_delay {
if !self.inner.lock().maintain_peers {
break;
}
sleep(1000).await;
}
2021-11-22 11:28:30 -05:00
}
2023-06-28 23:46:29 -04:00
self.update_attaching_detaching_state(AttachmentState::Detached);
2024-03-07 16:49:59 -05:00
log_net!(debug "attachment stopped");
2021-11-22 11:28:30 -05:00
}
2022-06-10 17:07:10 -04:00
#[instrument(level = "debug", skip_all, err)]
2022-07-10 17:36:50 -04:00
pub async fn init(&self, update_callback: UpdateCallback) -> EyreResult<()> {
2022-10-09 22:07:15 -04:00
{
2022-03-24 10:14:50 -04:00
let mut inner = self.inner.lock();
inner.update_callback = Some(update_callback.clone());
2022-12-26 16:33:48 -05:00
}
2021-11-22 11:28:30 -05:00
2022-10-09 22:07:15 -04:00
self.network_manager().init(update_callback).await?;
2021-11-22 11:28:30 -05:00
Ok(())
}
2022-06-10 17:07:10 -04:00
2024-07-03 21:00:12 -04:00
#[instrument(level = "debug", skip_all)]
2021-11-22 11:28:30 -05:00
pub async fn terminate(&self) {
// Ensure we detached
self.detach().await;
2022-10-09 22:07:15 -04:00
self.network_manager().terminate().await;
self.inner.lock().update_callback = None;
2021-11-22 11:28:30 -05:00
}
2024-07-03 21:00:12 -04:00
#[instrument(level = "trace", skip_all)]
2022-12-26 16:33:48 -05:00
pub async fn attach(&self) -> bool {
2021-11-22 11:28:30 -05:00
// Create long-running connection maintenance routine
2022-11-01 21:05:48 -04:00
let mut inner = self.inner.lock();
2022-10-09 22:07:15 -04:00
if inner.attachment_maintainer_jh.is_some() {
2022-12-26 16:33:48 -05:00
return false;
2022-10-09 22:07:15 -04:00
}
inner.maintain_peers = true;
2024-07-20 19:42:25 -04:00
inner.attachment_maintainer_jh = Some(spawn(
"attachment maintainer",
self.clone().attachment_maintainer(),
));
2022-12-26 16:33:48 -05:00
true
2021-11-22 11:28:30 -05:00
}
2024-07-03 21:00:12 -04:00
#[instrument(level = "trace", skip_all)]
2022-12-26 16:33:48 -05:00
pub async fn detach(&self) -> bool {
2022-10-09 22:07:15 -04:00
let attachment_maintainer_jh = {
let mut inner = self.inner.lock();
let attachment_maintainer_jh = inner.attachment_maintainer_jh.take();
if attachment_maintainer_jh.is_some() {
// Terminate long-running connection maintenance routine
inner.maintain_peers = false;
}
attachment_maintainer_jh
};
2021-11-22 11:28:30 -05:00
if let Some(jh) = attachment_maintainer_jh {
jh.await;
2022-12-26 16:33:48 -05:00
true
} else {
false
2021-11-22 11:28:30 -05:00
}
}
2023-09-01 21:13:05 -04:00
// pub fn get_attachment_state(&self) -> AttachmentState {
// self.inner.lock().last_attachment_state
// }
2021-11-22 11:28:30 -05:00
2023-09-18 15:22:40 -04:00
fn get_veilid_state_inner(inner: &AttachmentManagerInner) -> Box<VeilidStateAttachment> {
2024-10-19 15:18:26 +00:00
let now = Timestamp::now();
let uptime = now - inner.started_ts;
let attached_uptime = inner.attach_ts.map(|ts| now - ts);
2023-09-18 15:22:40 -04:00
Box::new(VeilidStateAttachment {
2022-12-26 16:33:48 -05:00
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),
2024-10-19 15:18:26 +00:00
uptime,
attached_uptime,
2023-09-18 15:22:40 -04:00
})
2021-11-22 11:28:30 -05:00
}
2023-09-18 15:22:40 -04:00
pub fn get_veilid_state(&self) -> Box<VeilidStateAttachment> {
2022-12-26 16:33:48 -05:00
let inner = self.inner.lock();
2023-09-18 15:22:40 -04:00
Self::get_veilid_state_inner(&inner)
2022-05-16 11:52:48 -04:00
}
2021-11-22 11:28:30 -05:00
}