mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-12-24 06:49:38 -05:00
route work
This commit is contained in:
parent
a1b40c79f1
commit
be55a42878
@ -1021,7 +1021,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// We expect the inbound noderef to be the same as the target noderef
|
// We expect the inbound noderef to be the same as the target noderef
|
||||||
// if they aren't the same, we should error on this and figure out what then hell is up
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
||||||
if target_nr != inbound_nr {
|
if target_nr.node_id() != inbound_nr.node_id() {
|
||||||
bail!("unexpected noderef mismatch on reverse connect");
|
bail!("unexpected noderef mismatch on reverse connect");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,7 +1122,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// We expect the inbound noderef to be the same as the target noderef
|
// We expect the inbound noderef to be the same as the target noderef
|
||||||
// if they aren't the same, we should error on this and figure out what then hell is up
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
||||||
if target_nr != inbound_nr {
|
if target_nr.node_id() != inbound_nr.node_id() {
|
||||||
bail!(
|
bail!(
|
||||||
"unexpected noderef mismatch on hole punch {}, expected {}",
|
"unexpected noderef mismatch on hole punch {}, expected {}",
|
||||||
inbound_nr,
|
inbound_nr,
|
||||||
|
@ -7,7 +7,7 @@ use routing_table::*;
|
|||||||
use stop_token::future::FutureExt;
|
use stop_token::future::FutureExt;
|
||||||
use xx::*;
|
use xx::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ReceiptEvent {
|
pub enum ReceiptEvent {
|
||||||
ReturnedOutOfBand,
|
ReturnedOutOfBand,
|
||||||
ReturnedInBand { inbound_noderef: NodeRef },
|
ReturnedInBand { inbound_noderef: NodeRef },
|
||||||
|
@ -2,18 +2,6 @@ use super::*;
|
|||||||
use crate::veilid_api::*;
|
use crate::veilid_api::*;
|
||||||
use serde::*;
|
use serde::*;
|
||||||
|
|
||||||
/// Options for safety routes (sender privacy)
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
|
||||||
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
|
|
||||||
pub hop_count: usize,
|
|
||||||
/// prefer reliability over speed
|
|
||||||
pub stability: Stability,
|
|
||||||
/// prefer connection-oriented sequenced protocols
|
|
||||||
pub sequencing: Sequencing,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compiled route (safety route + private route)
|
/// Compiled route (safety route + private route)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -98,15 +86,6 @@ 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 {
|
||||||
|
@ -204,21 +204,34 @@ 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, xxx continue here
|
sequencing: Sequencing,
|
||||||
) -> Option<DialInfoDetail> {
|
) -> Option<DialInfoDetail> {
|
||||||
let direct_dial_info_filter = dial_info_filter.clone().filtered(
|
let dial_info_filter = dial_info_filter.clone().filtered(
|
||||||
&DialInfoFilter::all()
|
&DialInfoFilter::all()
|
||||||
.with_address_type_set(from_node.address_types)
|
.with_address_type_set(from_node.address_types)
|
||||||
.with_protocol_type_set(from_node.outbound_protocols),
|
.with_protocol_type_set(from_node.outbound_protocols),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get first filtered dialinfo
|
// Get first filtered dialinfo
|
||||||
let sort = if reliable {
|
let (sort, dial_info_filter) = match sequencing {
|
||||||
Some(DialInfoDetail::ordered_sequencing_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 direct_filter = |did: &DialInfoDetail| did.matches_filter(&direct_dial_info_filter);
|
// If the filter is dead then we won't be able to connect
|
||||||
|
if dial_info_filter.is_dead() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let direct_filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
|
||||||
|
|
||||||
// Get the best match dial info for node B if we have it
|
// Get the best match dial info for node B if we have it
|
||||||
to_node.first_filtered_dial_info_detail(sort, direct_filter)
|
to_node.first_filtered_dial_info_detail(sort, direct_filter)
|
||||||
@ -242,11 +255,11 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
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 {
|
||||||
// Get the best match dial info for node B if we have it
|
// Get the best match dial info for node B if we have it
|
||||||
if let Some(target_did) =
|
if let Some(target_did) =
|
||||||
first_filtered_dial_info_detail(node_a, node_b, &dial_info_filter, reliable)
|
first_filtered_dial_info_detail(node_a, node_b, &dial_info_filter, sequencing)
|
||||||
{
|
{
|
||||||
// Do we need to signal before going inbound?
|
// Do we need to signal before going inbound?
|
||||||
if !target_did.class.requires_signal() {
|
if !target_did.class.requires_signal() {
|
||||||
@ -267,7 +280,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
node_a,
|
node_a,
|
||||||
&inbound_relay.signed_node_info.node_info,
|
&inbound_relay.signed_node_info.node_info,
|
||||||
&dial_info_filter,
|
&dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@ -280,7 +293,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
node_b,
|
node_b,
|
||||||
node_a,
|
node_a,
|
||||||
&dial_info_filter,
|
&dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
) {
|
) {
|
||||||
// Ensure we aren't on the same public IP address (no hairpin nat)
|
// Ensure we aren't on the same public IP address (no hairpin nat)
|
||||||
if reverse_did.dial_info.to_ip_addr()
|
if reverse_did.dial_info.to_ip_addr()
|
||||||
@ -306,14 +319,14 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
node_a,
|
node_a,
|
||||||
node_b,
|
node_b,
|
||||||
&udp_dial_info_filter,
|
&udp_dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
) {
|
) {
|
||||||
// Does node A have a direct udp dialinfo that node B can reach?
|
// Does node A have a direct udp dialinfo that node B can reach?
|
||||||
if let Some(reverse_udp_did) = first_filtered_dial_info_detail(
|
if let Some(reverse_udp_did) = first_filtered_dial_info_detail(
|
||||||
node_b,
|
node_b,
|
||||||
node_a,
|
node_a,
|
||||||
&udp_dial_info_filter,
|
&udp_dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
) {
|
) {
|
||||||
// Ensure we aren't on the same public IP address (no hairpin nat)
|
// Ensure we aren't on the same public IP address (no hairpin nat)
|
||||||
if reverse_udp_did.dial_info.to_ip_addr()
|
if reverse_udp_did.dial_info.to_ip_addr()
|
||||||
@ -341,7 +354,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
|||||||
node_a,
|
node_a,
|
||||||
&inbound_relay.signed_node_info.node_info,
|
&inbound_relay.signed_node_info.node_info,
|
||||||
&dial_info_filter,
|
&dial_info_filter,
|
||||||
reliable,
|
sequencing,
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@ -412,7 +425,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
|
|||||||
_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 {
|
||||||
// Scope the filter down to protocols node A can do outbound
|
// Scope the filter down to protocols node A can do outbound
|
||||||
let dial_info_filter = dial_info_filter.filtered(
|
let dial_info_filter = dial_info_filter.filtered(
|
||||||
@ -421,17 +434,25 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
|
|||||||
.with_protocol_type_set(node_a.outbound_protocols),
|
.with_protocol_type_set(node_a.outbound_protocols),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get first filtered dialinfo
|
||||||
|
let (sort, dial_info_filter) = match sequencing {
|
||||||
|
Sequencing::NoPreference => (None, dial_info_filter),
|
||||||
|
Sequencing::PreferOrdered => (
|
||||||
|
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()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
};
|
||||||
// If the filter is dead then we won't be able to connect
|
// If the filter is dead then we won't be able to connect
|
||||||
if dial_info_filter.is_dead() {
|
if dial_info_filter.is_dead() {
|
||||||
return ContactMethod::Unreachable;
|
return ContactMethod::Unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get first filtered dialinfo
|
|
||||||
let sort = if reliable {
|
|
||||||
Some(DialInfoDetail::ordered_sequencing_sort)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
|
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
|
||||||
|
|
||||||
let opt_target_did = node_b.first_filtered_dial_info_detail(sort, filter);
|
let opt_target_did = node_b.first_filtered_dial_info_detail(sort, filter);
|
||||||
|
@ -8,7 +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
|
||||||
safety_spec: Option<SafetySpec>,
|
safety_selection: SafetySelection,
|
||||||
},
|
},
|
||||||
/// Send to node for relay purposes
|
/// Send to node for relay purposes
|
||||||
Relay {
|
Relay {
|
||||||
@ -17,16 +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_spec: Option<SafetySpec>,
|
safety_selection: SafetySelection,
|
||||||
},
|
},
|
||||||
/// 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_spec: Option<SafetySpec>,
|
safety_selection: SafetySelection,
|
||||||
/// Prefer reliability or not
|
|
||||||
reliable: bool,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,70 +32,66 @@ impl Destination {
|
|||||||
pub fn direct(target: NodeRef) -> Self {
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
Self::Direct {
|
Self::Direct {
|
||||||
target,
|
target,
|
||||||
safety_spec: None,
|
safety_selection: SafetySelection::Unsafe(target.sequencing()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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_spec: None,
|
safety_selection: SafetySelection::Unsafe(relay.sequencing()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn private_route(private_route: PrivateRoute, reliable: bool) -> Self {
|
pub fn private_route(private_route: PrivateRoute, safety_selection: SafetySelection) -> Self {
|
||||||
Self::PrivateRoute {
|
Self::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec: None,
|
safety_selection,
|
||||||
reliable,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_safety(self, safety_spec: SafetySpec) -> Self {
|
pub fn with_safety(self, safety_selection: SafetySelection) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Destination::Direct {
|
Destination::Direct {
|
||||||
target,
|
target,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
} => Self::Direct {
|
} => Self::Direct {
|
||||||
target,
|
target,
|
||||||
safety_spec: Some(safety_spec),
|
safety_selection,
|
||||||
},
|
},
|
||||||
Destination::Relay {
|
Destination::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
} => Self::Relay {
|
} => Self::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety_spec: Some(safety_spec),
|
safety_selection,
|
||||||
},
|
},
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
reliable,
|
|
||||||
} => Self::PrivateRoute {
|
} => Self::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec: Some(safety_spec),
|
safety_selection,
|
||||||
reliable,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_safety_spec(&self) -> &Option<SafetySpec> {
|
pub fn get_safety_selection(&self) -> &SafetySelection {
|
||||||
match self {
|
match self {
|
||||||
Destination::Direct {
|
Destination::Direct {
|
||||||
target: _,
|
target: _,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
} => safety_spec,
|
} => safety_selection,
|
||||||
Destination::Relay {
|
Destination::Relay {
|
||||||
relay: _,
|
relay: _,
|
||||||
target: _,
|
target: _,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
} => safety_spec,
|
} => safety_selection,
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route: _,
|
private_route: _,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
reliable: _,
|
} => safety_selection,
|
||||||
} => safety_spec,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,30 +101,40 @@ impl fmt::Display for Destination {
|
|||||||
match self {
|
match self {
|
||||||
Destination::Direct {
|
Destination::Direct {
|
||||||
target,
|
target,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
} => {
|
} => {
|
||||||
let sr = if safety_spec.is_some() { "+SR" } else { "" };
|
let sr = if matches!(safety_selection, SafetySelection::Safe(_)) {
|
||||||
|
"+SR"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
write!(f, "{}{}", target, sr)
|
write!(f, "{}{}", target, sr)
|
||||||
}
|
}
|
||||||
Destination::Relay {
|
Destination::Relay {
|
||||||
relay,
|
relay,
|
||||||
target,
|
target,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
} => {
|
} => {
|
||||||
let sr = if safety_spec.is_some() { "+SR" } else { "" };
|
let sr = if matches!(safety_selection, SafetySelection::Safe(_)) {
|
||||||
|
"+SR"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
write!(f, "{}@{}{}", target.encode(), relay, sr)
|
write!(f, "{}@{}{}", target.encode(), relay, sr)
|
||||||
}
|
}
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
reliable,
|
|
||||||
} => {
|
} => {
|
||||||
let sr = if safety_spec.is_some() { "+SR" } else { "" };
|
let sr = if matches!(safety_selection, SafetySelection::Safe(_)) {
|
||||||
let rl = if *reliable { "+RL" } else { "" };
|
"+SR"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
write!(f, "{}{}{}", private_route, sr, rl)
|
write!(f, "{}{}", private_route, sr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,9 +400,8 @@ impl RPCProcessor {
|
|||||||
// Wrap an operation with a private route inside a safety route
|
// Wrap an operation with a private route inside a safety route
|
||||||
pub(super) fn wrap_with_route(
|
pub(super) fn wrap_with_route(
|
||||||
&self,
|
&self,
|
||||||
safety_spec: Option<SafetySpec>,
|
safety_selection: SafetySelection,
|
||||||
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();
|
||||||
@ -412,7 +411,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, reliable)
|
rss.compile_safety_route(rti, routing_table, safety_selection, private_route)
|
||||||
})? {
|
})? {
|
||||||
Some(cr) => cr,
|
Some(cr) => cr,
|
||||||
None => {
|
None => {
|
||||||
@ -456,7 +455,6 @@ 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,
|
||||||
@ -491,12 +489,12 @@ impl RPCProcessor {
|
|||||||
match dest {
|
match dest {
|
||||||
Destination::Direct {
|
Destination::Direct {
|
||||||
target: ref node_ref,
|
target: ref node_ref,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
}
|
}
|
||||||
| Destination::Relay {
|
| Destination::Relay {
|
||||||
relay: ref node_ref,
|
relay: ref node_ref,
|
||||||
target: _,
|
target: _,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
} => {
|
} => {
|
||||||
// Send to a node without a private route
|
// Send to a node without a private route
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
@ -505,7 +503,7 @@ impl RPCProcessor {
|
|||||||
let (node_ref, node_id) = if let Destination::Relay {
|
let (node_ref, node_id) = if let Destination::Relay {
|
||||||
relay: _,
|
relay: _,
|
||||||
target: ref dht_key,
|
target: ref dht_key,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
} = dest
|
} = dest
|
||||||
{
|
{
|
||||||
(node_ref.clone(), dht_key.clone())
|
(node_ref.clone(), dht_key.clone())
|
||||||
@ -515,8 +513,13 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Handle the existence of safety route
|
// Handle the existence of safety route
|
||||||
match safety_spec {
|
match safety_selection {
|
||||||
None => {
|
SafetySelection::Unsafe(sequencing) => {
|
||||||
|
// Apply safety selection sequencing requirement if it is more strict than the node_ref's sequencing requirement
|
||||||
|
if sequencing > node_ref.sequencing() {
|
||||||
|
node_ref.set_sequencing(sequencing)
|
||||||
|
}
|
||||||
|
|
||||||
// If no safety route is being used, and we're not sending to a private
|
// If no safety route is being used, and we're not sending to a private
|
||||||
// route, we can use a direct envelope instead of routing
|
// route, we can use a direct envelope instead of routing
|
||||||
out = NetworkResult::value(RenderedOperation {
|
out = NetworkResult::value(RenderedOperation {
|
||||||
@ -526,25 +529,24 @@ impl RPCProcessor {
|
|||||||
hop_count: 1,
|
hop_count: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(safety_spec) => {
|
SafetySelection::Safe(_) => {
|
||||||
// No private route was specified for the request
|
// No private route was specified for the request
|
||||||
// but we are using a safety route, so we must create an empty private route
|
// but we are using a safety route, so we must create an empty private route
|
||||||
let private_route = PrivateRoute::new_stub(node_id);
|
let private_route = PrivateRoute::new_stub(node_id);
|
||||||
|
|
||||||
// Wrap with safety route
|
// Wrap with safety route
|
||||||
out = self.wrap_with_route(Some(safety_spec), private_route, message)?;
|
out = self.wrap_with_route(safety_selection, private_route, message)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
safety_spec,
|
safety_selection,
|
||||||
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, reliable, message)?;
|
out = self.wrap_with_route(safety_selection, private_route, message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,8 +561,11 @@ impl RPCProcessor {
|
|||||||
// Don't do this if the sender is to remain private
|
// Don't do this if the sender is to remain private
|
||||||
// Otherwise we would be attaching the original sender's identity to the final destination,
|
// Otherwise we would be attaching the original sender's identity to the final destination,
|
||||||
// thus defeating the purpose of the safety route entirely :P
|
// thus defeating the purpose of the safety route entirely :P
|
||||||
if dest.get_safety_spec().is_some() {
|
match dest.get_safety_selection() {
|
||||||
return None;
|
SafetySelection::Unsafe(_) => {}
|
||||||
|
SafetySelection::Safe(_) => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Don't do this if our own signed node info isn't valid yet
|
// Don't do this if our own signed node info isn't valid yet
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
@ -571,7 +576,7 @@ impl RPCProcessor {
|
|||||||
match dest {
|
match dest {
|
||||||
Destination::Direct {
|
Destination::Direct {
|
||||||
target,
|
target,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
} => {
|
} => {
|
||||||
// If the target has seen our node info already don't do this
|
// If the target has seen our node info already don't do this
|
||||||
if target.has_seen_our_node_info(RoutingDomain::PublicInternet) {
|
if target.has_seen_our_node_info(RoutingDomain::PublicInternet) {
|
||||||
@ -582,7 +587,7 @@ impl RPCProcessor {
|
|||||||
Destination::Relay {
|
Destination::Relay {
|
||||||
relay: _,
|
relay: _,
|
||||||
target,
|
target,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
} => {
|
} => {
|
||||||
if let Some(target) = routing_table.lookup_node_ref(*target) {
|
if let Some(target) = routing_table.lookup_node_ref(*target) {
|
||||||
if target.has_seen_our_node_info(RoutingDomain::PublicInternet) {
|
if target.has_seen_our_node_info(RoutingDomain::PublicInternet) {
|
||||||
@ -595,8 +600,7 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route: _,
|
private_route: _,
|
||||||
safety_spec: _,
|
safety_selection: _,
|
||||||
reliable: _,
|
|
||||||
} => None,
|
} => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -741,6 +745,7 @@ impl RPCProcessor {
|
|||||||
Destination::relay(peer_noderef, sender_id)
|
Destination::relay(peer_noderef, sender_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//xxx needs to know what route the request came in on in order to reply over that same route as the preferred safety route
|
||||||
RespondTo::PrivateRoute(pr) => Destination::private_route(
|
RespondTo::PrivateRoute(pr) => Destination::private_route(
|
||||||
pr.clone(),
|
pr.clone(),
|
||||||
request
|
request
|
||||||
|
@ -7,6 +7,9 @@ impl RPCProcessor {
|
|||||||
pub(crate) async fn process_route(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
pub(crate) async fn process_route(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
||||||
// xxx do not process latency for routed messages
|
// xxx do not process latency for routed messages
|
||||||
// tracing::Span::current().record("res", &tracing::field::display(res));
|
// tracing::Span::current().record("res", &tracing::field::display(res));
|
||||||
|
|
||||||
|
xxx continue here
|
||||||
|
|
||||||
Err(RPCError::unimplemented("process_route"))
|
Err(RPCError::unimplemented("process_route"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,6 +420,28 @@ pub enum Stability {
|
|||||||
Reliable,
|
Reliable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The choice of safety route including in compiled routes
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Options for safety routes (sender privacy)
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
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
|
||||||
|
pub hop_count: usize,
|
||||||
|
/// prefer reliability over speed
|
||||||
|
pub stability: Stability,
|
||||||
|
/// prefer connection-oriented sequenced protocols
|
||||||
|
pub sequencing: Sequencing,
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
@ -1551,8 +1573,8 @@ impl DialInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ordered_sequencing_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(Sequencing::EnsureOrdered);
|
||||||
let cb = b.protocol_type().sort_order(true);
|
let cb = b.protocol_type().sort_order(Sequencing::EnsureOrdered);
|
||||||
if ca < cb {
|
if ca < cb {
|
||||||
return core::cmp::Ordering::Less;
|
return core::cmp::Ordering::Less;
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,8 @@ pub enum Target {
|
|||||||
pub struct RoutingContextInner {}
|
pub struct RoutingContextInner {}
|
||||||
|
|
||||||
pub struct RoutingContextUnlockedInner {
|
pub struct RoutingContextUnlockedInner {
|
||||||
/// Enforce use of private routing
|
/// Safety routing requirements
|
||||||
privacy: usize,
|
safety_selection: SafetySelection,
|
||||||
/// Choose reliable protocols over unreliable/faster protocols when available
|
|
||||||
reliable: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for RoutingContextInner {
|
impl Drop for RoutingContextInner {
|
||||||
@ -41,8 +39,7 @@ impl RoutingContext {
|
|||||||
api,
|
api,
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||||
privacy: 0,
|
safety_selection: SafetySelection::Unsafe(Sequencing::NoPreference),
|
||||||
reliable: false,
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,44 +51,54 @@ impl RoutingContext {
|
|||||||
api: self.api.clone(),
|
api: self.api.clone(),
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||||
privacy: c.network.rpc.default_route_hop_count as usize,
|
safety_selection: SafetySelection::Safe(SafetySpec {
|
||||||
reliable: self.unlocked_inner.reliable,
|
preferred_route: None,
|
||||||
|
hop_count: c.network.rpc.default_route_hop_count as usize,
|
||||||
|
stability: Stability::LowLatency,
|
||||||
|
sequencing: Sequencing::NoPreference,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn with_privacy(self, hops: usize) -> Result<Self, VeilidAPIError> {
|
pub fn with_privacy(self, safety_spec: SafetySpec) -> Result<Self, VeilidAPIError> {
|
||||||
let config = self.api.config()?;
|
|
||||||
let c = config.get();
|
|
||||||
|
|
||||||
let privacy = if hops > 0 && hops <= c.network.rpc.max_route_hop_count as usize {
|
|
||||||
hops
|
|
||||||
} else {
|
|
||||||
return Err(VeilidAPIError::invalid_argument(
|
|
||||||
"hops value is too large",
|
|
||||||
"hops",
|
|
||||||
hops,
|
|
||||||
));
|
|
||||||
};
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
api: self.api.clone(),
|
api: self.api.clone(),
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||||
privacy,
|
safety_selection: SafetySelection::Safe(safety_spec),
|
||||||
reliable: self.unlocked_inner.reliable,
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_reliability(self) -> Self {
|
pub fn with_sequencing(self, sequencing: Sequencing) -> Self {
|
||||||
Self {
|
Self {
|
||||||
api: self.api.clone(),
|
api: self.api.clone(),
|
||||||
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
inner: Arc::new(Mutex::new(RoutingContextInner {})),
|
||||||
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
unlocked_inner: Arc::new(RoutingContextUnlockedInner {
|
||||||
privacy: self.unlocked_inner.privacy,
|
safety_selection: match self.unlocked_inner.safety_selection {
|
||||||
reliable: true,
|
SafetySelection::Unsafe(_) => SafetySelection::Unsafe(sequencing),
|
||||||
|
SafetySelection::Safe(safety_spec) => SafetySelection::Safe(SafetySpec {
|
||||||
|
preferred_route: safety_spec.preferred_route,
|
||||||
|
hop_count: safety_spec.hop_count,
|
||||||
|
stability: safety_spec.stability,
|
||||||
|
sequencing,
|
||||||
|
}),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn sequencing(&self) -> Sequencing {
|
||||||
|
match self.unlocked_inner.safety_selection {
|
||||||
|
SafetySelection::Unsafe(sequencing) => sequencing,
|
||||||
|
SafetySelection::Safe(safety_spec) => safety_spec.sequencing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn safety_spec(&self) -> Option<SafetySpec> {
|
||||||
|
match self.unlocked_inner.safety_selection {
|
||||||
|
SafetySelection::Unsafe(_) => None,
|
||||||
|
SafetySelection::Safe(safety_spec) => Some(safety_spec.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn api(&self) -> VeilidAPI {
|
pub fn api(&self) -> VeilidAPI {
|
||||||
self.api.clone()
|
self.api.clone()
|
||||||
@ -111,27 +118,17 @@ impl RoutingContext {
|
|||||||
Ok(None) => return Err(VeilidAPIError::NodeNotFound { node_id }),
|
Ok(None) => return Err(VeilidAPIError::NodeNotFound { node_id }),
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
// Apply reliability sort
|
// Apply sequencing to match safety selection
|
||||||
if self.unlocked_inner.reliable {
|
nr.set_sequencing(self.sequencing());
|
||||||
nr.set_reliable();
|
|
||||||
}
|
|
||||||
Ok(rpc_processor::Destination::Direct {
|
Ok(rpc_processor::Destination::Direct {
|
||||||
target: nr,
|
target: nr,
|
||||||
safety_spec: Some(routing_table::SafetySpec {
|
safety_selection: self.unlocked_inner.safety_selection,
|
||||||
preferred_route: None,
|
|
||||||
hop_count: self.unlocked_inner.privacy,
|
|
||||||
reliable: self.unlocked_inner.reliable,
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Target::PrivateRoute(pr) => Ok(rpc_processor::Destination::PrivateRoute {
|
Target::PrivateRoute(pr) => Ok(rpc_processor::Destination::PrivateRoute {
|
||||||
private_route: pr,
|
private_route: pr,
|
||||||
safety_spec: Some(routing_table::SafetySpec {
|
safety_selection: self.unlocked_inner.safety_selection,
|
||||||
preferred_route: None,
|
|
||||||
hop_count: self.unlocked_inner.privacy,
|
|
||||||
reliable: self.unlocked_inner.reliable,
|
|
||||||
}),
|
|
||||||
reliable: self.unlocked_inner.reliable,
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user