checkpoint
This commit is contained in:
parent
e85d72f21a
commit
63768580c6
@ -63,7 +63,7 @@ core:
|
|||||||
max_timestamp_behind_ms: 10000
|
max_timestamp_behind_ms: 10000
|
||||||
max_timestamp_ahead_ms: 10000
|
max_timestamp_ahead_ms: 10000
|
||||||
timeout_ms: 10000
|
timeout_ms: 10000
|
||||||
max_route_hop_count: 7
|
max_route_hop_count: 5
|
||||||
default_route_hop_count: 2
|
default_route_hop_count: 2
|
||||||
|
|
||||||
dht:
|
dht:
|
||||||
|
@ -228,7 +228,7 @@ rpc:
|
|||||||
max_timestamp_behind_ms: 10000
|
max_timestamp_behind_ms: 10000
|
||||||
max_timestamp_ahead_ms: 10000
|
max_timestamp_ahead_ms: 10000
|
||||||
timeout_ms: 10000
|
timeout_ms: 10000
|
||||||
max_route_hop_count: 7
|
max_route_hop_count: 4
|
||||||
default_route_hop_count: 2
|
default_route_hop_count: 2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -218,17 +218,36 @@ impl RoutingTable {
|
|||||||
) -> core::cmp::Ordering,
|
) -> core::cmp::Ordering,
|
||||||
T: FnMut(&'a RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O,
|
T: FnMut(&'a RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O,
|
||||||
{
|
{
|
||||||
let inner = self.inner.read();
|
let inner = &*self.inner.read();
|
||||||
let inner = &*inner;
|
Self::find_peers_with_sort_and_filter_inner(
|
||||||
let self_node_id = self.unlocked_inner.node_id;
|
inner, node_count, cur_ts, filter, compare, transform,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_peers_with_sort_and_filter_inner<'a, 'b, F, C, T, O>(
|
||||||
|
inner: &RoutingTableInner,
|
||||||
|
node_count: usize,
|
||||||
|
cur_ts: u64,
|
||||||
|
mut filter: F,
|
||||||
|
compare: C,
|
||||||
|
mut transform: T,
|
||||||
|
) -> Vec<O>
|
||||||
|
where
|
||||||
|
F: FnMut(&'a RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> bool,
|
||||||
|
C: FnMut(
|
||||||
|
&'a RoutingTableInner,
|
||||||
|
&'b (DHTKey, Option<Arc<BucketEntry>>),
|
||||||
|
&'b (DHTKey, Option<Arc<BucketEntry>>),
|
||||||
|
) -> core::cmp::Ordering,
|
||||||
|
T: FnMut(&'a RoutingTableInner, DHTKey, Option<Arc<BucketEntry>>) -> O,
|
||||||
|
{
|
||||||
// collect all the nodes for sorting
|
// collect all the nodes for sorting
|
||||||
let mut nodes =
|
let mut nodes =
|
||||||
Vec::<(DHTKey, Option<Arc<BucketEntry>>)>::with_capacity(inner.bucket_entry_count + 1);
|
Vec::<(DHTKey, Option<Arc<BucketEntry>>)>::with_capacity(inner.bucket_entry_count + 1);
|
||||||
|
|
||||||
// add our own node (only one of there with the None entry)
|
// add our own node (only one of there with the None entry)
|
||||||
if filter(inner, self_node_id, None) {
|
if filter(inner, inner.node_id, None) {
|
||||||
nodes.push((self_node_id, None));
|
nodes.push((inner.node_id, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add all nodes from buckets
|
// add all nodes from buckets
|
||||||
|
@ -219,18 +219,18 @@ impl RoutingTable {
|
|||||||
|
|
||||||
pub fn with_route_spec_store_mut<F, R>(&self, f: F) -> R
|
pub fn with_route_spec_store_mut<F, R>(&self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut RouteSpecStore) -> R,
|
F: FnOnce(&mut RouteSpecStore, &mut RoutingTableInner) -> R,
|
||||||
{
|
{
|
||||||
let inner = self.inner.write();
|
let inner = &mut *self.inner.write();
|
||||||
f(&mut inner.route_spec_store)
|
f(&mut inner.route_spec_store, inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_route_spec_store<F, R>(&self, f: F) -> R
|
pub fn with_route_spec_store<F, R>(&self, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&RouteSpecStore) -> R,
|
F: FnOnce(&RouteSpecStore, &RoutingTableInner) -> R,
|
||||||
{
|
{
|
||||||
let inner = self.inner.read();
|
let inner = &*self.inner.read();
|
||||||
f(&inner.route_spec_store)
|
f(&inner.route_spec_store, inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
||||||
@ -339,6 +339,30 @@ impl RoutingTable {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(inner), ret)]
|
||||||
|
fn get_contact_method_inner(
|
||||||
|
inner: &RoutingTableInner,
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
|
node_a_id: &DHTKey,
|
||||||
|
node_a: &NodeInfo,
|
||||||
|
node_b_id: &DHTKey,
|
||||||
|
node_b: &NodeInfo,
|
||||||
|
dial_info_filter: DialInfoFilter,
|
||||||
|
reliable: bool,
|
||||||
|
) -> ContactMethod {
|
||||||
|
Self::with_routing_domain(inner, routing_domain, |rdd| {
|
||||||
|
rdd.get_contact_method(
|
||||||
|
inner,
|
||||||
|
node_a_id,
|
||||||
|
node_a,
|
||||||
|
node_b_id,
|
||||||
|
node_b,
|
||||||
|
dial_info_filter,
|
||||||
|
reliable,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Look up the best way for two nodes to reach each other over a specific routing domain
|
/// Look up the best way for two nodes to reach each other over a specific routing domain
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub fn get_contact_method(
|
pub fn get_contact_method(
|
||||||
@ -352,17 +376,16 @@ impl RoutingTable {
|
|||||||
reliable: bool,
|
reliable: bool,
|
||||||
) -> ContactMethod {
|
) -> ContactMethod {
|
||||||
let inner = &*self.inner.read();
|
let inner = &*self.inner.read();
|
||||||
Self::with_routing_domain(inner, routing_domain, |rdd| {
|
Self::get_contact_method_inner(
|
||||||
rdd.get_contact_method(
|
inner,
|
||||||
inner,
|
routing_domain,
|
||||||
node_a_id,
|
node_a_id,
|
||||||
node_a,
|
node_a,
|
||||||
node_b_id,
|
node_b_id,
|
||||||
node_b,
|
node_b,
|
||||||
dial_info_filter,
|
dial_info_filter,
|
||||||
reliable,
|
reliable,
|
||||||
)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out how to reach a node from our own node over the best routing domain and reference the nodes we want to access
|
// Figure out how to reach a node from our own node over the best routing domain and reference the nodes we want to access
|
||||||
@ -384,11 +407,11 @@ impl RoutingTable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Node A is our own node
|
// Node A is our own node
|
||||||
let node_a = self.get_own_node_info(routing_domain);
|
let node_a = get_own_node_info_inner(inner, routing_domain);
|
||||||
let node_a_id = self.node_id();
|
let node_a_id = self.node_id();
|
||||||
|
|
||||||
// Node B is the target node
|
// Node B is the target node
|
||||||
let node_b = target_node_ref.operate(|_rti, e| e.node_info(routing_domain).unwrap());
|
let node_b = target_node_ref.xxx operate(|_rti, e| e.node_info(routing_domain).unwrap());
|
||||||
let node_b_id = target_node_ref.node_id();
|
let node_b_id = target_node_ref.node_id();
|
||||||
|
|
||||||
// Dial info filter comes from the target node ref
|
// Dial info filter comes from the target node ref
|
||||||
@ -411,8 +434,7 @@ impl RoutingTable {
|
|||||||
ContactMethod::Existing => NodeContactMethod::Existing,
|
ContactMethod::Existing => NodeContactMethod::Existing,
|
||||||
ContactMethod::Direct(di) => NodeContactMethod::Direct(di),
|
ContactMethod::Direct(di) => NodeContactMethod::Direct(di),
|
||||||
ContactMethod::SignalReverse(relay_key, target_key) => {
|
ContactMethod::SignalReverse(relay_key, target_key) => {
|
||||||
let relay_nr = self
|
let relay_nr = Self::lookup_and_filter_noderef_inner(inner, self.clone(), relay_key, routing_domain.into(), dial_info_filter)
|
||||||
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
||||||
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
||||||
if target_node_ref.node_id() != target_key {
|
if target_node_ref.node_id() != target_key {
|
||||||
bail!("target noderef didn't match target key");
|
bail!("target noderef didn't match target key");
|
||||||
@ -420,8 +442,7 @@ impl RoutingTable {
|
|||||||
NodeContactMethod::SignalReverse(relay_nr, target_node_ref)
|
NodeContactMethod::SignalReverse(relay_nr, target_node_ref)
|
||||||
}
|
}
|
||||||
ContactMethod::SignalHolePunch(relay_key, target_key) => {
|
ContactMethod::SignalHolePunch(relay_key, target_key) => {
|
||||||
let relay_nr = self
|
let relay_nr = Self::lookup_and_filter_noderef_inner(inner, self.clone(), relay_key, routing_domain.into(), dial_info_filter)
|
||||||
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
||||||
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
||||||
if target_node_ref.node_id() != target_key {
|
if target_node_ref.node_id() != target_key {
|
||||||
bail!("target noderef didn't match target key");
|
bail!("target noderef didn't match target key");
|
||||||
@ -429,14 +450,12 @@ impl RoutingTable {
|
|||||||
NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref)
|
NodeContactMethod::SignalHolePunch(relay_nr, target_node_ref)
|
||||||
}
|
}
|
||||||
ContactMethod::InboundRelay(relay_key) => {
|
ContactMethod::InboundRelay(relay_key) => {
|
||||||
let relay_nr = self
|
let relay_nr = Self::lookup_and_filter_noderef_nner(inner, self.clone(), relay_key, routing_domain.into(), dial_info_filter)
|
||||||
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
||||||
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
||||||
NodeContactMethod::InboundRelay(relay_nr)
|
NodeContactMethod::InboundRelay(relay_nr)
|
||||||
}
|
}
|
||||||
ContactMethod::OutboundRelay(relay_key) => {
|
ContactMethod::OutboundRelay(relay_key) => {
|
||||||
let relay_nr = self
|
let relay_nr = Self::lookup_and_filter_noderef(inner, self.clone(), relay_key, routing_domain.into(), dial_info_filter)
|
||||||
.lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)
|
|
||||||
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
.ok_or_else(|| eyre!("couldn't look up relay"))?;
|
||||||
NodeContactMethod::OutboundRelay(relay_nr)
|
NodeContactMethod::OutboundRelay(relay_nr)
|
||||||
}
|
}
|
||||||
@ -486,13 +505,19 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return a copy of our node's nodeinfo
|
/// Return a copy of our node's nodeinfo
|
||||||
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
|
fn get_own_node_info_inner(
|
||||||
let inner = &*self.inner.read();
|
inner: &RoutingTableInner,
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
|
) -> NodeInfo {
|
||||||
Self::with_routing_domain(inner, routing_domain, |rdd| {
|
Self::with_routing_domain(inner, routing_domain, |rdd| {
|
||||||
rdd.common()
|
rdd.common()
|
||||||
.with_peer_info(|pi| pi.signed_node_info.node_info.clone())
|
.with_peer_info(|pi| pi.signed_node_info.node_info.clone())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
|
||||||
|
let inner = &*self.inner.read();
|
||||||
|
Self::get_own_node_info_inner(inner, routing_domain)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return our currently registered network class
|
/// Return our currently registered network class
|
||||||
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||||
@ -880,6 +905,15 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve an existing routing table entry and return a reference to it
|
/// Resolve an existing routing table entry and return a reference to it
|
||||||
|
fn lookup_node_ref_inner(inner: &RoutingTableInner, routing_table: RoutingTable, node_id: DHTKey) -> Option<NodeRef> {
|
||||||
|
{
|
||||||
|
let idx = routing_table.find_bucket_index(node_id);
|
||||||
|
let bucket = &inner.buckets[idx];
|
||||||
|
bucket
|
||||||
|
.entry(&node_id)
|
||||||
|
.map(|e| NodeRef::new(routing_table, node_id, e, None))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn lookup_node_ref(&self, node_id: DHTKey) -> Option<NodeRef> {
|
pub fn lookup_node_ref(&self, node_id: DHTKey) -> Option<NodeRef> {
|
||||||
if node_id == self.unlocked_inner.node_id {
|
if node_id == self.unlocked_inner.node_id {
|
||||||
log_rtab!(debug "can't look up own node id in routing table");
|
log_rtab!(debug "can't look up own node id in routing table");
|
||||||
|
@ -5,6 +5,8 @@ use serde::*;
|
|||||||
/// Options for safety routes (sender privacy)
|
/// Options for safety routes (sender privacy)
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct SafetySpec {
|
pub struct SafetySpec {
|
||||||
|
/// preferred safety route if it still exists
|
||||||
|
pub preferred_route: Option<DHTKey>,
|
||||||
/// 0 = no safety route, just use node's node id, more hops is safer but slower
|
/// 0 = no safety route, just use node's node id, more hops is safer but slower
|
||||||
pub hop_count: usize,
|
pub hop_count: usize,
|
||||||
/// prefer more reliable protocols and relays over faster ones
|
/// prefer more reliable protocols and relays over faster ones
|
||||||
@ -76,6 +78,10 @@ pub struct RouteSpecStoreCache {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouteSpecStore {
|
pub struct RouteSpecStore {
|
||||||
|
/// Our node id
|
||||||
|
node_id: DHTKey,
|
||||||
|
/// Our node id secret
|
||||||
|
node_id_secret: DHTKeySecret,
|
||||||
/// Maximum number of hops in a route
|
/// Maximum number of hops in a route
|
||||||
max_route_hop_count: usize,
|
max_route_hop_count: usize,
|
||||||
/// Default number of hops in a route
|
/// Default number of hops in a route
|
||||||
@ -83,7 +89,7 @@ pub struct RouteSpecStore {
|
|||||||
/// Serialize RouteSpecStore content
|
/// Serialize RouteSpecStore content
|
||||||
content: RouteSpecStoreContent,
|
content: RouteSpecStoreContent,
|
||||||
/// RouteSpecStore cache
|
/// RouteSpecStore cache
|
||||||
cache: Mutex<RouteSpecStoreCache>,
|
cache: RouteSpecStoreCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
|
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
|
||||||
@ -170,16 +176,13 @@ where
|
|||||||
|
|
||||||
impl RouteSpecStore {
|
impl RouteSpecStore {
|
||||||
pub fn new(config: VeilidConfig) -> Self {
|
pub fn new(config: VeilidConfig) -> Self {
|
||||||
let (max_route_hop_count, default_route_hop_count) = {
|
let c = config.get();
|
||||||
let c = config.get();
|
|
||||||
let max_route_hop_count = c.network.rpc.max_route_hop_count;
|
|
||||||
let default_route_hop_count = c.network.rpc.max_route_hop_count;
|
|
||||||
(max_route_hop_count.into(), default_route_hop_count.into())
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
max_route_hop_count,
|
node_id: c.network.node_id,
|
||||||
default_route_hop_count,
|
node_id_secret: c.network.node_id_secret,
|
||||||
|
max_route_hop_count: c.network.rpc.max_route_hop_count.into(),
|
||||||
|
default_route_hop_count: c.network.rpc.default_route_hop_count.into(),
|
||||||
content: RouteSpecStoreContent {
|
content: RouteSpecStoreContent {
|
||||||
details: HashMap::new(),
|
details: HashMap::new(),
|
||||||
},
|
},
|
||||||
@ -188,20 +191,17 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load(routing_table: RoutingTable) -> EyreResult<RouteSpecStore> {
|
pub async fn load(routing_table: RoutingTable) -> EyreResult<RouteSpecStore> {
|
||||||
let (max_route_hop_count, default_route_hop_count) = {
|
let config = routing_table.network_manager().config();
|
||||||
let c = routing_table.unlocked_inner.config.get();
|
let c = config.get();
|
||||||
let max_route_hop_count = c.network.rpc.max_route_hop_count;
|
|
||||||
let default_route_hop_count = c.network.rpc.max_route_hop_count;
|
|
||||||
(max_route_hop_count.into(), default_route_hop_count.into())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get cbor blob from table store
|
// Get cbor blob from table store
|
||||||
let table_store = routing_table.network_manager().table_store();
|
let table_store = routing_table.network_manager().table_store();
|
||||||
let rsstdb = table_store.open("RouteSpecStore", 1).await?;
|
let rsstdb = table_store.open("RouteSpecStore", 1).await?;
|
||||||
let content = rsstdb.load_cbor(0, b"content").await?.unwrap_or_default();
|
let content = rsstdb.load_cbor(0, b"content").await?.unwrap_or_default();
|
||||||
let mut rss = RouteSpecStore {
|
let mut rss = RouteSpecStore {
|
||||||
max_route_hop_count,
|
node_id: c.network.node_id,
|
||||||
default_route_hop_count,
|
node_id_secret: c.network.node_id_secret,
|
||||||
|
max_route_hop_count: c.network.rpc.max_route_hop_count.into(),
|
||||||
|
default_route_hop_count: c.network.rpc.default_route_hop_count.into(),
|
||||||
content,
|
content,
|
||||||
cache: Default::default(),
|
cache: Default::default(),
|
||||||
};
|
};
|
||||||
@ -284,17 +284,17 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detail_mut(&mut self, public_key: &DHTKey) -> &mut RouteSpecDetail {
|
fn detail_mut(&mut self, public_key: &DHTKey) -> Option<&mut RouteSpecDetail> {
|
||||||
self.content.details.get_mut(&public_key).unwrap()
|
self.content.details.get_mut(&public_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new route
|
/// Create a new route
|
||||||
/// Prefers nodes that are not currently in use by another route
|
/// Prefers nodes that are not currently in use by another route
|
||||||
/// The route is not yet tested for its reachability
|
/// The route is not yet tested for its reachability
|
||||||
/// Returns None if no route could be allocated at this time
|
/// Returns None if no route could be allocated at this time
|
||||||
pub async fn allocate_route(
|
pub fn allocate_route(
|
||||||
&mut self,
|
&mut self,
|
||||||
routing_table: RoutingTable,
|
rti: &RoutingTableInner,
|
||||||
reliable: bool,
|
reliable: bool,
|
||||||
hop_count: usize,
|
hop_count: usize,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
@ -309,10 +309,6 @@ impl RouteSpecStore {
|
|||||||
bail!("Not allocating route longer than max route hop count");
|
bail!("Not allocating route longer than max route hop count");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock routing table for reading, make sure things don't change
|
|
||||||
// because we want to iterate the table without changes being made to it
|
|
||||||
let rti = routing_table.inner.read();
|
|
||||||
|
|
||||||
// Get list of all nodes, and sort them for selection
|
// Get list of all nodes, and sort them for selection
|
||||||
let cur_ts = intf::get_timestamp();
|
let cur_ts = intf::get_timestamp();
|
||||||
let dial_info_sort = if reliable {
|
let dial_info_sort = if reliable {
|
||||||
@ -417,12 +413,20 @@ impl RouteSpecStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Pull the whole routing table in sorted order
|
// Pull the whole routing table in sorted order
|
||||||
let node_count = routing_table.get_entry_count(
|
let node_count = RoutingTable::get_entry_count_inner(
|
||||||
|
rti,
|
||||||
RoutingDomain::PublicInternet.into(),
|
RoutingDomain::PublicInternet.into(),
|
||||||
BucketEntryState::Unreliable,
|
BucketEntryState::Unreliable,
|
||||||
);
|
);
|
||||||
let nodes = routing_table
|
let nodes = RoutingTable::find_peers_with_sort_and_filter_inner(
|
||||||
.find_peers_with_sort_and_filter(node_count, cur_ts, filter, compare, transform);
|
rti,
|
||||||
|
self.node_id,
|
||||||
|
node_count,
|
||||||
|
cur_ts,
|
||||||
|
filter,
|
||||||
|
compare,
|
||||||
|
transform,
|
||||||
|
);
|
||||||
|
|
||||||
// If we couldn't find enough nodes, wait until we have more nodes in the routing table
|
// If we couldn't find enough nodes, wait until we have more nodes in the routing table
|
||||||
if nodes.len() < hop_count {
|
if nodes.len() < hop_count {
|
||||||
@ -447,13 +451,14 @@ impl RouteSpecStore {
|
|||||||
// Ensure this route is viable by checking that each node can contact the next one
|
// Ensure this route is viable by checking that each node can contact the next one
|
||||||
if directions.contains(Direction::Outbound) {
|
if directions.contains(Direction::Outbound) {
|
||||||
let our_node_info =
|
let our_node_info =
|
||||||
routing_table.get_own_node_info(RoutingDomain::PublicInternet);
|
RoutingTable::get_own_node_info_inner(rti, RoutingDomain::PublicInternet);
|
||||||
let our_node_id = routing_table.node_id();
|
let our_node_id = self.node_id;
|
||||||
let mut previous_node = &(our_node_id, our_node_info);
|
let mut previous_node = &(our_node_id, our_node_info);
|
||||||
let mut reachable = true;
|
let mut reachable = true;
|
||||||
for n in permutation {
|
for n in permutation {
|
||||||
let current_node = nodes.get(*n).unwrap();
|
let current_node = nodes.get(*n).unwrap();
|
||||||
let cm = routing_table.get_contact_method(
|
let cm = RoutingTable::get_contact_method_inner(
|
||||||
|
rti,
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
&previous_node.0,
|
&previous_node.0,
|
||||||
&previous_node.1,
|
&previous_node.1,
|
||||||
@ -474,13 +479,14 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
if directions.contains(Direction::Inbound) {
|
if directions.contains(Direction::Inbound) {
|
||||||
let our_node_info =
|
let our_node_info =
|
||||||
routing_table.get_own_node_info(RoutingDomain::PublicInternet);
|
RoutingTable::get_own_node_info_inner(rti, RoutingDomain::PublicInternet);
|
||||||
let our_node_id = routing_table.node_id();
|
let our_node_id = self.node_id;
|
||||||
let mut next_node = &(our_node_id, our_node_info);
|
let mut next_node = &(our_node_id, our_node_info);
|
||||||
let mut reachable = true;
|
let mut reachable = true;
|
||||||
for n in permutation.iter().rev() {
|
for n in permutation.iter().rev() {
|
||||||
let current_node = nodes.get(*n).unwrap();
|
let current_node = nodes.get(*n).unwrap();
|
||||||
let cm = routing_table.get_contact_method(
|
let cm = RoutingTable::get_contact_method_inner(
|
||||||
|
rti,
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
&next_node.0,
|
&next_node.0,
|
||||||
&next_node.1,
|
&next_node.1,
|
||||||
@ -608,20 +614,53 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Compiles a safety route to the private route, with caching
|
/// Compiles a safety route to the private route, with caching
|
||||||
pub fn compile_safety_route(
|
pub fn compile_safety_route(
|
||||||
&self,
|
&mut self,
|
||||||
|
rti: &RoutingTableInner,
|
||||||
safety_spec: SafetySpec,
|
safety_spec: SafetySpec,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
) -> Result<CompiledRoute, RPCError> {
|
) -> Result<CompiledRoute, RPCError> {
|
||||||
|
let pr_hopcount = private_route.hop_count as usize;
|
||||||
|
if pr_hopcount > self.max_route_hop_count {
|
||||||
|
return Err(RPCError::internal("private route hop count too long"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the preferred route is here
|
||||||
|
let opt_safety_rsd: Option<&mut RouteSpecDetail> =
|
||||||
|
if let Some(preferred_route) = safety_spec.preferred_route {
|
||||||
|
self.detail_mut(&preferred_route)
|
||||||
|
} else {
|
||||||
|
// Preferred safety route was not requested
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let safety_rsd: &mut RouteSpecDetail = if let Some(safety_rsd) = opt_safety_rsd {
|
||||||
|
// Safety route exists
|
||||||
|
safety_rsd
|
||||||
|
} else {
|
||||||
|
// Select a safety route from the pool or make one if we don't have one that matches
|
||||||
|
if let Some(sr_pubkey) = self.first_unpublished_route(
|
||||||
|
safety_spec.reliable,
|
||||||
|
safety_spec.hop_count,
|
||||||
|
safety_spec.hop_count,
|
||||||
|
Direction::Outbound.into(),
|
||||||
|
) {
|
||||||
|
// Found a route to use
|
||||||
|
self.detail_mut(&sr_pubkey).unwrap()
|
||||||
|
} else {
|
||||||
|
// No route found, gotta allocate one
|
||||||
|
self.allocate_route(rti)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// xxx implement caching first!
|
// xxx implement caching first!
|
||||||
|
|
||||||
// xxx implement, ensure we handle hops == 0 for our safetyspec
|
// xxx implement, ensure we handle hops == 0 for our safetyspec
|
||||||
|
|
||||||
// Ensure the total hop count isn't too long for our config
|
// Ensure the total hop count isn't too long for our config
|
||||||
let pr_hopcount = private_route.hop_count as usize;
|
let sr_hopcount = safety_spec.hop_count;
|
||||||
let sr_hopcount = safety_route_spec.hops.len();
|
if sr_hopcount > self.max_route_hop_count {
|
||||||
let hopcount = 1 + sr_hopcount + pr_hopcount;
|
return Err(RPCError::internal("private route hop count too long"));
|
||||||
if hopcount > self.max_route_hop_count {
|
|
||||||
return Err(RPCError::internal("hop count too long for route"));
|
|
||||||
}
|
}
|
||||||
|
let total_hopcount = sr_hopcount + pr_hopcount;
|
||||||
|
|
||||||
// Create hops
|
// Create hops
|
||||||
let hops = if sr_hopcount == 0 {
|
let hops = if sr_hopcount == 0 {
|
||||||
@ -719,41 +758,66 @@ impl RouteSpecStore {
|
|||||||
/// Mark route as published
|
/// Mark route as published
|
||||||
/// When first deserialized, routes must be re-published in order to ensure they remain
|
/// When first deserialized, routes must be re-published in order to ensure they remain
|
||||||
/// in the RouteSpecStore.
|
/// in the RouteSpecStore.
|
||||||
pub fn mark_route_published(&mut self, key: &DHTKey) {
|
pub fn mark_route_published(&mut self, key: &DHTKey) -> EyreResult<()> {
|
||||||
self.detail_mut(&key).published = true;
|
self.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.published = true;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark route as checked
|
/// Mark route as checked
|
||||||
pub fn touch_route_checked(&mut self, key: &DHTKey, cur_ts: u64) {
|
pub fn touch_route_checked(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
||||||
self.detail_mut(&key).last_checked_ts = Some(cur_ts);
|
self.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.last_checked_ts = Some(cur_ts);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark route as used
|
/// Mark route as used
|
||||||
pub fn touch_route_used(&mut self, key: &DHTKey, cur_ts: u64) {
|
pub fn touch_route_used(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
||||||
self.detail_mut(&key).last_used_ts = Some(cur_ts);
|
self.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.last_used_ts = Some(cur_ts);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Record latency on the route
|
/// Record latency on the route
|
||||||
pub fn record_latency(&mut self, key: &DHTKey, latency: u64) {
|
pub fn record_latency(&mut self, key: &DHTKey, latency: u64) -> EyreResult<()> {
|
||||||
let lsa = &mut self.detail_mut(&key).latency_stats_accounting;
|
let lsa = &mut self
|
||||||
|
.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.latency_stats_accounting;
|
||||||
self.detail_mut(&key).latency_stats = lsa.record_latency(latency);
|
self.detail_mut(&key).latency_stats = lsa.record_latency(latency);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the calculated latency stats
|
/// Get the calculated latency stats
|
||||||
pub fn latency_stats(&self, key: &DHTKey) -> LatencyStats {
|
pub fn latency_stats(&mut self, key: &DHTKey) -> EyreResult<LatencyStats> {
|
||||||
self.detail_mut(&key).latency_stats.clone()
|
Ok(self
|
||||||
|
.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.latency_stats
|
||||||
|
.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add download transfers to route
|
/// Add download transfers to route
|
||||||
pub fn add_down(&mut self, key: &DHTKey, bytes: u64) {
|
pub fn add_down(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
||||||
let tsa = &mut self.detail_mut(&key).transfer_stats_accounting;
|
let tsa = &mut self
|
||||||
|
.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.transfer_stats_accounting;
|
||||||
tsa.add_down(bytes);
|
tsa.add_down(bytes);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add upload transfers to route
|
/// Add upload transfers to route
|
||||||
pub fn add_up(&mut self, key: &DHTKey, bytes: u64) {
|
pub fn add_up(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
||||||
let tsa = &mut self.detail_mut(&key).transfer_stats_accounting;
|
let tsa = &mut self
|
||||||
|
.detail_mut(&key)
|
||||||
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
|
.transfer_stats_accounting;
|
||||||
tsa.add_up(bytes);
|
tsa.add_up(bytes);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process transfer statistics to get averages
|
/// Process transfer statistics to get averages
|
||||||
|
@ -8,8 +8,7 @@ pub enum Destination {
|
|||||||
/// The node to send to
|
/// The node to send to
|
||||||
target: NodeRef,
|
target: NodeRef,
|
||||||
/// Require safety route or not
|
/// Require safety route or not
|
||||||
xxx convert back to safety spec, bubble up to api
|
safety: Option<SafetySpec>,
|
||||||
safety: bool,
|
|
||||||
},
|
},
|
||||||
/// Send to node for relay purposes
|
/// Send to node for relay purposes
|
||||||
Relay {
|
Relay {
|
||||||
@ -18,14 +17,14 @@ pub enum Destination {
|
|||||||
/// The final destination the relay should send to
|
/// The final destination the relay should send to
|
||||||
target: DHTKey,
|
target: DHTKey,
|
||||||
/// Require safety route or not
|
/// Require safety route or not
|
||||||
safety: bool,
|
safety: Option<SafetySpec>,
|
||||||
},
|
},
|
||||||
/// Send to private route (privateroute)
|
/// Send to private route (privateroute)
|
||||||
PrivateRoute {
|
PrivateRoute {
|
||||||
/// A private route to send to
|
/// A private route to send to
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
/// Require safety route or not
|
/// Require safety route or not
|
||||||
safety: bool,
|
safety: Option<SafetySpec>,
|
||||||
/// Prefer reliability or not
|
/// Prefer reliability or not
|
||||||
reliable: bool,
|
reliable: bool,
|
||||||
},
|
},
|
||||||
@ -35,29 +34,29 @@ impl Destination {
|
|||||||
pub fn direct(target: NodeRef) -> Self {
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
Self::Direct {
|
Self::Direct {
|
||||||
target,
|
target,
|
||||||
safety: false,
|
safety: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
||||||
Self::Relay {
|
Self::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety: false,
|
safety: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn private_route(private_route: PrivateRoute, reliable: bool) -> Self {
|
pub fn private_route(private_route: PrivateRoute, reliable: bool) -> Self {
|
||||||
Self::PrivateRoute {
|
Self::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety: false,
|
safety: None,
|
||||||
reliable,
|
reliable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_safety(self) -> Self {
|
pub fn with_safety(self, spec: SafetySpec) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Destination::Direct { target, safety: _ } => Self::Direct {
|
Destination::Direct { target, safety: _ } => Self::Direct {
|
||||||
target,
|
target,
|
||||||
safety: true,
|
safety: Some(spec),
|
||||||
},
|
},
|
||||||
Destination::Relay {
|
Destination::Relay {
|
||||||
relay,
|
relay,
|
||||||
@ -66,7 +65,7 @@ impl Destination {
|
|||||||
} => Self::Relay {
|
} => Self::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety: true,
|
safety: Some(spec),
|
||||||
},
|
},
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
@ -74,7 +73,7 @@ impl Destination {
|
|||||||
reliable,
|
reliable,
|
||||||
} => Self::PrivateRoute {
|
} => Self::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety: true,
|
safety: Some(spec),
|
||||||
reliable,
|
reliable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -85,7 +84,7 @@ impl fmt::Display for Destination {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Destination::Direct { target, safety } => {
|
Destination::Direct { target, safety } => {
|
||||||
let sr = if *safety { "+SR" } else { "" };
|
let sr = if safety.is_some() { "+SR" } else { "" };
|
||||||
|
|
||||||
write!(f, "{}{}", target, sr)
|
write!(f, "{}{}", target, sr)
|
||||||
}
|
}
|
||||||
@ -94,7 +93,7 @@ impl fmt::Display for Destination {
|
|||||||
target,
|
target,
|
||||||
safety,
|
safety,
|
||||||
} => {
|
} => {
|
||||||
let sr = if *safety { "+SR" } else { "" };
|
let sr = if safety.is_some() { "+SR" } else { "" };
|
||||||
|
|
||||||
write!(f, "{}@{}{}", target.encode(), relay, sr)
|
write!(f, "{}@{}{}", target.encode(), relay, sr)
|
||||||
}
|
}
|
||||||
@ -103,7 +102,7 @@ impl fmt::Display for Destination {
|
|||||||
safety,
|
safety,
|
||||||
reliable,
|
reliable,
|
||||||
} => {
|
} => {
|
||||||
let sr = if *safety { "+SR" } else { "" };
|
let sr = if safety.is_some() { "+SR" } else { "" };
|
||||||
let rl = if *reliable { "+RL" } else { "" };
|
let rl = if *reliable { "+RL" } else { "" };
|
||||||
|
|
||||||
write!(f, "{}{}{}", private_route, sr, rl)
|
write!(f, "{}{}{}", private_route, sr, rl)
|
||||||
|
@ -409,13 +409,6 @@ impl RPCProcessor {
|
|||||||
rss.compile_safety_route(safety_spec, private_route)
|
rss.compile_safety_route(safety_spec, private_route)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Verify hop count isn't larger than out maximum routed hop count
|
|
||||||
if compiled_route.safety_route.hop_count as usize > self.unlocked_inner.max_route_hop_count
|
|
||||||
{
|
|
||||||
return Err(RPCError::internal("hop count too long for route"))
|
|
||||||
.map_err(logthru_rpc!(warn));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt routed operation
|
// Encrypt routed operation
|
||||||
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
||||||
let nonce = Crypto::get_random_nonce();
|
let nonce = Crypto::get_random_nonce();
|
||||||
@ -613,17 +606,6 @@ impl RPCProcessor {
|
|||||||
hop_count,
|
hop_count,
|
||||||
} = self.render_operation(dest, &operation)?;
|
} = self.render_operation(dest, &operation)?;
|
||||||
|
|
||||||
// If we need to resolve the first hop, do it
|
|
||||||
let node_ref = match node_ref {
|
|
||||||
None => match self.resolve_node(node_id).await? {
|
|
||||||
None => {
|
|
||||||
return Ok(NetworkResult::no_connection_other(node_id));
|
|
||||||
}
|
|
||||||
Some(nr) => nr,
|
|
||||||
},
|
|
||||||
Some(nr) => nr,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate answer timeout
|
// Calculate answer timeout
|
||||||
// Timeout is number of hops times the timeout per hop
|
// Timeout is number of hops times the timeout per hop
|
||||||
let timeout = self.unlocked_inner.timeout * (hop_count as u64);
|
let timeout = self.unlocked_inner.timeout * (hop_count as u64);
|
||||||
@ -687,17 +669,6 @@ impl RPCProcessor {
|
|||||||
hop_count: _,
|
hop_count: _,
|
||||||
} = self.render_operation(dest, &operation)?;
|
} = self.render_operation(dest, &operation)?;
|
||||||
|
|
||||||
// If we need to resolve the first hop, do it
|
|
||||||
let node_ref = match node_ref {
|
|
||||||
None => match self.resolve_node(node_id).await? {
|
|
||||||
None => {
|
|
||||||
return Ok(NetworkResult::no_connection_other(node_id));
|
|
||||||
}
|
|
||||||
Some(nr) => nr,
|
|
||||||
},
|
|
||||||
Some(nr) => nr,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send statement
|
// Send statement
|
||||||
let bytes = message.len() as u64;
|
let bytes = message.len() as u64;
|
||||||
let send_ts = intf::get_timestamp();
|
let send_ts = intf::get_timestamp();
|
||||||
@ -782,17 +753,6 @@ impl RPCProcessor {
|
|||||||
hop_count: _,
|
hop_count: _,
|
||||||
} = self.render_operation(dest, &operation)?;
|
} = self.render_operation(dest, &operation)?;
|
||||||
|
|
||||||
// If we need to resolve the first hop, do it
|
|
||||||
let node_ref = match node_ref {
|
|
||||||
None => match self.resolve_node(node_id).await? {
|
|
||||||
None => {
|
|
||||||
return Ok(NetworkResult::no_connection_other(node_id));
|
|
||||||
}
|
|
||||||
Some(nr) => nr,
|
|
||||||
},
|
|
||||||
Some(nr) => nr,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send the reply
|
// Send the reply
|
||||||
let bytes = message.len() as u64;
|
let bytes = message.len() as u64;
|
||||||
let send_ts = intf::get_timestamp();
|
let send_ts = intf::get_timestamp();
|
||||||
|
@ -641,9 +641,9 @@ impl VeilidConfig {
|
|||||||
"max route hop count must be >= 1 in 'network.rpc.max_route_hop_count'"
|
"max route hop count must be >= 1 in 'network.rpc.max_route_hop_count'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if inner.network.rpc.max_route_hop_count > 7 {
|
if inner.network.rpc.max_route_hop_count > 5 {
|
||||||
apibail_generic!(
|
apibail_generic!(
|
||||||
"max route hop count must be <= 7 in 'network.rpc.max_route_hop_count'"
|
"max route hop count must be <= 5 in 'network.rpc.max_route_hop_count'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if inner.network.rpc.default_route_hop_count == 0 {
|
if inner.network.rpc.default_route_hop_count == 0 {
|
||||||
|
@ -65,7 +65,7 @@ Future<VeilidConfig> getDefaultVeilidConfig() async {
|
|||||||
maxTimestampBehindMs: 10000,
|
maxTimestampBehindMs: 10000,
|
||||||
maxTimestampAheadMs: 10000,
|
maxTimestampAheadMs: 10000,
|
||||||
timeoutMs: 10000,
|
timeoutMs: 10000,
|
||||||
maxRouteHopCount: 7,
|
maxRouteHopCount: 4,
|
||||||
defaultRouteHopCount: 2,
|
defaultRouteHopCount: 2,
|
||||||
),
|
),
|
||||||
dht: VeilidConfigDHT(
|
dht: VeilidConfigDHT(
|
||||||
|
@ -45,7 +45,7 @@ fn init_callbacks() {
|
|||||||
case "network.rpc.max_timestamp_behind": return 10000000;
|
case "network.rpc.max_timestamp_behind": return 10000000;
|
||||||
case "network.rpc.max_timestamp_ahead": return 10000000;
|
case "network.rpc.max_timestamp_ahead": return 10000000;
|
||||||
case "network.rpc.timeout": return 10000000;
|
case "network.rpc.timeout": return 10000000;
|
||||||
case "network.rpc.max_route_hop_count": return 7;
|
case "network.rpc.max_route_hop_count": return 4;
|
||||||
case "network.rpc.default_route_hop_count": return 2;
|
case "network.rpc.default_route_hop_count": return 2;
|
||||||
case "network.dht.resolve_node_timeout": return null;
|
case "network.dht.resolve_node_timeout": return null;
|
||||||
case "network.dht.resolve_node_count": return 20;
|
case "network.dht.resolve_node_count": return 20;
|
||||||
|
Loading…
Reference in New Issue
Block a user