mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-02-08 18:58:32 -05:00
more route work
This commit is contained in:
parent
c8ba88fb99
commit
a1b40c79f1
@ -1182,7 +1182,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Dial info filter comes from the target node ref
|
// Dial info filter comes from the target node ref
|
||||||
let dial_info_filter = target_node_ref.dial_info_filter();
|
let dial_info_filter = target_node_ref.dial_info_filter();
|
||||||
let reliable = target_node_ref.reliable();
|
let sequencing = target_node_ref.sequencing();
|
||||||
|
|
||||||
let cm = routing_table.get_contact_method(
|
let cm = routing_table.get_contact_method(
|
||||||
routing_domain,
|
routing_domain,
|
||||||
@ -1191,7 +1191,7 @@ impl NetworkManager {
|
|||||||
&node_b_id,
|
&node_b_id,
|
||||||
&node_b,
|
&node_b,
|
||||||
dial_info_filter,
|
dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Translate the raw contact method to a referenced contact method
|
// Translate the raw contact method to a referenced contact method
|
||||||
|
@ -263,7 +263,7 @@ impl RoutingTable {
|
|||||||
node_b_id: &DHTKey,
|
node_b_id: &DHTKey,
|
||||||
node_b: &NodeInfo,
|
node_b: &NodeInfo,
|
||||||
dial_info_filter: DialInfoFilter,
|
dial_info_filter: DialInfoFilter,
|
||||||
reliable: bool,
|
sequencing: Sequencing,
|
||||||
) -> ContactMethod {
|
) -> ContactMethod {
|
||||||
self.inner.read().get_contact_method(
|
self.inner.read().get_contact_method(
|
||||||
routing_domain,
|
routing_domain,
|
||||||
@ -272,7 +272,7 @@ impl RoutingTable {
|
|||||||
node_b_id,
|
node_b_id,
|
||||||
node_b,
|
node_b,
|
||||||
dial_info_filter,
|
dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,7 +836,7 @@ impl RoutingTable {
|
|||||||
.node_info(RoutingDomain::PublicInternet)
|
.node_info(RoutingDomain::PublicInternet)
|
||||||
.map(|n| {
|
.map(|n| {
|
||||||
let dids = n.all_filtered_dial_info_details(
|
let dids = n.all_filtered_dial_info_details(
|
||||||
Some(DialInfoDetail::reliable_sort), // By default, choose reliable protocol for relay
|
Some(DialInfoDetail::ordered_sequencing_sort), // By default, choose connection-oriented protocol for relay
|
||||||
|did| did.matches_filter(&outbound_dif),
|
|did| did.matches_filter(&outbound_dif),
|
||||||
);
|
);
|
||||||
for did in &dids {
|
for did in &dids {
|
||||||
@ -889,6 +889,7 @@ impl RoutingTable {
|
|||||||
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
|
if let Some(best_inbound_relay) = best_inbound_relay.as_mut() {
|
||||||
// Less is faster
|
// Less is faster
|
||||||
let better = best_inbound_relay.1.with(rti, |_rti, best| {
|
let better = best_inbound_relay.1.with(rti, |_rti, best| {
|
||||||
|
// choose low latency stability for relays
|
||||||
BucketEntryInner::cmp_fastest_reliable(cur_ts, e, best)
|
BucketEntryInner::cmp_fastest_reliable(cur_ts, e, best)
|
||||||
== std::cmp::Ordering::Less
|
== std::cmp::Ordering::Less
|
||||||
});
|
});
|
||||||
|
@ -71,7 +71,7 @@ pub struct NodeRef {
|
|||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
entry: Arc<BucketEntry>,
|
entry: Arc<BucketEntry>,
|
||||||
filter: Option<NodeRefFilter>,
|
filter: Option<NodeRefFilter>,
|
||||||
reliable: bool,
|
sequencing: Sequencing,
|
||||||
#[cfg(feature = "tracking")]
|
#[cfg(feature = "tracking")]
|
||||||
track_id: usize,
|
track_id: usize,
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ impl NodeRef {
|
|||||||
node_id,
|
node_id,
|
||||||
entry,
|
entry,
|
||||||
filter,
|
filter,
|
||||||
reliable: false,
|
sequencing: Sequencing::NoPreference,
|
||||||
#[cfg(feature = "tracking")]
|
#[cfg(feature = "tracking")]
|
||||||
track_id: entry.track(),
|
track_id: entry.track(),
|
||||||
}
|
}
|
||||||
@ -127,11 +127,11 @@ impl NodeRef {
|
|||||||
self.filter = filter
|
self.filter = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_reliable(&mut self) {
|
pub fn set_sequencing(&mut self, sequencing: Sequencing) {
|
||||||
self.reliable = true;
|
self.sequencing = sequencing;
|
||||||
}
|
}
|
||||||
pub fn reliable(&self) -> bool {
|
pub fn sequencing(&self) -> Sequencing {
|
||||||
self.reliable
|
self.sequencing
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge_filter(&mut self, filter: NodeRefFilter) {
|
pub fn merge_filter(&mut self, filter: NodeRefFilter) {
|
||||||
@ -278,10 +278,18 @@ impl NodeRef {
|
|||||||
let routing_domain_set = self.routing_domain_set();
|
let routing_domain_set = self.routing_domain_set();
|
||||||
let dial_info_filter = self.dial_info_filter();
|
let dial_info_filter = self.dial_info_filter();
|
||||||
|
|
||||||
let sort = if self.reliable {
|
let (sort, dial_info_filter) = match self.sequencing {
|
||||||
Some(DialInfoDetail::reliable_sort)
|
Sequencing::NoPreference => (None, dial_info_filter),
|
||||||
} else {
|
Sequencing::PreferOrdered => (
|
||||||
None
|
Some(DialInfoDetail::ordered_sequencing_sort),
|
||||||
|
dial_info_filter,
|
||||||
|
),
|
||||||
|
Sequencing::EnsureOrdered => (
|
||||||
|
Some(DialInfoDetail::ordered_sequencing_sort),
|
||||||
|
dial_info_filter.filtered(
|
||||||
|
&DialInfoFilter::all().with_protocol_type_set(ProtocolType::all_ordered_set()),
|
||||||
|
),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.operate(|_rt, e| {
|
self.operate(|_rt, e| {
|
||||||
@ -301,10 +309,18 @@ impl NodeRef {
|
|||||||
let routing_domain_set = self.routing_domain_set();
|
let routing_domain_set = self.routing_domain_set();
|
||||||
let dial_info_filter = self.dial_info_filter();
|
let dial_info_filter = self.dial_info_filter();
|
||||||
|
|
||||||
let sort = if self.reliable {
|
let (sort, dial_info_filter) = match self.sequencing {
|
||||||
Some(DialInfoDetail::reliable_sort)
|
Sequencing::NoPreference => (None, dial_info_filter),
|
||||||
} else {
|
Sequencing::PreferOrdered => (
|
||||||
None
|
Some(DialInfoDetail::ordered_sequencing_sort),
|
||||||
|
dial_info_filter,
|
||||||
|
),
|
||||||
|
Sequencing::EnsureOrdered => (
|
||||||
|
Some(DialInfoDetail::ordered_sequencing_sort),
|
||||||
|
dial_info_filter.filtered(
|
||||||
|
&DialInfoFilter::all().with_protocol_type_set(ProtocolType::all_ordered_set()),
|
||||||
|
),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -418,20 +434,20 @@ impl Clone for NodeRef {
|
|||||||
node_id: self.node_id,
|
node_id: self.node_id,
|
||||||
entry: self.entry.clone(),
|
entry: self.entry.clone(),
|
||||||
filter: self.filter.clone(),
|
filter: self.filter.clone(),
|
||||||
reliable: self.reliable,
|
sequencing: self.sequencing,
|
||||||
#[cfg(feature = "tracking")]
|
#[cfg(feature = "tracking")]
|
||||||
track_id: e.track(),
|
track_id: e.track(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for NodeRef {
|
// impl PartialEq for NodeRef {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
// fn eq(&self, other: &Self) -> bool {
|
||||||
self.node_id == other.node_id
|
// self.node_id == other.node_id
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Eq for NodeRef {}
|
// impl Eq for NodeRef {}
|
||||||
|
|
||||||
impl fmt::Display for NodeRef {
|
impl fmt::Display for NodeRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
@ -444,6 +460,7 @@ impl fmt::Debug for NodeRef {
|
|||||||
f.debug_struct("NodeRef")
|
f.debug_struct("NodeRef")
|
||||||
.field("node_id", &self.node_id)
|
.field("node_id", &self.node_id)
|
||||||
.field("filter", &self.filter)
|
.field("filter", &self.filter)
|
||||||
|
.field("sequencing", &self.sequencing)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,10 @@ pub struct SafetySpec {
|
|||||||
pub preferred_route: Option<DHTKey>,
|
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 reliability over speed
|
||||||
pub reliable: bool,
|
pub stability: Stability,
|
||||||
|
/// prefer connection-oriented sequenced protocols
|
||||||
|
pub sequencing: Sequencing,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compiled route (safety route + private route)
|
/// Compiled route (safety route + private route)
|
||||||
@ -59,8 +61,10 @@ struct RouteSpecDetail {
|
|||||||
last_used_ts: Option<u64>,
|
last_used_ts: Option<u64>,
|
||||||
/// Directions this route is guaranteed to work in
|
/// Directions this route is guaranteed to work in
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
/// Reliability
|
/// Stability preference (prefer reliable nodes over faster)
|
||||||
reliable: bool,
|
stability: Stability,
|
||||||
|
/// Sequencing preference (connection oriented protocols vs datagram)
|
||||||
|
sequencing: Sequencing,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The core representation of the RouteSpecStore that can be serialized
|
/// The core representation of the RouteSpecStore that can be serialized
|
||||||
@ -81,6 +85,7 @@ 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 RouteSpecStore {
|
||||||
/// Maximum number of hops in a route
|
/// Maximum number of hops in a route
|
||||||
@ -93,6 +98,15 @@ pub struct RouteSpecStore {
|
|||||||
cache: RouteSpecStoreCache,
|
cache: RouteSpecStoreCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The choice of safety route including in compiled routes
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum SafetySelection {
|
||||||
|
/// Don't use a safety route, only specify the sequencing preference
|
||||||
|
Unsafe(Sequencing),
|
||||||
|
/// Use a safety route and parameters specified by a SafetySpec
|
||||||
|
Safe(SafetySpec),
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
for hop in hops {
|
for hop in hops {
|
||||||
@ -293,7 +307,8 @@ impl RouteSpecStore {
|
|||||||
&mut self,
|
&mut self,
|
||||||
rti: &RoutingTableInner,
|
rti: &RoutingTableInner,
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
reliable: bool,
|
stability: Stability,
|
||||||
|
sequencing: Sequencing,
|
||||||
hop_count: usize,
|
hop_count: usize,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
) -> EyreResult<Option<DHTKey>> {
|
) -> EyreResult<Option<DHTKey>> {
|
||||||
@ -327,7 +342,7 @@ impl RouteSpecStore {
|
|||||||
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
||||||
v.with(rti, |_rti, e| {
|
v.with(rti, |_rti, e| {
|
||||||
let node_info_ok = if let Some(ni) = e.node_info(RoutingDomain::PublicInternet) {
|
let node_info_ok = if let Some(ni) = e.node_info(RoutingDomain::PublicInternet) {
|
||||||
ni.has_any_dial_info()
|
ni.has_sequencing_matched_dial_info(sequencing)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@ -383,12 +398,15 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
// always prioritize reliable nodes, but sort by oldest or fastest
|
// always prioritize reliable nodes, but sort by oldest or fastest
|
||||||
let cmpout = v1.1.as_ref().unwrap().with(rti, |rti, e1| {
|
let cmpout = v1.1.as_ref().unwrap().with(rti, |rti, e1| {
|
||||||
v2.1.as_ref().unwrap().with(rti, |_rti, e2| {
|
v2.1.as_ref()
|
||||||
if reliable {
|
.unwrap()
|
||||||
BucketEntryInner::cmp_oldest_reliable(cur_ts, e1, e2)
|
.with(rti, |_rti, e2| match stability {
|
||||||
} else {
|
Stability::LowLatency => {
|
||||||
BucketEntryInner::cmp_fastest_reliable(cur_ts, e1, e2)
|
BucketEntryInner::cmp_fastest_reliable(cur_ts, e1, e2)
|
||||||
}
|
}
|
||||||
|
Stability::Reliable => {
|
||||||
|
BucketEntryInner::cmp_oldest_reliable(cur_ts, e1, e2)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
cmpout
|
cmpout
|
||||||
@ -448,7 +466,7 @@ impl RouteSpecStore {
|
|||||||
¤t_node.0,
|
¤t_node.0,
|
||||||
¤t_node.1,
|
¤t_node.1,
|
||||||
DialInfoFilter::all(),
|
DialInfoFilter::all(),
|
||||||
reliable,
|
sequencing,
|
||||||
);
|
);
|
||||||
if matches!(cm, ContactMethod::Unreachable) {
|
if matches!(cm, ContactMethod::Unreachable) {
|
||||||
reachable = false;
|
reachable = false;
|
||||||
@ -474,7 +492,7 @@ impl RouteSpecStore {
|
|||||||
¤t_node.0,
|
¤t_node.0,
|
||||||
¤t_node.1,
|
¤t_node.1,
|
||||||
DialInfoFilter::all(),
|
DialInfoFilter::all(),
|
||||||
reliable,
|
sequencing,
|
||||||
);
|
);
|
||||||
if matches!(cm, ContactMethod::Unreachable) {
|
if matches!(cm, ContactMethod::Unreachable) {
|
||||||
reachable = false;
|
reachable = false;
|
||||||
@ -525,7 +543,8 @@ impl RouteSpecStore {
|
|||||||
last_checked_ts: None,
|
last_checked_ts: None,
|
||||||
last_used_ts: None,
|
last_used_ts: None,
|
||||||
directions,
|
directions,
|
||||||
reliable,
|
stability,
|
||||||
|
sequencing,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add to cache
|
// Add to cache
|
||||||
@ -575,15 +594,18 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find first matching unpublished route that fits into the selection criteria
|
||||||
pub fn first_unpublished_route(
|
pub fn first_unpublished_route(
|
||||||
&mut self,
|
&mut self,
|
||||||
reliable: bool,
|
|
||||||
min_hop_count: usize,
|
min_hop_count: usize,
|
||||||
max_hop_count: usize,
|
max_hop_count: usize,
|
||||||
|
stability: Stability,
|
||||||
|
sequencing: Sequencing,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
) -> Option<DHTKey> {
|
) -> Option<DHTKey> {
|
||||||
for detail in &self.content.details {
|
for detail in &self.content.details {
|
||||||
if detail.1.reliable == reliable
|
if detail.1.stability >= stability
|
||||||
|
&& detail.1.sequencing >= sequencing
|
||||||
&& detail.1.hops.len() >= min_hop_count
|
&& detail.1.hops.len() >= min_hop_count
|
||||||
&& detail.1.hops.len() <= max_hop_count
|
&& detail.1.hops.len() <= max_hop_count
|
||||||
&& detail.1.directions.is_subset(directions)
|
&& detail.1.directions.is_subset(directions)
|
||||||
@ -602,46 +624,54 @@ impl RouteSpecStore {
|
|||||||
/// 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,
|
&mut self,
|
||||||
rti: &RoutingTableInner,
|
rti: &mut RoutingTableInner,
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
safety_spec: Option<SafetySpec>,
|
safety_selection: SafetySelection,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
) -> Result<Option<CompiledRoute>, RPCError> {
|
) -> Result<Option<CompiledRoute>, RPCError> {
|
||||||
let pr_hopcount = private_route.hop_count as usize;
|
let pr_hopcount = private_route.hop_count as usize;
|
||||||
if pr_hopcount > self.max_route_hop_count {
|
let max_route_hop_count = self.max_route_hop_count;
|
||||||
|
if pr_hopcount > max_route_hop_count {
|
||||||
return Err(RPCError::internal("private route hop count too long"));
|
return Err(RPCError::internal("private route hop count too long"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we are using a safety route, if not, short circuit this operation
|
// See if we are using a safety route, if not, short circuit this operation
|
||||||
if safety_spec.is_none() {
|
let safety_spec = match safety_selection {
|
||||||
|
SafetySelection::Unsafe(sequencing) => {
|
||||||
// Safety route stub with the node's public key as the safety route key since it's the 0th hop
|
// Safety route stub with the node's public key as the safety route key since it's the 0th hop
|
||||||
if private_route.first_hop.is_none() {
|
if private_route.first_hop.is_none() {
|
||||||
return Err(RPCError::internal("can't compile zero length route"));
|
return Err(RPCError::internal("can't compile zero length route"));
|
||||||
}
|
}
|
||||||
let first_hop = private_route.first_hop.as_ref().unwrap();
|
let first_hop = private_route.first_hop.as_ref().unwrap();
|
||||||
let opt_first_hop_noderef = match &first_hop.node {
|
let opt_first_hop = match &first_hop.node {
|
||||||
RouteNode::NodeId(id) => rti.lookup_node_ref(routing_table, id.key),
|
RouteNode::NodeId(id) => rti.lookup_node_ref(routing_table.clone(), id.key),
|
||||||
RouteNode::PeerInfo(pi) => rti.register_node_with_signed_node_info(
|
RouteNode::PeerInfo(pi) => rti.register_node_with_signed_node_info(
|
||||||
routing_table.clone(),
|
routing_table.clone(),
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
pi.node_id.key,
|
pi.node_id.key,
|
||||||
pi.signed_node_info,
|
pi.signed_node_info.clone(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
if opt_first_hop_noderef.is_none() {
|
if opt_first_hop.is_none() {
|
||||||
// Can't reach this private route any more
|
// Can't reach this private route any more
|
||||||
log_rtab!(debug "can't reach private route any more");
|
log_rtab!(debug "can't reach private route any more");
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
let mut first_hop = opt_first_hop.unwrap();
|
||||||
|
|
||||||
|
// Set sequencing requirement
|
||||||
|
first_hop.set_sequencing(sequencing);
|
||||||
|
|
||||||
|
// Return the compiled safety route
|
||||||
return Ok(Some(CompiledRoute {
|
return Ok(Some(CompiledRoute {
|
||||||
safety_route: SafetyRoute::new_stub(routing_table.node_id(), private_route),
|
safety_route: SafetyRoute::new_stub(routing_table.node_id(), private_route),
|
||||||
secret: routing_table.node_id_secret(),
|
secret: routing_table.node_id_secret(),
|
||||||
first_hop: opt_first_hop_noderef.unwrap(),
|
first_hop,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
let safety_spec = safety_spec.unwrap();
|
SafetySelection::Safe(safety_spec) => safety_spec,
|
||||||
|
};
|
||||||
|
|
||||||
// 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)> =
|
||||||
@ -658,9 +688,10 @@ impl RouteSpecStore {
|
|||||||
} else {
|
} else {
|
||||||
// Select a safety route from the pool or make one if we don't have one that matches
|
// 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(
|
if let Some(sr_pubkey) = self.first_unpublished_route(
|
||||||
safety_spec.reliable,
|
|
||||||
safety_spec.hop_count,
|
safety_spec.hop_count,
|
||||||
safety_spec.hop_count,
|
safety_spec.hop_count,
|
||||||
|
safety_spec.stability,
|
||||||
|
safety_spec.sequencing,
|
||||||
Direction::Outbound.into(),
|
Direction::Outbound.into(),
|
||||||
) {
|
) {
|
||||||
// Found a route to use
|
// Found a route to use
|
||||||
@ -671,7 +702,8 @@ impl RouteSpecStore {
|
|||||||
.allocate_route(
|
.allocate_route(
|
||||||
rti,
|
rti,
|
||||||
routing_table.clone(),
|
routing_table.clone(),
|
||||||
safety_spec.reliable,
|
safety_spec.stability,
|
||||||
|
safety_spec.sequencing,
|
||||||
safety_spec.hop_count,
|
safety_spec.hop_count,
|
||||||
Direction::Outbound.into(),
|
Direction::Outbound.into(),
|
||||||
)
|
)
|
||||||
@ -689,7 +721,7 @@ impl RouteSpecStore {
|
|||||||
if sr_hopcount == 0 {
|
if sr_hopcount == 0 {
|
||||||
return Err(RPCError::internal("safety route hop count is zero"));
|
return Err(RPCError::internal("safety route hop count is zero"));
|
||||||
}
|
}
|
||||||
if sr_hopcount > self.max_route_hop_count {
|
if sr_hopcount > max_route_hop_count {
|
||||||
return Err(RPCError::internal("safety route hop count too long"));
|
return Err(RPCError::internal("safety route hop count too long"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,7 +779,7 @@ impl RouteSpecStore {
|
|||||||
let node_id = safety_rsd.hops[h];
|
let node_id = safety_rsd.hops[h];
|
||||||
let pi = rti
|
let pi = rti
|
||||||
.with_node_entry(node_id, |entry| {
|
.with_node_entry(node_id, |entry| {
|
||||||
entry.with(rti, |rti, e| {
|
entry.with(rti, |_rti, e| {
|
||||||
e.make_peer_info(node_id, RoutingDomain::PublicInternet)
|
e.make_peer_info(node_id, RoutingDomain::PublicInternet)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -800,14 +832,21 @@ impl RouteSpecStore {
|
|||||||
hops,
|
hops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut first_hop = safety_rsd.hop_node_refs.first().unwrap().clone();
|
||||||
|
|
||||||
|
// Ensure sequencing requirement is set on first hop
|
||||||
|
first_hop.set_sequencing(safety_spec.sequencing);
|
||||||
|
|
||||||
|
// Build compiled route
|
||||||
let compiled_route = CompiledRoute {
|
let compiled_route = CompiledRoute {
|
||||||
safety_route,
|
safety_route,
|
||||||
secret: safety_rsd.secret_key,
|
secret: safety_rsd.secret_key,
|
||||||
first_hop: safety_rsd.hop_node_refs.first().unwrap().clone(),
|
first_hop,
|
||||||
};
|
};
|
||||||
|
|
||||||
// xxx: add cache here
|
// xxx: add cache here
|
||||||
|
|
||||||
|
// Return compiled route
|
||||||
Ok(Some(compiled_route))
|
Ok(Some(compiled_route))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ pub trait RoutingDomainDetail {
|
|||||||
node_b_id: &DHTKey,
|
node_b_id: &DHTKey,
|
||||||
node_b: &NodeInfo,
|
node_b: &NodeInfo,
|
||||||
dial_info_filter: DialInfoFilter,
|
dial_info_filter: DialInfoFilter,
|
||||||
reliable: bool,
|
sequencing: Sequencing,
|
||||||
) -> ContactMethod;
|
) -> ContactMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ fn first_filtered_dial_info_detail(
|
|||||||
from_node: &NodeInfo,
|
from_node: &NodeInfo,
|
||||||
to_node: &NodeInfo,
|
to_node: &NodeInfo,
|
||||||
dial_info_filter: &DialInfoFilter,
|
dial_info_filter: &DialInfoFilter,
|
||||||
reliable: bool,
|
reliable: bool, xxx continue here
|
||||||
) -> Option<DialInfoDetail> {
|
) -> Option<DialInfoDetail> {
|
||||||
let direct_dial_info_filter = dial_info_filter.clone().filtered(
|
let direct_dial_info_filter = dial_info_filter.clone().filtered(
|
||||||
&DialInfoFilter::all()
|
&DialInfoFilter::all()
|
||||||
@ -214,7 +214,7 @@ fn first_filtered_dial_info_detail(
|
|||||||
|
|
||||||
// Get first filtered dialinfo
|
// Get first filtered dialinfo
|
||||||
let sort = if reliable {
|
let sort = if reliable {
|
||||||
Some(DialInfoDetail::reliable_sort)
|
Some(DialInfoDetail::ordered_sequencing_sort)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -428,7 +428,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
|
|||||||
|
|
||||||
// Get first filtered dialinfo
|
// Get first filtered dialinfo
|
||||||
let sort = if reliable {
|
let sort = if reliable {
|
||||||
Some(DialInfoDetail::reliable_sort)
|
Some(DialInfoDetail::ordered_sequencing_sort)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -224,7 +224,7 @@ impl RoutingTableInner {
|
|||||||
node_b_id: &DHTKey,
|
node_b_id: &DHTKey,
|
||||||
node_b: &NodeInfo,
|
node_b: &NodeInfo,
|
||||||
dial_info_filter: DialInfoFilter,
|
dial_info_filter: DialInfoFilter,
|
||||||
reliable: bool,
|
sequencing: Sequencing,
|
||||||
) -> ContactMethod {
|
) -> ContactMethod {
|
||||||
self.with_routing_domain(routing_domain, |rdd| {
|
self.with_routing_domain(routing_domain, |rdd| {
|
||||||
rdd.get_contact_method(
|
rdd.get_contact_method(
|
||||||
@ -234,7 +234,7 @@ impl RoutingTableInner {
|
|||||||
node_b_id,
|
node_b_id,
|
||||||
node_b,
|
node_b,
|
||||||
dial_info_filter,
|
dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -402,6 +402,7 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
safety_spec: Option<SafetySpec>,
|
safety_spec: Option<SafetySpec>,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
|
reliable: bool,
|
||||||
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();
|
||||||
@ -411,7 +412,7 @@ impl RPCProcessor {
|
|||||||
let compiled_route: CompiledRoute =
|
let compiled_route: CompiledRoute =
|
||||||
match self.routing_table().with_route_spec_store_mut(|rss, rti| {
|
match self.routing_table().with_route_spec_store_mut(|rss, rti| {
|
||||||
// Compile the safety route with the private route
|
// Compile the safety route with the private route
|
||||||
rss.compile_safety_route(rti, routing_table, safety_spec, private_route)
|
rss.compile_safety_route(rti, routing_table, safety_spec, private_route, reliable)
|
||||||
})? {
|
})? {
|
||||||
Some(cr) => cr,
|
Some(cr) => cr,
|
||||||
None => {
|
None => {
|
||||||
@ -455,6 +456,7 @@ impl RPCProcessor {
|
|||||||
let out_node_id = compiled_route.first_hop.node_id();
|
let out_node_id = compiled_route.first_hop.node_id();
|
||||||
let out_hop_count = (1 + sr_hop_count + pr_hop_count) as usize;
|
let out_hop_count = (1 + sr_hop_count + pr_hop_count) as usize;
|
||||||
|
|
||||||
|
|
||||||
let out = RenderedOperation {
|
let out = RenderedOperation {
|
||||||
message: out_message,
|
message: out_message,
|
||||||
node_id: out_node_id,
|
node_id: out_node_id,
|
||||||
@ -537,12 +539,12 @@ impl RPCProcessor {
|
|||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec,
|
safety_spec,
|
||||||
reliable,
|
reliable, xxxx does this need to be here? what about None safety spec, reliable is in there, does it need to not be? or something?
|
||||||
} => {
|
} => {
|
||||||
// Send to private route
|
// Send to private route
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// Reply with 'route' operation
|
// Reply with 'route' operation
|
||||||
out = self.wrap_with_route(safety_spec, private_route, message)?;
|
out = self.wrap_with_route(safety_spec, private_route, reliable, message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,6 +405,21 @@ impl DialInfoClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ordering here matters, >= is used to check strength of sequencing requirement
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum Sequencing {
|
||||||
|
NoPreference,
|
||||||
|
PreferOrdered,
|
||||||
|
EnsureOrdered,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordering here matters, >= is used to check strength of stability requirement
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum Stability {
|
||||||
|
LowLatency,
|
||||||
|
Reliable,
|
||||||
|
}
|
||||||
|
|
||||||
// Keep member order appropriate for sorting < preference
|
// Keep member order appropriate for sorting < preference
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize, Hash)]
|
||||||
pub struct DialInfoDetail {
|
pub struct DialInfoDetail {
|
||||||
@ -419,14 +434,14 @@ impl MatchesDialInfoFilter for DialInfoDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DialInfoDetail {
|
impl DialInfoDetail {
|
||||||
pub fn reliable_sort(a: &DialInfoDetail, b: &DialInfoDetail) -> core::cmp::Ordering {
|
pub fn ordered_sequencing_sort(a: &DialInfoDetail, b: &DialInfoDetail) -> core::cmp::Ordering {
|
||||||
if a.class < b.class {
|
if a.class < b.class {
|
||||||
return core::cmp::Ordering::Less;
|
return core::cmp::Ordering::Less;
|
||||||
}
|
}
|
||||||
if a.class > b.class {
|
if a.class > b.class {
|
||||||
return core::cmp::Ordering::Greater;
|
return core::cmp::Ordering::Greater;
|
||||||
}
|
}
|
||||||
DialInfo::reliable_sort(&a.dial_info, &b.dial_info)
|
DialInfo::ordered_sequencing_sort(&a.dial_info, &b.dial_info)
|
||||||
}
|
}
|
||||||
pub const NO_SORT: std::option::Option<
|
pub const NO_SORT: std::option::Option<
|
||||||
for<'r, 's> fn(
|
for<'r, 's> fn(
|
||||||
@ -592,6 +607,39 @@ impl NodeInfo {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_sequencing_matched_dial_info(&self, sequencing: Sequencing) -> bool {
|
||||||
|
// Check our dial info
|
||||||
|
for did in &self.dial_info_detail_list {
|
||||||
|
match sequencing {
|
||||||
|
Sequencing::NoPreference | Sequencing::PreferOrdered => return true,
|
||||||
|
Sequencing::EnsureOrdered => {
|
||||||
|
if did.dial_info.protocol_type().is_connection_oriented() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check our relay if we have one
|
||||||
|
return self
|
||||||
|
.relay_peer_info
|
||||||
|
.as_ref()
|
||||||
|
.map(|rpi| {
|
||||||
|
let relay_ni = &rpi.signed_node_info.node_info;
|
||||||
|
for did in relay_ni.dial_info_detail_list {
|
||||||
|
match sequencing {
|
||||||
|
Sequencing::NoPreference | Sequencing::PreferOrdered => return true,
|
||||||
|
Sequencing::EnsureOrdered => {
|
||||||
|
if did.dial_info.protocol_type().is_connection_oriented() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_direct_dial_info(&self) -> bool {
|
pub fn has_direct_dial_info(&self) -> bool {
|
||||||
!self.dial_info_detail_list.is_empty()
|
!self.dial_info_detail_list.is_empty()
|
||||||
}
|
}
|
||||||
@ -693,31 +741,31 @@ impl ProtocolType {
|
|||||||
ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS => LowLevelProtocolType::TCP,
|
ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS => LowLevelProtocolType::TCP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sort_order(&self, reliable: bool) -> usize {
|
pub fn sort_order(&self, sequencing: Sequencing) -> usize {
|
||||||
match self {
|
match self {
|
||||||
ProtocolType::UDP => {
|
ProtocolType::UDP => {
|
||||||
if reliable {
|
if sequencing != Sequencing::NoPreference {
|
||||||
3
|
3
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProtocolType::TCP => {
|
ProtocolType::TCP => {
|
||||||
if reliable {
|
if sequencing != Sequencing::NoPreference {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProtocolType::WS => {
|
ProtocolType::WS => {
|
||||||
if reliable {
|
if sequencing != Sequencing::NoPreference {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProtocolType::WSS => {
|
ProtocolType::WSS => {
|
||||||
if reliable {
|
if sequencing != Sequencing::NoPreference {
|
||||||
2
|
2
|
||||||
} else {
|
} else {
|
||||||
3
|
3
|
||||||
@ -725,6 +773,9 @@ impl ProtocolType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn all_ordered_set() -> ProtocolTypeSet {
|
||||||
|
ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub type ProtocolTypeSet = EnumSet<ProtocolType>;
|
pub type ProtocolTypeSet = EnumSet<ProtocolType>;
|
||||||
|
|
||||||
@ -1499,7 +1550,7 @@ impl DialInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reliable_sort(a: &DialInfo, b: &DialInfo) -> core::cmp::Ordering {
|
pub fn ordered_sequencing_sort(a: &DialInfo, b: &DialInfo) -> core::cmp::Ordering {
|
||||||
let ca = a.protocol_type().sort_order(true);
|
let ca = a.protocol_type().sort_order(true);
|
||||||
let cb = b.protocol_type().sort_order(true);
|
let cb = b.protocol_type().sort_order(true);
|
||||||
if ca < cb {
|
if ca < cb {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user