more route work
This commit is contained in:
parent
50718b7074
commit
68d55a5e77
@ -757,7 +757,9 @@ impl NetworkManager {
|
|||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
receipt_manager.handle_receipt(receipt, None).await
|
receipt_manager
|
||||||
|
.handle_receipt(receipt, ReceiptReturned::OutOfBand)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process a received in-band receipt
|
/// Process a received in-band receipt
|
||||||
@ -765,7 +767,7 @@ impl NetworkManager {
|
|||||||
pub async fn handle_in_band_receipt<R: AsRef<[u8]>>(
|
pub async fn handle_in_band_receipt<R: AsRef<[u8]>>(
|
||||||
&self,
|
&self,
|
||||||
receipt_data: R,
|
receipt_data: R,
|
||||||
inbound_nr: NodeRef,
|
inbound_noderef: NodeRef,
|
||||||
) -> NetworkResult<()> {
|
) -> NetworkResult<()> {
|
||||||
let receipt_manager = self.receipt_manager();
|
let receipt_manager = self.receipt_manager();
|
||||||
|
|
||||||
@ -777,7 +779,27 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
receipt_manager
|
receipt_manager
|
||||||
.handle_receipt(receipt, Some(inbound_nr))
|
.handle_receipt(receipt, ReceiptReturned::InBand { inbound_noderef })
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
) -> 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::Private)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,7 +1023,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Wait for the return receipt
|
// Wait for the return receipt
|
||||||
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
||||||
ReceiptEvent::ReturnedOutOfBand => {
|
ReceiptEvent::ReturnedPrivate | ReceiptEvent::ReturnedOutOfBand => {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"reverse connect receipt should be returned in-band",
|
"reverse connect receipt should be returned in-band",
|
||||||
));
|
));
|
||||||
@ -1102,7 +1124,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Wait for the return receipt
|
// Wait for the return receipt
|
||||||
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
let inbound_nr = match eventual_value.await.take_value().unwrap() {
|
||||||
ReceiptEvent::ReturnedOutOfBand => {
|
ReceiptEvent::ReturnedPrivate | ReceiptEvent::ReturnedOutOfBand => {
|
||||||
return Ok(NetworkResult::invalid_message(
|
return Ok(NetworkResult::invalid_message(
|
||||||
"hole punch receipt should be returned in-band",
|
"hole punch receipt should be returned in-band",
|
||||||
));
|
));
|
||||||
|
@ -11,10 +11,18 @@ use xx::*;
|
|||||||
pub enum ReceiptEvent {
|
pub enum ReceiptEvent {
|
||||||
ReturnedOutOfBand,
|
ReturnedOutOfBand,
|
||||||
ReturnedInBand { inbound_noderef: NodeRef },
|
ReturnedInBand { inbound_noderef: NodeRef },
|
||||||
|
ReturnedPrivate,
|
||||||
Expired,
|
Expired,
|
||||||
Cancelled,
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ReceiptReturned {
|
||||||
|
OutOfBand,
|
||||||
|
InBand { inbound_noderef: NodeRef },
|
||||||
|
Private,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ReceiptCallback: Send + 'static {
|
pub trait ReceiptCallback: Send + 'static {
|
||||||
fn call(
|
fn call(
|
||||||
&self,
|
&self,
|
||||||
@ -394,17 +402,17 @@ impl ReceiptManager {
|
|||||||
pub async fn handle_receipt(
|
pub async fn handle_receipt(
|
||||||
&self,
|
&self,
|
||||||
receipt: Receipt,
|
receipt: Receipt,
|
||||||
inbound_noderef: Option<NodeRef>,
|
receipt_returned: ReceiptReturned,
|
||||||
) -> NetworkResult<()> {
|
) -> NetworkResult<()> {
|
||||||
let receipt_nonce = receipt.get_nonce();
|
let receipt_nonce = receipt.get_nonce();
|
||||||
let extra_data = receipt.get_extra_data();
|
let extra_data = receipt.get_extra_data();
|
||||||
|
|
||||||
log_rpc!(debug "<<== RECEIPT {} <- {}{}",
|
log_rpc!(debug "<<== RECEIPT {} <- {}{}",
|
||||||
receipt_nonce.encode(),
|
receipt_nonce.encode(),
|
||||||
if let Some(nr) = &inbound_noderef {
|
match receipt_returned {
|
||||||
nr.to_string()
|
ReceiptReturned::OutOfBand => "OutOfBand".to_owned(),
|
||||||
} else {
|
ReceiptReturned::InBand { ref inbound_noderef } => format!("InBand({})", inbound_noderef),
|
||||||
"DIRECT".to_owned()
|
ReceiptReturned::Private => "Private".to_owned(),
|
||||||
},
|
},
|
||||||
if extra_data.is_empty() {
|
if extra_data.is_empty() {
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
@ -435,10 +443,14 @@ impl ReceiptManager {
|
|||||||
record_mut.returns_so_far += 1;
|
record_mut.returns_so_far += 1;
|
||||||
|
|
||||||
// Get the receipt event to return
|
// Get the receipt event to return
|
||||||
let receipt_event = if let Some(inbound_noderef) = inbound_noderef {
|
let receipt_event = match receipt_returned {
|
||||||
ReceiptEvent::ReturnedInBand { inbound_noderef }
|
ReceiptReturned::OutOfBand => ReceiptEvent::ReturnedOutOfBand,
|
||||||
} else {
|
ReceiptReturned::InBand {
|
||||||
ReceiptEvent::ReturnedOutOfBand
|
ref inbound_noderef,
|
||||||
|
} => ReceiptEvent::ReturnedInBand {
|
||||||
|
inbound_noderef: inbound_noderef.clone(),
|
||||||
|
},
|
||||||
|
ReceiptReturned::Private => ReceiptEvent::ReturnedPrivate,
|
||||||
};
|
};
|
||||||
|
|
||||||
let callback_future = Self::perform_callback(receipt_event, &mut record_mut);
|
let callback_future = Self::perform_callback(receipt_event, &mut record_mut);
|
||||||
|
@ -56,11 +56,7 @@ impl Bucket {
|
|||||||
self.entries.iter()
|
self.entries.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn kick(
|
pub(super) fn kick(&mut self, bucket_depth: usize) -> Option<BTreeSet<DHTKey>> {
|
||||||
&mut self,
|
|
||||||
inner: &mut RoutingTableInner,
|
|
||||||
bucket_depth: usize,
|
|
||||||
) -> Option<BTreeSet<DHTKey>> {
|
|
||||||
// Get number of entries to attempt to purge from bucket
|
// Get number of entries to attempt to purge from bucket
|
||||||
let bucket_len = self.entries.len();
|
let bucket_len = self.entries.len();
|
||||||
|
|
||||||
@ -84,8 +80,8 @@ impl Bucket {
|
|||||||
if a.0 == b.0 {
|
if a.0 == b.0 {
|
||||||
return core::cmp::Ordering::Equal;
|
return core::cmp::Ordering::Equal;
|
||||||
}
|
}
|
||||||
a.1.with(inner, |rti, ea| {
|
a.1.with_inner(|ea| {
|
||||||
b.1.with(rti, |_rti, eb| {
|
b.1.with_inner(|eb| {
|
||||||
let astate = state_ordering(ea.state(cur_ts));
|
let astate = state_ordering(ea.state(cur_ts));
|
||||||
let bstate = state_ordering(eb.state(cur_ts));
|
let bstate = state_ordering(eb.state(cur_ts));
|
||||||
// first kick dead nodes, then unreliable nodes
|
// first kick dead nodes, then unreliable nodes
|
||||||
|
@ -675,6 +675,24 @@ impl BucketEntry {
|
|||||||
let mut inner = self.inner.write();
|
let mut inner = self.inner.write();
|
||||||
f(rti, &mut *inner)
|
f(rti, &mut *inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal inner access for RoutingTableInner only
|
||||||
|
pub(super) fn with_inner<F, R>(&self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&BucketEntryInner) -> R,
|
||||||
|
{
|
||||||
|
let inner = self.inner.read();
|
||||||
|
f(&*inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal inner access for RoutingTableInner only
|
||||||
|
pub(super) fn with_mut_inner<F, R>(&self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut BucketEntryInner) -> R,
|
||||||
|
{
|
||||||
|
let mut inner = self.inner.write();
|
||||||
|
f(&mut *inner)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for BucketEntry {
|
impl Drop for BucketEntry {
|
||||||
|
@ -191,18 +191,8 @@ impl RoutingTable {
|
|||||||
self.inner.read().routing_domain_for_address(address)
|
self.inner.read().routing_domain_for_address(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_route_spec_store_mut<F, R>(&self, f: F) -> R
|
pub fn route_spec_store(&self) -> RouteSpecStore {
|
||||||
where
|
self.inner.read().route_spec_store.clone()
|
||||||
F: FnOnce(&mut RouteSpecStore, &mut RoutingTableInner) -> R,
|
|
||||||
{
|
|
||||||
self.inner.write().with_route_spec_store_mut(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_route_spec_store<F, R>(&self, f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&RouteSpecStore, &RoutingTableInner) -> R,
|
|
||||||
{
|
|
||||||
self.inner.read().with_route_spec_store(f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
||||||
|
@ -72,18 +72,27 @@ pub struct RouteSpecStoreCache {
|
|||||||
hop_cache: HashSet<Vec<u8>>,
|
hop_cache: HashSet<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The routing table's storage for private/safety routes
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouteSpecStore {
|
pub struct RouteSpecStoreInner {
|
||||||
/// Maximum number of hops in a route
|
|
||||||
max_route_hop_count: usize,
|
|
||||||
/// Default number of hops in a route
|
|
||||||
default_route_hop_count: usize,
|
|
||||||
/// Serialize RouteSpecStore content
|
/// Serialize RouteSpecStore content
|
||||||
content: RouteSpecStoreContent,
|
content: RouteSpecStoreContent,
|
||||||
/// RouteSpecStore cache
|
/// RouteSpecStore cache
|
||||||
cache: RouteSpecStoreCache,
|
cache: RouteSpecStoreCache,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RouteSpecStoreUnlockedInner {
|
||||||
|
/// Maximum number of hops in a route
|
||||||
|
max_route_hop_count: usize,
|
||||||
|
/// Default number of hops in a route
|
||||||
|
default_route_hop_count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The routing table's storage for private/safety routes
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct RouteSpecStore {
|
||||||
|
inner: Arc<Mutex<RouteSpecStoreInner>>,
|
||||||
|
unlocked_inner: Arc<RouteSpecStoreUnlockedInner>,
|
||||||
|
}
|
||||||
|
|
||||||
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
|
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
|
||||||
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * DHT_KEY_LENGTH);
|
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * DHT_KEY_LENGTH);
|
||||||
@ -167,17 +176,24 @@ where
|
|||||||
heaps_permutation(&mut permutation, hop_count - 1, f)
|
heaps_permutation(&mut permutation, hop_count - 1, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xxx get routing table handle into routespecstore
|
||||||
|
xxx first figure out when new/load get called, does routing table need 'init' or can we just pick the right time to load the cache? what about flushing the cache ? we don't 'save' it yet, that should probably get flushed at the same time as the DH cache.
|
||||||
|
|
||||||
impl RouteSpecStore {
|
impl RouteSpecStore {
|
||||||
pub fn new(config: VeilidConfig) -> Self {
|
pub fn new(config: VeilidConfig) -> Self {
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
max_route_hop_count: c.network.rpc.max_route_hop_count.into(),
|
unlocked_inner: Arc::new(RouteSpecStoreUnlockedInner {
|
||||||
default_route_hop_count: c.network.rpc.default_route_hop_count.into(),
|
max_route_hop_count: c.network.rpc.max_route_hop_count.into(),
|
||||||
content: RouteSpecStoreContent {
|
default_route_hop_count: c.network.rpc.default_route_hop_count.into(),
|
||||||
details: HashMap::new(),
|
}),
|
||||||
},
|
inner: Arc::new(Mutex::new(RouteSpecStoreInner {
|
||||||
cache: Default::default(),
|
content: RouteSpecStoreContent {
|
||||||
|
details: HashMap::new(),
|
||||||
|
},
|
||||||
|
cache: Default::default(),
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,18 +203,13 @@ impl RouteSpecStore {
|
|||||||
// 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 mut content: RouteSpecStoreContent =
|
||||||
let mut rss = RouteSpecStore {
|
rsstdb.load_cbor(0, b"content").await?.unwrap_or_default();
|
||||||
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,
|
|
||||||
cache: Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load secrets from pstore
|
// Load secrets from pstore
|
||||||
let pstore = routing_table.network_manager().protected_store();
|
let pstore = routing_table.network_manager().protected_store();
|
||||||
let mut dead_keys = Vec::new();
|
let mut dead_keys = Vec::new();
|
||||||
for (k, v) in &mut rss.content.details {
|
for (k, v) in &mut content.details {
|
||||||
if let Some(secret_key) = pstore
|
if let Some(secret_key) = pstore
|
||||||
.load_user_secret(&format!("RouteSpecStore_{}", k.encode()))
|
.load_user_secret(&format!("RouteSpecStore_{}", k.encode()))
|
||||||
.await?
|
.await?
|
||||||
@ -217,23 +228,39 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
for k in dead_keys {
|
for k in dead_keys {
|
||||||
log_rtab!(debug "killing off private route: {}", k.encode());
|
log_rtab!(debug "killing off private route: {}", k.encode());
|
||||||
rss.content.details.remove(&k);
|
content.details.remove(&k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut inner = RouteSpecStoreInner {
|
||||||
|
content,
|
||||||
|
cache: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
// Rebuild the routespecstore cache
|
// Rebuild the routespecstore cache
|
||||||
rss.rebuild_cache();
|
Self::rebuild_cache(&mut inner);
|
||||||
|
|
||||||
|
let rss = RouteSpecStore {
|
||||||
|
unlocked_inner: Arc::new(RouteSpecStoreUnlockedInner {
|
||||||
|
max_route_hop_count: c.network.rpc.max_route_hop_count.into(),
|
||||||
|
default_route_hop_count: c.network.rpc.default_route_hop_count.into(),
|
||||||
|
}),
|
||||||
|
inner: Arc::new(Mutex::new(inner)),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(rss)
|
Ok(rss)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&self, routing_table: RoutingTable) -> EyreResult<()> {
|
pub async fn save(&self, routing_table: RoutingTable) -> EyreResult<()> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
|
||||||
// Save all the fields we care about to the cbor blob in table storage
|
// Save all the fields we care about to the cbor blob in table storage
|
||||||
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?;
|
||||||
rsstdb.store_cbor(0, b"content", &self.content).await?;
|
rsstdb.store_cbor(0, b"content", &inner.content).await?;
|
||||||
|
|
||||||
// Keep secrets in protected store as well
|
// Keep secrets in protected store as well
|
||||||
let pstore = routing_table.network_manager().protected_store();
|
let pstore = routing_table.network_manager().protected_store();
|
||||||
for (k, v) in &self.content.details {
|
for (k, v) in &inner.content.details {
|
||||||
if pstore
|
if pstore
|
||||||
.save_user_secret(
|
.save_user_secret(
|
||||||
&format!("RouteSpecStore_{}", k.encode()),
|
&format!("RouteSpecStore_{}", k.encode()),
|
||||||
@ -266,18 +293,24 @@ impl RouteSpecStore {
|
|||||||
.or_insert(1);
|
.or_insert(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebuild_cache(&mut self) {
|
fn rebuild_cache(inner: &mut RouteSpecStoreInner) {
|
||||||
for v in self.content.details.values() {
|
for v in inner.content.details.values() {
|
||||||
let cache_key = route_hops_to_hop_cache(&v.hops);
|
let cache_key = route_hops_to_hop_cache(&v.hops);
|
||||||
Self::add_to_cache(&mut self.cache, cache_key, &v);
|
Self::add_to_cache(&mut inner.cache, cache_key, &v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detail(&self, public_key: &DHTKey) -> Option<&RouteSpecDetail> {
|
fn detail<'a>(
|
||||||
self.content.details.get(&public_key)
|
inner: &'a RouteSpecStoreInner,
|
||||||
|
public_key: &DHTKey,
|
||||||
|
) -> Option<&'a RouteSpecDetail> {
|
||||||
|
inner.content.details.get(public_key)
|
||||||
}
|
}
|
||||||
fn detail_mut(&mut self, public_key: &DHTKey) -> Option<&mut RouteSpecDetail> {
|
fn detail_mut<'a>(
|
||||||
self.content.details.get_mut(&public_key)
|
inner: &'a mut RouteSpecStoreInner,
|
||||||
|
public_key: &DHTKey,
|
||||||
|
) -> Option<&'a mut RouteSpecDetail> {
|
||||||
|
inner.content.details.get_mut(public_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new route
|
/// Create a new route
|
||||||
@ -285,7 +318,7 @@ impl RouteSpecStore {
|
|||||||
/// 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 fn allocate_route(
|
pub fn allocate_route(
|
||||||
&mut self,
|
&self,
|
||||||
rti: &RoutingTableInner,
|
rti: &RoutingTableInner,
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
@ -294,12 +327,13 @@ impl RouteSpecStore {
|
|||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
) -> EyreResult<Option<DHTKey>> {
|
) -> EyreResult<Option<DHTKey>> {
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
if hop_count < 1 {
|
if hop_count < 1 {
|
||||||
bail!("Not allocating route less than one hop in length");
|
bail!("Not allocating route less than one hop in length");
|
||||||
}
|
}
|
||||||
|
|
||||||
if hop_count > self.max_route_hop_count {
|
if hop_count > self.unlocked_inner.max_route_hop_count {
|
||||||
bail!("Not allocating route longer than max route hop count");
|
bail!("Not allocating route longer than max route hop count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,13 +376,13 @@ impl RouteSpecStore {
|
|||||||
v2: &(DHTKey, Option<Arc<BucketEntry>>)|
|
v2: &(DHTKey, Option<Arc<BucketEntry>>)|
|
||||||
-> Ordering {
|
-> Ordering {
|
||||||
// deprioritize nodes that we have already used as end points
|
// deprioritize nodes that we have already used as end points
|
||||||
let e1_used_end = self
|
let e1_used_end = inner
|
||||||
.cache
|
.cache
|
||||||
.used_end_nodes
|
.used_end_nodes
|
||||||
.get(&v1.0)
|
.get(&v1.0)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let e2_used_end = self
|
let e2_used_end = inner
|
||||||
.cache
|
.cache
|
||||||
.used_end_nodes
|
.used_end_nodes
|
||||||
.get(&v2.0)
|
.get(&v2.0)
|
||||||
@ -360,13 +394,13 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deprioritize nodes we have used already anywhere
|
// deprioritize nodes we have used already anywhere
|
||||||
let e1_used = self
|
let e1_used = inner
|
||||||
.cache
|
.cache
|
||||||
.used_nodes
|
.used_nodes
|
||||||
.get(&v1.0)
|
.get(&v1.0)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let e2_used = self
|
let e2_used = inner
|
||||||
.cache
|
.cache
|
||||||
.used_nodes
|
.used_nodes
|
||||||
.get(&v2.0)
|
.get(&v2.0)
|
||||||
@ -428,7 +462,7 @@ impl RouteSpecStore {
|
|||||||
cache_key = route_permutation_to_hop_cache(&nodes, permutation);
|
cache_key = route_permutation_to_hop_cache(&nodes, permutation);
|
||||||
|
|
||||||
// Skip routes we have already seen
|
// Skip routes we have already seen
|
||||||
if self.cache.hop_cache.contains(&cache_key) {
|
if inner.cache.hop_cache.contains(&cache_key) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,10 +563,10 @@ impl RouteSpecStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add to cache
|
// Add to cache
|
||||||
Self::add_to_cache(&mut self.cache, cache_key, &rsd);
|
Self::add_to_cache(&mut inner.cache, cache_key, &rsd);
|
||||||
|
|
||||||
// Keep route in spec store
|
// Keep route in spec store
|
||||||
self.content.details.insert(public_key, rsd);
|
inner.content.details.insert(public_key, rsd);
|
||||||
|
|
||||||
Ok(Some(public_key))
|
Ok(Some(public_key))
|
||||||
}
|
}
|
||||||
@ -541,19 +575,21 @@ impl RouteSpecStore {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&RouteSpecDetail) -> R,
|
F: FnOnce(&RouteSpecDetail) -> R,
|
||||||
{
|
{
|
||||||
self.detail(&public_key).map(|rsd| f(rsd))
|
let inner = self.inner.lock();
|
||||||
|
Self::detail(&*inner, &public_key).map(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_route(&mut self, public_key: DHTKey) {
|
pub fn release_route(&self, public_key: DHTKey) {
|
||||||
if let Some(detail) = self.content.details.remove(&public_key) {
|
let mut inner = self.inner.lock();
|
||||||
|
if let Some(detail) = inner.content.details.remove(&public_key) {
|
||||||
// Remove from hop cache
|
// Remove from hop cache
|
||||||
let cache_key = route_hops_to_hop_cache(&detail.hops);
|
let cache_key = route_hops_to_hop_cache(&detail.hops);
|
||||||
if !self.cache.hop_cache.remove(&cache_key) {
|
if !inner.cache.hop_cache.remove(&cache_key) {
|
||||||
panic!("hop cache should have contained cache key");
|
panic!("hop cache should have contained cache key");
|
||||||
}
|
}
|
||||||
// Remove from used nodes cache
|
// Remove from used nodes cache
|
||||||
for h in &detail.hops {
|
for h in &detail.hops {
|
||||||
match self.cache.used_nodes.entry(*h) {
|
match inner.cache.used_nodes.entry(*h) {
|
||||||
std::collections::hash_map::Entry::Occupied(mut o) => {
|
std::collections::hash_map::Entry::Occupied(mut o) => {
|
||||||
*o.get_mut() -= 1;
|
*o.get_mut() -= 1;
|
||||||
if *o.get() == 0 {
|
if *o.get() == 0 {
|
||||||
@ -566,7 +602,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove from end nodes cache
|
// Remove from end nodes cache
|
||||||
match self.cache.used_nodes.entry(*detail.hops.last().unwrap()) {
|
match inner.cache.used_nodes.entry(*detail.hops.last().unwrap()) {
|
||||||
std::collections::hash_map::Entry::Occupied(mut o) => {
|
std::collections::hash_map::Entry::Occupied(mut o) => {
|
||||||
*o.get_mut() -= 1;
|
*o.get_mut() -= 1;
|
||||||
if *o.get() == 0 {
|
if *o.get() == 0 {
|
||||||
@ -584,14 +620,16 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Find first matching unpublished route that fits into the selection criteria
|
/// Find first matching unpublished route that fits into the selection criteria
|
||||||
pub fn first_unpublished_route(
|
pub fn first_unpublished_route(
|
||||||
&mut self,
|
&self,
|
||||||
min_hop_count: usize,
|
min_hop_count: usize,
|
||||||
max_hop_count: usize,
|
max_hop_count: usize,
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
sequencing: Sequencing,
|
sequencing: Sequencing,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
) -> Option<DHTKey> {
|
) -> Option<DHTKey> {
|
||||||
for detail in &self.content.details {
|
let inner = self.inner.lock();
|
||||||
|
|
||||||
|
for detail in &inner.content.details {
|
||||||
if detail.1.stability >= stability
|
if detail.1.stability >= stability
|
||||||
&& detail.1.sequencing >= sequencing
|
&& detail.1.sequencing >= sequencing
|
||||||
&& detail.1.hops.len() >= min_hop_count
|
&& detail.1.hops.len() >= min_hop_count
|
||||||
@ -611,14 +649,16 @@ impl RouteSpecStore {
|
|||||||
/// Returns an Err() if the parameters are wrong
|
/// Returns an Err() if the parameters are wrong
|
||||||
/// Returns Ok(None) if no allocation could happen at this time (not an error)
|
/// Returns Ok(None) if no allocation could happen at this time (not an error)
|
||||||
pub fn compile_safety_route(
|
pub fn compile_safety_route(
|
||||||
&mut self,
|
&self,
|
||||||
rti: &mut RoutingTableInner,
|
rti: &mut RoutingTableInner,
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
safety_selection: SafetySelection,
|
safety_selection: SafetySelection,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
) -> EyreResult<Option<CompiledRoute>> {
|
) -> EyreResult<Option<CompiledRoute>> {
|
||||||
|
let inner = &mut *self.inner.lock();
|
||||||
|
|
||||||
let pr_hopcount = private_route.hop_count as usize;
|
let pr_hopcount = private_route.hop_count as usize;
|
||||||
let max_route_hop_count = self.max_route_hop_count;
|
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||||
if pr_hopcount > max_route_hop_count {
|
if pr_hopcount > max_route_hop_count {
|
||||||
bail!("private route hop count too long");
|
bail!("private route hop count too long");
|
||||||
}
|
}
|
||||||
@ -664,8 +704,7 @@ impl RouteSpecStore {
|
|||||||
// See if the preferred route is here
|
// See if the preferred route is here
|
||||||
let opt_safety_rsd: Option<(&mut RouteSpecDetail, DHTKey)> =
|
let opt_safety_rsd: Option<(&mut RouteSpecDetail, DHTKey)> =
|
||||||
if let Some(preferred_route) = safety_spec.preferred_route {
|
if let Some(preferred_route) = safety_spec.preferred_route {
|
||||||
self.detail_mut(&preferred_route)
|
Self::detail_mut(inner, &preferred_route).map(|rsd| (rsd, preferred_route))
|
||||||
.map(|rsd| (rsd, preferred_route))
|
|
||||||
} else {
|
} else {
|
||||||
// Preferred safety route was not requested
|
// Preferred safety route was not requested
|
||||||
None
|
None
|
||||||
@ -683,7 +722,7 @@ impl RouteSpecStore {
|
|||||||
Direction::Outbound.into(),
|
Direction::Outbound.into(),
|
||||||
) {
|
) {
|
||||||
// Found a route to use
|
// Found a route to use
|
||||||
(self.detail_mut(&sr_pubkey).unwrap(), sr_pubkey)
|
(Self::detail_mut(inner, &sr_pubkey).unwrap(), sr_pubkey)
|
||||||
} else {
|
} else {
|
||||||
// No route found, gotta allocate one
|
// No route found, gotta allocate one
|
||||||
let sr_pubkey = match self
|
let sr_pubkey = match self
|
||||||
@ -700,7 +739,7 @@ impl RouteSpecStore {
|
|||||||
Some(pk) => pk,
|
Some(pk) => pk,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
(self.detail_mut(&sr_pubkey).unwrap(), sr_pubkey)
|
(Self::detail_mut(inner, &sr_pubkey).unwrap(), sr_pubkey)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -837,14 +876,14 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Assemble private route for publication
|
/// Assemble private route for publication
|
||||||
pub fn assemble_private_route(
|
pub fn assemble_private_route(
|
||||||
&mut self,
|
&self,
|
||||||
rti: &RoutingTableInner,
|
rti: &RoutingTableInner,
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
key: &DHTKey,
|
key: &DHTKey,
|
||||||
) -> EyreResult<PrivateRoute> {
|
) -> EyreResult<PrivateRoute> {
|
||||||
let rsd = self
|
let inner = &*self.inner.lock();
|
||||||
.detail(&key)
|
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?;
|
let rsd = Self::detail(inner, &key).ok_or_else(|| eyre!("route does not exist"))?;
|
||||||
|
|
||||||
// See if we can optimize this compilation yet
|
// See if we can optimize this compilation yet
|
||||||
// We don't want to include full nodeinfo if we don't have to
|
// We don't want to include full nodeinfo if we don't have to
|
||||||
@ -919,7 +958,8 @@ impl RouteSpecStore {
|
|||||||
/// 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) -> EyreResult<()> {
|
pub fn mark_route_published(&mut self, key: &DHTKey) -> EyreResult<()> {
|
||||||
self.detail_mut(&key)
|
let inner = &mut *self.inner.lock();
|
||||||
|
Self::detail_mut(inner, &key)
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
.published = true;
|
.published = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -929,7 +969,8 @@ impl RouteSpecStore {
|
|||||||
/// When first deserialized, routes must be re-tested for reachability
|
/// When first deserialized, routes must be re-tested for reachability
|
||||||
/// This can be used to determine if routes need to be sent with full peerinfo or can just use a node id
|
/// This can be used to determine if routes need to be sent with full peerinfo or can just use a node id
|
||||||
pub fn mark_route_reachable(&mut self, key: &DHTKey) -> EyreResult<()> {
|
pub fn mark_route_reachable(&mut self, key: &DHTKey) -> EyreResult<()> {
|
||||||
self.detail_mut(&key)
|
let inner = &mut *self.inner.lock();
|
||||||
|
Self::detail_mut(inner, &key)
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
.published = true;
|
.published = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -937,7 +978,8 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Mark route as checked
|
/// Mark route as checked
|
||||||
pub fn touch_route_checked(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
pub fn touch_route_checked(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
||||||
self.detail_mut(&key)
|
let inner = &mut *self.inner.lock();
|
||||||
|
Self::detail_mut(inner, &key)
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
.last_checked_ts = Some(cur_ts);
|
.last_checked_ts = Some(cur_ts);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -945,7 +987,8 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Mark route as used
|
/// Mark route as used
|
||||||
pub fn touch_route_used(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
pub fn touch_route_used(&mut self, key: &DHTKey, cur_ts: u64) -> EyreResult<()> {
|
||||||
self.detail_mut(&key)
|
let inner = &mut *self.inner.lock();
|
||||||
|
Self::detail_mut(inner, &key)
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
.last_used_ts = Some(cur_ts);
|
.last_used_ts = Some(cur_ts);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -953,20 +996,17 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Record latency on the route
|
/// Record latency on the route
|
||||||
pub fn record_latency(&mut self, key: &DHTKey, latency: u64) -> EyreResult<()> {
|
pub fn record_latency(&mut self, key: &DHTKey, latency: u64) -> EyreResult<()> {
|
||||||
let lsa = &mut self
|
let inner = &mut *self.inner.lock();
|
||||||
.detail_mut(&key)
|
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
let rsd = Self::detail_mut(inner, &key).ok_or_else(|| eyre!("route does not exist"))?;
|
||||||
.latency_stats_accounting;
|
rsd.latency_stats = rsd.latency_stats_accounting.record_latency(latency);
|
||||||
self.detail_mut(&key)
|
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
|
||||||
.latency_stats = lsa.record_latency(latency);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the calculated latency stats
|
/// Get the calculated latency stats
|
||||||
pub fn latency_stats(&mut self, key: &DHTKey) -> EyreResult<LatencyStats> {
|
pub fn latency_stats(&mut self, key: &DHTKey) -> EyreResult<LatencyStats> {
|
||||||
Ok(self
|
let inner = &mut *self.inner.lock();
|
||||||
.detail_mut(&key)
|
Ok(Self::detail_mut(inner, &key)
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
.ok_or_else(|| eyre!("route does not exist"))?
|
||||||
.latency_stats
|
.latency_stats
|
||||||
.clone())
|
.clone())
|
||||||
@ -974,27 +1014,24 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Add download transfers to route
|
/// Add download transfers to route
|
||||||
pub fn add_down(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
pub fn add_down(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
||||||
let tsa = &mut self
|
let inner = &mut *self.inner.lock();
|
||||||
.detail_mut(&key)
|
let rsd = Self::detail_mut(inner, &key).ok_or_else(|| eyre!("route does not exist"))?;
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
rsd.transfer_stats_accounting.add_down(bytes);
|
||||||
.transfer_stats_accounting;
|
|
||||||
tsa.add_down(bytes);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add upload transfers to route
|
/// Add upload transfers to route
|
||||||
pub fn add_up(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
pub fn add_up(&mut self, key: &DHTKey, bytes: u64) -> EyreResult<()> {
|
||||||
let tsa = &mut self
|
let inner = &mut *self.inner.lock();
|
||||||
.detail_mut(&key)
|
let rsd = Self::detail_mut(inner, &key).ok_or_else(|| eyre!("route does not exist"))?;
|
||||||
.ok_or_else(|| eyre!("route does not exist"))?
|
rsd.transfer_stats_accounting.add_up(bytes);
|
||||||
.transfer_stats_accounting;
|
|
||||||
tsa.add_up(bytes);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process transfer statistics to get averages
|
/// Process transfer statistics to get averages
|
||||||
pub fn roll_transfers(&mut self, last_ts: u64, cur_ts: u64) {
|
pub fn roll_transfers(&mut self, last_ts: u64, cur_ts: u64) {
|
||||||
for rsd in self.content.details.values_mut() {
|
let inner = &mut *self.inner.lock();
|
||||||
|
for rsd in inner.content.details.values_mut() {
|
||||||
rsd.transfer_stats_accounting.roll_transfers(
|
rsd.transfer_stats_accounting.roll_transfers(
|
||||||
last_ts,
|
last_ts,
|
||||||
cur_ts,
|
cur_ts,
|
||||||
|
@ -116,7 +116,7 @@ impl RoutingDomainDetailCommon {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&PeerInfo) -> R,
|
F: FnOnce(&PeerInfo) -> R,
|
||||||
{
|
{
|
||||||
let cpi = self.cached_peer_info.lock();
|
let mut cpi = self.cached_peer_info.lock();
|
||||||
if cpi.is_none() {
|
if cpi.is_none() {
|
||||||
// Regenerate peer info
|
// Regenerate peer info
|
||||||
let pi = PeerInfo::new(
|
let pi = PeerInfo::new(
|
||||||
@ -131,6 +131,7 @@ impl RoutingDomainDetailCommon {
|
|||||||
dial_info_detail_list: self.dial_info_details.clone(),
|
dial_info_detail_list: self.dial_info_details.clone(),
|
||||||
relay_peer_info: self
|
relay_peer_info: self
|
||||||
.relay_node
|
.relay_node
|
||||||
|
.as_ref()
|
||||||
.and_then(|rn| rn.make_peer_info(self.routing_domain).map(Box::new)),
|
.and_then(|rn| rn.make_peer_info(self.routing_domain).map(Box::new)),
|
||||||
},
|
},
|
||||||
NodeId::new(self.node_id),
|
NodeId::new(self.node_id),
|
||||||
@ -268,7 +269,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the target's inbound relay, it must have one or it is not reachable
|
// Get the target's inbound relay, it must have one or it is not reachable
|
||||||
if let Some(inbound_relay) = node_b.relay_peer_info {
|
if let Some(inbound_relay) = &node_b.relay_peer_info {
|
||||||
// Note that relay_peer_info could be node_a, in which case a connection already exists
|
// Note that relay_peer_info could be node_a, in which case a connection already exists
|
||||||
// and we shouldn't have even gotten here
|
// and we shouldn't have even gotten here
|
||||||
if inbound_relay.node_id.key == *node_a_id {
|
if inbound_relay.node_id.key == *node_a_id {
|
||||||
@ -348,7 +349,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the node B has no direct dial info, it needs to have an inbound relay
|
// If the node B has no direct dial info, it needs to have an inbound relay
|
||||||
else if let Some(inbound_relay) = node_b.relay_peer_info {
|
else if let Some(inbound_relay) = &node_b.relay_peer_info {
|
||||||
// Can we reach the full relay?
|
// Can we reach the full relay?
|
||||||
if first_filtered_dial_info_detail(
|
if first_filtered_dial_info_detail(
|
||||||
node_a,
|
node_a,
|
||||||
@ -363,7 +364,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If node A can't reach the node by other means, it may need to use its own relay
|
// If node A can't reach the node by other means, it may need to use its own relay
|
||||||
if let Some(outbound_relay) = node_a.relay_peer_info {
|
if let Some(outbound_relay) = &node_a.relay_peer_info {
|
||||||
return ContactMethod::OutboundRelay(outbound_relay.node_id.key);
|
return ContactMethod::OutboundRelay(outbound_relay.node_id.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ pub struct RoutingTableInner {
|
|||||||
|
|
||||||
impl RoutingTableInner {
|
impl RoutingTableInner {
|
||||||
pub fn new(unlocked_inner: Arc<RoutingTableUnlockedInner>) -> RoutingTableInner {
|
pub fn new(unlocked_inner: Arc<RoutingTableUnlockedInner>) -> RoutingTableInner {
|
||||||
|
let config = unlocked_inner.config.clone();
|
||||||
RoutingTableInner {
|
RoutingTableInner {
|
||||||
unlocked_inner,
|
unlocked_inner,
|
||||||
buckets: Vec::new(),
|
buckets: Vec::new(),
|
||||||
@ -45,7 +46,7 @@ impl RoutingTableInner {
|
|||||||
self_transfer_stats_accounting: TransferStatsAccounting::new(),
|
self_transfer_stats_accounting: TransferStatsAccounting::new(),
|
||||||
self_transfer_stats: TransferStatsDownUp::default(),
|
self_transfer_stats: TransferStatsDownUp::default(),
|
||||||
recent_peers: LruCache::new(RECENT_PEERS_TABLE_SIZE),
|
recent_peers: LruCache::new(RECENT_PEERS_TABLE_SIZE),
|
||||||
route_spec_store: RouteSpecStore::new(unlocked_inner.config.clone()),
|
route_spec_store: RouteSpecStore::new(config),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,20 +106,6 @@ impl RoutingTableInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_route_spec_store_mut<F, R>(&mut self, f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut RouteSpecStore, &mut RoutingTableInner) -> R,
|
|
||||||
{
|
|
||||||
f(&mut self.route_spec_store, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_route_spec_store<F, R>(&self, f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&RouteSpecStore, &RoutingTableInner) -> R,
|
|
||||||
{
|
|
||||||
f(&self.route_spec_store, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
||||||
self.with_routing_domain(domain, |rd| rd.common().relay_node())
|
self.with_routing_domain(domain, |rd| rd.common().relay_node())
|
||||||
}
|
}
|
||||||
@ -382,8 +369,8 @@ impl RoutingTableInner {
|
|||||||
"Starting routing table buckets purge. Table currently has {} nodes",
|
"Starting routing table buckets purge. Table currently has {} nodes",
|
||||||
self.bucket_entry_count
|
self.bucket_entry_count
|
||||||
);
|
);
|
||||||
for bucket in &self.buckets {
|
for bucket in &mut self.buckets {
|
||||||
bucket.kick(self, 0);
|
bucket.kick(0);
|
||||||
}
|
}
|
||||||
log_rtab!(debug
|
log_rtab!(debug
|
||||||
"Routing table buckets purge complete. Routing table now has {} nodes",
|
"Routing table buckets purge complete. Routing table now has {} nodes",
|
||||||
@ -399,11 +386,12 @@ impl RoutingTableInner {
|
|||||||
);
|
);
|
||||||
for bucket in &self.buckets {
|
for bucket in &self.buckets {
|
||||||
for entry in bucket.entries() {
|
for entry in bucket.entries() {
|
||||||
entry.1.with_mut(self, |_rti, e| {
|
entry.1.with_mut_inner(|e| {
|
||||||
e.clear_last_connections();
|
e.clear_last_connections();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_rtab!(debug
|
log_rtab!(debug
|
||||||
"Routing table last_connections purge complete. Routing table now has {} nodes",
|
"Routing table last_connections purge complete. Routing table now has {} nodes",
|
||||||
self.bucket_entry_count
|
self.bucket_entry_count
|
||||||
@ -416,7 +404,7 @@ impl RoutingTableInner {
|
|||||||
let bucket = &mut self.buckets[idx];
|
let bucket = &mut self.buckets[idx];
|
||||||
let bucket_depth = Self::bucket_depth(idx);
|
let bucket_depth = Self::bucket_depth(idx);
|
||||||
|
|
||||||
if let Some(dead_node_ids) = bucket.kick(self, bucket_depth) {
|
if let Some(dead_node_ids) = bucket.kick(bucket_depth) {
|
||||||
// Remove counts
|
// Remove counts
|
||||||
self.bucket_entry_count -= dead_node_ids.len();
|
self.bucket_entry_count -= dead_node_ids.len();
|
||||||
log_rtab!(debug "Routing table now has {} nodes", self.bucket_entry_count);
|
log_rtab!(debug "Routing table now has {} nodes", self.bucket_entry_count);
|
||||||
|
@ -52,11 +52,11 @@ pub fn encode_route_hop(
|
|||||||
let node_builder = builder.reborrow().init_node();
|
let node_builder = builder.reborrow().init_node();
|
||||||
match &route_hop.node {
|
match &route_hop.node {
|
||||||
RouteNode::NodeId(ni) => {
|
RouteNode::NodeId(ni) => {
|
||||||
let ni_builder = node_builder.init_node_id();
|
let mut ni_builder = node_builder.init_node_id();
|
||||||
encode_public_key(&ni.key, &mut ni_builder)?;
|
encode_public_key(&ni.key, &mut ni_builder)?;
|
||||||
}
|
}
|
||||||
RouteNode::PeerInfo(pi) => {
|
RouteNode::PeerInfo(pi) => {
|
||||||
let pi_builder = node_builder.init_peer_info();
|
let mut pi_builder = node_builder.init_peer_info();
|
||||||
encode_peer_info(&pi, &mut pi_builder)?;
|
encode_peer_info(&pi, &mut pi_builder)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,16 +30,18 @@ pub enum Destination {
|
|||||||
|
|
||||||
impl Destination {
|
impl Destination {
|
||||||
pub fn direct(target: NodeRef) -> Self {
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
|
let sequencing = target.sequencing();
|
||||||
Self::Direct {
|
Self::Direct {
|
||||||
target,
|
target,
|
||||||
safety_selection: SafetySelection::Unsafe(target.sequencing()),
|
safety_selection: SafetySelection::Unsafe(sequencing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
||||||
|
let sequencing = relay.sequencing();
|
||||||
Self::Relay {
|
Self::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety_selection: SafetySelection::Unsafe(relay.sequencing()),
|
safety_selection: SafetySelection::Unsafe(sequencing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn private_route(private_route: PrivateRoute, safety_selection: SafetySelection) -> Self {
|
pub fn private_route(private_route: PrivateRoute, safety_selection: SafetySelection) -> Self {
|
||||||
|
@ -425,22 +425,23 @@ impl RPCProcessor {
|
|||||||
message_data: Vec<u8>,
|
message_data: Vec<u8>,
|
||||||
) -> Result<NetworkResult<RenderedOperation>, RPCError> {
|
) -> Result<NetworkResult<RenderedOperation>, RPCError> {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
let rss = routing_table.route_spec_store();
|
||||||
|
|
||||||
let pr_hop_count = private_route.hop_count;
|
let pr_hop_count = private_route.hop_count;
|
||||||
let pr_pubkey = private_route.public_key;
|
let pr_pubkey = private_route.public_key;
|
||||||
|
|
||||||
let compiled_route: CompiledRoute =
|
// Compile the safety route with the private route
|
||||||
match self.routing_table().with_route_spec_store_mut(|rss, rti| {
|
let compiled_route: CompiledRoute = match rss
|
||||||
// Compile the safety route with the private route
|
.compile_safety_route(rti, routing_table, safety_selection, private_route)
|
||||||
rss.compile_safety_route(rti, routing_table, safety_selection, private_route)
|
.map_err(RPCError::internal)?
|
||||||
.map_err(RPCError::internal)
|
{
|
||||||
})? {
|
Some(cr) => cr,
|
||||||
Some(cr) => cr,
|
None => {
|
||||||
None => {
|
return Ok(NetworkResult::no_connection_other(
|
||||||
return Ok(NetworkResult::no_connection_other(
|
"private route could not be compiled at this time",
|
||||||
"private route could not be compiled at this time",
|
))
|
||||||
))
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// Encrypt routed operation
|
// Encrypt routed operation
|
||||||
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
||||||
@ -917,7 +918,7 @@ impl RPCProcessor {
|
|||||||
opt_sender_nr,
|
opt_sender_nr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RPCMessageHeaderDetail::PrivateRoute(detail) => {
|
RPCMessageHeaderDetail::PrivateRoute(_) => {
|
||||||
// Decode the RPC message
|
// Decode the RPC message
|
||||||
let operation = {
|
let operation = {
|
||||||
let reader = capnp::message::Reader::new(encoded_msg.data, Default::default());
|
let reader = capnp::message::Reader::new(encoded_msg.data, Default::default());
|
||||||
|
@ -31,8 +31,14 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
||||||
pub(crate) async fn process_node_info_update(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
pub(crate) async fn process_node_info_update(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
||||||
let sender_node_id = msg.header.envelope.get_sender_id();
|
let detail = match msg.header.detail {
|
||||||
let routing_domain = msg.header.routing_domain;
|
RPCMessageHeaderDetail::Direct(detail) => detail,
|
||||||
|
RPCMessageHeaderDetail::PrivateRoute(_) => {
|
||||||
|
return Err(RPCError::protocol("node_info_update must be direct"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let sender_node_id = detail.envelope.get_sender_id();
|
||||||
|
let routing_domain = detail.routing_domain;
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let node_info_update = match msg.operation.into_kind() {
|
let node_info_update = match msg.operation.into_kind() {
|
||||||
|
@ -33,11 +33,23 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Handle it
|
// Handle it
|
||||||
let network_manager = self.network_manager();
|
let network_manager = self.network_manager();
|
||||||
network_result_value_or_log!(debug
|
|
||||||
network_manager
|
match msg.header.detail {
|
||||||
.handle_in_band_receipt(receipt, msg.header.peer_noderef)
|
RPCMessageHeaderDetail::Direct(detail) => {
|
||||||
.await => {}
|
network_result_value_or_log!(debug
|
||||||
);
|
network_manager
|
||||||
|
.handle_in_band_receipt(receipt, detail.peer_noderef)
|
||||||
|
.await => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
RPCMessageHeaderDetail::PrivateRoute(detail) => {
|
||||||
|
network_result_value_or_log!(debug
|
||||||
|
network_manager
|
||||||
|
.handle_private_receipt(receipt)
|
||||||
|
.await => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -170,8 +170,13 @@ impl RPCProcessor {
|
|||||||
// If the private route public key is our node id, then this was sent via safety route to our node directly
|
// If the private route public key is our node id, then this was sent via safety route to our node directly
|
||||||
// so there will be no signatures to validate
|
// so there will be no signatures to validate
|
||||||
let opt_pr_info = if private_route.public_key == self.routing_table.node_id() {
|
let opt_pr_info = if private_route.public_key == self.routing_table.node_id() {
|
||||||
// the private route was a stub to our own node's secret
|
// The private route was a stub
|
||||||
// return our secret key and an appropriate safety selection
|
// Return our secret key and an appropriate safety selection
|
||||||
|
//
|
||||||
|
// Note: it is important that we never respond with a safety route to questions that come
|
||||||
|
// in without a private route. Giving away a safety route when the node id is known is
|
||||||
|
// a privacy violation!
|
||||||
|
|
||||||
// Get sequencing preference
|
// Get sequencing preference
|
||||||
let sequencing = if detail
|
let sequencing = if detail
|
||||||
.connection_descriptor
|
.connection_descriptor
|
||||||
@ -191,46 +196,45 @@ impl RPCProcessor {
|
|||||||
let sender_id = detail.envelope.get_sender_id();
|
let sender_id = detail.envelope.get_sender_id();
|
||||||
|
|
||||||
// Look up the private route and ensure it's one in our spec store
|
// Look up the private route and ensure it's one in our spec store
|
||||||
let opt_signatures_valid = self.routing_table.with_route_spec_store(|rss, rti| {
|
let rss= self.routing_table.route_spec_store();
|
||||||
rss.with_route_spec_detail(&private_route.public_key, |rsd| {
|
let opt_signatures_valid = rss.with_route_spec_detail(&private_route.public_key, |rsd| {
|
||||||
// Ensure we have the right number of signatures
|
// Ensure we have the right number of signatures
|
||||||
if routed_operation.signatures.len() != rsd.hops.len() - 1 {
|
if routed_operation.signatures.len() != rsd.hops.len() - 1 {
|
||||||
// Wrong number of signatures
|
// Wrong number of signatures
|
||||||
log_rpc!(debug "wrong number of signatures ({} should be {}) for routed operation on private route {}", routed_operation.signatures.len(), rsd.hops.len() - 1, private_route.public_key);
|
log_rpc!(debug "wrong number of signatures ({} should be {}) for routed operation on private route {}", routed_operation.signatures.len(), rsd.hops.len() - 1, private_route.public_key);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Validate signatures to ensure the route was handled by the nodes and not messed with
|
// Validate signatures to ensure the route was handled by the nodes and not messed with
|
||||||
for (hop_n, hop_public_key) in rsd.hops.iter().enumerate() {
|
for (hop_n, hop_public_key) in rsd.hops.iter().enumerate() {
|
||||||
// The last hop is not signed, as the whole packet is signed
|
// The last hop is not signed, as the whole packet is signed
|
||||||
if hop_n == routed_operation.signatures.len() {
|
if hop_n == routed_operation.signatures.len() {
|
||||||
// Verify the node we received the routed operation from is the last hop in our route
|
// Verify the node we received the routed operation from is the last hop in our route
|
||||||
if *hop_public_key != sender_id {
|
if *hop_public_key != sender_id {
|
||||||
log_rpc!(debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_public_key.encode(), sender_id.encode(), private_route.public_key);
|
log_rpc!(debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_public_key.encode(), sender_id.encode(), private_route.public_key);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Verify a signature for a hop node along the route
|
// Verify a signature for a hop node along the route
|
||||||
if let Err(e) = verify(
|
if let Err(e) = verify(
|
||||||
hop_public_key,
|
hop_public_key,
|
||||||
&routed_operation.data,
|
&routed_operation.data,
|
||||||
&routed_operation.signatures[hop_n],
|
&routed_operation.signatures[hop_n],
|
||||||
) {
|
) {
|
||||||
log_rpc!(debug "failed to verify signature for hop {} at {} on private route {}", hop_n, hop_public_key, private_route.public_key);
|
log_rpc!(debug "failed to verify signature for hop {} at {} on private route {}", hop_n, hop_public_key, private_route.public_key);
|
||||||
return None;
|
return None;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We got the correct signatures, return a key ans
|
}
|
||||||
Some((
|
// We got the correct signatures, return a key ans
|
||||||
rsd.secret_key,
|
Some((
|
||||||
SafetySelection::Safe(SafetySpec {
|
rsd.secret_key,
|
||||||
preferred_route: Some(private_route.public_key),
|
SafetySelection::Safe(SafetySpec {
|
||||||
hop_count: rsd.hops.len(),
|
preferred_route: Some(private_route.public_key),
|
||||||
stability: rsd.stability,
|
hop_count: rsd.hops.len(),
|
||||||
sequencing: rsd.sequencing,
|
stability: rsd.stability,
|
||||||
})
|
sequencing: rsd.sequencing,
|
||||||
))
|
})
|
||||||
})
|
))
|
||||||
});
|
});
|
||||||
opt_signatures_valid.ok_or_else(|| {
|
opt_signatures_valid.ok_or_else(|| {
|
||||||
RPCError::protocol("routed operation received on unallocated private route")
|
RPCError::protocol("routed operation received on unallocated private route")
|
||||||
|
@ -32,7 +32,7 @@ impl RPCProcessor {
|
|||||||
// Handle it
|
// Handle it
|
||||||
let network_manager = self.network_manager();
|
let network_manager = self.network_manager();
|
||||||
network_result_value_or_log!(debug network_manager
|
network_result_value_or_log!(debug network_manager
|
||||||
.handle_signal(msg.header.envelope.get_sender_id(), signal.signal_info)
|
.handle_signal(signal.signal_info)
|
||||||
.await
|
.await
|
||||||
.map_err(RPCError::network)? => {
|
.map_err(RPCError::network)? => {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -103,8 +103,15 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id, res), err)]
|
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id, res), err)]
|
||||||
pub(crate) async fn process_status_q(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
pub(crate) async fn process_status_q(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
||||||
let connection_descriptor = msg.header.connection_descriptor;
|
let detail = match &msg.header.detail {
|
||||||
let routing_domain = msg.header.routing_domain;
|
RPCMessageHeaderDetail::Direct(detail) => detail,
|
||||||
|
RPCMessageHeaderDetail::PrivateRoute(_) => {
|
||||||
|
return Err(RPCError::protocol("status_q must be direct"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection_descriptor = detail.connection_descriptor;
|
||||||
|
let routing_domain = detail.routing_domain;
|
||||||
|
|
||||||
// Get the question
|
// Get the question
|
||||||
let status_q = match msg.operation.kind() {
|
let status_q = match msg.operation.kind() {
|
||||||
|
@ -34,7 +34,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Wait for receipt
|
// Wait for receipt
|
||||||
match eventual_value.await.take_value().unwrap() {
|
match eventual_value.await.take_value().unwrap() {
|
||||||
ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => {
|
ReceiptEvent::ReturnedPrivate | ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => {
|
||||||
log_net!(debug "validate_dial_info receipt should be returned out-of-band".green());
|
log_net!(debug "validate_dial_info receipt should be returned out-of-band".green());
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
@ -54,6 +54,13 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
||||||
pub(crate) async fn process_validate_dial_info(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
pub(crate) async fn process_validate_dial_info(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
||||||
|
let detail = match msg.header.detail {
|
||||||
|
RPCMessageHeaderDetail::Direct(detail) => detail,
|
||||||
|
RPCMessageHeaderDetail::PrivateRoute(_) => {
|
||||||
|
return Err(RPCError::protocol("validate_dial_info must be direct"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Get the statement
|
// Get the statement
|
||||||
let RPCOperationValidateDialInfo {
|
let RPCOperationValidateDialInfo {
|
||||||
dial_info,
|
dial_info,
|
||||||
@ -74,8 +81,8 @@ impl RPCProcessor {
|
|||||||
// Use the address type though, to ensure we reach an ipv6 capable node if this is
|
// Use the address type though, to ensure we reach an ipv6 capable node if this is
|
||||||
// an ipv6 address
|
// an ipv6 address
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let sender_id = msg.header.envelope.get_sender_id();
|
let sender_id = detail.envelope.get_sender_id();
|
||||||
let routing_domain = msg.header.routing_domain;
|
let routing_domain = detail.routing_domain;
|
||||||
let node_count = {
|
let node_count = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
c.network.dht.max_find_node_count as usize
|
c.network.dht.max_find_node_count as usize
|
||||||
@ -141,8 +148,6 @@ impl RPCProcessor {
|
|||||||
.await
|
.await
|
||||||
.map_err(RPCError::network)?;
|
.map_err(RPCError::network)?;
|
||||||
|
|
||||||
// tracing::Span::current().record("res", &tracing::field::display(res));
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user