2021-11-22 16:28:30 +00:00
|
|
|
use crate::*;
|
2022-05-31 23:54:52 +00:00
|
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
|
mod native;
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
mod wasm;
|
|
|
|
|
2022-06-05 00:18:26 +00:00
|
|
|
mod connection_handle;
|
2022-05-31 23:54:52 +00:00
|
|
|
mod connection_limits;
|
|
|
|
mod connection_manager;
|
|
|
|
mod connection_table;
|
|
|
|
mod network_connection;
|
2022-07-22 17:05:28 +00:00
|
|
|
mod tasks;
|
2022-05-31 23:54:52 +00:00
|
|
|
|
|
|
|
pub mod tests;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
pub use connection_manager::*;
|
2022-05-31 23:54:52 +00:00
|
|
|
pub use network_connection::*;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
2022-06-05 17:23:18 +00:00
|
|
|
use connection_handle::*;
|
2022-06-05 00:18:26 +00:00
|
|
|
use connection_limits::*;
|
2022-10-30 23:29:31 +00:00
|
|
|
use crypto::*;
|
2022-09-04 18:17:28 +00:00
|
|
|
use futures_util::stream::{FuturesOrdered, FuturesUnordered, StreamExt};
|
2022-03-20 14:52:03 +00:00
|
|
|
use hashlink::LruCache;
|
2021-11-22 16:28:30 +00:00
|
|
|
use intf::*;
|
2022-05-31 23:54:52 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
|
use native::*;
|
2021-11-22 16:28:30 +00:00
|
|
|
use receipt_manager::*;
|
|
|
|
use routing_table::*;
|
2022-04-17 17:28:39 +00:00
|
|
|
use rpc_processor::*;
|
2022-05-31 23:54:52 +00:00
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
use wasm::*;
|
2021-11-22 16:28:30 +00:00
|
|
|
use xx::*;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-04-07 13:55:09 +00:00
|
|
|
pub const RELAY_MANAGEMENT_INTERVAL_SECS: u32 = 1;
|
2022-10-09 18:59:01 +00:00
|
|
|
pub const PRIVATE_ROUTE_MANAGEMENT_INTERVAL_SECS: u32 = 1;
|
2021-11-22 16:28:30 +00:00
|
|
|
pub const MAX_MESSAGE_SIZE: usize = MAX_ENVELOPE_SIZE;
|
2022-03-19 22:19:40 +00:00
|
|
|
pub const IPADDR_TABLE_SIZE: usize = 1024;
|
|
|
|
pub const IPADDR_MAX_INACTIVE_DURATION_US: u64 = 300_000_000u64; // 5 minutes
|
2022-08-27 02:52:08 +00:00
|
|
|
pub const PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT: usize = 3;
|
|
|
|
pub const PUBLIC_ADDRESS_CHECK_CACHE_SIZE: usize = 8;
|
|
|
|
pub const PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS: u32 = 60;
|
|
|
|
pub const PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US: u64 = 300_000_000u64; // 5 minutes
|
2022-08-27 16:54:09 +00:00
|
|
|
pub const PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US: u64 = 3600_000_000u64; // 60 minutes
|
2022-06-25 14:57:33 +00:00
|
|
|
pub const BOOT_MAGIC: &[u8; 4] = b"BOOT";
|
2022-07-22 17:05:28 +00:00
|
|
|
pub const BOOTSTRAP_TXT_VERSION: u8 = 0;
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct BootstrapRecord {
|
|
|
|
min_version: u8,
|
|
|
|
max_version: u8,
|
|
|
|
dial_info_details: Vec<DialInfoDetail>,
|
|
|
|
}
|
|
|
|
pub type BootstrapRecordMap = BTreeMap<DHTKey, BootstrapRecord>;
|
|
|
|
|
2021-12-22 03:20:55 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Default)]
|
|
|
|
pub struct ProtocolConfig {
|
2022-08-02 01:06:31 +00:00
|
|
|
pub outbound: ProtocolTypeSet,
|
|
|
|
pub inbound: ProtocolTypeSet,
|
|
|
|
pub family_global: AddressTypeSet,
|
|
|
|
pub family_local: AddressTypeSet,
|
2021-12-24 01:34:52 +00:00
|
|
|
}
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Things we get when we start up and go away when we shut down
|
|
|
|
// Routing table is not in here because we want it to survive a network shutdown/startup restart
|
|
|
|
#[derive(Clone)]
|
|
|
|
struct NetworkComponents {
|
|
|
|
net: Network,
|
2022-01-03 04:49:01 +00:00
|
|
|
connection_manager: ConnectionManager,
|
2021-11-22 16:28:30 +00:00
|
|
|
rpc_processor: RPCProcessor,
|
|
|
|
receipt_manager: ReceiptManager,
|
|
|
|
}
|
|
|
|
|
2022-03-19 22:19:40 +00:00
|
|
|
// Statistics per address
|
|
|
|
#[derive(Clone, Default)]
|
|
|
|
pub struct PerAddressStats {
|
|
|
|
last_seen_ts: u64,
|
|
|
|
transfer_stats_accounting: TransferStatsAccounting,
|
|
|
|
transfer_stats: TransferStatsDownUp,
|
|
|
|
}
|
|
|
|
|
2022-03-20 14:52:03 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct PerAddressStatsKey(IpAddr);
|
|
|
|
|
|
|
|
impl Default for PerAddressStatsKey {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-19 22:19:40 +00:00
|
|
|
// Statistics about the low-level network
|
2022-03-20 14:52:03 +00:00
|
|
|
#[derive(Clone)]
|
2022-03-19 22:19:40 +00:00
|
|
|
pub struct NetworkManagerStats {
|
|
|
|
self_stats: PerAddressStats,
|
2022-03-20 14:52:03 +00:00
|
|
|
per_address_stats: LruCache<PerAddressStatsKey, PerAddressStats>,
|
2022-03-19 22:19:40 +00:00
|
|
|
}
|
|
|
|
|
2022-03-20 14:52:03 +00:00
|
|
|
impl Default for NetworkManagerStats {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
self_stats: PerAddressStats::default(),
|
|
|
|
per_address_stats: LruCache::new(IPADDR_TABLE_SIZE),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-03 16:58:06 +00:00
|
|
|
|
2022-06-15 19:03:13 +00:00
|
|
|
#[derive(Debug)]
|
2022-04-03 16:58:06 +00:00
|
|
|
struct ClientWhitelistEntry {
|
2022-05-24 21:13:52 +00:00
|
|
|
last_seen_ts: u64,
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
|
2022-10-13 02:53:40 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub enum SendDataKind {
|
|
|
|
Direct(ConnectionDescriptor),
|
|
|
|
Indirect,
|
|
|
|
Existing(ConnectionDescriptor),
|
|
|
|
}
|
|
|
|
|
2022-08-27 02:52:08 +00:00
|
|
|
/// Mechanism required to contact another node
|
2022-05-24 21:13:52 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2022-10-13 02:53:40 +00:00
|
|
|
pub(crate) enum NodeContactMethod {
|
2022-08-27 02:52:08 +00:00
|
|
|
/// Node is not reachable by any means
|
|
|
|
Unreachable,
|
2022-10-13 02:53:40 +00:00
|
|
|
/// Connection should have already existed
|
|
|
|
Existing,
|
2022-08-27 02:52:08 +00:00
|
|
|
/// Contact the node directly
|
|
|
|
Direct(DialInfo),
|
2022-10-13 02:53:40 +00:00
|
|
|
/// Request via signal the node connect back directly (relay, target)
|
2022-08-27 02:52:08 +00:00
|
|
|
SignalReverse(NodeRef, NodeRef),
|
2022-10-13 02:53:40 +00:00
|
|
|
/// Request via signal the node negotiate a hole punch (relay, target_node)
|
2022-08-27 02:52:08 +00:00
|
|
|
SignalHolePunch(NodeRef, NodeRef),
|
|
|
|
/// Must use an inbound relay to reach the node
|
|
|
|
InboundRelay(NodeRef),
|
|
|
|
/// Must use outbound relay to reach the node
|
|
|
|
OutboundRelay(NodeRef),
|
2022-04-21 00:49:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-09 00:42:27 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
|
|
|
struct PublicAddressCheckCacheKey(ProtocolType, AddressType);
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// The mutable state of the network manager
|
2022-03-19 22:19:40 +00:00
|
|
|
struct NetworkManagerInner {
|
|
|
|
stats: NetworkManagerStats,
|
2022-05-31 23:54:52 +00:00
|
|
|
client_whitelist: LruCache<DHTKey, ClientWhitelistEntry>,
|
2022-08-09 00:42:27 +00:00
|
|
|
public_address_check_cache:
|
2022-08-27 02:52:08 +00:00
|
|
|
BTreeMap<PublicAddressCheckCacheKey, LruCache<IpAddr, SocketAddress>>,
|
|
|
|
public_address_inconsistencies_table:
|
|
|
|
BTreeMap<PublicAddressCheckCacheKey, HashMap<IpAddr, u64>>,
|
2022-03-19 22:19:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct NetworkManagerUnlockedInner {
|
2022-10-10 02:07:15 +00:00
|
|
|
// Handles
|
|
|
|
config: VeilidConfig,
|
|
|
|
protected_store: ProtectedStore,
|
|
|
|
table_store: TableStore,
|
|
|
|
block_store: BlockStore,
|
|
|
|
crypto: Crypto,
|
2022-09-08 01:52:08 +00:00
|
|
|
// Accessors
|
|
|
|
routing_table: RwLock<Option<RoutingTable>>,
|
|
|
|
components: RwLock<Option<NetworkComponents>>,
|
|
|
|
update_callback: RwLock<Option<UpdateCallback>>,
|
2022-03-19 22:19:40 +00:00
|
|
|
// Background processes
|
2022-07-10 21:36:50 +00:00
|
|
|
rolling_transfers_task: TickTask<EyreReport>,
|
|
|
|
relay_management_task: TickTask<EyreReport>,
|
2022-10-09 18:59:01 +00:00
|
|
|
private_route_management_task: TickTask<EyreReport>,
|
2022-07-22 17:05:28 +00:00
|
|
|
bootstrap_task: TickTask<EyreReport>,
|
|
|
|
peer_minimum_refresh_task: TickTask<EyreReport>,
|
|
|
|
ping_validator_task: TickTask<EyreReport>,
|
2022-08-27 02:52:08 +00:00
|
|
|
public_address_check_task: TickTask<EyreReport>,
|
2022-07-22 17:05:28 +00:00
|
|
|
node_info_update_single_future: MustJoinSingleFuture<()>,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct NetworkManager {
|
|
|
|
inner: Arc<Mutex<NetworkManagerInner>>,
|
2022-03-19 22:19:40 +00:00
|
|
|
unlocked_inner: Arc<NetworkManagerUnlockedInner>,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl NetworkManager {
|
|
|
|
fn new_inner() -> NetworkManagerInner {
|
2021-11-26 14:54:38 +00:00
|
|
|
NetworkManagerInner {
|
2022-03-19 22:19:40 +00:00
|
|
|
stats: NetworkManagerStats::default(),
|
2022-04-03 16:58:06 +00:00
|
|
|
client_whitelist: LruCache::new_unbounded(),
|
2022-08-09 00:42:27 +00:00
|
|
|
public_address_check_cache: BTreeMap::new(),
|
2022-08-27 02:52:08 +00:00
|
|
|
public_address_inconsistencies_table: BTreeMap::new(),
|
2022-03-19 22:19:40 +00:00
|
|
|
}
|
|
|
|
}
|
2022-10-10 02:07:15 +00:00
|
|
|
fn new_unlocked_inner(
|
|
|
|
config: VeilidConfig,
|
|
|
|
protected_store: ProtectedStore,
|
|
|
|
table_store: TableStore,
|
|
|
|
block_store: BlockStore,
|
|
|
|
crypto: Crypto,
|
|
|
|
) -> NetworkManagerUnlockedInner {
|
2022-10-21 03:11:41 +00:00
|
|
|
let min_peer_refresh_time_ms = config.get().network.dht.min_peer_refresh_time_ms;
|
2022-03-19 22:19:40 +00:00
|
|
|
NetworkManagerUnlockedInner {
|
2022-10-10 02:07:15 +00:00
|
|
|
config,
|
|
|
|
protected_store,
|
|
|
|
table_store,
|
|
|
|
block_store,
|
|
|
|
crypto,
|
2022-09-08 01:52:08 +00:00
|
|
|
routing_table: RwLock::new(None),
|
|
|
|
components: RwLock::new(None),
|
|
|
|
update_callback: RwLock::new(None),
|
2022-03-19 22:19:40 +00:00
|
|
|
rolling_transfers_task: TickTask::new(ROLLING_TRANSFERS_INTERVAL_SECS),
|
2022-04-07 13:55:09 +00:00
|
|
|
relay_management_task: TickTask::new(RELAY_MANAGEMENT_INTERVAL_SECS),
|
2022-10-09 18:59:01 +00:00
|
|
|
private_route_management_task: TickTask::new(PRIVATE_ROUTE_MANAGEMENT_INTERVAL_SECS),
|
2022-07-22 17:05:28 +00:00
|
|
|
bootstrap_task: TickTask::new(1),
|
2022-10-21 03:11:41 +00:00
|
|
|
peer_minimum_refresh_task: TickTask::new_ms(min_peer_refresh_time_ms),
|
2022-07-22 17:05:28 +00:00
|
|
|
ping_validator_task: TickTask::new(1),
|
2022-08-27 02:52:08 +00:00
|
|
|
public_address_check_task: TickTask::new(PUBLIC_ADDRESS_CHECK_TASK_INTERVAL_SECS),
|
2022-07-22 17:05:28 +00:00
|
|
|
node_info_update_single_future: MustJoinSingleFuture::new(),
|
2021-11-26 14:54:38 +00:00
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-10 02:07:15 +00:00
|
|
|
pub fn new(
|
|
|
|
config: VeilidConfig,
|
|
|
|
protected_store: ProtectedStore,
|
|
|
|
table_store: TableStore,
|
|
|
|
block_store: BlockStore,
|
|
|
|
crypto: Crypto,
|
|
|
|
) -> Self {
|
2022-03-19 22:19:40 +00:00
|
|
|
let this = Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
inner: Arc::new(Mutex::new(Self::new_inner())),
|
2022-10-10 02:07:15 +00:00
|
|
|
unlocked_inner: Arc::new(Self::new_unlocked_inner(
|
|
|
|
config,
|
|
|
|
protected_store,
|
|
|
|
table_store,
|
|
|
|
block_store,
|
|
|
|
crypto,
|
|
|
|
)),
|
2022-03-19 22:19:40 +00:00
|
|
|
};
|
|
|
|
// Set rolling transfers tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.rolling_transfers_task
|
2022-06-13 00:58:02 +00:00
|
|
|
.set_routine(move |s, l, t| {
|
2022-10-04 17:09:03 +00:00
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.rolling_transfers_task_routine(s, l, t)
|
|
|
|
.instrument(trace_span!(
|
|
|
|
parent: None,
|
|
|
|
"NetworkManager rolling transfers task routine"
|
|
|
|
)),
|
|
|
|
)
|
2022-03-19 22:19:40 +00:00
|
|
|
});
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-04-07 13:55:09 +00:00
|
|
|
// Set relay management tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.relay_management_task
|
2022-06-13 00:58:02 +00:00
|
|
|
.set_routine(move |s, l, t| {
|
2022-10-04 17:09:03 +00:00
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.relay_management_task_routine(s, l, t)
|
|
|
|
.instrument(trace_span!(parent: None, "relay management task routine")),
|
|
|
|
)
|
2022-04-07 13:55:09 +00:00
|
|
|
});
|
|
|
|
}
|
2022-10-09 18:59:01 +00:00
|
|
|
// Set private route management tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.private_route_management_task
|
|
|
|
.set_routine(move |s, l, t| {
|
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.private_route_management_task_routine(s, l, t)
|
|
|
|
.instrument(trace_span!(
|
|
|
|
parent: None,
|
|
|
|
"private route management task routine"
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
});
|
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
// Set bootstrap tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.bootstrap_task
|
2022-10-04 17:09:03 +00:00
|
|
|
.set_routine(move |s, _l, _t| {
|
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.bootstrap_task_routine(s)
|
|
|
|
.instrument(trace_span!(parent: None, "bootstrap task routine")),
|
|
|
|
)
|
|
|
|
});
|
2022-07-22 17:05:28 +00:00
|
|
|
}
|
|
|
|
// Set peer minimum refresh tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.peer_minimum_refresh_task
|
|
|
|
.set_routine(move |s, _l, _t| {
|
2022-10-04 17:09:03 +00:00
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.peer_minimum_refresh_task_routine(s)
|
|
|
|
.instrument(trace_span!(
|
|
|
|
parent: None,
|
|
|
|
"peer minimum refresh task routine"
|
|
|
|
)),
|
|
|
|
)
|
2022-07-22 17:05:28 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
// Set ping validator tick task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.ping_validator_task
|
|
|
|
.set_routine(move |s, l, t| {
|
2022-10-04 17:09:03 +00:00
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.ping_validator_task_routine(s, l, t)
|
|
|
|
.instrument(trace_span!(parent: None, "ping validator task routine")),
|
|
|
|
)
|
2022-07-22 17:05:28 +00:00
|
|
|
});
|
|
|
|
}
|
2022-08-27 02:52:08 +00:00
|
|
|
// Set public address check task
|
|
|
|
{
|
|
|
|
let this2 = this.clone();
|
|
|
|
this.unlocked_inner
|
|
|
|
.public_address_check_task
|
|
|
|
.set_routine(move |s, l, t| {
|
2022-10-04 17:09:03 +00:00
|
|
|
Box::pin(
|
|
|
|
this2
|
|
|
|
.clone()
|
|
|
|
.public_address_check_task_routine(s, l, t)
|
|
|
|
.instrument(trace_span!(
|
|
|
|
parent: None,
|
|
|
|
"public address check task routine"
|
|
|
|
)),
|
|
|
|
)
|
2022-08-27 02:52:08 +00:00
|
|
|
});
|
|
|
|
}
|
2022-03-19 22:19:40 +00:00
|
|
|
this
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn config(&self) -> VeilidConfig {
|
2022-10-10 02:07:15 +00:00
|
|
|
self.unlocked_inner.config.clone()
|
|
|
|
}
|
|
|
|
pub fn with_config<F, R>(&self, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&VeilidConfigInner) -> R,
|
|
|
|
{
|
|
|
|
f(&*self.unlocked_inner.config.get())
|
|
|
|
}
|
|
|
|
pub fn protected_store(&self) -> ProtectedStore {
|
|
|
|
self.unlocked_inner.protected_store.clone()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn table_store(&self) -> TableStore {
|
2022-10-10 02:07:15 +00:00
|
|
|
self.unlocked_inner.table_store.clone()
|
|
|
|
}
|
|
|
|
pub fn block_store(&self) -> BlockStore {
|
|
|
|
self.unlocked_inner.block_store.clone()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn crypto(&self) -> Crypto {
|
2022-10-10 02:07:15 +00:00
|
|
|
self.unlocked_inner.crypto.clone()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn routing_table(&self) -> RoutingTable {
|
2022-09-08 01:52:08 +00:00
|
|
|
self.unlocked_inner
|
|
|
|
.routing_table
|
|
|
|
.read()
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.clone()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn net(&self) -> Network {
|
2022-09-08 01:52:08 +00:00
|
|
|
self.unlocked_inner
|
|
|
|
.components
|
|
|
|
.read()
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.net
|
|
|
|
.clone()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn rpc_processor(&self) -> RPCProcessor {
|
2022-09-08 01:52:08 +00:00
|
|
|
self.unlocked_inner
|
2021-11-22 16:28:30 +00:00
|
|
|
.components
|
2022-09-08 01:52:08 +00:00
|
|
|
.read()
|
2021-11-22 16:28:30 +00:00
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.rpc_processor
|
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
pub fn receipt_manager(&self) -> ReceiptManager {
|
2022-09-08 01:52:08 +00:00
|
|
|
self.unlocked_inner
|
2021-11-22 16:28:30 +00:00
|
|
|
.components
|
2022-09-08 01:52:08 +00:00
|
|
|
.read()
|
2021-11-22 16:28:30 +00:00
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.receipt_manager
|
|
|
|
.clone()
|
|
|
|
}
|
2022-01-03 04:49:01 +00:00
|
|
|
pub fn connection_manager(&self) -> ConnectionManager {
|
2022-09-08 01:52:08 +00:00
|
|
|
self.unlocked_inner
|
2021-11-22 16:28:30 +00:00
|
|
|
.components
|
2022-09-08 01:52:08 +00:00
|
|
|
.read()
|
2021-11-22 16:28:30 +00:00
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
2022-01-03 04:49:01 +00:00
|
|
|
.connection_manager
|
2021-11-22 16:28:30 +00:00
|
|
|
.clone()
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip_all, err)]
|
2022-07-10 21:36:50 +00:00
|
|
|
pub async fn init(&self, update_callback: UpdateCallback) -> EyreResult<()> {
|
2021-11-22 16:28:30 +00:00
|
|
|
let routing_table = RoutingTable::new(self.clone());
|
|
|
|
routing_table.init().await?;
|
2022-09-08 01:52:08 +00:00
|
|
|
*self.unlocked_inner.routing_table.write() = Some(routing_table.clone());
|
|
|
|
*self.unlocked_inner.update_callback.write() = Some(update_callback);
|
2021-11-22 16:28:30 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2022-06-10 21:07:10 +00:00
|
|
|
|
|
|
|
#[instrument(level = "debug", skip_all)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn terminate(&self) {
|
2022-09-08 01:52:08 +00:00
|
|
|
let routing_table = self.unlocked_inner.routing_table.write().take();
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Some(routing_table) = routing_table {
|
2021-11-22 16:28:30 +00:00
|
|
|
routing_table.terminate().await;
|
|
|
|
}
|
2022-09-08 01:52:08 +00:00
|
|
|
*self.unlocked_inner.update_callback.write() = None;
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip_all, err)]
|
2022-07-10 21:36:50 +00:00
|
|
|
pub async fn internal_startup(&self) -> EyreResult<()> {
|
2021-11-22 16:28:30 +00:00
|
|
|
trace!("NetworkManager::internal_startup begin");
|
2022-09-08 01:52:08 +00:00
|
|
|
if self.unlocked_inner.components.read().is_some() {
|
2021-11-22 16:28:30 +00:00
|
|
|
debug!("NetworkManager::internal_startup already started");
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create network components
|
2022-01-03 04:49:01 +00:00
|
|
|
let connection_manager = ConnectionManager::new(self.clone());
|
2022-07-06 18:11:44 +00:00
|
|
|
let net = Network::new(
|
|
|
|
self.clone(),
|
|
|
|
self.routing_table(),
|
|
|
|
connection_manager.clone(),
|
|
|
|
);
|
2022-09-25 22:04:53 +00:00
|
|
|
let rpc_processor = RPCProcessor::new(
|
|
|
|
self.clone(),
|
|
|
|
self.unlocked_inner
|
|
|
|
.update_callback
|
|
|
|
.read()
|
|
|
|
.as_ref()
|
|
|
|
.unwrap()
|
|
|
|
.clone(),
|
|
|
|
);
|
2021-11-22 16:28:30 +00:00
|
|
|
let receipt_manager = ReceiptManager::new(self.clone());
|
2022-09-08 01:52:08 +00:00
|
|
|
*self.unlocked_inner.components.write() = Some(NetworkComponents {
|
2021-11-22 16:28:30 +00:00
|
|
|
net: net.clone(),
|
2022-01-03 04:49:01 +00:00
|
|
|
connection_manager: connection_manager.clone(),
|
2021-11-22 16:28:30 +00:00
|
|
|
rpc_processor: rpc_processor.clone(),
|
|
|
|
receipt_manager: receipt_manager.clone(),
|
|
|
|
});
|
|
|
|
|
|
|
|
// Start network components
|
2022-06-13 00:58:02 +00:00
|
|
|
connection_manager.startup().await;
|
|
|
|
net.startup().await?;
|
2021-11-22 16:28:30 +00:00
|
|
|
rpc_processor.startup().await?;
|
|
|
|
receipt_manager.startup().await?;
|
|
|
|
|
|
|
|
trace!("NetworkManager::internal_startup end");
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip_all, err)]
|
2022-07-10 21:36:50 +00:00
|
|
|
pub async fn startup(&self) -> EyreResult<()> {
|
2021-11-22 16:28:30 +00:00
|
|
|
if let Err(e) = self.internal_startup().await {
|
|
|
|
self.shutdown().await;
|
|
|
|
return Err(e);
|
|
|
|
}
|
2022-05-16 15:52:48 +00:00
|
|
|
|
2022-07-22 17:05:28 +00:00
|
|
|
// Inform api clients that things have changed
|
2022-05-16 15:52:48 +00:00
|
|
|
self.send_network_update();
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip_all)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn shutdown(&self) {
|
2022-06-15 18:05:04 +00:00
|
|
|
debug!("starting network manager shutdown");
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-25 15:12:19 +00:00
|
|
|
// Cancel all tasks
|
2022-06-15 18:05:04 +00:00
|
|
|
debug!("stopping rolling transfers task");
|
2022-06-13 00:58:02 +00:00
|
|
|
if let Err(e) = self.unlocked_inner.rolling_transfers_task.stop().await {
|
|
|
|
warn!("rolling_transfers_task not stopped: {}", e);
|
2022-05-25 15:12:19 +00:00
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
debug!("stopping relay management task");
|
2022-06-13 00:58:02 +00:00
|
|
|
if let Err(e) = self.unlocked_inner.relay_management_task.stop().await {
|
|
|
|
warn!("relay_management_task not stopped: {}", e);
|
2022-05-25 15:12:19 +00:00
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
debug!("stopping bootstrap task");
|
|
|
|
if let Err(e) = self.unlocked_inner.bootstrap_task.stop().await {
|
|
|
|
error!("bootstrap_task not stopped: {}", e);
|
|
|
|
}
|
|
|
|
debug!("stopping peer minimum refresh task");
|
|
|
|
if let Err(e) = self.unlocked_inner.peer_minimum_refresh_task.stop().await {
|
|
|
|
error!("peer_minimum_refresh_task not stopped: {}", e);
|
|
|
|
}
|
|
|
|
debug!("stopping ping_validator task");
|
|
|
|
if let Err(e) = self.unlocked_inner.ping_validator_task.stop().await {
|
|
|
|
error!("ping_validator_task not stopped: {}", e);
|
|
|
|
}
|
|
|
|
debug!("stopping node info update singlefuture");
|
|
|
|
if self
|
|
|
|
.unlocked_inner
|
|
|
|
.node_info_update_single_future
|
|
|
|
.join()
|
|
|
|
.await
|
|
|
|
.is_err()
|
|
|
|
{
|
|
|
|
error!("node_info_update_single_future not stopped");
|
|
|
|
}
|
2022-05-25 15:12:19 +00:00
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Shutdown network components if they started up
|
2022-06-15 18:05:04 +00:00
|
|
|
debug!("shutting down network components");
|
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
let components = self.unlocked_inner.components.read().clone();
|
2021-11-22 16:28:30 +00:00
|
|
|
if let Some(components) = components {
|
2022-06-13 00:58:02 +00:00
|
|
|
components.net.shutdown().await;
|
2022-06-15 18:05:04 +00:00
|
|
|
components.rpc_processor.shutdown().await;
|
|
|
|
components.receipt_manager.shutdown().await;
|
2022-06-29 14:13:49 +00:00
|
|
|
components.connection_manager.shutdown().await;
|
2022-09-08 01:52:08 +00:00
|
|
|
|
|
|
|
*self.unlocked_inner.components.write() = None;
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// reset the state
|
2022-06-15 18:05:04 +00:00
|
|
|
debug!("resetting network manager state");
|
2022-05-16 15:52:48 +00:00
|
|
|
{
|
2022-10-09 18:59:01 +00:00
|
|
|
*self.inner.lock() = NetworkManager::new_inner();
|
2022-05-16 15:52:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// send update
|
2022-09-08 01:52:08 +00:00
|
|
|
debug!("sending network state update to api clients");
|
2022-05-16 15:52:48 +00:00
|
|
|
self.send_network_update();
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-06-15 18:05:04 +00:00
|
|
|
debug!("finished network manager shutdown");
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 23:54:52 +00:00
|
|
|
pub fn update_client_whitelist(&self, client: DHTKey) {
|
2022-04-03 16:58:06 +00:00
|
|
|
let mut inner = self.inner.lock();
|
|
|
|
match inner.client_whitelist.entry(client) {
|
|
|
|
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
2022-05-24 21:13:52 +00:00
|
|
|
entry.get_mut().last_seen_ts = intf::get_timestamp()
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
|
|
|
hashlink::lru_cache::Entry::Vacant(entry) => {
|
|
|
|
entry.insert(ClientWhitelistEntry {
|
2022-05-24 21:13:52 +00:00
|
|
|
last_seen_ts: intf::get_timestamp(),
|
2022-04-03 16:58:06 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self), ret)]
|
2022-05-31 23:54:52 +00:00
|
|
|
pub fn check_client_whitelist(&self, client: DHTKey) -> bool {
|
2022-04-03 16:58:06 +00:00
|
|
|
let mut inner = self.inner.lock();
|
|
|
|
|
|
|
|
match inner.client_whitelist.entry(client) {
|
|
|
|
hashlink::lru_cache::Entry::Occupied(mut entry) => {
|
2022-05-24 21:13:52 +00:00
|
|
|
entry.get_mut().last_seen_ts = intf::get_timestamp();
|
2022-04-03 16:58:06 +00:00
|
|
|
true
|
|
|
|
}
|
|
|
|
hashlink::lru_cache::Entry::Vacant(_) => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn purge_client_whitelist(&self) {
|
2022-10-10 02:07:15 +00:00
|
|
|
let timeout_ms = self.with_config(|c| c.network.client_whitelist_timeout_ms);
|
2022-04-03 16:58:06 +00:00
|
|
|
let mut inner = self.inner.lock();
|
|
|
|
let cutoff_timestamp = intf::get_timestamp() - ((timeout_ms as u64) * 1000u64);
|
|
|
|
// Remove clients from the whitelist that haven't been since since our whitelist timeout
|
|
|
|
while inner
|
|
|
|
.client_whitelist
|
|
|
|
.peek_lru()
|
2022-05-24 21:13:52 +00:00
|
|
|
.map(|v| v.1.last_seen_ts < cutoff_timestamp)
|
2022-04-03 16:58:06 +00:00
|
|
|
.unwrap_or_default()
|
|
|
|
{
|
2022-06-15 19:03:13 +00:00
|
|
|
let (k, v) = inner.client_whitelist.remove_lru().unwrap();
|
|
|
|
trace!(key=?k, value=?v, "purge_client_whitelist: remove_lru")
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-22 17:05:28 +00:00
|
|
|
pub fn needs_restart(&self) -> bool {
|
|
|
|
let net = self.net();
|
|
|
|
net.needs_restart()
|
2022-06-10 21:07:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-10 21:36:50 +00:00
|
|
|
pub async fn tick(&self) -> EyreResult<()> {
|
2022-09-08 01:52:08 +00:00
|
|
|
let routing_table = self.routing_table();
|
|
|
|
let net = self.net();
|
|
|
|
let receipt_manager = self.receipt_manager();
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-18 14:17:04 +00:00
|
|
|
// Run the rolling transfers task
|
|
|
|
self.unlocked_inner.rolling_transfers_task.tick().await?;
|
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
// Run the relay management task
|
|
|
|
self.unlocked_inner.relay_management_task.tick().await?;
|
2022-07-22 17:05:28 +00:00
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
// See how many live PublicInternet entries we have
|
|
|
|
let live_public_internet_entry_count = routing_table.get_entry_count(
|
2022-09-04 18:17:28 +00:00
|
|
|
RoutingDomain::PublicInternet.into(),
|
2022-09-03 17:57:25 +00:00
|
|
|
BucketEntryState::Unreliable,
|
|
|
|
);
|
2022-10-10 02:07:15 +00:00
|
|
|
let min_peer_count = self.with_config(|c| c.network.dht.min_peer_count as usize);
|
2022-10-05 00:09:32 +00:00
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
// If none, then add the bootstrap nodes to it
|
|
|
|
if live_public_internet_entry_count == 0 {
|
|
|
|
self.unlocked_inner.bootstrap_task.tick().await?;
|
|
|
|
}
|
|
|
|
// If we still don't have enough peers, find nodes until we do
|
2022-10-05 00:09:32 +00:00
|
|
|
else if !self.unlocked_inner.bootstrap_task.is_running()
|
|
|
|
&& live_public_internet_entry_count < min_peer_count
|
|
|
|
{
|
2022-09-03 17:57:25 +00:00
|
|
|
self.unlocked_inner.peer_minimum_refresh_task.tick().await?;
|
2022-07-22 17:05:28 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
// Ping validate some nodes to groom the table
|
|
|
|
self.unlocked_inner.ping_validator_task.tick().await?;
|
|
|
|
|
2021-12-09 21:00:47 +00:00
|
|
|
// Run the routing table tick
|
|
|
|
routing_table.tick().await?;
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Run the low level network tick
|
|
|
|
net.tick().await?;
|
|
|
|
|
|
|
|
// Run the receipt manager tick
|
|
|
|
receipt_manager.tick().await?;
|
|
|
|
|
2022-04-03 16:58:06 +00:00
|
|
|
// Purge the client whitelist
|
|
|
|
self.purge_client_whitelist();
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Get our node's capabilities in the PublicInternet routing domain
|
2022-09-03 17:57:25 +00:00
|
|
|
fn generate_public_internet_node_status(&self) -> PublicInternetNodeStatus {
|
|
|
|
let node_info = self
|
2022-08-31 01:21:16 +00:00
|
|
|
.routing_table()
|
2022-09-03 17:57:25 +00:00
|
|
|
.get_own_node_info(RoutingDomain::PublicInternet);
|
2022-04-03 16:58:06 +00:00
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
let will_route = node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
|
|
|
let will_tunnel = node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
|
|
|
let will_signal = node_info.can_signal();
|
|
|
|
let will_relay = node_info.can_inbound_relay();
|
|
|
|
let will_validate_dial_info = node_info.can_validate_dial_info();
|
2022-04-03 16:58:06 +00:00
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
PublicInternetNodeStatus {
|
2022-04-03 16:58:06 +00:00
|
|
|
will_route,
|
|
|
|
will_tunnel,
|
|
|
|
will_signal,
|
|
|
|
will_relay,
|
|
|
|
will_validate_dial_info,
|
|
|
|
}
|
|
|
|
}
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Get our node's capabilities in the LocalNetwork routing domain
|
2022-09-03 17:57:25 +00:00
|
|
|
fn generate_local_network_node_status(&self) -> LocalNetworkNodeStatus {
|
|
|
|
let node_info = self
|
|
|
|
.routing_table()
|
|
|
|
.get_own_node_info(RoutingDomain::LocalNetwork);
|
|
|
|
|
|
|
|
let will_relay = node_info.can_inbound_relay();
|
|
|
|
let will_validate_dial_info = node_info.can_validate_dial_info();
|
|
|
|
|
|
|
|
LocalNetworkNodeStatus {
|
|
|
|
will_relay,
|
|
|
|
will_validate_dial_info,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn generate_node_status(&self, routing_domain: RoutingDomain) -> NodeStatus {
|
|
|
|
match routing_domain {
|
|
|
|
RoutingDomain::PublicInternet => {
|
|
|
|
NodeStatus::PublicInternet(self.generate_public_internet_node_status())
|
|
|
|
}
|
|
|
|
RoutingDomain::LocalNetwork => {
|
|
|
|
NodeStatus::LocalNetwork(self.generate_local_network_node_status())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-03 16:58:06 +00:00
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Generates a multi-shot/normal receipt
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, extra_data, callback), err)]
|
2022-05-28 20:11:50 +00:00
|
|
|
pub fn generate_receipt<D: AsRef<[u8]>>(
|
2021-11-22 16:28:30 +00:00
|
|
|
&self,
|
|
|
|
expiration_us: u64,
|
|
|
|
expected_returns: u32,
|
2022-05-28 20:11:50 +00:00
|
|
|
extra_data: D,
|
2021-11-22 16:28:30 +00:00
|
|
|
callback: impl ReceiptCallback,
|
2022-07-10 21:36:50 +00:00
|
|
|
) -> EyreResult<Vec<u8>> {
|
2021-11-22 16:28:30 +00:00
|
|
|
let receipt_manager = self.receipt_manager();
|
2022-05-28 20:11:50 +00:00
|
|
|
let routing_table = self.routing_table();
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-28 20:11:50 +00:00
|
|
|
// Generate receipt and serialized form to return
|
|
|
|
let nonce = Crypto::get_random_nonce();
|
|
|
|
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
|
|
|
|
let out = receipt
|
|
|
|
.to_signed_data(&routing_table.node_id_secret())
|
2022-07-10 21:36:50 +00:00
|
|
|
.wrap_err("failed to generate signed receipt")?;
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Record the receipt for later
|
|
|
|
let exp_ts = intf::get_timestamp() + expiration_us;
|
2022-05-28 20:11:50 +00:00
|
|
|
receipt_manager.record_receipt(receipt, exp_ts, expected_returns, callback);
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-28 20:11:50 +00:00
|
|
|
Ok(out)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Generates a single-shot/normal receipt
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, extra_data), err)]
|
2022-05-28 20:11:50 +00:00
|
|
|
pub fn generate_single_shot_receipt<D: AsRef<[u8]>>(
|
2021-11-22 16:28:30 +00:00
|
|
|
&self,
|
|
|
|
expiration_us: u64,
|
2022-05-28 20:11:50 +00:00
|
|
|
extra_data: D,
|
2022-07-10 21:36:50 +00:00
|
|
|
) -> EyreResult<(Vec<u8>, EventualValueFuture<ReceiptEvent>)> {
|
2021-11-22 16:28:30 +00:00
|
|
|
let receipt_manager = self.receipt_manager();
|
2022-05-28 20:11:50 +00:00
|
|
|
let routing_table = self.routing_table();
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-28 20:11:50 +00:00
|
|
|
// Generate receipt and serialized form to return
|
|
|
|
let nonce = Crypto::get_random_nonce();
|
|
|
|
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
|
|
|
|
let out = receipt
|
|
|
|
.to_signed_data(&routing_table.node_id_secret())
|
2022-07-10 21:36:50 +00:00
|
|
|
.wrap_err("failed to generate signed receipt")?;
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Record the receipt for later
|
|
|
|
let exp_ts = intf::get_timestamp() + expiration_us;
|
2022-05-24 21:13:52 +00:00
|
|
|
let eventual = SingleShotEventual::new(Some(ReceiptEvent::Cancelled));
|
2021-11-22 16:28:30 +00:00
|
|
|
let instance = eventual.instance();
|
2022-05-28 20:11:50 +00:00
|
|
|
receipt_manager.record_single_shot_receipt(receipt, exp_ts, eventual);
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-28 20:11:50 +00:00
|
|
|
Ok((out, instance))
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Process a received out-of-band receipt
|
2022-07-20 13:39:38 +00:00
|
|
|
#[instrument(level = "trace", skip(self, receipt_data), ret)]
|
2022-04-17 23:10:10 +00:00
|
|
|
pub async fn handle_out_of_band_receipt<R: AsRef<[u8]>>(
|
2022-04-17 17:28:39 +00:00
|
|
|
&self,
|
|
|
|
receipt_data: R,
|
2022-07-20 13:39:38 +00:00
|
|
|
) -> NetworkResult<()> {
|
2022-04-17 17:28:39 +00:00
|
|
|
let receipt_manager = self.receipt_manager();
|
|
|
|
|
2022-07-20 13:39:38 +00:00
|
|
|
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
|
|
|
|
Err(e) => {
|
|
|
|
return NetworkResult::invalid_message(e.to_string());
|
|
|
|
}
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
2022-04-17 17:28:39 +00:00
|
|
|
|
2022-10-31 03:23:12 +00:00
|
|
|
receipt_manager
|
|
|
|
.handle_receipt(receipt, ReceiptReturned::OutOfBand)
|
|
|
|
.await
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Process a received in-band receipt
|
2022-07-20 13:39:38 +00:00
|
|
|
#[instrument(level = "trace", skip(self, receipt_data), ret)]
|
2022-05-28 20:11:50 +00:00
|
|
|
pub async fn handle_in_band_receipt<R: AsRef<[u8]>>(
|
2022-04-17 17:28:39 +00:00
|
|
|
&self,
|
2022-05-28 20:11:50 +00:00
|
|
|
receipt_data: R,
|
2022-10-31 03:23:12 +00:00
|
|
|
inbound_noderef: NodeRef,
|
|
|
|
) -> NetworkResult<()> {
|
|
|
|
let receipt_manager = self.receipt_manager();
|
|
|
|
|
|
|
|
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
|
|
|
|
Err(e) => {
|
|
|
|
return NetworkResult::invalid_message(e.to_string());
|
|
|
|
}
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
|
|
|
|
|
|
|
receipt_manager
|
|
|
|
.handle_receipt(receipt, ReceiptReturned::InBand { inbound_noderef })
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-11-02 19:36:01 +00:00
|
|
|
/// Process a received safety receipt
|
|
|
|
#[instrument(level = "trace", skip(self, receipt_data), ret)]
|
|
|
|
pub async fn handle_safety_receipt<R: AsRef<[u8]>>(
|
|
|
|
&self,
|
|
|
|
receipt_data: R,
|
|
|
|
) -> NetworkResult<()> {
|
|
|
|
let receipt_manager = self.receipt_manager();
|
|
|
|
|
|
|
|
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
|
|
|
|
Err(e) => {
|
|
|
|
return NetworkResult::invalid_message(e.to_string());
|
|
|
|
}
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
|
|
|
|
|
|
|
receipt_manager
|
|
|
|
.handle_receipt(receipt, ReceiptReturned::Safety)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-10-31 03:23:12 +00:00
|
|
|
/// Process a received private receipt
|
|
|
|
#[instrument(level = "trace", skip(self, receipt_data), ret)]
|
|
|
|
pub async fn handle_private_receipt<R: AsRef<[u8]>>(
|
|
|
|
&self,
|
|
|
|
receipt_data: R,
|
2022-11-02 01:05:48 +00:00
|
|
|
private_route: DHTKey,
|
2022-07-20 13:39:38 +00:00
|
|
|
) -> NetworkResult<()> {
|
2021-11-22 16:28:30 +00:00
|
|
|
let receipt_manager = self.receipt_manager();
|
2022-04-17 17:28:39 +00:00
|
|
|
|
2022-07-20 13:39:38 +00:00
|
|
|
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
|
|
|
|
Err(e) => {
|
|
|
|
return NetworkResult::invalid_message(e.to_string());
|
|
|
|
}
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
2022-05-28 20:11:50 +00:00
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
receipt_manager
|
2022-11-02 01:05:48 +00:00
|
|
|
.handle_receipt(receipt, ReceiptReturned::Private { private_route })
|
2022-05-28 14:07:57 +00:00
|
|
|
.await
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-04-17 23:10:10 +00:00
|
|
|
// Process a received signal
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self), err)]
|
2022-10-30 23:29:31 +00:00
|
|
|
pub async fn handle_signal(&self, signal_info: SignalInfo) -> EyreResult<NetworkResult<()>> {
|
2022-04-17 23:10:10 +00:00
|
|
|
match signal_info {
|
2022-05-28 20:11:50 +00:00
|
|
|
SignalInfo::ReverseConnect { receipt, peer_info } => {
|
2022-04-17 23:10:10 +00:00
|
|
|
let routing_table = self.routing_table();
|
|
|
|
let rpc = self.rpc_processor();
|
|
|
|
|
|
|
|
// Add the peer info to our routing table
|
2022-07-20 13:39:38 +00:00
|
|
|
let peer_nr = match routing_table.register_node_with_signed_node_info(
|
2022-08-31 01:21:16 +00:00
|
|
|
RoutingDomain::PublicInternet,
|
2022-05-11 01:49:42 +00:00
|
|
|
peer_info.node_id.key,
|
|
|
|
peer_info.signed_node_info,
|
2022-08-27 02:52:08 +00:00
|
|
|
false,
|
2022-07-20 13:39:38 +00:00
|
|
|
) {
|
|
|
|
None => {
|
|
|
|
return Ok(NetworkResult::invalid_message(
|
|
|
|
"unable to register reverse connect peerinfo",
|
|
|
|
))
|
|
|
|
}
|
|
|
|
Some(nr) => nr,
|
|
|
|
};
|
2022-04-17 23:10:10 +00:00
|
|
|
|
|
|
|
// Make a reverse connection to the peer and send the receipt to it
|
2022-09-04 18:17:28 +00:00
|
|
|
rpc.rpc_call_return_receipt(Destination::direct(peer_nr), receipt)
|
2022-04-17 23:10:10 +00:00
|
|
|
.await
|
2022-07-20 13:39:38 +00:00
|
|
|
.wrap_err("rpc failure")
|
2022-04-17 23:10:10 +00:00
|
|
|
}
|
2022-05-28 20:11:50 +00:00
|
|
|
SignalInfo::HolePunch { receipt, peer_info } => {
|
2022-04-17 23:10:10 +00:00
|
|
|
let routing_table = self.routing_table();
|
2022-05-28 14:07:57 +00:00
|
|
|
let rpc = self.rpc_processor();
|
2022-04-17 23:10:10 +00:00
|
|
|
|
|
|
|
// Add the peer info to our routing table
|
2022-07-20 13:39:38 +00:00
|
|
|
let mut peer_nr = match routing_table.register_node_with_signed_node_info(
|
2022-08-31 01:21:16 +00:00
|
|
|
RoutingDomain::PublicInternet,
|
2022-05-11 01:49:42 +00:00
|
|
|
peer_info.node_id.key,
|
|
|
|
peer_info.signed_node_info,
|
2022-08-27 02:52:08 +00:00
|
|
|
false,
|
2022-07-20 13:39:38 +00:00
|
|
|
) {
|
|
|
|
None => {
|
|
|
|
return Ok(NetworkResult::invalid_message(
|
|
|
|
//sender_id,
|
|
|
|
"unable to register hole punch connect peerinfo",
|
|
|
|
));
|
|
|
|
}
|
|
|
|
Some(nr) => nr,
|
|
|
|
};
|
2022-04-17 23:10:10 +00:00
|
|
|
|
|
|
|
// Get the udp direct dialinfo for the hole punch
|
2022-10-09 18:59:01 +00:00
|
|
|
let outbound_nrf = routing_table
|
2022-09-04 18:17:28 +00:00
|
|
|
.get_outbound_node_ref_filter(RoutingDomain::PublicInternet)
|
2022-08-02 01:06:31 +00:00
|
|
|
.with_protocol_type(ProtocolType::UDP);
|
2022-09-04 18:17:28 +00:00
|
|
|
peer_nr.set_filter(Some(outbound_nrf));
|
2022-04-25 00:16:13 +00:00
|
|
|
let hole_punch_dial_info_detail = peer_nr
|
2022-09-04 18:17:28 +00:00
|
|
|
.first_filtered_dial_info_detail()
|
2022-07-10 21:36:50 +00:00
|
|
|
.ok_or_else(|| eyre!("No hole punch capable dialinfo found for node"))?;
|
2022-04-17 23:10:10 +00:00
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
// Now that we picked a specific dialinfo, further restrict the noderef to the specific address type
|
2022-08-02 01:06:31 +00:00
|
|
|
let filter = peer_nr.take_filter().unwrap();
|
|
|
|
let filter =
|
|
|
|
filter.with_address_type(hole_punch_dial_info_detail.dial_info.address_type());
|
2022-05-28 14:07:57 +00:00
|
|
|
peer_nr.set_filter(Some(filter));
|
|
|
|
|
2022-04-17 23:10:10 +00:00
|
|
|
// Do our half of the hole punch by sending an empty packet
|
|
|
|
// Both sides will do this and then the receipt will get sent over the punched hole
|
2022-08-06 16:36:07 +00:00
|
|
|
let connection_descriptor = network_result_try!(
|
2022-07-20 13:39:38 +00:00
|
|
|
self.net()
|
|
|
|
.send_data_to_dial_info(
|
|
|
|
hole_punch_dial_info_detail.dial_info.clone(),
|
|
|
|
Vec::new(),
|
|
|
|
)
|
|
|
|
.await?
|
|
|
|
);
|
2022-04-17 23:10:10 +00:00
|
|
|
|
|
|
|
// XXX: do we need a delay here? or another hole punch packet?
|
|
|
|
|
2022-08-06 16:36:07 +00:00
|
|
|
// Set the hole punch as our 'last connection' to ensure we return the receipt over the direct hole punch
|
|
|
|
peer_nr.set_last_connection(connection_descriptor, intf::get_timestamp());
|
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
// Return the receipt using the same dial info send the receipt to it
|
2022-09-04 18:17:28 +00:00
|
|
|
rpc.rpc_call_return_receipt(Destination::direct(peer_nr), receipt)
|
2022-04-17 23:10:10 +00:00
|
|
|
.await
|
2022-07-20 13:39:38 +00:00
|
|
|
.wrap_err("rpc failure")
|
2022-04-17 23:10:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Builds an envelope for sending over the network
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, body), err)]
|
2021-11-22 16:28:30 +00:00
|
|
|
fn build_envelope<B: AsRef<[u8]>>(
|
|
|
|
&self,
|
2022-05-31 23:54:52 +00:00
|
|
|
dest_node_id: DHTKey,
|
2021-11-22 16:28:30 +00:00
|
|
|
version: u8,
|
|
|
|
body: B,
|
2022-07-10 21:36:50 +00:00
|
|
|
) -> EyreResult<Vec<u8>> {
|
2021-11-22 16:28:30 +00:00
|
|
|
// DH to get encryption key
|
|
|
|
let routing_table = self.routing_table();
|
|
|
|
let node_id = routing_table.node_id();
|
|
|
|
let node_id_secret = routing_table.node_id_secret();
|
|
|
|
|
|
|
|
// Get timestamp, nonce
|
|
|
|
let ts = intf::get_timestamp();
|
|
|
|
let nonce = Crypto::get_random_nonce();
|
|
|
|
|
|
|
|
// Encode envelope
|
|
|
|
let envelope = Envelope::new(version, ts, nonce, node_id, dest_node_id);
|
|
|
|
envelope
|
2022-10-10 02:07:15 +00:00
|
|
|
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret)
|
2022-07-10 21:36:50 +00:00
|
|
|
.wrap_err("envelope failed to encode")
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Called by the RPC handler when we want to issue an RPC request or response
|
|
|
|
/// node_ref is the direct destination to which the envelope will be sent
|
|
|
|
/// If 'node_id' is specified, it can be different than node_ref.node_id()
|
|
|
|
/// which will cause the envelope to be relayed
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, body), ret, err)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn send_envelope<B: AsRef<[u8]>>(
|
|
|
|
&self,
|
|
|
|
node_ref: NodeRef,
|
2022-04-23 01:30:09 +00:00
|
|
|
envelope_node_id: Option<DHTKey>,
|
2021-11-22 16:28:30 +00:00
|
|
|
body: B,
|
2022-07-20 13:39:38 +00:00
|
|
|
) -> EyreResult<NetworkResult<SendDataKind>> {
|
2022-04-23 01:30:09 +00:00
|
|
|
let via_node_id = node_ref.node_id();
|
|
|
|
let envelope_node_id = envelope_node_id.unwrap_or(via_node_id);
|
|
|
|
|
|
|
|
if envelope_node_id != via_node_id {
|
|
|
|
log_net!(
|
|
|
|
"sending envelope to {:?} via {:?}",
|
|
|
|
envelope_node_id,
|
|
|
|
node_ref
|
|
|
|
);
|
2022-04-16 15:18:54 +00:00
|
|
|
} else {
|
|
|
|
log_net!("sending envelope to {:?}", node_ref);
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
// Get node's min/max version and see if we can send to it
|
|
|
|
// and if so, get the max version we can use
|
2022-08-31 01:21:16 +00:00
|
|
|
let version = if let Some((node_min, node_max)) = node_ref.min_max_version() {
|
2021-11-27 17:44:21 +00:00
|
|
|
#[allow(clippy::absurd_extreme_comparisons)]
|
2022-10-30 23:29:31 +00:00
|
|
|
if node_min > MAX_CRYPTO_VERSION || node_max < MIN_CRYPTO_VERSION {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!(
|
2021-11-22 16:28:30 +00:00
|
|
|
"can't talk to this node {} because version is unsupported: ({},{})",
|
2022-07-10 21:36:50 +00:00
|
|
|
via_node_id,
|
|
|
|
node_min,
|
|
|
|
node_max
|
|
|
|
);
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-10-30 23:29:31 +00:00
|
|
|
cmp::min(node_max, MAX_CRYPTO_VERSION)
|
2021-11-22 16:28:30 +00:00
|
|
|
} else {
|
2022-10-30 23:29:31 +00:00
|
|
|
MAX_CRYPTO_VERSION
|
2021-11-22 16:28:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Build the envelope to send
|
2022-07-20 13:39:38 +00:00
|
|
|
let out = self.build_envelope(envelope_node_id, version, body)?;
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-04-16 15:18:54 +00:00
|
|
|
// Send the envelope via whatever means necessary
|
2022-08-09 00:42:27 +00:00
|
|
|
self.send_data(node_ref.clone(), out).await
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Called by the RPC handler when we want to issue an direct receipt
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, rcpt_data), err)]
|
2022-05-28 20:11:50 +00:00
|
|
|
pub async fn send_out_of_band_receipt(
|
2021-11-22 16:28:30 +00:00
|
|
|
&self,
|
2022-01-04 19:25:32 +00:00
|
|
|
dial_info: DialInfo,
|
2022-05-28 20:11:50 +00:00
|
|
|
rcpt_data: Vec<u8>,
|
2022-07-10 21:36:50 +00:00
|
|
|
) -> EyreResult<()> {
|
2022-05-28 20:11:50 +00:00
|
|
|
// Do we need to validate the outgoing receipt? Probably not
|
|
|
|
// because it is supposed to be opaque and the
|
|
|
|
// recipient/originator does the validation
|
|
|
|
// Also, in the case of an old 'version', returning the receipt
|
|
|
|
// should not be subject to our ability to decode it
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Send receipt directly
|
2022-08-28 17:13:09 +00:00
|
|
|
log_net!(debug "send_out_of_band_receipt: dial_info={}", dial_info);
|
2022-07-20 13:39:38 +00:00
|
|
|
network_result_value_or_log!(debug self
|
2022-07-14 20:57:34 +00:00
|
|
|
.net()
|
2022-05-28 14:07:57 +00:00
|
|
|
.send_data_unbound_to_dial_info(dial_info, rcpt_data)
|
2022-07-20 13:39:38 +00:00
|
|
|
.await? => {
|
|
|
|
return Ok(());
|
2022-07-14 20:57:34 +00:00
|
|
|
}
|
2022-07-20 13:39:38 +00:00
|
|
|
);
|
2022-07-14 20:57:34 +00:00
|
|
|
Ok(())
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Send a reverse connection signal and wait for the return receipt over it
|
|
|
|
/// Then send the data across the new connection
|
|
|
|
/// Only usable for PublicInternet routing domain
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, data), err)]
|
2022-04-16 15:18:54 +00:00
|
|
|
pub async fn do_reverse_connect(
|
|
|
|
&self,
|
2022-04-17 17:28:39 +00:00
|
|
|
relay_nr: NodeRef,
|
|
|
|
target_nr: NodeRef,
|
2022-04-16 15:18:54 +00:00
|
|
|
data: Vec<u8>,
|
2022-08-09 00:42:27 +00:00
|
|
|
) -> EyreResult<NetworkResult<ConnectionDescriptor>> {
|
2022-04-16 15:18:54 +00:00
|
|
|
// Build a return receipt for the signal
|
2022-10-10 02:07:15 +00:00
|
|
|
let receipt_timeout = ms_to_us(
|
|
|
|
self.unlocked_inner
|
|
|
|
.config
|
|
|
|
.get()
|
|
|
|
.network
|
|
|
|
.reverse_connection_receipt_time_ms,
|
|
|
|
);
|
2022-07-10 21:36:50 +00:00
|
|
|
let (receipt, eventual_value) = self.generate_single_shot_receipt(receipt_timeout, [])?;
|
2022-04-17 17:28:39 +00:00
|
|
|
|
|
|
|
// Get our peer info
|
2022-08-31 01:21:16 +00:00
|
|
|
let peer_info = self
|
|
|
|
.routing_table()
|
|
|
|
.get_own_peer_info(RoutingDomain::PublicInternet);
|
2022-04-16 15:18:54 +00:00
|
|
|
|
|
|
|
// Issue the signal
|
|
|
|
let rpc = self.rpc_processor();
|
2022-07-20 13:39:38 +00:00
|
|
|
network_result_try!(rpc
|
|
|
|
.rpc_call_signal(
|
2022-09-04 18:17:28 +00:00
|
|
|
Destination::relay(relay_nr, target_nr.node_id()),
|
2022-07-20 13:39:38 +00:00
|
|
|
SignalInfo::ReverseConnect { receipt, peer_info },
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.wrap_err("failed to send signal")?);
|
|
|
|
|
2022-04-16 15:18:54 +00:00
|
|
|
// Wait for the return receipt
|
2022-05-24 21:13:52 +00:00
|
|
|
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
2022-11-02 01:05:48 +00:00
|
|
|
ReceiptEvent::ReturnedPrivate { private_route: _ }
|
2022-11-02 19:36:01 +00:00
|
|
|
| ReceiptEvent::ReturnedOutOfBand
|
|
|
|
| ReceiptEvent::ReturnedSafety => {
|
2022-08-05 00:21:03 +00:00
|
|
|
return Ok(NetworkResult::invalid_message(
|
|
|
|
"reverse connect receipt should be returned in-band",
|
|
|
|
));
|
2022-05-28 14:07:57 +00:00
|
|
|
}
|
2022-05-28 20:11:50 +00:00
|
|
|
ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef,
|
2022-04-16 15:18:54 +00:00
|
|
|
ReceiptEvent::Expired => {
|
2022-07-20 13:39:38 +00:00
|
|
|
return Ok(NetworkResult::timeout());
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
ReceiptEvent::Cancelled => {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!("reverse connect receipt cancelled from {:?}", target_nr);
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-04-17 17:28:39 +00:00
|
|
|
// We expect the inbound noderef to be the same as the target noderef
|
|
|
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
2022-10-22 01:27:07 +00:00
|
|
|
if target_nr.node_id() != inbound_nr.node_id() {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!("unexpected noderef mismatch on reverse connect");
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
|
|
|
|
2022-04-16 15:18:54 +00:00
|
|
|
// And now use the existing connection to send over
|
2022-09-07 15:30:43 +00:00
|
|
|
if let Some(descriptor) = inbound_nr.last_connection() {
|
2022-04-16 15:18:54 +00:00
|
|
|
match self
|
|
|
|
.net()
|
|
|
|
.send_data_to_existing_connection(descriptor, data)
|
2022-06-15 18:05:04 +00:00
|
|
|
.await?
|
2022-04-16 15:18:54 +00:00
|
|
|
{
|
2022-08-09 00:42:27 +00:00
|
|
|
None => Ok(NetworkResult::value(descriptor)),
|
2022-07-20 13:39:38 +00:00
|
|
|
Some(_) => Ok(NetworkResult::no_connection_other(
|
|
|
|
"unable to send over reverse connection",
|
|
|
|
)),
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
2022-04-17 17:28:39 +00:00
|
|
|
} else {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!("no reverse connection available")
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Send a hole punch signal and do a negotiating ping and wait for the return receipt
|
|
|
|
/// Then send the data across the new connection
|
|
|
|
/// Only usable for PublicInternet routing domain
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "trace", skip(self, data), err)]
|
2022-04-17 17:28:39 +00:00
|
|
|
pub async fn do_hole_punch(
|
|
|
|
&self,
|
|
|
|
relay_nr: NodeRef,
|
|
|
|
target_nr: NodeRef,
|
|
|
|
data: Vec<u8>,
|
2022-08-09 00:42:27 +00:00
|
|
|
) -> EyreResult<NetworkResult<ConnectionDescriptor>> {
|
2022-04-21 00:49:16 +00:00
|
|
|
// Ensure we are filtered down to UDP (the only hole punch protocol supported today)
|
2022-09-04 18:17:28 +00:00
|
|
|
// and only in the PublicInternet routing domain
|
2022-04-21 00:49:16 +00:00
|
|
|
assert!(target_nr
|
|
|
|
.filter_ref()
|
2022-09-04 18:17:28 +00:00
|
|
|
.map(|nrf| nrf.dial_info_filter.protocol_type_set
|
|
|
|
== ProtocolTypeSet::only(ProtocolType::UDP))
|
|
|
|
.unwrap_or_default());
|
|
|
|
assert!(target_nr
|
|
|
|
.filter_ref()
|
|
|
|
.map(|nrf| nrf.routing_domain_set
|
|
|
|
== RoutingDomainSet::only(RoutingDomain::PublicInternet))
|
2022-04-21 00:49:16 +00:00
|
|
|
.unwrap_or_default());
|
|
|
|
|
2022-04-17 17:28:39 +00:00
|
|
|
// Build a return receipt for the signal
|
2022-10-10 02:07:15 +00:00
|
|
|
let receipt_timeout = ms_to_us(
|
|
|
|
self.unlocked_inner
|
|
|
|
.config
|
|
|
|
.get()
|
|
|
|
.network
|
|
|
|
.hole_punch_receipt_time_ms,
|
|
|
|
);
|
2022-07-10 21:36:50 +00:00
|
|
|
let (receipt, eventual_value) = self.generate_single_shot_receipt(receipt_timeout, [])?;
|
2022-04-17 17:28:39 +00:00
|
|
|
// Get our peer info
|
2022-08-31 01:21:16 +00:00
|
|
|
let peer_info = self
|
|
|
|
.routing_table()
|
|
|
|
.get_own_peer_info(RoutingDomain::PublicInternet);
|
2022-04-17 17:28:39 +00:00
|
|
|
|
|
|
|
// Get the udp direct dialinfo for the hole punch
|
2022-04-25 00:16:13 +00:00
|
|
|
let hole_punch_did = target_nr
|
2022-09-04 18:17:28 +00:00
|
|
|
.first_filtered_dial_info_detail()
|
2022-07-10 21:36:50 +00:00
|
|
|
.ok_or_else(|| eyre!("No hole punch capable dialinfo found for node"))?;
|
2022-04-17 17:28:39 +00:00
|
|
|
|
|
|
|
// Do our half of the hole punch by sending an empty packet
|
|
|
|
// Both sides will do this and then the receipt will get sent over the punched hole
|
2022-08-06 16:36:07 +00:00
|
|
|
// Don't bother storing the returned connection descriptor as the 'last connection' because the other side of the hole
|
|
|
|
// punch should come through and create a real 'last connection' for us if this succeeds
|
2022-07-20 13:39:38 +00:00
|
|
|
network_result_try!(
|
|
|
|
self.net()
|
|
|
|
.send_data_to_dial_info(hole_punch_did.dial_info, Vec::new())
|
|
|
|
.await?
|
|
|
|
);
|
2022-04-17 17:28:39 +00:00
|
|
|
|
|
|
|
// Issue the signal
|
|
|
|
let rpc = self.rpc_processor();
|
2022-07-20 13:39:38 +00:00
|
|
|
network_result_try!(rpc
|
|
|
|
.rpc_call_signal(
|
2022-09-04 18:17:28 +00:00
|
|
|
Destination::relay(relay_nr, target_nr.node_id()),
|
2022-07-20 13:39:38 +00:00
|
|
|
SignalInfo::HolePunch { receipt, peer_info },
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.wrap_err("failed to send signal")?);
|
2022-04-17 17:28:39 +00:00
|
|
|
|
|
|
|
// Wait for the return receipt
|
2022-05-24 21:13:52 +00:00
|
|
|
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
2022-11-02 01:05:48 +00:00
|
|
|
ReceiptEvent::ReturnedPrivate { private_route: _ }
|
2022-11-02 19:36:01 +00:00
|
|
|
| ReceiptEvent::ReturnedOutOfBand
|
|
|
|
| ReceiptEvent::ReturnedSafety => {
|
2022-08-05 00:21:03 +00:00
|
|
|
return Ok(NetworkResult::invalid_message(
|
|
|
|
"hole punch receipt should be returned in-band",
|
|
|
|
));
|
2022-05-28 14:07:57 +00:00
|
|
|
}
|
2022-05-28 20:11:50 +00:00
|
|
|
ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef,
|
2022-04-17 17:28:39 +00:00
|
|
|
ReceiptEvent::Expired => {
|
2022-08-05 00:21:03 +00:00
|
|
|
return Ok(NetworkResult::timeout());
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
|
|
|
ReceiptEvent::Cancelled => {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!("hole punch receipt cancelled from {}", target_nr);
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// We expect the inbound noderef to be the same as the target noderef
|
|
|
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
2022-10-22 01:27:07 +00:00
|
|
|
if target_nr.node_id() != inbound_nr.node_id() {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!(
|
2022-05-28 14:07:57 +00:00
|
|
|
"unexpected noderef mismatch on hole punch {}, expected {}",
|
2022-07-10 21:36:50 +00:00
|
|
|
inbound_nr,
|
|
|
|
target_nr
|
|
|
|
);
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// And now use the existing connection to send over
|
2022-09-07 15:30:43 +00:00
|
|
|
if let Some(descriptor) = inbound_nr.last_connection() {
|
2022-04-17 17:28:39 +00:00
|
|
|
match self
|
|
|
|
.net()
|
|
|
|
.send_data_to_existing_connection(descriptor, data)
|
2022-06-15 18:05:04 +00:00
|
|
|
.await?
|
2022-04-17 17:28:39 +00:00
|
|
|
{
|
2022-08-09 00:42:27 +00:00
|
|
|
None => Ok(NetworkResult::value(descriptor)),
|
2022-07-20 13:39:38 +00:00
|
|
|
Some(_) => Ok(NetworkResult::no_connection_other(
|
|
|
|
"unable to send over hole punch",
|
|
|
|
)),
|
2022-04-17 17:28:39 +00:00
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
} else {
|
2022-07-10 21:36:50 +00:00
|
|
|
bail!("no hole punch available")
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-19 01:53:45 +00:00
|
|
|
/// Figure out how to reach a node from our own node over the best routing domain and reference the nodes we want to access
|
|
|
|
/// Uses NodeRefs to ensure nodes are referenced, this is not a part of 'RoutingTable' because RoutingTable is not
|
|
|
|
/// allowed to use NodeRefs due to recursive locking
|
|
|
|
#[instrument(level = "trace", skip(self), ret)]
|
|
|
|
pub(crate) fn get_node_contact_method(
|
|
|
|
&self,
|
|
|
|
target_node_ref: NodeRef,
|
|
|
|
) -> EyreResult<NodeContactMethod> {
|
|
|
|
let routing_table = self.routing_table();
|
|
|
|
|
|
|
|
// Figure out the best routing domain to get the contact method over
|
|
|
|
let routing_domain = match target_node_ref.best_routing_domain() {
|
|
|
|
Some(rd) => rd,
|
|
|
|
None => {
|
|
|
|
log_net!("no routing domain for node {:?}", target_node_ref);
|
|
|
|
return Ok(NodeContactMethod::Unreachable);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Node A is our own node
|
|
|
|
let node_a = routing_table.get_own_node_info(routing_domain);
|
|
|
|
let node_a_id = routing_table.node_id();
|
|
|
|
|
|
|
|
// Node B is the target node
|
|
|
|
let node_b = match target_node_ref.node_info(routing_domain) {
|
|
|
|
Some(ni) => ni,
|
|
|
|
None => {
|
|
|
|
log_net!("no node info for node {:?}", target_node_ref);
|
|
|
|
return Ok(NodeContactMethod::Unreachable);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let node_b_id = target_node_ref.node_id();
|
|
|
|
|
|
|
|
// Dial info filter comes from the target node ref
|
|
|
|
let dial_info_filter = target_node_ref.dial_info_filter();
|
2022-10-21 14:35:03 +00:00
|
|
|
let sequencing = target_node_ref.sequencing();
|
2022-10-19 01:53:45 +00:00
|
|
|
|
|
|
|
let cm = routing_table.get_contact_method(
|
|
|
|
routing_domain,
|
|
|
|
&node_a_id,
|
|
|
|
&node_a,
|
|
|
|
&node_b_id,
|
|
|
|
&node_b,
|
|
|
|
dial_info_filter,
|
2022-10-21 14:35:03 +00:00
|
|
|
sequencing,
|
2022-10-19 01:53:45 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
// Translate the raw contact method to a referenced contact method
|
|
|
|
Ok(match cm {
|
|
|
|
ContactMethod::Unreachable => NodeContactMethod::Unreachable,
|
|
|
|
ContactMethod::Existing => NodeContactMethod::Existing,
|
|
|
|
ContactMethod::Direct(di) => NodeContactMethod::Direct(di),
|
|
|
|
ContactMethod::SignalReverse(relay_key, target_key) => {
|
|
|
|
let relay_nr = routing_table
|
|
|
|
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
|
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
|
|
|
if target_node_ref.node_id() != target_key {
|
|
|
|
bail!("target noderef didn't match target key");
|
|
|
|
}
|
|
|
|
NodeContactMethod::SignalReverse(relay_nr, target_node_ref)
|
|
|
|
}
|
|
|
|
ContactMethod::SignalHolePunch(relay_key, target_key) => {
|
|
|
|
let relay_nr = routing_table
|
|
|
|
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
|
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
|
|
|
if target_node_ref.node_id() != target_key {
|
|
|
|
bail!("target noderef didn't match target key");
|
|
|
|
}
|
|
|
|
NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref)
|
|
|
|
}
|
|
|
|
ContactMethod::InboundRelay(relay_key) => {
|
|
|
|
let relay_nr = routing_table
|
|
|
|
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
|
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
|
|
|
NodeContactMethod::InboundRelay(relay_nr)
|
|
|
|
}
|
|
|
|
ContactMethod::OutboundRelay(relay_key) => {
|
|
|
|
let relay_nr = routing_table
|
|
|
|
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
|
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
|
|
|
NodeContactMethod::OutboundRelay(relay_nr)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Send raw data to a node
|
|
|
|
///
|
|
|
|
/// We may not have dial info for a node, but have an existing connection for it
|
|
|
|
/// because an inbound connection happened first, and no FindNodeQ has happened to that
|
|
|
|
/// node yet to discover its dial info. The existing connection should be tried first
|
|
|
|
/// in this case.
|
|
|
|
///
|
|
|
|
/// Sending to a node requires determining a NetworkClass compatible mechanism
|
2022-04-17 17:28:39 +00:00
|
|
|
pub fn send_data(
|
|
|
|
&self,
|
|
|
|
node_ref: NodeRef,
|
|
|
|
data: Vec<u8>,
|
2022-07-20 13:39:38 +00:00
|
|
|
) -> SendPinBoxFuture<EyreResult<NetworkResult<SendDataKind>>> {
|
2022-04-16 15:18:54 +00:00
|
|
|
let this = self.clone();
|
2022-10-02 22:47:36 +00:00
|
|
|
Box::pin(
|
|
|
|
async move {
|
|
|
|
// info!("{}", format!("send_data to: {:?}", node_ref).red());
|
|
|
|
|
|
|
|
// First try to send data to the last socket we've seen this peer on
|
|
|
|
let data = if let Some(connection_descriptor) = node_ref.last_connection() {
|
|
|
|
// info!(
|
|
|
|
// "{}",
|
|
|
|
// format!("last_connection to: {:?}", connection_descriptor).red()
|
|
|
|
// );
|
|
|
|
|
|
|
|
match this
|
|
|
|
.net()
|
|
|
|
.send_data_to_existing_connection(connection_descriptor, data)
|
|
|
|
.await?
|
|
|
|
{
|
|
|
|
None => {
|
|
|
|
// info!(
|
|
|
|
// "{}",
|
|
|
|
// format!("sent to existing connection: {:?}", connection_descriptor)
|
|
|
|
// .red()
|
|
|
|
// );
|
|
|
|
|
|
|
|
// Update timestamp for this last connection since we just sent to it
|
|
|
|
node_ref
|
|
|
|
.set_last_connection(connection_descriptor, intf::get_timestamp());
|
|
|
|
|
|
|
|
return Ok(NetworkResult::value(SendDataKind::Existing(
|
|
|
|
connection_descriptor,
|
|
|
|
)));
|
|
|
|
}
|
|
|
|
Some(d) => d,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
data
|
|
|
|
};
|
|
|
|
|
|
|
|
// info!("{}", "no existing connection".red());
|
2022-09-14 18:36:29 +00:00
|
|
|
|
2022-10-02 22:47:36 +00:00
|
|
|
// If we don't have last_connection, try to reach out to the peer via its dial info
|
2022-10-19 01:53:45 +00:00
|
|
|
let contact_method = this.get_node_contact_method(node_ref.clone())?;
|
2022-10-02 22:47:36 +00:00
|
|
|
log_net!(
|
|
|
|
"send_data via {:?} to dialinfo {:?}",
|
|
|
|
contact_method,
|
|
|
|
node_ref
|
|
|
|
);
|
|
|
|
match contact_method {
|
2022-10-13 02:53:40 +00:00
|
|
|
NodeContactMethod::OutboundRelay(relay_nr)
|
|
|
|
| NodeContactMethod::InboundRelay(relay_nr) => {
|
2022-10-02 22:47:36 +00:00
|
|
|
network_result_try!(this.send_data(relay_nr, data).await?);
|
|
|
|
Ok(NetworkResult::value(SendDataKind::Indirect))
|
|
|
|
}
|
2022-10-13 02:53:40 +00:00
|
|
|
NodeContactMethod::Direct(dial_info) => {
|
2022-10-02 22:47:36 +00:00
|
|
|
let connection_descriptor = network_result_try!(
|
|
|
|
this.net().send_data_to_dial_info(dial_info, data).await?
|
|
|
|
);
|
|
|
|
// If we connected to this node directly, save off the last connection so we can use it again
|
2022-08-09 00:42:27 +00:00
|
|
|
node_ref.set_last_connection(connection_descriptor, intf::get_timestamp());
|
|
|
|
|
2022-10-02 22:47:36 +00:00
|
|
|
Ok(NetworkResult::value(SendDataKind::Direct(
|
2022-08-09 00:42:27 +00:00
|
|
|
connection_descriptor,
|
2022-10-02 22:47:36 +00:00
|
|
|
)))
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
2022-10-13 02:53:40 +00:00
|
|
|
NodeContactMethod::SignalReverse(relay_nr, target_node_ref) => {
|
2022-10-02 22:47:36 +00:00
|
|
|
let connection_descriptor = network_result_try!(
|
|
|
|
this.do_reverse_connect(relay_nr, target_node_ref, data)
|
|
|
|
.await?
|
|
|
|
);
|
|
|
|
Ok(NetworkResult::value(SendDataKind::Direct(
|
|
|
|
connection_descriptor,
|
|
|
|
)))
|
|
|
|
}
|
2022-10-13 02:53:40 +00:00
|
|
|
NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref) => {
|
2022-10-02 22:47:36 +00:00
|
|
|
let connection_descriptor = network_result_try!(
|
|
|
|
this.do_hole_punch(relay_nr, target_node_ref, data).await?
|
|
|
|
);
|
|
|
|
Ok(NetworkResult::value(SendDataKind::Direct(
|
|
|
|
connection_descriptor,
|
|
|
|
)))
|
|
|
|
}
|
2022-10-13 02:53:40 +00:00
|
|
|
NodeContactMethod::Existing => Ok(NetworkResult::no_connection_other(
|
|
|
|
"should have found an existing connection",
|
|
|
|
)),
|
|
|
|
NodeContactMethod::Unreachable => Ok(NetworkResult::no_connection_other(
|
2022-10-02 22:47:36 +00:00
|
|
|
"Can't send to this node",
|
|
|
|
)),
|
2022-07-20 13:39:38 +00:00
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
2022-10-02 22:47:36 +00:00
|
|
|
.instrument(trace_span!("send_data")),
|
|
|
|
)
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
|
2022-06-25 14:57:33 +00:00
|
|
|
// Direct bootstrap request handler (separate fallback mechanism from cheaper TXT bootstrap mechanism)
|
2022-07-20 13:39:38 +00:00
|
|
|
#[instrument(level = "trace", skip(self), ret, err)]
|
|
|
|
async fn handle_boot_request(
|
|
|
|
&self,
|
|
|
|
descriptor: ConnectionDescriptor,
|
|
|
|
) -> EyreResult<NetworkResult<()>> {
|
2022-06-25 14:57:33 +00:00
|
|
|
let routing_table = self.routing_table();
|
|
|
|
|
|
|
|
// Get a bunch of nodes with the various
|
|
|
|
let bootstrap_nodes = routing_table.find_bootstrap_nodes_filtered(2);
|
|
|
|
|
|
|
|
// Serialize out peer info
|
|
|
|
let bootstrap_peerinfo: Vec<PeerInfo> = bootstrap_nodes
|
|
|
|
.iter()
|
2022-09-04 18:17:28 +00:00
|
|
|
.filter_map(|nr| nr.make_peer_info(RoutingDomain::PublicInternet))
|
2022-06-25 14:57:33 +00:00
|
|
|
.collect();
|
|
|
|
let json_bytes = serialize_json(bootstrap_peerinfo).as_bytes().to_vec();
|
|
|
|
|
|
|
|
// Reply with a chunk of signed routing table
|
|
|
|
match self
|
|
|
|
.net()
|
|
|
|
.send_data_to_existing_connection(descriptor, json_bytes)
|
|
|
|
.await?
|
|
|
|
{
|
|
|
|
None => {
|
|
|
|
// Bootstrap reply was sent
|
2022-07-20 13:39:38 +00:00
|
|
|
Ok(NetworkResult::value(()))
|
2022-06-25 14:57:33 +00:00
|
|
|
}
|
2022-07-20 13:39:38 +00:00
|
|
|
Some(_) => Ok(NetworkResult::no_connection_other(
|
|
|
|
"bootstrap reply could not be sent",
|
|
|
|
)),
|
2022-06-25 14:57:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-25 19:28:27 +00:00
|
|
|
// Direct bootstrap request
|
2022-07-10 21:36:50 +00:00
|
|
|
#[instrument(level = "trace", err, skip(self))]
|
|
|
|
pub async fn boot_request(&self, dial_info: DialInfo) -> EyreResult<Vec<PeerInfo>> {
|
2022-10-10 02:07:15 +00:00
|
|
|
let timeout_ms = self.with_config(|c| c.network.rpc.timeout_ms);
|
2022-06-25 19:28:27 +00:00
|
|
|
// Send boot magic to requested peer address
|
|
|
|
let data = BOOT_MAGIC.to_vec();
|
2022-09-09 20:27:13 +00:00
|
|
|
let out_data: Vec<u8> = network_result_value_or_log!(debug self
|
2022-06-25 19:28:27 +00:00
|
|
|
.net()
|
|
|
|
.send_recv_data_unbound_to_dial_info(dial_info, data, timeout_ms)
|
2022-09-09 20:27:13 +00:00
|
|
|
.await? =>
|
2022-07-13 13:51:56 +00:00
|
|
|
{
|
2022-09-09 20:27:13 +00:00
|
|
|
return Ok(Vec::new());
|
|
|
|
});
|
2022-06-25 19:28:27 +00:00
|
|
|
|
|
|
|
let bootstrap_peerinfo: Vec<PeerInfo> =
|
2022-07-10 21:36:50 +00:00
|
|
|
deserialize_json(std::str::from_utf8(&out_data).wrap_err("bad utf8 in boot peerinfo")?)
|
|
|
|
.wrap_err("failed to deserialize boot peerinfo")?;
|
2022-06-25 19:28:27 +00:00
|
|
|
|
|
|
|
Ok(bootstrap_peerinfo)
|
|
|
|
}
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Called when a packet potentially containing an RPC envelope is received by a low-level
|
|
|
|
// network protocol handler. Processes the envelope, authenticates and decrypts the RPC message
|
|
|
|
// and passes it to the RPC handler
|
2022-10-02 22:47:36 +00:00
|
|
|
#[instrument(level = "trace", ret, err, skip(self, data), fields(data.len = data.len()))]
|
2022-06-05 00:18:26 +00:00
|
|
|
async fn on_recv_envelope(
|
2021-11-22 16:28:30 +00:00
|
|
|
&self,
|
|
|
|
data: &[u8],
|
2022-08-25 23:21:50 +00:00
|
|
|
connection_descriptor: ConnectionDescriptor,
|
2022-07-10 21:36:50 +00:00
|
|
|
) -> EyreResult<bool> {
|
2022-07-20 13:39:38 +00:00
|
|
|
let root = span!(
|
|
|
|
parent: None,
|
|
|
|
Level::TRACE,
|
|
|
|
"on_recv_envelope",
|
|
|
|
"data.len" = data.len(),
|
2022-08-25 23:21:50 +00:00
|
|
|
"descriptor" = ?connection_descriptor
|
2022-07-20 13:39:38 +00:00
|
|
|
);
|
|
|
|
let _root_enter = root.enter();
|
|
|
|
|
2022-01-05 17:01:02 +00:00
|
|
|
log_net!(
|
|
|
|
"envelope of {} bytes received from {:?}",
|
|
|
|
data.len(),
|
2022-08-25 23:21:50 +00:00
|
|
|
connection_descriptor
|
2022-01-05 17:01:02 +00:00
|
|
|
);
|
2022-03-20 14:52:03 +00:00
|
|
|
|
|
|
|
// Network accounting
|
2022-08-25 23:21:50 +00:00
|
|
|
self.stats_packet_rcvd(
|
|
|
|
connection_descriptor.remote_address().to_ip_addr(),
|
|
|
|
data.len() as u64,
|
|
|
|
);
|
2022-03-20 14:52:03 +00:00
|
|
|
|
2022-07-06 18:12:28 +00:00
|
|
|
// If this is a zero length packet, just drop it, because these are used for hole punching
|
|
|
|
// and possibly other low-level network connectivity tasks and will never require
|
|
|
|
// more processing or forwarding
|
|
|
|
if data.len() == 0 {
|
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
// Ensure we can read the magic number
|
|
|
|
if data.len() < 4 {
|
2022-08-20 21:08:48 +00:00
|
|
|
log_net!(debug "short packet");
|
2022-07-20 13:39:38 +00:00
|
|
|
return Ok(false);
|
2022-05-28 14:07:57 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 17:57:25 +00:00
|
|
|
// Get the routing domain for this data
|
|
|
|
let routing_domain = match self
|
|
|
|
.routing_table()
|
2022-09-04 18:17:28 +00:00
|
|
|
.routing_domain_for_address(connection_descriptor.remote_address().address())
|
2022-09-03 17:57:25 +00:00
|
|
|
{
|
|
|
|
Some(rd) => rd,
|
|
|
|
None => {
|
|
|
|
log_net!(debug "no routing domain for envelope received from {:?}", connection_descriptor);
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-06-25 14:57:33 +00:00
|
|
|
// Is this a direct bootstrap request instead of an envelope?
|
|
|
|
if data[0..4] == *BOOT_MAGIC {
|
2022-08-25 23:21:50 +00:00
|
|
|
network_result_value_or_log!(debug self.handle_boot_request(connection_descriptor).await? => {});
|
2022-06-25 14:57:33 +00:00
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Is this an out-of-band receipt instead of an envelope?
|
|
|
|
if data[0..4] == *RECEIPT_MAGIC {
|
2022-07-20 13:39:38 +00:00
|
|
|
network_result_value_or_log!(debug self.handle_out_of_band_receipt(data).await => {});
|
2021-11-22 16:28:30 +00:00
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
|
2022-04-03 16:58:06 +00:00
|
|
|
// Decode envelope header (may fail signature validation)
|
2022-08-20 21:08:48 +00:00
|
|
|
let envelope = match Envelope::from_signed_data(data) {
|
|
|
|
Ok(v) => v,
|
|
|
|
Err(e) => {
|
|
|
|
log_net!(debug "envelope failed to decode: {}", e);
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
};
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Get timestamp range
|
2022-10-10 02:07:15 +00:00
|
|
|
let (tsbehind, tsahead) = self.with_config(|c| {
|
2021-11-22 16:28:30 +00:00
|
|
|
(
|
2022-01-27 14:53:01 +00:00
|
|
|
c.network.rpc.max_timestamp_behind_ms.map(ms_to_us),
|
|
|
|
c.network.rpc.max_timestamp_ahead_ms.map(ms_to_us),
|
2021-11-22 16:28:30 +00:00
|
|
|
)
|
2022-10-10 02:07:15 +00:00
|
|
|
});
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Validate timestamp isn't too old
|
|
|
|
let ts = intf::get_timestamp();
|
|
|
|
let ets = envelope.get_timestamp();
|
|
|
|
if let Some(tsbehind) = tsbehind {
|
|
|
|
if tsbehind > 0 && (ts > ets && ts - ets > tsbehind) {
|
2022-08-20 21:08:48 +00:00
|
|
|
log_net!(debug
|
2021-11-22 16:28:30 +00:00
|
|
|
"envelope time was too far in the past: {}ms ",
|
|
|
|
timestamp_to_secs(ts - ets) * 1000f64
|
2022-07-10 21:36:50 +00:00
|
|
|
);
|
2022-08-20 21:08:48 +00:00
|
|
|
return Ok(false);
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(tsahead) = tsahead {
|
|
|
|
if tsahead > 0 && (ts < ets && ets - ts > tsahead) {
|
2022-08-20 21:08:48 +00:00
|
|
|
log_net!(debug
|
2021-11-22 16:28:30 +00:00
|
|
|
"envelope time was too far in the future: {}ms",
|
|
|
|
timestamp_to_secs(ets - ts) * 1000f64
|
2022-07-10 21:36:50 +00:00
|
|
|
);
|
2022-08-20 21:08:48 +00:00
|
|
|
return Ok(false);
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
// Get routing table and rpc processor
|
|
|
|
let routing_table = self.routing_table();
|
|
|
|
let rpc = self.rpc_processor();
|
|
|
|
|
2022-04-03 16:58:06 +00:00
|
|
|
// Peek at header and see if we need to relay this
|
|
|
|
// If the recipient id is not our node id, then it needs relaying
|
|
|
|
let sender_id = envelope.get_sender_id();
|
|
|
|
let recipient_id = envelope.get_recipient_id();
|
|
|
|
if recipient_id != routing_table.node_id() {
|
|
|
|
// See if the source node is allowed to resolve nodes
|
|
|
|
// This is a costly operation, so only outbound-relay permitted
|
|
|
|
// nodes are allowed to do this, for example PWA users
|
|
|
|
|
2022-07-20 13:39:38 +00:00
|
|
|
let some_relay_nr = if self.check_client_whitelist(sender_id) {
|
2022-04-16 15:18:54 +00:00
|
|
|
// Full relay allowed, do a full resolve_node
|
2022-07-10 21:36:50 +00:00
|
|
|
rpc.resolve_node(recipient_id).await.wrap_err(
|
|
|
|
"failed to resolve recipient node for relay, dropping outbound relayed packet",
|
|
|
|
)?
|
2022-04-03 16:58:06 +00:00
|
|
|
} else {
|
|
|
|
// If this is not a node in the client whitelist, only allow inbound relay
|
|
|
|
// which only performs a lightweight lookup before passing the packet back out
|
|
|
|
|
|
|
|
// See if we have the node in our routing table
|
|
|
|
// We should, because relays are chosen by nodes that have established connectivity and
|
|
|
|
// should be mutually in each others routing tables. The node needing the relay will be
|
|
|
|
// pinging this node regularly to keep itself in the routing table
|
2022-07-20 13:39:38 +00:00
|
|
|
routing_table.lookup_node_ref(recipient_id)
|
2022-04-03 16:58:06 +00:00
|
|
|
};
|
|
|
|
|
2022-07-20 13:39:38 +00:00
|
|
|
if let Some(relay_nr) = some_relay_nr {
|
|
|
|
// Relay the packet to the desired destination
|
|
|
|
log_net!("relaying {} bytes to {}", data.len(), relay_nr);
|
|
|
|
network_result_value_or_log!(debug self.send_data(relay_nr, data.to_vec())
|
|
|
|
.await
|
|
|
|
.wrap_err("failed to forward envelope")? => {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2022-04-03 16:58:06 +00:00
|
|
|
// Inform caller that we dealt with the envelope, but did not process it locally
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// DH to get decryption key (cached)
|
|
|
|
let node_id_secret = routing_table.node_id_secret();
|
|
|
|
|
|
|
|
// Decrypt the envelope body
|
|
|
|
// xxx: punish nodes that send messages that fail to decrypt eventually
|
|
|
|
let body = envelope
|
|
|
|
.decrypt_body(self.crypto(), data, &node_id_secret)
|
2022-07-10 21:36:50 +00:00
|
|
|
.wrap_err("failed to decrypt envelope body")?;
|
2022-04-03 16:58:06 +00:00
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// Cache the envelope information in the routing table
|
2022-07-20 13:39:38 +00:00
|
|
|
let source_noderef = match routing_table.register_node_with_existing_connection(
|
2022-07-10 21:36:50 +00:00
|
|
|
envelope.get_sender_id(),
|
2022-08-25 23:21:50 +00:00
|
|
|
connection_descriptor,
|
2022-07-10 21:36:50 +00:00
|
|
|
ts,
|
2022-07-20 13:39:38 +00:00
|
|
|
) {
|
|
|
|
None => {
|
|
|
|
// If the node couldn't be registered just skip this envelope,
|
|
|
|
// the error will have already been logged
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
Some(v) => v,
|
|
|
|
};
|
2022-08-31 01:21:16 +00:00
|
|
|
source_noderef.set_min_max_version(envelope.get_min_max_version());
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// xxx: deal with spoofing and flooding here?
|
|
|
|
|
|
|
|
// Pass message to RPC system
|
2022-10-30 02:15:50 +00:00
|
|
|
rpc.enqueue_direct_message(
|
2022-09-03 17:57:25 +00:00
|
|
|
envelope,
|
|
|
|
source_noderef,
|
|
|
|
connection_descriptor,
|
|
|
|
routing_domain,
|
2022-10-30 02:15:50 +00:00
|
|
|
body,
|
2022-09-03 17:57:25 +00:00
|
|
|
)?;
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
// Inform caller that we dealt with the envelope locally
|
|
|
|
Ok(true)
|
|
|
|
}
|
2022-03-19 22:19:40 +00:00
|
|
|
|
|
|
|
// Callbacks from low level network for statistics gathering
|
2022-03-20 14:52:03 +00:00
|
|
|
pub fn stats_packet_sent(&self, addr: IpAddr, bytes: u64) {
|
2022-03-19 22:19:40 +00:00
|
|
|
let inner = &mut *self.inner.lock();
|
|
|
|
inner
|
|
|
|
.stats
|
|
|
|
.self_stats
|
|
|
|
.transfer_stats_accounting
|
|
|
|
.add_up(bytes);
|
|
|
|
inner
|
|
|
|
.stats
|
|
|
|
.per_address_stats
|
2022-03-20 14:52:03 +00:00
|
|
|
.entry(PerAddressStatsKey(addr))
|
|
|
|
.or_insert(PerAddressStats::default())
|
2022-03-19 22:19:40 +00:00
|
|
|
.transfer_stats_accounting
|
|
|
|
.add_up(bytes);
|
|
|
|
}
|
|
|
|
|
2022-03-20 14:52:03 +00:00
|
|
|
pub fn stats_packet_rcvd(&self, addr: IpAddr, bytes: u64) {
|
2022-03-19 22:19:40 +00:00
|
|
|
let inner = &mut *self.inner.lock();
|
|
|
|
inner
|
|
|
|
.stats
|
|
|
|
.self_stats
|
|
|
|
.transfer_stats_accounting
|
|
|
|
.add_down(bytes);
|
|
|
|
inner
|
|
|
|
.stats
|
|
|
|
.per_address_stats
|
2022-03-20 14:52:03 +00:00
|
|
|
.entry(PerAddressStatsKey(addr))
|
|
|
|
.or_insert(PerAddressStats::default())
|
2022-03-19 22:19:40 +00:00
|
|
|
.transfer_stats_accounting
|
|
|
|
.add_down(bytes);
|
|
|
|
}
|
2022-04-23 01:30:09 +00:00
|
|
|
|
2022-05-16 15:52:48 +00:00
|
|
|
// Get stats
|
|
|
|
pub fn get_stats(&self) -> NetworkManagerStats {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
inner.stats.clone()
|
|
|
|
}
|
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
pub fn get_veilid_state(&self) -> VeilidStateNetwork {
|
|
|
|
let has_state = self
|
|
|
|
.unlocked_inner
|
|
|
|
.components
|
|
|
|
.read()
|
|
|
|
.as_ref()
|
|
|
|
.map(|c| c.net.is_started())
|
|
|
|
.unwrap_or(false);
|
2022-09-06 20:49:43 +00:00
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
if !has_state {
|
|
|
|
return VeilidStateNetwork {
|
2022-05-16 15:52:48 +00:00
|
|
|
started: false,
|
|
|
|
bps_down: 0,
|
|
|
|
bps_up: 0,
|
2022-09-06 20:49:43 +00:00
|
|
|
peers: Vec::new(),
|
2022-09-08 01:52:08 +00:00
|
|
|
};
|
2022-05-16 15:52:48 +00:00
|
|
|
}
|
2022-09-08 01:52:08 +00:00
|
|
|
let routing_table = self.routing_table();
|
2022-05-16 15:52:48 +00:00
|
|
|
|
2022-09-08 01:52:08 +00:00
|
|
|
let (bps_down, bps_up) = {
|
2022-05-16 15:52:48 +00:00
|
|
|
let inner = self.inner.lock();
|
2022-09-08 01:52:08 +00:00
|
|
|
(
|
|
|
|
inner.stats.self_stats.transfer_stats.down.average,
|
|
|
|
inner.stats.self_stats.transfer_stats.up.average,
|
|
|
|
)
|
2022-05-16 15:52:48 +00:00
|
|
|
};
|
2022-09-08 01:52:08 +00:00
|
|
|
|
|
|
|
VeilidStateNetwork {
|
|
|
|
started: true,
|
|
|
|
bps_down,
|
|
|
|
bps_up,
|
|
|
|
peers: {
|
|
|
|
let mut out = Vec::new();
|
|
|
|
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
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn send_network_update(&self) {
|
|
|
|
let update_cb = self.unlocked_inner.update_callback.read().clone();
|
|
|
|
if update_cb.is_none() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let state = self.get_veilid_state();
|
|
|
|
(update_cb.unwrap())(VeilidUpdate::Network(state));
|
2022-05-16 15:52:48 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 01:30:09 +00:00
|
|
|
// Determine if a local IP address has changed
|
|
|
|
// this means we should restart the low level network and and recreate all of our dial info
|
|
|
|
// Wait until we have received confirmation from N different peers
|
2022-09-03 17:57:25 +00:00
|
|
|
pub fn report_local_network_socket_address(
|
2022-04-23 01:30:09 +00:00
|
|
|
&self,
|
|
|
|
_socket_address: SocketAddress,
|
2022-08-09 00:42:27 +00:00
|
|
|
_connection_descriptor: ConnectionDescriptor,
|
2022-04-23 01:30:09 +00:00
|
|
|
_reporting_peer: NodeRef,
|
|
|
|
) {
|
|
|
|
// XXX: Nothing here yet.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine if a global IP address has changed
|
|
|
|
// this means we should recreate our public dial info if it is not static and rediscover it
|
|
|
|
// Wait until we have received confirmation from N different peers
|
2022-09-03 17:57:25 +00:00
|
|
|
pub fn report_public_internet_socket_address(
|
2022-04-23 01:30:09 +00:00
|
|
|
&self,
|
2022-08-09 00:42:27 +00:00
|
|
|
socket_address: SocketAddress, // the socket address as seen by the remote peer
|
|
|
|
connection_descriptor: ConnectionDescriptor, // the connection descriptor used
|
|
|
|
reporting_peer: NodeRef, // the peer's noderef reporting the socket address
|
2022-04-23 01:30:09 +00:00
|
|
|
) {
|
2022-08-22 17:27:26 +00:00
|
|
|
// debug code
|
|
|
|
//info!("report_global_socket_address\nsocket_address: {:#?}\nconnection_descriptor: {:#?}\nreporting_peer: {:#?}", socket_address, connection_descriptor, reporting_peer);
|
2022-08-20 21:08:48 +00:00
|
|
|
|
2022-08-28 17:13:09 +00:00
|
|
|
// Ignore these reports if we are currently detecting public dial info
|
2022-09-08 01:52:08 +00:00
|
|
|
let net = self.net();
|
2022-11-04 23:29:44 +00:00
|
|
|
if net.needs_public_dial_info_check() {
|
2022-08-28 17:13:09 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-09-08 01:52:08 +00:00
|
|
|
|
|
|
|
let routing_table = self.routing_table();
|
2022-10-10 02:07:15 +00:00
|
|
|
let (detect_address_changes, ip6_prefix_size) = self.with_config(|c| {
|
|
|
|
(
|
|
|
|
c.network.detect_address_changes,
|
|
|
|
c.network.max_connections_per_ip6_prefix_size as usize,
|
|
|
|
)
|
|
|
|
});
|
2022-08-28 17:13:09 +00:00
|
|
|
|
|
|
|
// Get the ip(block) this report is coming from
|
|
|
|
let ipblock = ip_to_ipblock(
|
|
|
|
ip6_prefix_size,
|
|
|
|
connection_descriptor.remote_address().to_ip_addr(),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Store the reported address if it isn't denylisted
|
2022-08-09 00:42:27 +00:00
|
|
|
let key = PublicAddressCheckCacheKey(
|
|
|
|
connection_descriptor.protocol_type(),
|
|
|
|
connection_descriptor.address_type(),
|
|
|
|
);
|
2022-09-08 01:52:08 +00:00
|
|
|
|
|
|
|
let mut inner = self.inner.lock();
|
|
|
|
let inner = &mut *inner;
|
|
|
|
|
2022-08-28 17:13:09 +00:00
|
|
|
let pacc = inner
|
|
|
|
.public_address_check_cache
|
|
|
|
.entry(key)
|
|
|
|
.or_insert_with(|| LruCache::new(PUBLIC_ADDRESS_CHECK_CACHE_SIZE));
|
|
|
|
let pait = inner
|
|
|
|
.public_address_inconsistencies_table
|
|
|
|
.entry(key)
|
|
|
|
.or_insert_with(|| HashMap::new());
|
|
|
|
if pait.contains_key(&ipblock) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pacc.insert(ipblock, socket_address);
|
2022-04-23 01:30:09 +00:00
|
|
|
|
2022-04-26 13:16:48 +00:00
|
|
|
// Determine if our external address has likely changed
|
2022-08-27 16:54:09 +00:00
|
|
|
let mut bad_public_address_detection_punishment: Option<
|
|
|
|
Box<dyn FnOnce() + Send + 'static>,
|
|
|
|
> = None;
|
2022-10-09 18:59:01 +00:00
|
|
|
let public_internet_network_class = routing_table
|
2022-08-31 01:21:16 +00:00
|
|
|
.get_network_class(RoutingDomain::PublicInternet)
|
|
|
|
.unwrap_or(NetworkClass::Invalid);
|
2022-08-22 17:27:26 +00:00
|
|
|
let needs_public_address_detection =
|
2022-08-31 01:21:16 +00:00
|
|
|
if matches!(public_internet_network_class, NetworkClass::InboundCapable) {
|
2022-08-22 17:27:26 +00:00
|
|
|
// Get the dial info filter for this connection so we can check if we have any public dialinfo that may have changed
|
|
|
|
let dial_info_filter = connection_descriptor.make_dial_info_filter();
|
|
|
|
|
|
|
|
// Get current external ip/port from registered global dialinfo
|
|
|
|
let current_addresses: BTreeSet<SocketAddress> = routing_table
|
|
|
|
.all_filtered_dial_info_details(
|
2022-09-04 18:17:28 +00:00
|
|
|
RoutingDomain::PublicInternet.into(),
|
2022-08-22 17:27:26 +00:00
|
|
|
&dial_info_filter,
|
|
|
|
)
|
|
|
|
.iter()
|
|
|
|
.map(|did| did.dial_info.socket_address())
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
// If we are inbound capable, but start to see inconsistent socket addresses from multiple reporting peers
|
|
|
|
// then we zap the network class and re-detect it
|
2022-08-27 02:52:08 +00:00
|
|
|
let mut inconsistencies = Vec::new();
|
2022-08-28 17:13:09 +00:00
|
|
|
|
2022-08-22 17:27:26 +00:00
|
|
|
// Iteration goes from most recent to least recent node/address pair
|
2022-08-27 02:52:08 +00:00
|
|
|
for (reporting_ip_block, a) in pacc {
|
|
|
|
// If this address is not one of our current addresses (inconsistent)
|
|
|
|
// and we haven't already denylisted the reporting source,
|
|
|
|
if !current_addresses.contains(a) && !pait.contains_key(reporting_ip_block) {
|
|
|
|
// Record the origin of the inconsistency
|
|
|
|
inconsistencies.push(*reporting_ip_block);
|
2022-08-27 16:54:09 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-27 02:52:08 +00:00
|
|
|
|
2022-08-27 16:54:09 +00:00
|
|
|
// If we have enough inconsistencies to consider changing our public dial info,
|
|
|
|
// add them to our denylist (throttling) and go ahead and check for new
|
|
|
|
// public dialinfo
|
|
|
|
let inconsistent = if inconsistencies.len() >= PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT
|
|
|
|
{
|
|
|
|
let exp_ts = intf::get_timestamp() + PUBLIC_ADDRESS_INCONSISTENCY_TIMEOUT_US;
|
|
|
|
for i in &inconsistencies {
|
|
|
|
pait.insert(*i, exp_ts);
|
|
|
|
}
|
2022-08-27 02:52:08 +00:00
|
|
|
|
2022-08-27 16:54:09 +00:00
|
|
|
// Run this routine if the inconsistent nodes turn out to be lying
|
|
|
|
let this = self.clone();
|
|
|
|
bad_public_address_detection_punishment = Some(Box::new(move || {
|
|
|
|
let mut inner = this.inner.lock();
|
|
|
|
let pait = inner
|
|
|
|
.public_address_inconsistencies_table
|
|
|
|
.entry(key)
|
|
|
|
.or_insert_with(|| HashMap::new());
|
|
|
|
let exp_ts = intf::get_timestamp()
|
|
|
|
+ PUBLIC_ADDRESS_INCONSISTENCY_PUNISHMENT_TIMEOUT_US;
|
|
|
|
for i in inconsistencies {
|
|
|
|
pait.insert(i, exp_ts);
|
2022-08-22 17:27:26 +00:00
|
|
|
}
|
2022-08-27 16:54:09 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
2022-08-22 17:27:26 +00:00
|
|
|
// // debug code
|
2022-08-27 16:54:09 +00:00
|
|
|
// if inconsistent {
|
2022-08-22 17:27:26 +00:00
|
|
|
// trace!("public_address_check_cache: {:#?}\ncurrent_addresses: {:#?}\ninconsistencies: {}", inner
|
|
|
|
// .public_address_check_cache, current_addresses, inconsistencies);
|
|
|
|
// }
|
2022-08-20 21:08:48 +00:00
|
|
|
|
2022-08-27 02:52:08 +00:00
|
|
|
inconsistent
|
2022-08-22 17:27:26 +00:00
|
|
|
} else {
|
|
|
|
// If we are currently outbound only, we don't have any public dial info
|
|
|
|
// but if we are starting to see consistent socket address from multiple reporting peers
|
|
|
|
// then we may be become inbound capable, so zap the network class so we can re-detect it and any public dial info
|
2022-08-20 21:08:48 +00:00
|
|
|
|
2022-08-22 17:27:26 +00:00
|
|
|
let mut consistencies = 0;
|
|
|
|
let mut consistent = false;
|
|
|
|
let mut current_address = Option::<SocketAddress>::None;
|
|
|
|
// Iteration goes from most recent to least recent node/address pair
|
|
|
|
let pacc = inner
|
|
|
|
.public_address_check_cache
|
|
|
|
.entry(key)
|
2022-08-27 02:52:08 +00:00
|
|
|
.or_insert_with(|| LruCache::new(PUBLIC_ADDRESS_CHECK_CACHE_SIZE));
|
2022-08-22 17:27:26 +00:00
|
|
|
|
|
|
|
for (_, a) in pacc {
|
|
|
|
if let Some(current_address) = current_address {
|
|
|
|
if current_address == *a {
|
|
|
|
consistencies += 1;
|
2022-08-27 02:52:08 +00:00
|
|
|
if consistencies >= PUBLIC_ADDRESS_CHANGE_DETECTION_COUNT {
|
2022-08-22 17:27:26 +00:00
|
|
|
consistent = true;
|
|
|
|
break;
|
|
|
|
}
|
2022-04-26 13:16:48 +00:00
|
|
|
}
|
2022-08-22 17:27:26 +00:00
|
|
|
} else {
|
|
|
|
current_address = Some(*a);
|
2022-04-26 13:16:48 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-22 17:27:26 +00:00
|
|
|
consistent
|
|
|
|
};
|
2022-04-26 13:16:48 +00:00
|
|
|
|
|
|
|
if needs_public_address_detection {
|
2022-08-07 18:55:48 +00:00
|
|
|
if detect_address_changes {
|
|
|
|
// Reset the address check cache now so we can start detecting fresh
|
|
|
|
info!("Public address has changed, detecting public dial info");
|
2022-08-07 00:55:24 +00:00
|
|
|
|
2022-08-07 18:55:48 +00:00
|
|
|
inner.public_address_check_cache.clear();
|
2022-04-23 01:30:09 +00:00
|
|
|
|
2022-08-27 16:54:09 +00:00
|
|
|
// Re-detect the public dialinfo
|
|
|
|
net.set_needs_public_dial_info_check(bad_public_address_detection_punishment);
|
2022-08-07 18:55:48 +00:00
|
|
|
} else {
|
|
|
|
warn!("Public address may have changed. Restarting the server may be required.");
|
2022-08-25 23:29:39 +00:00
|
|
|
warn!("report_global_socket_address\nsocket_address: {:#?}\nconnection_descriptor: {:#?}\nreporting_peer: {:#?}", socket_address, connection_descriptor, reporting_peer);
|
|
|
|
warn!(
|
2022-08-25 23:21:50 +00:00
|
|
|
"public_address_check_cache: {:#?}",
|
|
|
|
inner.public_address_check_cache
|
|
|
|
);
|
2022-08-07 18:55:48 +00:00
|
|
|
}
|
2022-04-23 01:30:09 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
|
|
|
|
// Inform routing table entries that our dial info has changed
|
2022-08-31 01:21:16 +00:00
|
|
|
pub async fn send_node_info_updates(&self, routing_domain: RoutingDomain, all: bool) {
|
2022-07-22 17:05:28 +00:00
|
|
|
let this = self.clone();
|
|
|
|
|
|
|
|
// Run in background only once
|
|
|
|
let _ = self
|
|
|
|
.clone()
|
|
|
|
.unlocked_inner
|
|
|
|
.node_info_update_single_future
|
2022-10-04 15:27:38 +00:00
|
|
|
.single_spawn(
|
|
|
|
async move {
|
|
|
|
// Only update if we actually have valid signed node info for this routing domain
|
|
|
|
if !this.routing_table().has_valid_own_node_info(routing_domain) {
|
|
|
|
trace!(
|
2022-07-22 17:05:28 +00:00
|
|
|
"not sending node info update because our network class is not yet valid"
|
|
|
|
);
|
2022-10-04 15:27:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
|
2022-10-04 15:27:38 +00:00
|
|
|
// Get the list of refs to all nodes to update
|
|
|
|
let cur_ts = intf::get_timestamp();
|
|
|
|
let node_refs =
|
|
|
|
this.routing_table()
|
|
|
|
.get_nodes_needing_updates(routing_domain, cur_ts, all);
|
|
|
|
|
|
|
|
// Send the updates
|
|
|
|
log_net!(debug "Sending node info updates to {} nodes", node_refs.len());
|
|
|
|
let mut unord = FuturesUnordered::new();
|
|
|
|
for nr in node_refs {
|
|
|
|
let rpc = this.rpc_processor();
|
|
|
|
unord.push(
|
|
|
|
async move {
|
|
|
|
// Update the node
|
|
|
|
if let Err(e) = rpc
|
|
|
|
.rpc_call_node_info_update(nr.clone(), routing_domain)
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
// Not fatal, but we should be able to see if this is happening
|
|
|
|
trace!("failed to send node info update to {:?}: {}", nr, e);
|
|
|
|
return;
|
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
|
2022-10-04 15:27:38 +00:00
|
|
|
// Mark the node as having seen our node info
|
|
|
|
nr.set_seen_our_node_info(routing_domain);
|
|
|
|
}
|
|
|
|
.instrument(Span::current()),
|
|
|
|
);
|
|
|
|
}
|
2022-07-22 17:05:28 +00:00
|
|
|
|
2022-10-04 15:27:38 +00:00
|
|
|
// Wait for futures to complete
|
|
|
|
while unord.next().await.is_some() {}
|
2022-07-22 17:05:28 +00:00
|
|
|
|
2022-10-04 15:27:38 +00:00
|
|
|
log_rtab!(debug "Finished sending node updates");
|
|
|
|
}
|
|
|
|
.instrument(Span::current()),
|
|
|
|
)
|
2022-07-22 17:05:28 +00:00
|
|
|
.await;
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|