refactor checkpoint
This commit is contained in:
parent
9966d25672
commit
e0a5b1bd69
@ -3,5 +3,4 @@ core:
|
|||||||
network:
|
network:
|
||||||
dht:
|
dht:
|
||||||
min_peer_count: 1
|
min_peer_count: 1
|
||||||
enable_local_peer_scope: true
|
|
||||||
bootstrap: []
|
bootstrap: []
|
||||||
|
@ -175,10 +175,6 @@ struct ValueData {
|
|||||||
# Operations
|
# Operations
|
||||||
##############################
|
##############################
|
||||||
|
|
||||||
struct OperationStatusQ {
|
|
||||||
nodeStatus @0 :NodeStatus; # node status update about the statusq sender
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NetworkClass {
|
enum NetworkClass {
|
||||||
inboundCapable @0; # I = Inbound capable without relay, may require signal
|
inboundCapable @0; # I = Inbound capable without relay, may require signal
|
||||||
outboundOnly @1; # O = Outbound only, inbound relay required except with reverse connect signal
|
outboundOnly @1; # O = Outbound only, inbound relay required except with reverse connect signal
|
||||||
@ -199,7 +195,7 @@ struct DialInfoDetail {
|
|||||||
class @1 :DialInfoClass;
|
class @1 :DialInfoClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeStatus {
|
struct PublicInternetNodeStatus {
|
||||||
willRoute @0 :Bool;
|
willRoute @0 :Bool;
|
||||||
willTunnel @1 :Bool;
|
willTunnel @1 :Bool;
|
||||||
willSignal @2 :Bool;
|
willSignal @2 :Bool;
|
||||||
@ -207,6 +203,18 @@ struct NodeStatus {
|
|||||||
willValidateDialInfo @4 :Bool;
|
willValidateDialInfo @4 :Bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LocalNetworkNodeStatus {
|
||||||
|
willRelay @0 :Bool;
|
||||||
|
willValidateDialInfo @1 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NodeStatus {
|
||||||
|
union {
|
||||||
|
publicInternet @0 :PublicInternetNodeStatus;
|
||||||
|
localNetwork @1 :LocalNetworkNodeStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ProtocolTypeSet {
|
struct ProtocolTypeSet {
|
||||||
udp @0 :Bool;
|
udp @0 :Bool;
|
||||||
tcp @1 :Bool;
|
tcp @1 :Bool;
|
||||||
@ -239,6 +247,21 @@ struct SenderInfo {
|
|||||||
socketAddress @0 :SocketAddress; # socket address was available for peer
|
socketAddress @0 :SocketAddress; # socket address was available for peer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PeerInfo {
|
||||||
|
nodeId @0 :NodeID; # node id for 'closer peer'
|
||||||
|
signedNodeInfo @1 :SignedNodeInfo; # signed node info for 'closer peer'
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoutedOperation {
|
||||||
|
signatures @0 :List(Signature); # signatures from nodes that have handled the private route
|
||||||
|
nonce @1 :Nonce; # nonce Xmsg
|
||||||
|
data @2 :Data; # Operation encrypted with ENC(Xmsg,DH(PKapr,SKbsr))
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OperationStatusQ {
|
||||||
|
nodeStatus @0 :NodeStatus; # node status update about the statusq sender
|
||||||
|
}
|
||||||
|
|
||||||
struct OperationStatusA {
|
struct OperationStatusA {
|
||||||
nodeStatus @0 :NodeStatus; # returned node status
|
nodeStatus @0 :NodeStatus; # returned node status
|
||||||
senderInfo @1 :SenderInfo; # info about StatusQ sender from the perspective of the replier
|
senderInfo @1 :SenderInfo; # info about StatusQ sender from the perspective of the replier
|
||||||
@ -258,21 +281,10 @@ struct OperationFindNodeQ {
|
|||||||
nodeId @0 :NodeID; # node id to locate
|
nodeId @0 :NodeID; # node id to locate
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfo {
|
|
||||||
nodeId @0 :NodeID; # node id for 'closer peer'
|
|
||||||
signedNodeInfo @1 :SignedNodeInfo; # signed node info for 'closer peer'
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OperationFindNodeA {
|
struct OperationFindNodeA {
|
||||||
peers @0 :List(PeerInfo); # returned 'closer peer' information
|
peers @0 :List(PeerInfo); # returned 'closer peer' information
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RoutedOperation {
|
|
||||||
signatures @0 :List(Signature); # signatures from nodes that have handled the private route
|
|
||||||
nonce @1 :Nonce; # nonce Xmsg
|
|
||||||
data @2 :Data; # Operation encrypted with ENC(Xmsg,DH(PKapr,SKbsr))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OperationRoute {
|
struct OperationRoute {
|
||||||
safetyRoute @0 :SafetyRoute; # Where this should go
|
safetyRoute @0 :SafetyRoute; # Where this should go
|
||||||
operation @1 :RoutedOperation; # The operation to be routed
|
operation @1 :RoutedOperation; # The operation to be routed
|
||||||
@ -419,26 +431,25 @@ struct OperationCancelTunnelA {
|
|||||||
# Things that want an answer
|
# Things that want an answer
|
||||||
struct Question {
|
struct Question {
|
||||||
respondTo :union {
|
respondTo :union {
|
||||||
sender @0 :Void; # sender without node info
|
sender @0 :Void; # sender
|
||||||
senderWithInfo @1 :SignedNodeInfo; # some envelope-sender signed node info to be used for reply
|
privateRoute @1 :PrivateRoute; # embedded private route to be used for reply
|
||||||
privateRoute @2 :PrivateRoute; # embedded private route to be used for reply
|
|
||||||
}
|
}
|
||||||
detail :union {
|
detail :union {
|
||||||
# Direct operations
|
# Direct operations
|
||||||
statusQ @3 :OperationStatusQ;
|
statusQ @2 :OperationStatusQ;
|
||||||
findNodeQ @4 :OperationFindNodeQ;
|
findNodeQ @3 :OperationFindNodeQ;
|
||||||
|
|
||||||
# Routable operations
|
# Routable operations
|
||||||
getValueQ @5 :OperationGetValueQ;
|
getValueQ @4 :OperationGetValueQ;
|
||||||
setValueQ @6 :OperationSetValueQ;
|
setValueQ @5 :OperationSetValueQ;
|
||||||
watchValueQ @7 :OperationWatchValueQ;
|
watchValueQ @6 :OperationWatchValueQ;
|
||||||
supplyBlockQ @8 :OperationSupplyBlockQ;
|
supplyBlockQ @7 :OperationSupplyBlockQ;
|
||||||
findBlockQ @9 :OperationFindBlockQ;
|
findBlockQ @8 :OperationFindBlockQ;
|
||||||
|
|
||||||
# Tunnel operations
|
# Tunnel operations
|
||||||
startTunnelQ @10 :OperationStartTunnelQ;
|
startTunnelQ @9 :OperationStartTunnelQ;
|
||||||
completeTunnelQ @11 :OperationCompleteTunnelQ;
|
completeTunnelQ @10 :OperationCompleteTunnelQ;
|
||||||
cancelTunnelQ @12 :OperationCancelTunnelQ;
|
cancelTunnelQ @11 :OperationCancelTunnelQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,10 +491,10 @@ struct Answer {
|
|||||||
|
|
||||||
struct Operation {
|
struct Operation {
|
||||||
opId @0 :UInt64; # Random RPC ID. Must be random to foil reply forgery attacks.
|
opId @0 :UInt64; # Random RPC ID. Must be random to foil reply forgery attacks.
|
||||||
|
senderInfo @1 :SignedNodeInfo; # (optional) SignedNodeInfo for the sender to be cached by the receiver.
|
||||||
kind :union {
|
kind :union {
|
||||||
question @1 :Question;
|
question @2 :Question;
|
||||||
statement @2 :Statement;
|
statement @3 :Statement;
|
||||||
answer @3 :Answer;
|
answer @4 :Answer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,33 +552,29 @@ impl NetworkManager {
|
|||||||
// Run the rolling transfers task
|
// Run the rolling transfers task
|
||||||
self.unlocked_inner.rolling_transfers_task.tick().await?;
|
self.unlocked_inner.rolling_transfers_task.tick().await?;
|
||||||
|
|
||||||
// Process global peer scope ticks
|
// Run the relay management task
|
||||||
// These only make sense when connected to the actual internet and not just the local network
|
self.unlocked_inner.relay_management_task.tick().await?;
|
||||||
// Must have at least one outbound protocol enabled, and one global peer scope address family enabled
|
|
||||||
let global_peer_scope_enabled =
|
|
||||||
!protocol_config.outbound.is_empty() && !protocol_config.family_global.is_empty();
|
|
||||||
if global_peer_scope_enabled {
|
|
||||||
// Run the relay management task
|
|
||||||
self.unlocked_inner.relay_management_task.tick().await?;
|
|
||||||
|
|
||||||
// If routing table has no live entries, then add the bootstrap nodes to it
|
// See how many live PublicInternet entries we have
|
||||||
let live_entry_count = routing_table.get_entry_count(BucketEntryState::Unreliable);
|
let live_public_internet_entry_count = routing_table.get_entry_count(
|
||||||
if live_entry_count == 0 {
|
RoutingTableSet::only(RoutingTable::PublicInternet),
|
||||||
self.unlocked_inner.bootstrap_task.tick().await?;
|
BucketEntryState::Unreliable,
|
||||||
}
|
);
|
||||||
|
let min_peer_count = {
|
||||||
// If we still don't have enough peers, find nodes until we do
|
let c = self.config.get();
|
||||||
let min_peer_count = {
|
c.network.dht.min_peer_count as usize
|
||||||
let c = self.config.get();
|
};
|
||||||
c.network.dht.min_peer_count as usize
|
// If none, then add the bootstrap nodes to it
|
||||||
};
|
if live_public_internet_entry_count == 0 {
|
||||||
if live_entry_count < min_peer_count {
|
self.unlocked_inner.bootstrap_task.tick().await?;
|
||||||
self.unlocked_inner.peer_minimum_refresh_task.tick().await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping validate some nodes to groom the table
|
|
||||||
self.unlocked_inner.ping_validator_task.tick().await?;
|
|
||||||
}
|
}
|
||||||
|
// If we still don't have enough peers, find nodes until we do
|
||||||
|
else if live_public_internet_entry_count < min_peer_count {
|
||||||
|
self.unlocked_inner.peer_minimum_refresh_task.tick().await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping validate some nodes to groom the table
|
||||||
|
self.unlocked_inner.ping_validator_task.tick().await?;
|
||||||
|
|
||||||
// Run the routing table tick
|
// Run the routing table tick
|
||||||
routing_table.tick().await?;
|
routing_table.tick().await?;
|
||||||
@ -605,21 +601,18 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get our node's capabilities
|
// Get our node's capabilities
|
||||||
pub fn generate_node_status(&self) -> NodeStatus {
|
fn generate_public_internet_node_status(&self) -> PublicInternetNodeStatus {
|
||||||
let peer_info = self
|
let node_info = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.get_own_peer_info(RoutingDomain::PublicInternet);
|
.get_own_node_info(RoutingDomain::PublicInternet);
|
||||||
|
|
||||||
let will_route = peer_info.signed_node_info.node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
let will_route = node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
||||||
let will_tunnel = peer_info.signed_node_info.node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
let will_tunnel = node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
||||||
let will_signal = peer_info.signed_node_info.node_info.can_signal();
|
let will_signal = node_info.can_signal();
|
||||||
let will_relay = peer_info.signed_node_info.node_info.can_inbound_relay();
|
let will_relay = node_info.can_inbound_relay();
|
||||||
let will_validate_dial_info = peer_info
|
let will_validate_dial_info = node_info.can_validate_dial_info();
|
||||||
.signed_node_info
|
|
||||||
.node_info
|
|
||||||
.can_validate_dial_info();
|
|
||||||
|
|
||||||
NodeStatus {
|
PublicInternetNodeStatus {
|
||||||
will_route,
|
will_route,
|
||||||
will_tunnel,
|
will_tunnel,
|
||||||
will_signal,
|
will_signal,
|
||||||
@ -627,6 +620,30 @@ impl NetworkManager {
|
|||||||
will_validate_dial_info,
|
will_validate_dial_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn generate_local_network_node_status(&self) -> LocalNetworkNodeStatus {
|
||||||
|
let node_info = self
|
||||||
|
.routing_table()
|
||||||
|
.get_own_node_info(RoutingDomain::LocalNetwork);
|
||||||
|
|
||||||
|
let will_relay = node_info.can_inbound_relay();
|
||||||
|
let will_validate_dial_info = node_info.can_validate_dial_info();
|
||||||
|
|
||||||
|
LocalNetworkNodeStatus {
|
||||||
|
will_relay,
|
||||||
|
will_validate_dial_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_node_status(&self, routing_domain: RoutingDomain) -> NodeStatus {
|
||||||
|
match routing_domain {
|
||||||
|
RoutingDomain::PublicInternet => {
|
||||||
|
NodeStatus::PublicInternet(self.generate_public_internet_node_status())
|
||||||
|
}
|
||||||
|
RoutingDomain::LocalNetwork => {
|
||||||
|
NodeStatus::LocalNetwork(self.generate_local_network_node_status())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return what protocols we have enabled
|
// Return what protocols we have enabled
|
||||||
pub fn get_protocol_config(&self) -> ProtocolConfig {
|
pub fn get_protocol_config(&self) -> ProtocolConfig {
|
||||||
@ -650,6 +667,12 @@ impl NetworkManager {
|
|||||||
.clone(),
|
.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn get_inbound_node_ref_filter(&self, routing_domain: RoutingDomain) -> NodeRefFilter {
|
||||||
|
let dif = self.get_inbound_dial_info_filter(routing_domain);
|
||||||
|
NodeRefFilter::new()
|
||||||
|
.with_routing_domain(routing_domain)
|
||||||
|
.with_dial_info_filter(dif)
|
||||||
|
}
|
||||||
|
|
||||||
// Return a dial info filter for what we can send out
|
// Return a dial info filter for what we can send out
|
||||||
pub fn get_outbound_dial_info_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter {
|
pub fn get_outbound_dial_info_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter {
|
||||||
@ -667,6 +690,12 @@ impl NetworkManager {
|
|||||||
.clone(),
|
.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn get_outbound_node_ref_filter(&self, routing_domain: RoutingDomain) -> NodeRefFilter {
|
||||||
|
let dif = self.get_outbound_dial_info_filter(routing_domain);
|
||||||
|
NodeRefFilter::new()
|
||||||
|
.with_routing_domain(routing_domain)
|
||||||
|
.with_dial_info_filter(dif)
|
||||||
|
}
|
||||||
|
|
||||||
// Generates a multi-shot/normal receipt
|
// Generates a multi-shot/normal receipt
|
||||||
#[instrument(level = "trace", skip(self, extra_data, callback), err)]
|
#[instrument(level = "trace", skip(self, extra_data, callback), err)]
|
||||||
@ -949,12 +978,11 @@ impl NetworkManager {
|
|||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn get_contact_method_public(&self, target_node_ref: NodeRef) -> ContactMethod {
|
fn get_contact_method_public(&self, target_node_ref: NodeRef) -> ContactMethod {
|
||||||
// Scope noderef down to protocols we can do outbound
|
// Scope noderef down to protocols we can do outbound
|
||||||
let public_outbound_dif = self.get_outbound_dial_info_filter(RoutingDomain::PublicInternet);
|
let public_outbound_nrf = self.get_outbound_node_ref_filter(RoutingDomain::PublicInternet);
|
||||||
let target_node_ref = target_node_ref.filtered_clone(public_outbound_dif.clone());
|
let target_node_ref = target_node_ref.filtered_clone(public_outbound_nrf.clone());
|
||||||
|
|
||||||
// Get the best match internet dial info if we have it
|
// Get the best match internet dial info if we have it
|
||||||
let opt_target_public_did =
|
let opt_target_public_did = target_node_ref.first_filtered_dial_info_detail();
|
||||||
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet));
|
|
||||||
if let Some(target_public_did) = opt_target_public_did {
|
if let Some(target_public_did) = opt_target_public_did {
|
||||||
// Do we need to signal before going inbound?
|
// Do we need to signal before going inbound?
|
||||||
if !target_public_did.class.requires_signal() {
|
if !target_public_did.class.requires_signal() {
|
||||||
@ -966,12 +994,9 @@ impl NetworkManager {
|
|||||||
// Note that .relay() never returns our own node. We can't relay to ourselves.
|
// Note that .relay() never returns our own node. We can't relay to ourselves.
|
||||||
if let Some(inbound_relay_nr) = target_node_ref.relay(RoutingDomain::PublicInternet) {
|
if let Some(inbound_relay_nr) = target_node_ref.relay(RoutingDomain::PublicInternet) {
|
||||||
// Scope down to protocols we can do outbound
|
// Scope down to protocols we can do outbound
|
||||||
let inbound_relay_nr = inbound_relay_nr.filtered_clone(public_outbound_dif.clone());
|
let inbound_relay_nr = inbound_relay_nr.filtered_clone(public_outbound_nrf.clone());
|
||||||
// Can we reach the inbound relay?
|
// Can we reach the inbound relay?
|
||||||
if inbound_relay_nr
|
if inbound_relay_nr.first_filtered_dial_info_detail().is_some() {
|
||||||
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
// Can we receive anything inbound ever?
|
// Can we receive anything inbound ever?
|
||||||
let our_network_class = self
|
let our_network_class = self
|
||||||
.get_network_class(RoutingDomain::PublicInternet)
|
.get_network_class(RoutingDomain::PublicInternet)
|
||||||
@ -985,11 +1010,11 @@ impl NetworkManager {
|
|||||||
let reverse_dif = self
|
let reverse_dif = self
|
||||||
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
|
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
|
||||||
.filtered(
|
.filtered(
|
||||||
target_node_ref
|
&target_node_ref
|
||||||
.node_info_outbound_filter(RoutingDomain::PublicInternet),
|
.node_info_outbound_filter(RoutingDomain::PublicInternet),
|
||||||
);
|
);
|
||||||
if let Some(reverse_did) = routing_table.first_filtered_dial_info_detail(
|
if let Some(reverse_did) = routing_table.first_filtered_dial_info_detail(
|
||||||
Some(RoutingDomain::PublicInternet),
|
RoutingDomainSet::only(RoutingDomain::PublicInternet),
|
||||||
&reverse_dif,
|
&reverse_dif,
|
||||||
) {
|
) {
|
||||||
// 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)
|
||||||
@ -1010,16 +1035,16 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Does the target have a direct udp dialinfo we can reach?
|
// Does the target have a direct udp dialinfo we can reach?
|
||||||
let udp_target_nr = target_node_ref.filtered_clone(
|
let udp_target_nr = target_node_ref.filtered_clone(
|
||||||
DialInfoFilter::global().with_protocol_type(ProtocolType::UDP),
|
NodeRefFilter::new().with_protocol_type(ProtocolType::UDP),
|
||||||
);
|
);
|
||||||
if let Some(target_udp_dialinfo_detail) = udp_target_nr
|
if let Some(target_udp_dialinfo_detail) =
|
||||||
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
udp_target_nr.first_filtered_dial_info_detail()
|
||||||
{
|
{
|
||||||
// Does the self node have a direct udp dialinfo the target can reach?
|
// Does the self node have a direct udp dialinfo the target can reach?
|
||||||
let inbound_udp_dif = self
|
let inbound_udp_dif = self
|
||||||
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
|
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
|
||||||
.filtered(
|
.filtered(
|
||||||
target_node_ref
|
&target_node_ref
|
||||||
.node_info_outbound_filter(RoutingDomain::PublicInternet),
|
.node_info_outbound_filter(RoutingDomain::PublicInternet),
|
||||||
)
|
)
|
||||||
.filtered(
|
.filtered(
|
||||||
@ -1027,7 +1052,7 @@ impl NetworkManager {
|
|||||||
);
|
);
|
||||||
if let Some(self_udp_dialinfo_detail) = routing_table
|
if let Some(self_udp_dialinfo_detail) = routing_table
|
||||||
.first_filtered_dial_info_detail(
|
.first_filtered_dial_info_detail(
|
||||||
Some(RoutingDomain::PublicInternet),
|
RoutingDomainSet::only(RoutingDomain::PublicInternet),
|
||||||
&inbound_udp_dif,
|
&inbound_udp_dif,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1056,7 +1081,7 @@ impl NetworkManager {
|
|||||||
{
|
{
|
||||||
// Can we reach the full relay?
|
// Can we reach the full relay?
|
||||||
if target_inbound_relay_nr
|
if target_inbound_relay_nr
|
||||||
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
.first_filtered_dial_info_detail()
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
return ContactMethod::InboundRelay(target_inbound_relay_nr);
|
return ContactMethod::InboundRelay(target_inbound_relay_nr);
|
||||||
@ -1078,15 +1103,13 @@ impl NetworkManager {
|
|||||||
fn get_contact_method_local(&self, target_node_ref: NodeRef) -> ContactMethod {
|
fn get_contact_method_local(&self, target_node_ref: NodeRef) -> ContactMethod {
|
||||||
// Scope noderef down to protocols we can do outbound
|
// Scope noderef down to protocols we can do outbound
|
||||||
let local_outbound_dif = self.get_outbound_dial_info_filter(RoutingDomain::LocalNetwork);
|
let local_outbound_dif = self.get_outbound_dial_info_filter(RoutingDomain::LocalNetwork);
|
||||||
let target_node_ref = target_node_ref.filtered_clone(local_outbound_dif);
|
let target_node_ref = target_node_ref.filtered_clone(NodeRefFilter::local_outbound_dif);
|
||||||
|
|
||||||
// Get the best matching local direct dial info if we have it
|
// Get the best matching local direct dial info if we have it
|
||||||
// ygjghhtiygiukuymyg
|
|
||||||
if target_node_ref.is_filter_dead() {
|
if target_node_ref.is_filter_dead() {
|
||||||
return ContactMethod::Unreachable;
|
return ContactMethod::Unreachable;
|
||||||
}
|
}
|
||||||
let opt_target_local_did =
|
let opt_target_local_did = target_node_ref.first_filtered_dial_info_detail();
|
||||||
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::LocalNetwork));
|
|
||||||
if let Some(target_local_did) = opt_target_local_did {
|
if let Some(target_local_did) = opt_target_local_did {
|
||||||
return ContactMethod::Direct(target_local_did.dial_info);
|
return ContactMethod::Direct(target_local_did.dial_info);
|
||||||
}
|
}
|
||||||
@ -1096,21 +1119,18 @@ impl NetworkManager {
|
|||||||
// Figure out how to reach a node
|
// Figure out how to reach a node
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub(crate) fn get_contact_method(&self, target_node_ref: NodeRef) -> ContactMethod {
|
pub(crate) fn get_contact_method(&self, target_node_ref: NodeRef) -> ContactMethod {
|
||||||
// Try local first
|
let routing_domain = match target_node_ref.best_routing_domain() {
|
||||||
let out = self.get_contact_method_local(target_node_ref.clone());
|
Some(rd) => rd,
|
||||||
if !matches!(out, ContactMethod::Unreachable) {
|
None => {
|
||||||
return out;
|
log_net!("no routing domain for node {:?}", target_node_ref);
|
||||||
}
|
return ContactMethod::Unreachable;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Try public next
|
match routing_domain {
|
||||||
let out = self.get_contact_method_public(target_node_ref.clone());
|
RoutingDomain::LocalNetwork => self.get_contact_method_local(target_node_ref),
|
||||||
if !matches!(out, ContactMethod::Unreachable) {
|
RoutingDomain::PublicInternet => self.get_contact_method_public(target_node_ref),
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we can't reach this node
|
|
||||||
log_net!("unable to reach node {:?}", target_node_ref);
|
|
||||||
ContactMethod::Unreachable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a reverse connection signal and wait for the return receipt over it
|
// Send a reverse connection signal and wait for the return receipt over it
|
||||||
@ -1461,6 +1481,18 @@ impl NetworkManager {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the routing domain for this data
|
||||||
|
let routing_domain = match self
|
||||||
|
.routing_table()
|
||||||
|
.routing_domain_for_address(connection_descriptor.remote().address())
|
||||||
|
{
|
||||||
|
Some(rd) => rd,
|
||||||
|
None => {
|
||||||
|
log_net!(debug "no routing domain for envelope received from {:?}", connection_descriptor);
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Is this a direct bootstrap request instead of an envelope?
|
// Is this a direct bootstrap request instead of an envelope?
|
||||||
if data[0..4] == *BOOT_MAGIC {
|
if data[0..4] == *BOOT_MAGIC {
|
||||||
network_result_value_or_log!(debug self.handle_boot_request(connection_descriptor).await? => {});
|
network_result_value_or_log!(debug self.handle_boot_request(connection_descriptor).await? => {});
|
||||||
@ -1588,7 +1620,13 @@ impl NetworkManager {
|
|||||||
// xxx: deal with spoofing and flooding here?
|
// xxx: deal with spoofing and flooding here?
|
||||||
|
|
||||||
// Pass message to RPC system
|
// Pass message to RPC system
|
||||||
rpc.enqueue_message(envelope, body, source_noderef, connection_descriptor)?;
|
rpc.enqueue_message(
|
||||||
|
envelope,
|
||||||
|
body,
|
||||||
|
source_noderef,
|
||||||
|
connection_descriptor,
|
||||||
|
routing_domain,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Inform caller that we dealt with the envelope locally
|
// Inform caller that we dealt with the envelope locally
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -1669,7 +1707,7 @@ impl NetworkManager {
|
|||||||
// Determine if a local IP address has changed
|
// Determine if a local IP address has changed
|
||||||
// this means we should restart the low level network and and recreate all of our dial info
|
// this means we should restart the low level network and and recreate all of our dial info
|
||||||
// Wait until we have received confirmation from N different peers
|
// Wait until we have received confirmation from N different peers
|
||||||
pub fn report_local_socket_address(
|
pub fn report_local_network_socket_address(
|
||||||
&self,
|
&self,
|
||||||
_socket_address: SocketAddress,
|
_socket_address: SocketAddress,
|
||||||
_connection_descriptor: ConnectionDescriptor,
|
_connection_descriptor: ConnectionDescriptor,
|
||||||
@ -1681,7 +1719,7 @@ impl NetworkManager {
|
|||||||
// Determine if a global IP address has changed
|
// Determine if a global IP address has changed
|
||||||
// this means we should recreate our public dial info if it is not static and rediscover it
|
// this means we should recreate our public dial info if it is not static and rediscover it
|
||||||
// Wait until we have received confirmation from N different peers
|
// Wait until we have received confirmation from N different peers
|
||||||
pub fn report_global_socket_address(
|
pub fn report_public_internet_socket_address(
|
||||||
&self,
|
&self,
|
||||||
socket_address: SocketAddress, // the socket address as seen by the remote peer
|
socket_address: SocketAddress, // the socket address as seen by the remote peer
|
||||||
connection_descriptor: ConnectionDescriptor, // the connection descriptor used
|
connection_descriptor: ConnectionDescriptor, // the connection descriptor used
|
||||||
|
@ -603,6 +603,29 @@ impl Network {
|
|||||||
// initialize interfaces
|
// initialize interfaces
|
||||||
self.unlocked_inner.interfaces.refresh().await?;
|
self.unlocked_inner.interfaces.refresh().await?;
|
||||||
|
|
||||||
|
// build the set of networks we should consider for the 'LocalNetwork' routing domain
|
||||||
|
let mut local_networks: HashSet<(IpAddr, IpAddr)> = HashSet::new();
|
||||||
|
self.unlocked_inner
|
||||||
|
.interfaces
|
||||||
|
.with_interfaces(|interfaces| {
|
||||||
|
for (name, intf) in interfaces {
|
||||||
|
// Skip networks that we should never encounter
|
||||||
|
if intf.is_loopback() || !intf.is_running() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Add network to local networks table
|
||||||
|
for addr in intf.addrs {
|
||||||
|
let netmask = addr.if_addr().netmask();
|
||||||
|
let network_ip = ipaddr_apply_netmask(addr.if_addr().ip(), netmask);
|
||||||
|
local_networks.insert((network_ip, netmask));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let local_networks: Vec<(IpAddr, IpAddr)> = local_networks.into_iter().collect();
|
||||||
|
self.unlocked_inner
|
||||||
|
.routing_table
|
||||||
|
.configure_local_network_routing_domain(local_networks);
|
||||||
|
|
||||||
// determine if we have ipv4/ipv6 addresses
|
// determine if we have ipv4/ipv6 addresses
|
||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
@ -367,13 +367,12 @@ xxx write routing table sieve for routing domain from dialinfo and local network
|
|||||||
pub(super) async fn start_ws_listeners(&self) -> EyreResult<()> {
|
pub(super) async fn start_ws_listeners(&self) -> EyreResult<()> {
|
||||||
trace!("starting ws listeners");
|
trace!("starting ws listeners");
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let (listen_address, url, path, enable_local_peer_scope, detect_address_changes) = {
|
let (listen_address, url, path, detect_address_changes) = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
(
|
(
|
||||||
c.network.protocol.ws.listen_address.clone(),
|
c.network.protocol.ws.listen_address.clone(),
|
||||||
c.network.protocol.ws.url.clone(),
|
c.network.protocol.ws.url.clone(),
|
||||||
c.network.protocol.ws.path.clone(),
|
c.network.protocol.ws.path.clone(),
|
||||||
c.network.enable_local_peer_scope,
|
|
||||||
c.network.detect_address_changes,
|
c.network.detect_address_changes,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -586,12 +585,11 @@ xxx write routing table sieve for routing domain from dialinfo and local network
|
|||||||
trace!("starting tcp listeners");
|
trace!("starting tcp listeners");
|
||||||
|
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let (listen_address, public_address, enable_local_peer_scope, detect_address_changes) = {
|
let (listen_address, public_address, detect_address_changes) = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
(
|
(
|
||||||
c.network.protocol.tcp.listen_address.clone(),
|
c.network.protocol.tcp.listen_address.clone(),
|
||||||
c.network.protocol.tcp.public_address.clone(),
|
c.network.protocol.tcp.public_address.clone(),
|
||||||
c.network.enable_local_peer_scope,
|
|
||||||
c.network.detect_address_changes,
|
c.network.detect_address_changes,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -197,7 +197,11 @@ impl NetworkManager {
|
|||||||
let routing_table = routing_table.clone();
|
let routing_table = routing_table.clone();
|
||||||
unord.push(
|
unord.push(
|
||||||
// lets ask bootstrap to find ourselves now
|
// lets ask bootstrap to find ourselves now
|
||||||
async move { routing_table.reverse_find_node(nr, true).await },
|
async move {
|
||||||
|
routing_table
|
||||||
|
.reverse_find_node(RoutingDomain::PublicInternet, nr, true)
|
||||||
|
.await
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +303,9 @@ impl NetworkManager {
|
|||||||
unord.push(async move {
|
unord.push(async move {
|
||||||
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
||||||
// which will ensure it has the bootstrap's signed peer info as part of the response
|
// which will ensure it has the bootstrap's signed peer info as part of the response
|
||||||
let _ = routing_table.find_target(nr.clone()).await;
|
let _ = routing_table
|
||||||
|
.find_target(RoutingDomain::PublicInternet, nr.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
// Ensure we got the signed peer info
|
// Ensure we got the signed peer info
|
||||||
if !nr.has_valid_signed_node_info(Some(RoutingDomain::PublicInternet)) {
|
if !nr.has_valid_signed_node_info(Some(RoutingDomain::PublicInternet)) {
|
||||||
@ -310,7 +316,9 @@ impl NetworkManager {
|
|||||||
// If this node info is invalid, it will time out after being unpingable
|
// If this node info is invalid, it will time out after being unpingable
|
||||||
} else {
|
} else {
|
||||||
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
||||||
routing_table.reverse_find_node(nr, true).await
|
routing_table
|
||||||
|
.reverse_find_node(RoutingDomain::PublicInternet, nr, true)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -324,33 +332,35 @@ impl NetworkManager {
|
|||||||
// Ping each node in the routing table if they need to be pinged
|
// Ping each node in the routing table if they need to be pinged
|
||||||
// to determine their reliability
|
// to determine their reliability
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub(super) async fn ping_validator_task_routine(
|
fn ping_validator_public_internet(
|
||||||
self,
|
&self,
|
||||||
stop_token: StopToken,
|
|
||||||
_last_ts: u64,
|
|
||||||
cur_ts: u64,
|
cur_ts: u64,
|
||||||
|
unord: &mut FuturesUnordered,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
let rpc = self.rpc_processor();
|
let rpc = self.rpc_processor();
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
let mut unord = FuturesUnordered::new();
|
// Get all nodes needing pings in the PublicInternet routing domain
|
||||||
|
let node_refs = routing_table.get_nodes_needing_ping(RoutingDomain::PublicInternet, cur_ts);
|
||||||
|
|
||||||
let node_refs = routing_table.get_nodes_needing_ping(cur_ts);
|
// Look up any NAT mappings we may need to try to preserve with keepalives
|
||||||
let mut mapped_port_info = routing_table.get_mapped_port_info();
|
let mut mapped_port_info = routing_table.get_mapped_port_info();
|
||||||
let opt_public_internet_relay_nr = routing_table.relay_node(RoutingDomain::PublicInternet);
|
|
||||||
let opt_public_internet_relay_id = opt_public_internet_relay_nr.map(|nr| nr.node_id());
|
|
||||||
// let opt_local_network_relay_nr = routing_table.relay_node(RoutingDomain::LocalNetwork);
|
|
||||||
// let opt_local_network_relay_id = opt_local_network_relay_nr.map(|nr| nr.node_id());
|
|
||||||
|
|
||||||
// Public Internet Routing Domain
|
// Get the PublicInternet relay if we are using one
|
||||||
|
let opt_relay_nr = routing_table.relay_node(RoutingDomain::PublicInternet);
|
||||||
|
let opt_relay_id = opt_relay_nr.map(|nr| nr.node_id());
|
||||||
|
|
||||||
|
// Get our publicinternet dial info
|
||||||
let dids = routing_table.all_filtered_dial_info_details(
|
let dids = routing_table.all_filtered_dial_info_details(
|
||||||
Some(RoutingDomain::PublicInternet),
|
RoutingDomainSet::only(RoutingDomain::PublicInternet),
|
||||||
&DialInfoFilter::global(),
|
&DialInfoFilter::all(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// For all nodes needing pings, figure out how many and over what protocols
|
||||||
for nr in node_refs {
|
for nr in node_refs {
|
||||||
let rpc = rpc.clone();
|
// If this is a relay, let's check for NAT keepalives
|
||||||
if Some(nr.node_id()) == opt_public_internet_relay_id {
|
let mut did_pings = false;
|
||||||
|
if Some(nr.node_id()) == opt_relay_id {
|
||||||
// Relay nodes get pinged over all protocols we have inbound dialinfo for
|
// Relay nodes get pinged over all protocols we have inbound dialinfo for
|
||||||
// This is so we can preserve the inbound NAT mappings at our router
|
// This is so we can preserve the inbound NAT mappings at our router
|
||||||
for did in &dids {
|
for did in &dids {
|
||||||
@ -370,19 +380,84 @@ impl NetworkManager {
|
|||||||
};
|
};
|
||||||
if needs_ping {
|
if needs_ping {
|
||||||
let rpc = rpc.clone();
|
let rpc = rpc.clone();
|
||||||
let dif = did.dial_info.make_filter(true);
|
let dif = did.dial_info.make_filter();
|
||||||
let nr_filtered = nr.filtered_clone(dif);
|
let nr_filtered = nr.filtered_clone(dif);
|
||||||
log_net!("--> Keepalive ping to {:?}", nr_filtered);
|
log_net!("--> Keepalive ping to {:?}", nr_filtered);
|
||||||
unord.push(async move { rpc.rpc_call_status(nr_filtered).await }.boxed());
|
unord.push(
|
||||||
|
async move {
|
||||||
|
rpc.rpc_call_status(Some(routing_domain), nr_filtered).await
|
||||||
|
}
|
||||||
|
.boxed(),
|
||||||
|
);
|
||||||
|
did_pings = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// Just do a single ping with the best protocol for all the other nodes
|
// Just do a single ping with the best protocol for all the other nodes,
|
||||||
unord.push(async move { rpc.rpc_call_status(nr).await }.boxed());
|
// ensuring that we at least ping a relay with -something- even if we didnt have
|
||||||
|
// any mapped ports to preserve
|
||||||
|
if !did_pings {
|
||||||
|
let rpc = rpc.clone();
|
||||||
|
unord.push(
|
||||||
|
async move { rpc.rpc_call_status(Some(routing_domain), nr).await }.boxed(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for futures to complete
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping each node in the LocalNetwork routing domain if they
|
||||||
|
// need to be pinged to determine their reliability
|
||||||
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
|
fn ping_validator_local_network(
|
||||||
|
&self,
|
||||||
|
cur_ts: u64,
|
||||||
|
unord: &mut FuturesUnordered,
|
||||||
|
) -> EyreResult<()> {
|
||||||
|
let rpc = self.rpc_processor();
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
|
// Get all nodes needing pings in the LocalNetwork routing domain
|
||||||
|
let node_refs = routing_table.get_nodes_needing_ping(RoutingDomain::LocalNetwork, cur_ts);
|
||||||
|
|
||||||
|
// Get our LocalNetwork dial info
|
||||||
|
let dids = routing_table.all_filtered_dial_info_details(
|
||||||
|
RoutingDomainSet::only(RoutingDomain::LocalNetwork),
|
||||||
|
&DialInfoFilter::all(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// For all nodes needing pings, figure out how many and over what protocols
|
||||||
|
for nr in node_refs {
|
||||||
|
let rpc = rpc.clone();
|
||||||
|
|
||||||
|
// Just do a single ping with the best protocol for all the nodes
|
||||||
|
unord.push(async move { rpc.rpc_call_status(Some(routing_domain), nr).await }.boxed());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping each node in the routing table if they need to be pinged
|
||||||
|
// to determine their reliability
|
||||||
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
|
pub(super) async fn ping_validator_task_routine(
|
||||||
|
self,
|
||||||
|
stop_token: StopToken,
|
||||||
|
_last_ts: u64,
|
||||||
|
cur_ts: u64,
|
||||||
|
) -> EyreResult<()> {
|
||||||
|
let rpc = self.rpc_processor();
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
let mut unord = FuturesUnordered::new();
|
||||||
|
|
||||||
|
// PublicInternet
|
||||||
|
self.ping_validator_public_internet(cur_ts, &mut unord)?;
|
||||||
|
|
||||||
|
// LocalNetwork
|
||||||
|
self.ping_validator_local_network(cur_ts, &mut unord)?;
|
||||||
|
|
||||||
|
// Wait for ping futures to complete in parallel
|
||||||
while let Ok(Some(_)) = unord.next().timeout_at(stop_token.clone()).await {}
|
while let Ok(Some(_)) = unord.next().timeout_at(stop_token.clone()).await {}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -390,24 +465,38 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Ask our remaining peers to give us more peers before we go
|
// Ask our remaining peers to give us more peers before we go
|
||||||
// back to the bootstrap servers to keep us from bothering them too much
|
// back to the bootstrap servers to keep us from bothering them too much
|
||||||
|
// This only adds PublicInternet routing domain peers. The discovery
|
||||||
|
// mechanism for LocalNetwork suffices for locating all the local network
|
||||||
|
// peers that are available. This, however, may query other LocalNetwork
|
||||||
|
// nodes for their PublicInternet peers, which is a very fast way to get
|
||||||
|
// a new node online.
|
||||||
#[instrument(level = "trace", skip(self), err)]
|
#[instrument(level = "trace", skip(self), err)]
|
||||||
pub(super) async fn peer_minimum_refresh_task_routine(
|
pub(super) async fn peer_minimum_refresh_task_routine(
|
||||||
self,
|
self,
|
||||||
stop_token: StopToken,
|
stop_token: StopToken,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let cur_ts = intf::get_timestamp();
|
let mut unord = FuturesOrdered::new();
|
||||||
|
let min_peer_count = {
|
||||||
|
let c = self.config.get();
|
||||||
|
c.network.dht.min_peer_count as usize
|
||||||
|
};
|
||||||
|
|
||||||
// get list of all peers we know about, even the unreliable ones, and ask them to find nodes close to our node too
|
// For the PublicInternet routing domain, get list of all peers we know about
|
||||||
let noderefs = routing_table.get_all_nodes(cur_ts);
|
// even the unreliable ones, and ask them to find nodes close to our node too
|
||||||
|
let noderefs = routing_table.find_fastest_nodes(
|
||||||
// do peer minimum search concurrently
|
min_peer_count,
|
||||||
let mut unord = FuturesUnordered::new();
|
None,
|
||||||
|
|k: DHTKey, v: Option<Arc<BucketEntry>>| {
|
||||||
|
NodeRef::new(self.clone(), k, v.unwrap().clone(), None)
|
||||||
|
},
|
||||||
|
);
|
||||||
for nr in noderefs {
|
for nr in noderefs {
|
||||||
log_net!("--- peer minimum search with {:?}", nr);
|
|
||||||
let routing_table = routing_table.clone();
|
let routing_table = routing_table.clone();
|
||||||
unord.push(async move { routing_table.reverse_find_node(nr, false).await });
|
unord.push(async move { routing_table.reverse_find_node(nr, false).await });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do peer minimum search in order from fastest to slowest
|
||||||
while let Ok(Some(_)) = unord.next().timeout_at(stop_token.clone()).await {}
|
while let Ok(Some(_)) = unord.next().timeout_at(stop_token.clone()).await {}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -39,7 +39,7 @@ pub enum BucketEntryState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||||
struct LastConnectionKey(ProtocolType, AddressType);
|
struct LastConnectionKey(RoutingDomain, ProtocolType, AddressType);
|
||||||
|
|
||||||
/// Bucket entry information specific to the LocalNetwork RoutingDomain
|
/// Bucket entry information specific to the LocalNetwork RoutingDomain
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -136,10 +136,18 @@ impl BucketEntryInner {
|
|||||||
move |e1, e2| Self::cmp_fastest_reliable(cur_ts, e1, e2)
|
move |e1, e2| Self::cmp_fastest_reliable(cur_ts, e1, e2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_signed_node_info(&mut self, routing_domain: RoutingDomain) {
|
||||||
|
// Get the correct signed_node_info for the chosen routing domain
|
||||||
|
let opt_current_sni = match routing_domain {
|
||||||
|
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||||
|
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||||
|
};
|
||||||
|
*opt_current_sni = None;
|
||||||
|
}
|
||||||
|
|
||||||
// Retuns true if the node info changed
|
// Retuns true if the node info changed
|
||||||
pub fn update_signed_node_info(
|
pub fn update_signed_node_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
routing_domain: RoutingDomain,
|
|
||||||
signed_node_info: SignedNodeInfo,
|
signed_node_info: SignedNodeInfo,
|
||||||
allow_invalid_signature: bool,
|
allow_invalid_signature: bool,
|
||||||
) {
|
) {
|
||||||
@ -150,7 +158,7 @@ impl BucketEntryInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the correct signed_node_info for the chosen routing domain
|
// Get the correct signed_node_info for the chosen routing domain
|
||||||
let opt_current_sni = match routing_domain {
|
let opt_current_sni = match signed_node_info.routing_domain {
|
||||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||||
};
|
};
|
||||||
@ -160,7 +168,8 @@ impl BucketEntryInner {
|
|||||||
// If the timestamp hasn't changed or is less, ignore this update
|
// If the timestamp hasn't changed or is less, ignore this update
|
||||||
if signed_node_info.timestamp <= current_sni.timestamp {
|
if signed_node_info.timestamp <= current_sni.timestamp {
|
||||||
// If we received a node update with the same timestamp
|
// If we received a node update with the same timestamp
|
||||||
// we can make this node live again, but only if our network hasn't changed
|
// we can make this node live again, but only if our network has recently changed
|
||||||
|
// which may make nodes that were unreachable now reachable with the same dialinfo
|
||||||
if !self.updated_since_last_network_change
|
if !self.updated_since_last_network_change
|
||||||
&& signed_node_info.timestamp == current_sni.timestamp
|
&& signed_node_info.timestamp == current_sni.timestamp
|
||||||
{
|
{
|
||||||
@ -185,50 +194,34 @@ impl BucketEntryInner {
|
|||||||
self.touch_last_seen(intf::get_timestamp());
|
self.touch_last_seen(intf::get_timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_node_info(&self, opt_routing_domain: Option<RoutingDomain>) -> bool {
|
pub fn has_node_info(&self, routing_domain_set: RoutingDomainSet) -> bool {
|
||||||
if let Some(routing_domain) = opt_routing_domain {
|
for routing_domain in routing_domain_set {
|
||||||
// Get the correct signed_node_info for the chosen routing domain
|
// Get the correct signed_node_info for the chosen routing domain
|
||||||
let opt_current_sni = match routing_domain {
|
let opt_current_sni = match routing_domain {
|
||||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||||
};
|
};
|
||||||
opt_current_sni.is_some()
|
if opt_current_sni.is_some() {
|
||||||
} else {
|
return true;
|
||||||
if self.local_network.signed_node_info.is_some() {
|
|
||||||
true
|
|
||||||
} else if self.public_internet.signed_node_info.is_some() {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_valid_signed_node_info(&self, opt_routing_domain: Option<RoutingDomain>) -> bool {
|
pub fn has_valid_signed_node_info(&self, routing_domain_set: RoutingDomainSet) -> bool {
|
||||||
if let Some(routing_domain) = opt_routing_domain {
|
for routing_domain in routing_domain_set {
|
||||||
// Get the correct signed_node_info for the chosen routing domain
|
// Get the correct signed_node_info for the chosen routing domain
|
||||||
let opt_current_sni = match routing_domain {
|
let opt_current_sni = match routing_domain {
|
||||||
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||||
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||||
};
|
};
|
||||||
if let Some(sni) = opt_current_sni {
|
if let Some(sni) = opt_current_sni {
|
||||||
sni.is_valid()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Some(sni) = self.local_network.signed_node_info {
|
|
||||||
if sni.is_valid() {
|
if sni.is_valid() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(sni) = self.public_internet.signed_node_info {
|
|
||||||
if sni.is_valid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_info(&self, routing_domain: RoutingDomain) -> Option<NodeInfo> {
|
pub fn node_info(&self, routing_domain: RoutingDomain) -> Option<NodeInfo> {
|
||||||
@ -250,8 +243,28 @@ impl BucketEntryInner {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn descriptor_to_key(last_connection: ConnectionDescriptor) -> LastConnectionKey {
|
pub fn best_routing_domain(
|
||||||
|
&self,
|
||||||
|
routing_domain_set: RoutingDomainSet,
|
||||||
|
) -> Option<RoutingDomain> {
|
||||||
|
for routing_domain in routing_domain_set {
|
||||||
|
let opt_current_sni = match routing_domain {
|
||||||
|
RoutingDomain::LocalNetwork => &mut self.local_network.signed_node_info,
|
||||||
|
RoutingDomain::PublicInternet => &mut self.public_internet.signed_node_info,
|
||||||
|
};
|
||||||
|
if let Some(sni) = opt_current_sni {
|
||||||
|
if sni.is_valid() {
|
||||||
|
return Some(routing_domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descriptor_to_key(&self, last_connection: ConnectionDescriptor) -> LastConnectionKey {
|
||||||
|
let routing_domain = self.routing_domain_for_address(last_connection.remote().address());
|
||||||
LastConnectionKey(
|
LastConnectionKey(
|
||||||
|
routing_domain,
|
||||||
last_connection.protocol_type(),
|
last_connection.protocol_type(),
|
||||||
last_connection.address_type(),
|
last_connection.address_type(),
|
||||||
)
|
)
|
||||||
@ -259,7 +272,7 @@ impl BucketEntryInner {
|
|||||||
|
|
||||||
// Stores a connection descriptor in this entry's table of last connections
|
// Stores a connection descriptor in this entry's table of last connections
|
||||||
pub fn set_last_connection(&mut self, last_connection: ConnectionDescriptor, timestamp: u64) {
|
pub fn set_last_connection(&mut self, last_connection: ConnectionDescriptor, timestamp: u64) {
|
||||||
let key = Self::descriptor_to_key(last_connection);
|
let key = self.descriptor_to_key(last_connection);
|
||||||
self.last_connections
|
self.last_connections
|
||||||
.insert(key, (last_connection, timestamp));
|
.insert(key, (last_connection, timestamp));
|
||||||
}
|
}
|
||||||
@ -269,18 +282,21 @@ impl BucketEntryInner {
|
|||||||
self.last_connections.clear();
|
self.last_connections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the best 'last connection' that matches a set of protocol types and address types
|
// Gets the best 'last connection' that matches a set of routing domain, protocol types and address types
|
||||||
pub fn last_connection(
|
pub fn last_connection(
|
||||||
&self,
|
&self,
|
||||||
|
routing_domain_set: RoutingDomainSet,
|
||||||
dial_info_filter: Option<DialInfoFilter>,
|
dial_info_filter: Option<DialInfoFilter>,
|
||||||
) -> Option<(ConnectionDescriptor, u64)> {
|
) -> Option<(ConnectionDescriptor, u64)> {
|
||||||
// Iterate peer scopes and protocol types and address type in order to ensure we pick the preferred protocols if all else is the same
|
// Iterate peer scopes and protocol types and address type in order to ensure we pick the preferred protocols if all else is the same
|
||||||
let dif = dial_info_filter.unwrap_or_default();
|
let dif = dial_info_filter.unwrap_or_default();
|
||||||
for pt in dif.protocol_type_set {
|
for rd in routing_domain_set {
|
||||||
for at in dif.address_type_set {
|
for pt in dif.protocol_type_set {
|
||||||
let key = LastConnectionKey(pt, at);
|
for at in dif.address_type_set {
|
||||||
if let Some(v) = self.last_connections.get(&key) {
|
let key = LastConnectionKey(rd, pt, at);
|
||||||
return Some(*v);
|
if let Some(v) = self.last_connections.get(&key) {
|
||||||
|
return Some(*v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +341,7 @@ impl BucketEntryInner {
|
|||||||
.node_status
|
.node_status
|
||||||
.map(|ln| NodeStatus::LocalNetwork(ln)),
|
.map(|ln| NodeStatus::LocalNetwork(ln)),
|
||||||
RoutingDomain::PublicInternet => self
|
RoutingDomain::PublicInternet => self
|
||||||
.local_network
|
.public_internet
|
||||||
.node_status
|
.node_status
|
||||||
.map(|pi| NodeStatus::PublicInternet(pi)),
|
.map(|pi| NodeStatus::PublicInternet(pi)),
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ impl RoutingTable {
|
|||||||
let entry = v.unwrap();
|
let entry = v.unwrap();
|
||||||
entry.with(|e| {
|
entry.with(|e| {
|
||||||
// skip nodes on our local network here
|
// skip nodes on our local network here
|
||||||
if e.has_node_info(Some(RoutingDomain::LocalNetwork)) {
|
if e.has_node_info(RoutingDomainSet::only(RoutingDomain::LocalNetwork)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,25 +130,22 @@ impl RoutingTable {
|
|||||||
let filter = |n: NodeInfo| {
|
let filter = |n: NodeInfo| {
|
||||||
let mut keep = false;
|
let mut keep = false;
|
||||||
for did in n.dial_info_detail_list {
|
for did in n.dial_info_detail_list {
|
||||||
if did.dial_info.is_global() {
|
if matches!(did.dial_info.address_type(), AddressType::IPV4) {
|
||||||
if matches!(did.dial_info.address_type(), AddressType::IPV4) {
|
for (n, protocol_type) in protocol_types.iter().enumerate() {
|
||||||
for (n, protocol_type) in protocol_types.iter().enumerate() {
|
if nodes_proto_v4[n] < max_per_type
|
||||||
if nodes_proto_v4[n] < max_per_type
|
&& did.dial_info.protocol_type() == *protocol_type
|
||||||
&& did.dial_info.protocol_type() == *protocol_type
|
{
|
||||||
{
|
nodes_proto_v4[n] += 1;
|
||||||
nodes_proto_v4[n] += 1;
|
keep = true;
|
||||||
keep = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if matches!(did.dial_info.address_type(), AddressType::IPV6)
|
}
|
||||||
{
|
} else if matches!(did.dial_info.address_type(), AddressType::IPV6) {
|
||||||
for (n, protocol_type) in protocol_types.iter().enumerate() {
|
for (n, protocol_type) in protocol_types.iter().enumerate() {
|
||||||
if nodes_proto_v6[n] < max_per_type
|
if nodes_proto_v6[n] < max_per_type
|
||||||
&& did.dial_info.protocol_type() == *protocol_type
|
&& did.dial_info.protocol_type() == *protocol_type
|
||||||
{
|
{
|
||||||
nodes_proto_v6[n] += 1;
|
nodes_proto_v6[n] += 1;
|
||||||
keep = true;
|
keep = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,48 +165,16 @@ impl RoutingTable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get our own node's peer info (public node info) so we can share it with other nodes
|
|
||||||
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
|
||||||
PeerInfo::new(
|
|
||||||
NodeId::new(self.node_id()),
|
|
||||||
self.get_own_signed_node_info(routing_domain),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedNodeInfo {
|
|
||||||
let node_id = NodeId::new(self.node_id());
|
|
||||||
let secret = self.node_id_secret();
|
|
||||||
SignedNodeInfo::with_secret(self.get_own_node_info(routing_domain), node_id, &secret)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
|
|
||||||
let netman = self.network_manager();
|
|
||||||
let relay_node = self.relay_node(routing_domain);
|
|
||||||
let pc = netman.get_protocol_config();
|
|
||||||
NodeInfo {
|
|
||||||
network_class: netman
|
|
||||||
.get_network_class(routing_domain)
|
|
||||||
.unwrap_or(NetworkClass::Invalid),
|
|
||||||
outbound_protocols: pc.outbound,
|
|
||||||
address_types: pc.family_global,
|
|
||||||
min_version: MIN_VERSION,
|
|
||||||
max_version: MAX_VERSION,
|
|
||||||
dial_info_detail_list: self.dial_info_details(routing_domain),
|
|
||||||
relay_peer_info: relay_node.and_then(|rn| rn.peer_info(routing_domain).map(Box::new)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn filter_has_valid_signed_node_info(
|
pub fn filter_has_valid_signed_node_info(
|
||||||
&self,
|
&self,
|
||||||
v: Option<Arc<BucketEntry>>,
|
v: Option<Arc<BucketEntry>>,
|
||||||
own_peer_info_is_valid: bool,
|
own_peer_info_is_valid: bool,
|
||||||
opt_routing_domain: Option<RoutingDomain>,
|
routing_domain_set: RoutingDomainSet,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let routing_table = self.clone();
|
let routing_table = self.clone();
|
||||||
match v {
|
match v {
|
||||||
None => own_peer_info_is_valid,
|
None => own_peer_info_is_valid,
|
||||||
Some(entry) => entry.with(|e| e.has_valid_signed_node_info(opt_routing_domain)),
|
Some(entry) => entry.with(|e| e.has_valid_signed_node_info(routing_domain_set)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +390,7 @@ impl RoutingTable {
|
|||||||
let mut protocol_to_port =
|
let mut protocol_to_port =
|
||||||
BTreeMap::<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>::new();
|
BTreeMap::<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>::new();
|
||||||
let our_dids = self.all_filtered_dial_info_details(
|
let our_dids = self.all_filtered_dial_info_details(
|
||||||
Some(RoutingDomain::PublicInternet),
|
RoutingDomainSet::only(RoutingDomain::PublicInternet),
|
||||||
&DialInfoFilter::all(),
|
&DialInfoFilter::all(),
|
||||||
);
|
);
|
||||||
for did in our_dids {
|
for did in our_dids {
|
||||||
@ -452,12 +417,12 @@ impl RoutingTable {
|
|||||||
// Get all our outbound protocol/address types
|
// Get all our outbound protocol/address types
|
||||||
let outbound_dif = self
|
let outbound_dif = self
|
||||||
.network_manager()
|
.network_manager()
|
||||||
.get_outbound_dial_info_filter(RoutingDomain::PublicInternet);
|
.get_outbound_node_ref_filter(RoutingDomain::PublicInternet);
|
||||||
let mapped_port_info = self.get_mapped_port_info();
|
let mapped_port_info = self.get_mapped_port_info();
|
||||||
|
|
||||||
move |e: &BucketEntryInner| {
|
move |e: &BucketEntryInner| {
|
||||||
// Ensure this node is not on the local network
|
// Ensure this node is not on the local network
|
||||||
if e.has_node_info(Some(RoutingDomain::LocalNetwork)) {
|
if e.has_node_info(RoutingDomainSet::only(RoutingDomain::LocalNetwork)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,11 +507,7 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub fn register_find_node_answer(
|
pub fn register_find_node_answer(&self, peers: Vec<PeerInfo>) -> Vec<NodeRef> {
|
||||||
&self,
|
|
||||||
routing_domain: RoutingDomain,
|
|
||||||
peers: Vec<PeerInfo>,
|
|
||||||
) -> Vec<NodeRef> {
|
|
||||||
let node_id = self.node_id();
|
let node_id = self.node_id();
|
||||||
|
|
||||||
// register nodes we'd found
|
// register nodes we'd found
|
||||||
@ -566,7 +527,7 @@ impl RoutingTable {
|
|||||||
|
|
||||||
// register the node if it's new
|
// register the node if it's new
|
||||||
if let Some(nr) = self.register_node_with_signed_node_info(
|
if let Some(nr) = self.register_node_with_signed_node_info(
|
||||||
routing_domain,
|
RoutingDomain::PublicInternet,
|
||||||
p.node_id.key,
|
p.node_id.key,
|
||||||
p.signed_node_info.clone(),
|
p.signed_node_info.clone(),
|
||||||
false,
|
false,
|
||||||
@ -580,7 +541,6 @@ impl RoutingTable {
|
|||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub async fn find_node(
|
pub async fn find_node(
|
||||||
&self,
|
&self,
|
||||||
routing_domain: RoutingDomain,
|
|
||||||
node_ref: NodeRef,
|
node_ref: NodeRef,
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||||
@ -589,18 +549,13 @@ impl RoutingTable {
|
|||||||
let res = network_result_try!(
|
let res = network_result_try!(
|
||||||
rpc_processor
|
rpc_processor
|
||||||
.clone()
|
.clone()
|
||||||
.rpc_call_find_node(
|
.rpc_call_find_node(Destination::direct(node_ref), node_id,)
|
||||||
Destination::direct(node_ref.clone()).with_routing_domain(routing_domain),
|
|
||||||
node_id,
|
|
||||||
None,
|
|
||||||
rpc_processor.make_respond_to_sender(routing_domain, node_ref.clone()),
|
|
||||||
)
|
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
|
|
||||||
// register nodes we'd found
|
// register nodes we'd found
|
||||||
Ok(NetworkResult::value(
|
Ok(NetworkResult::value(
|
||||||
self.register_find_node_answer(routing_domain, res.answer),
|
self.register_find_node_answer(res.answer),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ mod bucket_entry;
|
|||||||
mod debug;
|
mod debug;
|
||||||
mod find_nodes;
|
mod find_nodes;
|
||||||
mod node_ref;
|
mod node_ref;
|
||||||
|
mod routing_domains;
|
||||||
mod stats_accounting;
|
mod stats_accounting;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
|
|
||||||
@ -17,34 +18,31 @@ pub use debug::*;
|
|||||||
pub use find_nodes::*;
|
pub use find_nodes::*;
|
||||||
use hashlink::LruCache;
|
use hashlink::LruCache;
|
||||||
pub use node_ref::*;
|
pub use node_ref::*;
|
||||||
|
pub use routing_domains::*;
|
||||||
pub use stats_accounting::*;
|
pub use stats_accounting::*;
|
||||||
|
|
||||||
const RECENT_PEERS_TABLE_SIZE: usize = 64;
|
const RECENT_PEERS_TABLE_SIZE: usize = 64;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct RoutingDomainDetail {
|
|
||||||
relay_node: Option<NodeRef>,
|
|
||||||
dial_info_details: Vec<DialInfoDetail>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct RecentPeersEntry {
|
pub struct RecentPeersEntry {
|
||||||
last_connection: ConnectionDescriptor,
|
last_connection: ConnectionDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RoutingTable rwlock-internal data
|
||||||
struct RoutingTableInner {
|
struct RoutingTableInner {
|
||||||
network_manager: NetworkManager,
|
network_manager: NetworkManager,
|
||||||
node_id: DHTKey, // The current node's public DHT key
|
// The current node's public DHT key
|
||||||
|
node_id: DHTKey,
|
||||||
node_id_secret: DHTKeySecret, // The current node's DHT key secret
|
node_id_secret: DHTKeySecret, // The current node's DHT key secret
|
||||||
|
|
||||||
buckets: Vec<Bucket>, // Routing table buckets that hold entries
|
buckets: Vec<Bucket>, // Routing table buckets that hold entries
|
||||||
kick_queue: BTreeSet<usize>, // Buckets to kick on our next kick task
|
kick_queue: BTreeSet<usize>, // Buckets to kick on our next kick task
|
||||||
bucket_entry_count: usize, // A fast counter for the number of entries in the table, total
|
bucket_entry_count: usize, // A fast counter for the number of entries in the table, total
|
||||||
|
|
||||||
public_internet_routing_domain: RoutingDomainDetail, // The dial info we use on the public internet
|
public_internet_routing_domain: PublicInternetRoutingDomainDetail, // The public internet
|
||||||
local_network_routing_domain: RoutingDomainDetail, // The dial info we use on the local network
|
local_network_routing_domain: LocalInternetRoutingDomainDetail, // The dial info we use on the local network
|
||||||
|
|
||||||
self_latency_stats_accounting: LatencyStatsAccounting, // Interim accounting mechanism for this node's RPC latency to any other node
|
self_latency_stats_accounting: LatencyStatsAccounting, // Interim accounting mechanism for this node's RPC latency to any other node
|
||||||
self_transfer_stats_accounting: TransferStatsAccounting, // Interim accounting mechanism for the total bandwidth to/from this node
|
self_transfer_stats_accounting: TransferStatsAccounting, // Interim accounting mechanism for the total bandwidth to/from this node
|
||||||
@ -80,8 +78,8 @@ impl RoutingTable {
|
|||||||
node_id_secret: DHTKeySecret::default(),
|
node_id_secret: DHTKeySecret::default(),
|
||||||
buckets: Vec::new(),
|
buckets: Vec::new(),
|
||||||
kick_queue: BTreeSet::default(),
|
kick_queue: BTreeSet::default(),
|
||||||
public_internet_routing_domain: RoutingDomainDetail::default(),
|
public_internet_routing_domain: PublicInternetRoutingDomainDetail::default(),
|
||||||
local_network_routing_domain: RoutingDomainDetail::default(),
|
local_network_routing_domain: LocalInternetRoutingDomainDetail::default(),
|
||||||
bucket_entry_count: 0,
|
bucket_entry_count: 0,
|
||||||
self_latency_stats_accounting: LatencyStatsAccounting::new(),
|
self_latency_stats_accounting: LatencyStatsAccounting::new(),
|
||||||
self_transfer_stats_accounting: TransferStatsAccounting::new(),
|
self_transfer_stats_accounting: TransferStatsAccounting::new(),
|
||||||
@ -140,9 +138,21 @@ impl RoutingTable {
|
|||||||
self.inner.read().node_id_secret
|
self.inner.read().node_id_secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn routing_domain_for_address(&self, address: Address) -> Option<RoutingDomain> {
|
||||||
|
let inner = self.inner.read();
|
||||||
|
for rd in RoutingDomain::all() {
|
||||||
|
let can_contain =
|
||||||
|
Self::with_routing_domain(&*inner, rd, |rdd| rdd.can_contain_address(address));
|
||||||
|
if can_contain {
|
||||||
|
return Some(rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn with_routing_domain<F, R>(inner: &RoutingTableInner, domain: RoutingDomain, f: F) -> R
|
fn with_routing_domain<F, R>(inner: &RoutingTableInner, domain: RoutingDomain, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&RoutingDomainDetail) -> R,
|
F: FnOnce(&dyn RoutingDomainDetail) -> R,
|
||||||
{
|
{
|
||||||
match domain {
|
match domain {
|
||||||
RoutingDomain::PublicInternet => f(&inner.public_internet_routing_domain),
|
RoutingDomain::PublicInternet => f(&inner.public_internet_routing_domain),
|
||||||
@ -156,7 +166,7 @@ impl RoutingTable {
|
|||||||
f: F,
|
f: F,
|
||||||
) -> R
|
) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut RoutingDomainDetail) -> R,
|
F: FnOnce(&mut dyn RoutingDomainDetail) -> R,
|
||||||
{
|
{
|
||||||
match domain {
|
match domain {
|
||||||
RoutingDomain::PublicInternet => f(&mut inner.public_internet_routing_domain),
|
RoutingDomain::PublicInternet => f(&mut inner.public_internet_routing_domain),
|
||||||
@ -166,79 +176,56 @@ impl RoutingTable {
|
|||||||
|
|
||||||
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
pub fn relay_node(&self, domain: RoutingDomain) -> Option<NodeRef> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
Self::with_routing_domain(&*inner, domain, |rd| rd.relay_node.clone())
|
Self::with_routing_domain(&*inner, domain, |rd| rd.relay_node())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_relay_node(&self, domain: RoutingDomain, opt_relay_node: Option<NodeRef>) {
|
pub fn set_relay_node(&self, domain: RoutingDomain, opt_relay_node: Option<NodeRef>) {
|
||||||
let inner = self.inner.write();
|
let inner = self.inner.write();
|
||||||
Self::with_routing_domain(&mut *inner, domain, |rd| rd.relay_node = opt_relay_node);
|
Self::with_routing_domain_mut(&mut *inner, domain, |rd| rd.set_relay_node(opt_relay_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_dial_info(&self, domain: RoutingDomain) -> bool {
|
pub fn has_dial_info(&self, domain: RoutingDomain) -> bool {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
Self::with_routing_domain(&*inner, domain, |rd| !rd.dial_info_details.is_empty())
|
Self::with_routing_domain(&*inner, domain, |rd| !rd.dial_info_details().is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dial_info_details(&self, domain: RoutingDomain) -> Vec<DialInfoDetail> {
|
pub fn dial_info_details(&self, domain: RoutingDomain) -> Vec<DialInfoDetail> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
Self::with_routing_domain(&*inner, domain, |rd| rd.dial_info_details.clone())
|
Self::with_routing_domain(&*inner, domain, |rd| rd.dial_info_details().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_filtered_dial_info_detail(
|
pub fn first_filtered_dial_info_detail(
|
||||||
&self,
|
&self,
|
||||||
domain: Option<RoutingDomain>,
|
routing_domain_set: RoutingDomainSet,
|
||||||
filter: &DialInfoFilter,
|
filter: &DialInfoFilter,
|
||||||
) -> Option<DialInfoDetail> {
|
) -> Option<DialInfoDetail> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
// Prefer local network first if it isn't filtered out
|
for routing_domain in routing_domain_set {
|
||||||
if domain == None || domain == Some(RoutingDomain::LocalNetwork) {
|
let did = Self::with_routing_domain(&*inner, routing_domain, |rd| {
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::LocalNetwork, |rd| {
|
for did in rd.dial_info_details() {
|
||||||
for did in &rd.dial_info_details {
|
|
||||||
if did.matches_filter(filter) {
|
if did.matches_filter(filter) {
|
||||||
return Some(did.clone());
|
return Some(did.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
})
|
});
|
||||||
} else {
|
if did.is_some() {
|
||||||
None
|
return did;
|
||||||
}
|
|
||||||
.or_else(|| {
|
|
||||||
if domain == None || domain == Some(RoutingDomain::PublicInternet) {
|
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::PublicInternet, |rd| {
|
|
||||||
for did in &rd.dial_info_details {
|
|
||||||
if did.matches_filter(filter) {
|
|
||||||
return Some(did.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_filtered_dial_info_details(
|
pub fn all_filtered_dial_info_details(
|
||||||
&self,
|
&self,
|
||||||
domain: Option<RoutingDomain>,
|
routing_domain_set: RoutingDomainSet,
|
||||||
filter: &DialInfoFilter,
|
filter: &DialInfoFilter,
|
||||||
) -> Vec<DialInfoDetail> {
|
) -> Vec<DialInfoDetail> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
|
for routing_domain in routing_domain_set {
|
||||||
if domain == None || domain == Some(RoutingDomain::LocalNetwork) {
|
Self::with_routing_domain(&*inner, routing_domain, |rd| {
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::LocalNetwork, |rd| {
|
for did in rd.dial_info_details() {
|
||||||
for did in &rd.dial_info_details {
|
|
||||||
if did.matches_filter(filter) {
|
|
||||||
ret.push(did.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if domain == None || domain == Some(RoutingDomain::PublicInternet) {
|
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::PublicInternet, |rd| {
|
|
||||||
for did in &rd.dial_info_details {
|
|
||||||
if did.matches_filter(filter) {
|
if did.matches_filter(filter) {
|
||||||
ret.push(did.clone());
|
ret.push(did.clone());
|
||||||
}
|
}
|
||||||
@ -250,17 +237,13 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_dial_info_is_valid(&self, domain: RoutingDomain, dial_info: &DialInfo) -> bool {
|
pub fn ensure_dial_info_is_valid(&self, domain: RoutingDomain, dial_info: &DialInfo) -> bool {
|
||||||
let enable_local_peer_scope = {
|
let address = dial_info.socket_address().address();
|
||||||
let config = self.network_manager().config();
|
let inner = self.inner.read();
|
||||||
let c = config.get();
|
let can_contain_address =
|
||||||
c.network.enable_local_peer_scope
|
Self::with_routing_domain(&*inner, domain, |rd| rd.can_contain_address(address));
|
||||||
};
|
|
||||||
|
|
||||||
if !enable_local_peer_scope
|
if !can_contain_address {
|
||||||
&& matches!(domain, RoutingDomain::PublicInternet)
|
log_rtab!(debug "can not add dial info to this routing domain");
|
||||||
&& dial_info.is_local()
|
|
||||||
{
|
|
||||||
log_rtab!(debug "shouldn't be registering local addresses as public");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if !dial_info.is_valid() {
|
if !dial_info.is_valid() {
|
||||||
@ -281,25 +264,20 @@ impl RoutingTable {
|
|||||||
class: DialInfoClass,
|
class: DialInfoClass,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
if !self.ensure_dial_info_is_valid(domain, &dial_info) {
|
if !self.ensure_dial_info_is_valid(domain, &dial_info) {
|
||||||
return Err(eyre!("dial info is not valid"));
|
return Err(eyre!("dial info is not valid in this routing domain"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inner = self.inner.write();
|
let mut inner = self.inner.write();
|
||||||
Self::with_routing_domain_mut(&mut *inner, domain, |rd| {
|
Self::with_routing_domain_mut(&mut *inner, domain, |rd| {
|
||||||
rd.dial_info_details.push(DialInfoDetail {
|
rd.add_dial_info_detail(DialInfoDetail {
|
||||||
dial_info: dial_info.clone(),
|
dial_info: dial_info.clone(),
|
||||||
class,
|
class,
|
||||||
});
|
});
|
||||||
rd.dial_info_details.sort();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let domain_str = match domain {
|
|
||||||
RoutingDomain::PublicInternet => "Public",
|
|
||||||
RoutingDomain::LocalNetwork => "Local",
|
|
||||||
};
|
|
||||||
info!(
|
info!(
|
||||||
"{} Dial Info: {}",
|
"{:?} Dial Info: {}",
|
||||||
domain_str,
|
domain,
|
||||||
NodeDialInfo {
|
NodeDialInfo {
|
||||||
node_id: NodeId::new(inner.node_id),
|
node_id: NodeId::new(inner.node_id),
|
||||||
dial_info
|
dial_info
|
||||||
@ -308,19 +286,18 @@ impl RoutingTable {
|
|||||||
);
|
);
|
||||||
debug!(" Class: {:?}", class);
|
debug!(" Class: {:?}", class);
|
||||||
|
|
||||||
// Public dial info changed, go through all nodes and reset their 'seen our node info' bit
|
Self::reset_all_seen_our_node_info(&mut *inner, domain);
|
||||||
if matches!(domain, RoutingDomain::PublicInternet) {
|
Self::reset_all_updated_since_last_network_change(&mut *inner);
|
||||||
Self::reset_all_seen_our_node_info(&mut *inner);
|
|
||||||
Self::reset_all_updated_since_last_network_change(&mut *inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_all_seen_our_node_info(inner: &mut RoutingTableInner) {
|
fn reset_all_seen_our_node_info(inner: &mut RoutingTableInner, routing_domain: RoutingDomain) {
|
||||||
let cur_ts = intf::get_timestamp();
|
let cur_ts = intf::get_timestamp();
|
||||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Dead, |_, v| {
|
Self::with_entries(&*inner, cur_ts, BucketEntryState::Dead, |_, v| {
|
||||||
v.with_mut(|e| e.set_seen_our_node_info(false));
|
v.with_mut(|e| {
|
||||||
|
e.set_seen_our_node_info(routing_domain, false);
|
||||||
|
});
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -333,20 +310,57 @@ impl RoutingTable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_dial_info_details(&self, domain: RoutingDomain) {
|
pub fn clear_dial_info_details(&self, routing_domain: RoutingDomain) {
|
||||||
trace!("clearing dial info domain: {:?}", domain);
|
trace!("clearing dial info domain: {:?}", routing_domain);
|
||||||
|
|
||||||
let mut inner = self.inner.write();
|
let mut inner = self.inner.write();
|
||||||
Self::with_routing_domain_mut(&mut *inner, domain, |rd| {
|
Self::with_routing_domain_mut(&mut *inner, routing_domain, |rd| {
|
||||||
rd.dial_info_details.clear();
|
rd.clear_dial_info_details();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Public dial info changed, go through all nodes and reset their 'seen our node info' bit
|
// Public dial info changed, go through all nodes and reset their 'seen our node info' bit
|
||||||
if matches!(domain, RoutingDomain::PublicInternet) {
|
Self::reset_all_seen_our_node_info(&mut *inner, routing_domain);
|
||||||
Self::reset_all_seen_our_node_info(&mut *inner);
|
}
|
||||||
|
|
||||||
|
pub fn get_own_peer_info(&self, routing_domain: RoutingDomain) -> PeerInfo {
|
||||||
|
PeerInfo::new(
|
||||||
|
NodeId::new(self.node_id()),
|
||||||
|
self.get_own_signed_node_info(routing_domain),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedNodeInfo {
|
||||||
|
let node_id = NodeId::new(self.node_id());
|
||||||
|
let secret = self.node_id_secret();
|
||||||
|
SignedNodeInfo::with_secret(self.get_own_node_info(routing_domain), node_id, &secret)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_own_node_info(&self, routing_domain: RoutingDomain) -> NodeInfo {
|
||||||
|
let netman = self.network_manager();
|
||||||
|
let relay_node = self.relay_node(routing_domain);
|
||||||
|
let pc = netman.get_protocol_config();
|
||||||
|
NodeInfo {
|
||||||
|
network_class: netman
|
||||||
|
.get_network_class(routing_domain)
|
||||||
|
.unwrap_or(NetworkClass::Invalid),
|
||||||
|
outbound_protocols: pc.outbound,
|
||||||
|
address_types: pc.family_global,
|
||||||
|
min_version: MIN_VERSION,
|
||||||
|
max_version: MAX_VERSION,
|
||||||
|
dial_info_detail_list: self.dial_info_details(routing_domain),
|
||||||
|
relay_peer_info: relay_node.and_then(|rn| rn.peer_info(routing_domain).map(Box::new)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_valid_own_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||||
|
let netman = self.network_manager();
|
||||||
|
let nc = netman
|
||||||
|
.get_network_class(routing_domain)
|
||||||
|
.unwrap_or(NetworkClass::Invalid);
|
||||||
|
!matches!(nc, NetworkClass::Invalid)
|
||||||
|
}
|
||||||
|
|
||||||
fn bucket_depth(index: usize) -> usize {
|
fn bucket_depth(index: usize) -> usize {
|
||||||
match index {
|
match index {
|
||||||
0 => 256,
|
0 => 256,
|
||||||
@ -398,6 +412,24 @@ impl RoutingTable {
|
|||||||
debug!("finished routing table terminate");
|
debug!("finished routing table terminate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn configure_local_network_routing_domain(&self, local_networks: Vec<(IpAddr, IpAddr)>) {
|
||||||
|
let mut inner = self.inner.write();
|
||||||
|
let changed = inner
|
||||||
|
.local_network_routing_domain
|
||||||
|
.set_local_networks(local_networks);
|
||||||
|
|
||||||
|
// If the local network topology has changed, nuke the existing local node info and let new local discovery happen
|
||||||
|
if changed {
|
||||||
|
let cur_ts = intf::get_timestamp();
|
||||||
|
Self::with_entries(&*inner, cur_ts, BucketEntryState::Dead, |_rti, e| {
|
||||||
|
e.with_mut(|e| {
|
||||||
|
e.clear_signed_node_info(RoutingDomain::LocalNetwork);
|
||||||
|
});
|
||||||
|
Option::<()>::None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to empty the routing table
|
// Attempt to empty the routing table
|
||||||
// should only be performed when there are no node_refs (detached)
|
// should only be performed when there are no node_refs (detached)
|
||||||
pub fn purge_buckets(&self) {
|
pub fn purge_buckets(&self) {
|
||||||
@ -461,16 +493,28 @@ impl RoutingTable {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_entry_count(&self, min_state: BucketEntryState) -> usize {
|
pub fn get_entry_count(
|
||||||
|
&self,
|
||||||
|
routing_domain_set: RoutingDomainSet,
|
||||||
|
min_state: BucketEntryState,
|
||||||
|
) -> usize {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
Self::get_entry_count_inner(&*inner, min_state)
|
Self::get_entry_count_inner(&*inner, routing_domain_set, min_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entry_count_inner(inner: &RoutingTableInner, min_state: BucketEntryState) -> usize {
|
fn get_entry_count_inner(
|
||||||
|
inner: &RoutingTableInner,
|
||||||
|
routing_domain_set: RoutingDomainSet,
|
||||||
|
min_state: BucketEntryState,
|
||||||
|
) -> usize {
|
||||||
let mut count = 0usize;
|
let mut count = 0usize;
|
||||||
let cur_ts = intf::get_timestamp();
|
let cur_ts = intf::get_timestamp();
|
||||||
Self::with_entries(inner, cur_ts, min_state, |_, _| {
|
Self::with_entries(inner, cur_ts, min_state, |_, e| {
|
||||||
count += 1;
|
if e.with(|e| e.best_routing_domain(routing_domain_set))
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
});
|
});
|
||||||
count
|
count
|
||||||
@ -505,38 +549,32 @@ impl RoutingTable {
|
|||||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
||||||
// Only update nodes that haven't seen our node info yet
|
// Only update nodes that haven't seen our node info yet
|
||||||
if all || !v.with(|e| e.has_seen_our_node_info(routing_domain)) {
|
if all || !v.with(|e| e.has_seen_our_node_info(routing_domain)) {
|
||||||
node_refs.push(NodeRef::new(
|
node_refs.push(NodeRef::new(self.clone(), k, v, None));
|
||||||
self.clone(),
|
|
||||||
k,
|
|
||||||
v,
|
|
||||||
RoutingDomainSet::only(routing_domain),
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
});
|
});
|
||||||
node_refs
|
node_refs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_nodes_needing_ping(&self, cur_ts: u64) -> Vec<NodeRef> {
|
pub fn get_nodes_needing_ping(
|
||||||
|
&self,
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
|
cur_ts: u64,
|
||||||
|
) -> Vec<NodeRef> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
|
|
||||||
// Collect relay nodes
|
// Collect relay nodes
|
||||||
let mut relays: HashSet<DHTKey> = HashSet::new();
|
let opt_relay_id = Self::with_routing_domain(&*inner, routing_domain, |rd| {
|
||||||
for rd in RoutingDomain::all() {
|
rd.relay_node().map(|rn| rn.node_id())
|
||||||
let opt_relay_id =
|
});
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::PublicInternet, |rd| {
|
|
||||||
rd.relay_node.map(|rn| rn.node_id())
|
|
||||||
});
|
|
||||||
if let Some(relay_id) = opt_relay_id {
|
|
||||||
relays.insert(relay_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect all entries that are 'needs_ping' and have some node info making them reachable somehow
|
// Collect all entries that are 'needs_ping' and have some node info making them reachable somehow
|
||||||
let mut node_refs = Vec::<NodeRef>::with_capacity(inner.bucket_entry_count);
|
let mut node_refs = Vec::<NodeRef>::with_capacity(inner.bucket_entry_count);
|
||||||
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
Self::with_entries(&*inner, cur_ts, BucketEntryState::Unreliable, |k, v| {
|
||||||
if v.with(|e| e.has_node_info(None) && e.needs_ping(&k, cur_ts, relays.contains(&k))) {
|
if v.with(|e| {
|
||||||
|
e.has_node_info(RoutingDomainSet::only(routing_domain))
|
||||||
|
&& e.needs_ping(&k, cur_ts, opt_relay_id == Some(k))
|
||||||
|
}) {
|
||||||
node_refs.push(NodeRef::new(self.clone(), k, v, None));
|
node_refs.push(NodeRef::new(self.clone(), k, v, None));
|
||||||
}
|
}
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
@ -599,7 +637,7 @@ impl RoutingTable {
|
|||||||
|
|
||||||
// Kick the bucket
|
// Kick the bucket
|
||||||
inner.kick_queue.insert(idx);
|
inner.kick_queue.insert(idx);
|
||||||
log_rtab!(debug "Routing table now has {} nodes, {} live", cnt, Self::get_entry_count_inner(&mut *inner, BucketEntryState::Unreliable));
|
log_rtab!(debug "Routing table now has {} nodes, {} live", cnt, Self::get_entry_count_inner(&mut *inner, RoutingDomainSet::all(), BucketEntryState::Unreliable));
|
||||||
|
|
||||||
nr
|
nr
|
||||||
}
|
}
|
||||||
@ -635,7 +673,6 @@ impl RoutingTable {
|
|||||||
// and add the dial info we have for it, since that's pretty common
|
// and add the dial info we have for it, since that's pretty common
|
||||||
pub fn register_node_with_signed_node_info(
|
pub fn register_node_with_signed_node_info(
|
||||||
&self,
|
&self,
|
||||||
routing_domain: RoutingDomain,
|
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
signed_node_info: SignedNodeInfo,
|
signed_node_info: SignedNodeInfo,
|
||||||
allow_invalid_signature: bool,
|
allow_invalid_signature: bool,
|
||||||
@ -651,9 +688,12 @@ impl RoutingTable {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.create_node_ref(node_id, |e| {
|
self.create_node_ref(node_id, |e| {
|
||||||
e.update_signed_node_info(routing_domain, signed_node_info, allow_invalid_signature);
|
e.update_signed_node_info(signed_node_info, allow_invalid_signature);
|
||||||
|
})
|
||||||
|
.map(|mut nr| {
|
||||||
|
nr.set_filter(Some(NodeRefFilter::new().with_routing_domain(signed_node_info.routing_domain)))
|
||||||
|
nr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,11 +6,71 @@ use alloc::fmt;
|
|||||||
// We should ping them with some frequency and 30 seconds is typical timeout
|
// We should ping them with some frequency and 30 seconds is typical timeout
|
||||||
const CONNECTIONLESS_TIMEOUT_SECS: u32 = 29;
|
const CONNECTIONLESS_TIMEOUT_SECS: u32 = 29;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct NodeRefFilter {
|
||||||
|
pub routing_domain_set: RoutingDomainSet,
|
||||||
|
pub dial_info_filter: DialInfoFilter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NodeRefFilter {
|
||||||
|
fn default() -> Self {
|
||||||
|
self.new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeRefFilter {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
routing_domain_set: RoutingDomainSet::all(),
|
||||||
|
dial_info_filter: DialInfoFilter::all(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_routing_domain(mut self, routing_domain: RoutingDomain) -> Self {
|
||||||
|
self.routing_domain_set = RoutingDomainSet::only(routing_domain);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_routing_domain_set(mut self, routing_domain_set: RoutingDomainSet) -> Self {
|
||||||
|
self.routing_domain_set = routing_domain_set;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_dial_info_filter(mut self, dial_info_filter: DialInfoFilter) -> Self {
|
||||||
|
self.dial_info_filter = dial_info_filter;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_protocol_type(mut self, protocol_type: ProtocolType) -> Self {
|
||||||
|
self.dial_info_filter = self.dial_info_filter.with_protocol_type(protocol_type);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_protocol_type_set(mut self, protocol_set: ProtocolTypeSet) -> Self {
|
||||||
|
self.dial_info_filter = self.dial_info_filter.with_protocol_type_set(protocol_set);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
|
||||||
|
self.dial_info_filter = self.dial_info_filter.with_address_type(address_type);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn with_address_type_set(mut self, address_set: AddressTypeSet) -> Self {
|
||||||
|
self.dial_info_filter = self.dial_info_filter.with_address_type_set(address_set);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn filtered(mut self, other_filter: &NodeRefFilter) -> Self {
|
||||||
|
self.routing_domain_set &= other_filter.routing_domain_set;
|
||||||
|
self.dial_info_filter = self
|
||||||
|
.dial_info_filter
|
||||||
|
.filtered(&other_filter.dial_info_filter);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn is_dead(&self) -> bool {
|
||||||
|
self.dial_info_filter.is_empty() || self.routing_domain_set.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct NodeRef {
|
pub struct NodeRef {
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
entry: Arc<BucketEntry>,
|
entry: Arc<BucketEntry>,
|
||||||
filter: Option<DialInfoFilter>,
|
filter: Option<NodeRefFilter>,
|
||||||
#[cfg(feature = "tracking")]
|
#[cfg(feature = "tracking")]
|
||||||
track_id: usize,
|
track_id: usize,
|
||||||
}
|
}
|
||||||
@ -20,7 +80,7 @@ impl NodeRef {
|
|||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
node_id: DHTKey,
|
node_id: DHTKey,
|
||||||
entry: Arc<BucketEntry>,
|
entry: Arc<BucketEntry>,
|
||||||
filter: Option<DialInfoFilter>,
|
filter: Option<NodeRefFilter>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
entry.ref_count.fetch_add(1u32, Ordering::Relaxed);
|
entry.ref_count.fetch_add(1u32, Ordering::Relaxed);
|
||||||
|
|
||||||
@ -34,43 +94,7 @@ impl NodeRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id(&self) -> DHTKey {
|
// Operate on entry accessors
|
||||||
self.node_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn filter_ref(&self) -> Option<&DialInfoFilter> {
|
|
||||||
self.filter.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn take_filter(&mut self) -> Option<DialInfoFilter> {
|
|
||||||
self.filter.take()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_filter(&mut self, filter: Option<DialInfoFilter>) {
|
|
||||||
self.filter = filter
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn merge_filter(&mut self, filter: DialInfoFilter) {
|
|
||||||
if let Some(self_filter) = self.filter.take() {
|
|
||||||
self.filter = Some(self_filter.filtered(&filter));
|
|
||||||
} else {
|
|
||||||
self.filter = Some(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn filtered_clone(&self, filter: DialInfoFilter) -> Self {
|
|
||||||
let mut out = self.clone();
|
|
||||||
out.merge_filter(filter);
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_filter_dead(&self) -> bool {
|
|
||||||
if let Some(filter) = &self.filter {
|
|
||||||
filter.is_dead()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn operate<T, F>(&self, f: F) -> T
|
pub(super) fn operate<T, F>(&self, f: F) -> T
|
||||||
where
|
where
|
||||||
@ -88,17 +112,67 @@ impl NodeRef {
|
|||||||
self.entry.with_mut(|e| f(inner, e))
|
self.entry.with_mut(|e| f(inner, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
// Filtering
|
||||||
self.operate(|_rti, e| e.peer_info(self.node_id(), routing_domain))
|
|
||||||
|
pub fn filter_ref(&self) -> Option<&NodeRefFilter> {
|
||||||
|
self.filter.as_ref()
|
||||||
}
|
}
|
||||||
pub fn has_valid_signed_node_info(&self, opt_routing_domain: Option<RoutingDomain>) -> bool {
|
|
||||||
self.operate(|_rti, e| e.has_valid_signed_node_info(opt_routing_domain))
|
pub fn take_filter(&mut self) -> Option<NodeRefFilter> {
|
||||||
|
self.filter.take()
|
||||||
}
|
}
|
||||||
pub fn has_seen_our_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
|
||||||
self.operate(|_rti, e| e.has_seen_our_node_info(routing_domain))
|
pub fn set_filter(&mut self, filter: Option<NodeRefFilter>) {
|
||||||
|
self.filter = filter
|
||||||
}
|
}
|
||||||
pub fn set_seen_our_node_info(&self, routing_domain: RoutingDomain) {
|
|
||||||
self.operate_mut(|_rti, e| e.set_seen_our_node_info(routing_domain, true));
|
pub fn merge_filter(&mut self, filter: NodeRefFilter) {
|
||||||
|
if let Some(self_filter) = self.filter.take() {
|
||||||
|
self.filter = Some(self_filter.filtered(&filter));
|
||||||
|
} else {
|
||||||
|
self.filter = Some(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filtered_clone(&self, filter: NodeRefFilter) -> Self {
|
||||||
|
let mut out = self.clone();
|
||||||
|
out.merge_filter(filter);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_filter_dead(&self) -> bool {
|
||||||
|
if let Some(filter) = &self.filter {
|
||||||
|
filter.is_dead()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn routing_domain_set(&self) -> RoutingDomainSet {
|
||||||
|
self.filter
|
||||||
|
.map(|f| f.routing_domain_set)
|
||||||
|
.unwrap_or(RoutingDomainSet::all())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn best_routing_domain(&self) -> Option<RoutingDomain> {
|
||||||
|
self.operate(|_rti, e| {
|
||||||
|
e.best_routing_domain(
|
||||||
|
self.filter
|
||||||
|
.map(|f| f.routing_domain_set)
|
||||||
|
.unwrap_or(RoutingDomainSet::all()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
pub fn routing_table(&self) -> RoutingTable {
|
||||||
|
self.routing_table.clone()
|
||||||
|
}
|
||||||
|
pub fn node_id(&self) -> DHTKey {
|
||||||
|
self.node_id
|
||||||
|
}
|
||||||
|
pub fn has_valid_signed_node_info(&self) -> bool {
|
||||||
|
self.operate(|_rti, e| e.has_valid_signed_node_info(self.routing_domain_set()))
|
||||||
}
|
}
|
||||||
pub fn has_updated_since_last_network_change(&self) -> bool {
|
pub fn has_updated_since_last_network_change(&self) -> bool {
|
||||||
self.operate(|_rti, e| e.has_updated_since_last_network_change())
|
self.operate(|_rti, e| e.has_updated_since_last_network_change())
|
||||||
@ -106,24 +180,31 @@ impl NodeRef {
|
|||||||
pub fn set_updated_since_last_network_change(&self) {
|
pub fn set_updated_since_last_network_change(&self) {
|
||||||
self.operate_mut(|_rti, e| e.set_updated_since_last_network_change(true));
|
self.operate_mut(|_rti, e| e.set_updated_since_last_network_change(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_node_status(&self, node_status: NodeStatus) {
|
pub fn update_node_status(&self, node_status: NodeStatus) {
|
||||||
self.operate_mut(|_rti, e| {
|
self.operate_mut(|_rti, e| {
|
||||||
e.update_node_status(node_status);
|
e.update_node_status(node_status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min_max_version(&self) -> Option<(u8, u8)> {
|
pub fn min_max_version(&self) -> Option<(u8, u8)> {
|
||||||
self.operate(|_rti, e| e.min_max_version())
|
self.operate(|_rti, e| e.min_max_version())
|
||||||
}
|
}
|
||||||
pub fn set_min_max_version(&self, min_max_version: (u8, u8)) {
|
pub fn set_min_max_version(&self, min_max_version: (u8, u8)) {
|
||||||
self.operate_mut(|_rti, e| e.set_min_max_version(min_max_version))
|
self.operate_mut(|_rti, e| e.set_min_max_version(min_max_version))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn state(&self, cur_ts: u64) -> BucketEntryState {
|
pub fn state(&self, cur_ts: u64) -> BucketEntryState {
|
||||||
self.operate(|_rti, e| e.state(cur_ts))
|
self.operate(|_rti, e| e.state(cur_ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Per-RoutingDomain accessors
|
||||||
|
pub fn peer_info(&self, routing_domain: RoutingDomain) -> Option<PeerInfo> {
|
||||||
|
self.operate(|_rti, e| e.peer_info(self.node_id(), routing_domain))
|
||||||
|
}
|
||||||
|
pub fn has_seen_our_node_info(&self, routing_domain: RoutingDomain) -> bool {
|
||||||
|
self.operate(|_rti, e| e.has_seen_our_node_info(routing_domain))
|
||||||
|
}
|
||||||
|
pub fn set_seen_our_node_info(&self, routing_domain: RoutingDomain) {
|
||||||
|
self.operate_mut(|_rti, e| e.set_seen_our_node_info(routing_domain, true));
|
||||||
|
}
|
||||||
pub fn network_class(&self, routing_domain: RoutingDomain) -> Option<NetworkClass> {
|
pub fn network_class(&self, routing_domain: RoutingDomain) -> Option<NetworkClass> {
|
||||||
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.network_class))
|
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.network_class))
|
||||||
}
|
}
|
||||||
@ -143,7 +224,6 @@ impl NodeRef {
|
|||||||
}
|
}
|
||||||
dif
|
dif
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn relay(&self, routing_domain: RoutingDomain) -> Option<NodeRef> {
|
pub fn relay(&self, routing_domain: RoutingDomain) -> Option<NodeRef> {
|
||||||
let target_rpi =
|
let target_rpi =
|
||||||
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.relay_peer_info))?;
|
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.relay_peer_info))?;
|
||||||
@ -155,83 +235,50 @@ impl NodeRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register relay node and return noderef
|
// Register relay node and return noderef
|
||||||
self.routing_table
|
self.routing_table.register_node_with_signed_node_info(
|
||||||
.register_node_with_signed_node_info(
|
t.node_id.key,
|
||||||
routing_domain,
|
t.signed_node_info,
|
||||||
t.node_id.key,
|
false,
|
||||||
t.signed_node_info,
|
)
|
||||||
false,
|
|
||||||
)
|
|
||||||
.map(|mut nr| {
|
|
||||||
nr.set_filter(self.filter_ref().cloned());
|
|
||||||
nr
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn first_filtered_dial_info_detail(
|
|
||||||
&self,
|
|
||||||
routing_domain: Option<RoutingDomain>,
|
|
||||||
) -> Option<DialInfoDetail> {
|
|
||||||
self.operate(|_rt, e| {
|
|
||||||
// Prefer local dial info first unless it is filtered out
|
|
||||||
if routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork) {
|
|
||||||
e.node_info(RoutingDomain::LocalNetwork).and_then(|l| {
|
|
||||||
l.first_filtered_dial_info_detail(|did| {
|
|
||||||
if let Some(filter) = self.filter.as_ref() {
|
|
||||||
did.matches_filter(filter)
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
.or_else(|| {
|
|
||||||
if routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet) {
|
|
||||||
e.node_info(RoutingDomain::PublicInternet).and_then(|n| {
|
|
||||||
n.first_filtered_dial_info_detail(|did| {
|
|
||||||
if let Some(filter) = self.filter.as_ref() {
|
|
||||||
did.matches_filter(filter)
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_filtered_dial_info_details<F>(
|
// Filtered accessors
|
||||||
&self,
|
pub fn first_filtered_dial_info_detail(&self) -> Option<DialInfoDetail> {
|
||||||
routing_domain: Option<RoutingDomain>,
|
let routing_domain_set = self.routing_domain_set();
|
||||||
) -> Vec<DialInfoDetail> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
self.operate(|_rt, e| {
|
self.operate(|_rt, e| {
|
||||||
// Prefer local dial info first unless it is filtered out
|
for routing_domain in routing_domain_set {
|
||||||
if routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork) {
|
if let Some(ni) = e.node_info(routing_domain) {
|
||||||
if let Some(ni) = e.node_info(RoutingDomain::LocalNetwork) {
|
let filter = |did: &DialInfoDetail| {
|
||||||
out.append(&mut ni.all_filtered_dial_info_details(|did| {
|
self.filter
|
||||||
if let Some(filter) = self.filter.as_ref() {
|
.as_ref()
|
||||||
did.matches_filter(filter)
|
.map(|f| did.matches_filter(f))
|
||||||
} else {
|
.unwrap_or(true)
|
||||||
true
|
};
|
||||||
}
|
if let Some(did) = ni.first_filtered_dial_info_detail(filter) {
|
||||||
}))
|
return Some(did);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet) {
|
None
|
||||||
if let Some(ni) = e.node_info(RoutingDomain::PublicInternet) {
|
})
|
||||||
out.append(&mut ni.all_filtered_dial_info_details(|did| {
|
}
|
||||||
if let Some(filter) = self.filter.as_ref() {
|
|
||||||
did.matches_filter(filter)
|
pub fn all_filtered_dial_info_details<F>(&self) -> Vec<DialInfoDetail> {
|
||||||
} else {
|
let routing_domain_set = self.routing_domain_set();
|
||||||
true
|
let mut out = Vec::new();
|
||||||
}
|
self.operate(|_rt, e| {
|
||||||
}))
|
for routing_domain in routing_domain_set {
|
||||||
|
if let Some(ni) = e.node_info(routing_domain) {
|
||||||
|
let filter = |did: &DialInfoDetail| {
|
||||||
|
self.filter
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| did.matches_filter(f))
|
||||||
|
.unwrap_or(true)
|
||||||
|
};
|
||||||
|
if let Some(did) = ni.first_filtered_dial_info_detail(filter) {
|
||||||
|
out.push(did);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -241,8 +288,12 @@ impl NodeRef {
|
|||||||
|
|
||||||
pub async fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
pub async fn last_connection(&self) -> Option<ConnectionDescriptor> {
|
||||||
// Get the last connection and the last time we saw anything with this connection
|
// Get the last connection and the last time we saw anything with this connection
|
||||||
let (last_connection, last_seen) =
|
let (last_connection, last_seen) = self.operate(|_rti, e| {
|
||||||
self.operate(|_rti, e| e.last_connection(self.filter.clone()))?;
|
e.last_connection(
|
||||||
|
self.filter.routing_domain_set,
|
||||||
|
self.filter.dial_info_filter.clone(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Should we check the connection table?
|
// Should we check the connection table?
|
||||||
if last_connection.protocol_type().is_connection_oriented() {
|
if last_connection.protocol_type().is_connection_oriented() {
|
||||||
|
94
veilid-core/src/routing_table/routing_domains.rs
Normal file
94
veilid-core/src/routing_table/routing_domains.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// General trait for all routing domains
|
||||||
|
pub trait RoutingDomainDetail {
|
||||||
|
fn can_contain_address(&self, address: Address) -> bool;
|
||||||
|
fn relay_node(&self) -> Option<NodeRef>;
|
||||||
|
fn set_relay_node(&mut self, opt_relay_node: Option<NodeRef>);
|
||||||
|
fn dial_info_details(&self) -> &Vec<DialInfoDetail>;
|
||||||
|
fn clear_dial_info_details(&mut self);
|
||||||
|
fn add_dial_info_detail(&mut self, did: DialInfoDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public Internet routing domain internals
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct PublicInternetRoutingDomainDetail {
|
||||||
|
/// An optional node we relay through for this domain
|
||||||
|
relay_node: Option<NodeRef>,
|
||||||
|
/// The dial infos on this domain we can be reached by
|
||||||
|
dial_info_details: Vec<DialInfoDetail>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
|
||||||
|
fn can_contain_address(&self, address: Address) -> bool {
|
||||||
|
address.is_global()
|
||||||
|
}
|
||||||
|
fn relay_node(&self) -> Option<NodeRef> {
|
||||||
|
self.relay_node.clone()
|
||||||
|
}
|
||||||
|
fn set_relay_node(&mut self, opt_relay_node: Option<NodeRef>) {
|
||||||
|
self.relay_node = opt_relay_node
|
||||||
|
.map(|nr| nr.filtered_clone(NodeRefFilter::new().with_routing_domain(PublicInternet)))
|
||||||
|
}
|
||||||
|
fn dial_info_details(&self) -> &Vec<DialInfoDetail> {
|
||||||
|
&self.dial_info_details
|
||||||
|
}
|
||||||
|
fn clear_dial_info_details(&mut self) {
|
||||||
|
self.dial_info_details.clear();
|
||||||
|
}
|
||||||
|
fn add_dial_info_detail(&mut self, did: DialInfoDetail) {
|
||||||
|
self.dial_info_details.push(did);
|
||||||
|
self.dial_info_details.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Local Network routing domain internals
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct LocalInternetRoutingDomainDetail {
|
||||||
|
/// An optional node we relay through for this domain
|
||||||
|
relay_node: Option<NodeRef>,
|
||||||
|
/// The dial infos on this domain we can be reached by
|
||||||
|
dial_info_details: Vec<DialInfoDetail>,
|
||||||
|
/// The local networks this domain will communicate with
|
||||||
|
local_networks: Vec<(IpAddr, IpAddr)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalInternetRoutingDomainDetail {
|
||||||
|
pub fn set_local_networks(&mut self, local_networks: Vec<(IpAddr, IpAddr)>) -> bool {
|
||||||
|
local_networks.sort();
|
||||||
|
if local_networks == self.local_networks {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.local_networks = local_networks;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoutingDomainDetail for LocalInternetRoutingDomainDetail {
|
||||||
|
fn can_contain_address(&self, address: Address) -> bool {
|
||||||
|
let ip = address.to_ip_addr();
|
||||||
|
for localnet in self.local_networks {
|
||||||
|
if ipaddr_in_network(ip, localnet.0, localnet.1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn relay_node(&self) -> Option<NodeRef> {
|
||||||
|
self.relay_node.clone()
|
||||||
|
}
|
||||||
|
fn set_relay_node(&mut self, opt_relay_node: Option<NodeRef>) {
|
||||||
|
self.relay_node = opt_relay_node
|
||||||
|
.map(|nr| nr.filtered_clone(NodeRefFilter::new().with_routing_domain(LocalNetwork)));
|
||||||
|
}
|
||||||
|
fn dial_info_details(&self) -> &Vec<DialInfoDetail> {
|
||||||
|
&self.dial_info_details
|
||||||
|
}
|
||||||
|
fn clear_dial_info_details(&mut self) {
|
||||||
|
self.dial_info_details.clear();
|
||||||
|
}
|
||||||
|
fn add_dial_info_detail(&mut self, did: DialInfoDetail) {
|
||||||
|
self.dial_info_details.push(did);
|
||||||
|
self.dial_info_details.sort();
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use rpc_processor::*;
|
use rpc_processor::*;
|
||||||
|
|
||||||
pub fn encode_node_status(
|
pub fn encode_public_internet_node_status(
|
||||||
node_status: &NodeStatus,
|
public_internet_node_status: &PublicInternetNodeStatus,
|
||||||
builder: &mut veilid_capnp::node_status::Builder,
|
builder: &mut veilid_capnp::public_internet_node_status::Builder,
|
||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
builder.set_will_route(node_status.will_route);
|
builder.set_will_route(node_status.will_route);
|
||||||
builder.set_will_tunnel(node_status.will_tunnel);
|
builder.set_will_tunnel(node_status.will_tunnel);
|
||||||
@ -14,10 +14,10 @@ pub fn encode_node_status(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_node_status(
|
pub fn decode_public_internet_node_status(
|
||||||
reader: &veilid_capnp::node_status::Reader,
|
reader: &veilid_capnp::public_internet_node_status::Reader,
|
||||||
) -> Result<NodeStatus, RPCError> {
|
) -> Result<PublicInternetNodeStatus, RPCError> {
|
||||||
Ok(NodeStatus {
|
Ok(PublicInternetNodeStatus {
|
||||||
will_route: reader.reborrow().get_will_route(),
|
will_route: reader.reborrow().get_will_route(),
|
||||||
will_tunnel: reader.reborrow().get_will_tunnel(),
|
will_tunnel: reader.reborrow().get_will_tunnel(),
|
||||||
will_signal: reader.reborrow().get_will_signal(),
|
will_signal: reader.reborrow().get_will_signal(),
|
||||||
@ -25,3 +25,62 @@ pub fn decode_node_status(
|
|||||||
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
|
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn encode_local_network_node_status(
|
||||||
|
local_network_node_status: &LocalNetworkNodeStatus,
|
||||||
|
builder: &mut veilid_capnp::local_network_node_status::Builder,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
builder.set_will_relay(node_status.will_relay);
|
||||||
|
builder.set_will_validate_dial_info(node_status.will_validate_dial_info);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_local_network_node_status(
|
||||||
|
reader: &veilid_capnp::local_network_node_status::Reader,
|
||||||
|
) -> Result<LocalNetworkNodeStatus, RPCError> {
|
||||||
|
Ok(NodeStatus {
|
||||||
|
will_relay: reader.reborrow().get_will_relay(),
|
||||||
|
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_node_status(
|
||||||
|
node_status: &NodeStatus,
|
||||||
|
builder: &mut veilid_capnp::node_status::Builder,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
match node_status {
|
||||||
|
NodeStatus::PublicInternetNodeStatus(ns) => {
|
||||||
|
let mut pi_builder = builder.reborrow().init_public_internet();
|
||||||
|
encode_public_internet_node_status(&ns, &mut pi_builder)
|
||||||
|
}
|
||||||
|
NodeStatus::LocalNetworkNodeStatus(ns) => {
|
||||||
|
let mut ln_builder = builder.reborrow().init_local_network();
|
||||||
|
encode_local_network_node_status(&ns, &mut ln_builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_node_status(
|
||||||
|
reader: &veilid_capnp::node_status::Reader,
|
||||||
|
) -> Result<NodeStatus, RPCError> {
|
||||||
|
Ok(
|
||||||
|
match reader
|
||||||
|
.which()
|
||||||
|
.map_err(RPCError::map_internal("invalid node status"))?
|
||||||
|
{
|
||||||
|
veilid_capnp::node_status::PublicInternet(pi) => {
|
||||||
|
let r = r.map_err(RPCError::protocol)?;
|
||||||
|
let pins = decode_public_internet_node_status(&r)?;
|
||||||
|
NodeStatus::PublicInternet(pins)
|
||||||
|
}
|
||||||
|
veilid_capnp::node_status::LocalNetwork(ln) => {
|
||||||
|
let r = ln.map_err(RPCError::protocol)?;
|
||||||
|
let lnns = decode_local_network_node_status(&r)?;
|
||||||
|
NodeStatus::LocalNetwork(lnns)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -58,26 +58,34 @@ impl RPCOperationKind {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RPCOperation {
|
pub struct RPCOperation {
|
||||||
op_id: u64,
|
op_id: u64,
|
||||||
|
sender_info: Option<SignedNodeInfo>,
|
||||||
kind: RPCOperationKind,
|
kind: RPCOperationKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RPCOperation {
|
impl RPCOperation {
|
||||||
pub fn new_question(question: RPCQuestion) -> Self {
|
pub fn new_question(question: RPCQuestion, sender_info: Option<SignedNodeInfo>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
op_id: intf::get_random_u64(),
|
op_id: intf::get_random_u64(),
|
||||||
|
sender_info,
|
||||||
kind: RPCOperationKind::Question(question),
|
kind: RPCOperationKind::Question(question),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new_statement(statement: RPCStatement) -> Self {
|
pub fn new_statement(statement: RPCStatement, sender_info: Option<SignedNodeInfo>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
op_id: intf::get_random_u64(),
|
op_id: intf::get_random_u64(),
|
||||||
|
sender_info,
|
||||||
kind: RPCOperationKind::Statement(statement),
|
kind: RPCOperationKind::Statement(statement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_answer(request: &RPCOperation, answer: RPCAnswer) -> Self {
|
pub fn new_answer(
|
||||||
|
request: &RPCOperation,
|
||||||
|
answer: RPCAnswer,
|
||||||
|
sender_info: Option<SignedNodeInfo>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
op_id: request.op_id,
|
op_id: request.op_id,
|
||||||
|
sender_info,
|
||||||
kind: RPCOperationKind::Answer(answer),
|
kind: RPCOperationKind::Answer(answer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +94,10 @@ impl RPCOperation {
|
|||||||
self.op_id
|
self.op_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sender_info(&self) -> Option<&SignedNodeInfo> {
|
||||||
|
self.sender_info.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> &RPCOperationKind {
|
pub fn kind(&self) -> &RPCOperationKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
@ -100,16 +112,32 @@ impl RPCOperation {
|
|||||||
) -> Result<Self, RPCError> {
|
) -> Result<Self, RPCError> {
|
||||||
let op_id = operation_reader.get_op_id();
|
let op_id = operation_reader.get_op_id();
|
||||||
|
|
||||||
|
let sender_info = if operation_reader.has_sender_info() {
|
||||||
|
let sni_reader = operation_reader.get_sender_info();
|
||||||
|
let sni = decode_signed_node_info(&sni_reader, sender_node_id, true)?;
|
||||||
|
Some(sni)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let kind_reader = operation_reader.get_kind();
|
let kind_reader = operation_reader.get_kind();
|
||||||
let kind = RPCOperationKind::decode(&kind_reader, sender_node_id)?;
|
let kind = RPCOperationKind::decode(&kind_reader, sender_node_id)?;
|
||||||
|
|
||||||
Ok(RPCOperation { op_id, kind })
|
Ok(RPCOperation {
|
||||||
|
op_id,
|
||||||
|
sender_info,
|
||||||
|
kind,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(&self, builder: &mut veilid_capnp::operation::Builder) -> Result<(), RPCError> {
|
pub fn encode(&self, builder: &mut veilid_capnp::operation::Builder) -> Result<(), RPCError> {
|
||||||
builder.set_op_id(self.op_id);
|
builder.set_op_id(self.op_id);
|
||||||
let mut k_builder = builder.reborrow().init_kind();
|
let mut k_builder = builder.reborrow().init_kind();
|
||||||
self.kind.encode(&mut k_builder)?;
|
self.kind.encode(&mut k_builder)?;
|
||||||
|
if let Some(sender_info) = self.sender_info {
|
||||||
|
let si_builder = builder.reborrow().init_sender_info();
|
||||||
|
encode_signed_node_info(&self.sender_info, &mut si_builder)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,6 @@ impl RPCQuestion {
|
|||||||
pub fn detail(&self) -> &RPCQuestionDetail {
|
pub fn detail(&self) -> &RPCQuestionDetail {
|
||||||
&self.detail
|
&self.detail
|
||||||
}
|
}
|
||||||
// pub fn into_detail(self) -> RPCQuestionDetail {
|
|
||||||
// self.detail
|
|
||||||
// }
|
|
||||||
// pub fn into_respond_to_detail(self) -> (RespondTo, RPCQuestionDetail) {
|
|
||||||
// (self.respond_to, self.detail)
|
|
||||||
// }
|
|
||||||
pub fn desc(&self) -> &'static str {
|
pub fn desc(&self) -> &'static str {
|
||||||
self.detail.desc()
|
self.detail.desc()
|
||||||
}
|
}
|
||||||
@ -32,7 +26,7 @@ impl RPCQuestion {
|
|||||||
sender_node_id: &DHTKey,
|
sender_node_id: &DHTKey,
|
||||||
) -> Result<RPCQuestion, RPCError> {
|
) -> Result<RPCQuestion, RPCError> {
|
||||||
let rt_reader = reader.get_respond_to();
|
let rt_reader = reader.get_respond_to();
|
||||||
let respond_to = RespondTo::decode(&rt_reader, sender_node_id)?;
|
let respond_to = RespondTo::decode(&rt_reader)?;
|
||||||
let d_reader = reader.get_detail();
|
let d_reader = reader.get_detail();
|
||||||
let detail = RPCQuestionDetail::decode(&d_reader)?;
|
let detail = RPCQuestionDetail::decode(&d_reader)?;
|
||||||
Ok(RPCQuestion { respond_to, detail })
|
Ok(RPCQuestion { respond_to, detail })
|
||||||
|
@ -3,7 +3,7 @@ use rpc_processor::*;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum RespondTo {
|
pub enum RespondTo {
|
||||||
Sender(Option<SignedNodeInfo>),
|
Sender,
|
||||||
PrivateRoute(PrivateRoute),
|
PrivateRoute(PrivateRoute),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,11 +13,7 @@ impl RespondTo {
|
|||||||
builder: &mut veilid_capnp::question::respond_to::Builder,
|
builder: &mut veilid_capnp::question::respond_to::Builder,
|
||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Sender(Some(sni)) => {
|
Self::Sender => {
|
||||||
let mut sni_builder = builder.reborrow().init_sender_with_info();
|
|
||||||
encode_signed_node_info(sni, &mut sni_builder)?;
|
|
||||||
}
|
|
||||||
Self::Sender(None) => {
|
|
||||||
builder.reborrow().set_sender(());
|
builder.reborrow().set_sender(());
|
||||||
}
|
}
|
||||||
Self::PrivateRoute(pr) => {
|
Self::PrivateRoute(pr) => {
|
||||||
@ -28,17 +24,9 @@ impl RespondTo {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(
|
pub fn decode(reader: &veilid_capnp::question::respond_to::Reader) -> Result<Self, RPCError> {
|
||||||
reader: &veilid_capnp::question::respond_to::Reader,
|
|
||||||
sender_node_id: &DHTKey,
|
|
||||||
) -> Result<Self, RPCError> {
|
|
||||||
let respond_to = match reader.which().map_err(RPCError::protocol)? {
|
let respond_to = match reader.which().map_err(RPCError::protocol)? {
|
||||||
veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender(None),
|
veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender,
|
||||||
veilid_capnp::question::respond_to::SenderWithInfo(sender_ni_reader) => {
|
|
||||||
let sender_ni_reader = sender_ni_reader.map_err(RPCError::protocol)?;
|
|
||||||
let sni = decode_signed_node_info(&sender_ni_reader, sender_node_id, true)?;
|
|
||||||
RespondTo::Sender(Some(sni))
|
|
||||||
}
|
|
||||||
veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => {
|
veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => {
|
||||||
let pr_reader = pr_reader.map_err(RPCError::protocol)?;
|
let pr_reader = pr_reader.map_err(RPCError::protocol)?;
|
||||||
let pr = decode_private_route(&pr_reader)?;
|
let pr = decode_private_route(&pr_reader)?;
|
||||||
|
135
veilid-core/src/rpc_processor/destination.rs
Normal file
135
veilid-core/src/rpc_processor/destination.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Where to send an RPC message
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Destination {
|
||||||
|
/// Send to node directly
|
||||||
|
Direct {
|
||||||
|
/// The node to send to
|
||||||
|
target: NodeRef,
|
||||||
|
/// An optional safety route specification to send from for sender privacy
|
||||||
|
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
||||||
|
},
|
||||||
|
/// Send to node for relay purposes
|
||||||
|
Relay {
|
||||||
|
/// The relay to send to
|
||||||
|
relay: NodeRef,
|
||||||
|
/// The final destination the relay should send to
|
||||||
|
target: DHTKey,
|
||||||
|
/// An optional safety route specification to send from for sender privacy
|
||||||
|
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
||||||
|
},
|
||||||
|
/// Send to private route (privateroute)
|
||||||
|
PrivateRoute {
|
||||||
|
/// A private route to send to
|
||||||
|
private_route: PrivateRoute,
|
||||||
|
/// An optional safety route specification to send from for sender privacy
|
||||||
|
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Destination {
|
||||||
|
pub fn direct(target: NodeRef) -> Self {
|
||||||
|
Self::Direct {
|
||||||
|
target,
|
||||||
|
safety_route_spec: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
||||||
|
Self::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn private_route(private_route: PrivateRoute) -> Self {
|
||||||
|
Self::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn safety_route_spec(&self) -> Option<Arc<SafetyRouteSpec>> {
|
||||||
|
match self {
|
||||||
|
Destination::Direct {
|
||||||
|
target,
|
||||||
|
safety_route_spec,
|
||||||
|
} => safety_route_spec.clone(),
|
||||||
|
Destination::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec,
|
||||||
|
} => safety_route_spec.clone(),
|
||||||
|
Destination::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec,
|
||||||
|
} => safety_route_spec.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_safety_route_spec(self, safety_route_spec: Arc<SafetyRouteSpec>) -> Self {
|
||||||
|
match self {
|
||||||
|
Destination::Direct {
|
||||||
|
target,
|
||||||
|
safety_route_spec: _,
|
||||||
|
} => Self::Direct {
|
||||||
|
target,
|
||||||
|
safety_route_spec: Some(safety_route_spec),
|
||||||
|
},
|
||||||
|
Destination::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec: _,
|
||||||
|
} => Self::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec: Some(safety_route_spec),
|
||||||
|
},
|
||||||
|
Destination::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec: _,
|
||||||
|
} => Self::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec: Some(safety_route_spec),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Destination {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Destination::Direct {
|
||||||
|
target,
|
||||||
|
routing_domain,
|
||||||
|
safety_route_spec,
|
||||||
|
} => {
|
||||||
|
let sr = safety_route_spec
|
||||||
|
.map(|_sr| "+SR".to_owned())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
write!(f, "{:?}{}", target, sr)
|
||||||
|
}
|
||||||
|
Destination::Relay {
|
||||||
|
relay,
|
||||||
|
target,
|
||||||
|
safety_route_spec,
|
||||||
|
} => {
|
||||||
|
let sr = safety_route_spec
|
||||||
|
.map(|_sr| "+SR".to_owned())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
write!(f, "{:?}@{:?}{}", target.encode(), relay, sr)
|
||||||
|
}
|
||||||
|
Destination::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec,
|
||||||
|
} => {
|
||||||
|
let sr = safety_route_spec
|
||||||
|
.map(|_sr| "+SR".to_owned())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
write!(f, "{}{}", private_route, sr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
mod coders;
|
mod coders;
|
||||||
|
mod destination;
|
||||||
mod private_route;
|
mod private_route;
|
||||||
mod rpc_cancel_tunnel;
|
mod rpc_cancel_tunnel;
|
||||||
mod rpc_complete_tunnel;
|
mod rpc_complete_tunnel;
|
||||||
@ -18,6 +19,7 @@ mod rpc_validate_dial_info;
|
|||||||
mod rpc_value_changed;
|
mod rpc_value_changed;
|
||||||
mod rpc_watch_value;
|
mod rpc_watch_value;
|
||||||
|
|
||||||
|
pub use destination::*;
|
||||||
pub use private_route::*;
|
pub use private_route::*;
|
||||||
pub use rpc_error::*;
|
pub use rpc_error::*;
|
||||||
|
|
||||||
@ -36,208 +38,6 @@ use stop_token::future::FutureExt;
|
|||||||
|
|
||||||
type OperationId = u64;
|
type OperationId = u64;
|
||||||
|
|
||||||
/// Where to send an RPC message
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Destination {
|
|
||||||
/// Send to node directly
|
|
||||||
Direct {
|
|
||||||
/// The node to send to
|
|
||||||
target: NodeRef,
|
|
||||||
/// An optional routing domain to require
|
|
||||||
routing_domain: Option<RoutingDomain>,
|
|
||||||
/// An optional safety route specification to send from for sender privacy
|
|
||||||
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
|
||||||
},
|
|
||||||
/// Send to node for relay purposes
|
|
||||||
Relay {
|
|
||||||
/// The relay to send to
|
|
||||||
relay: NodeRef,
|
|
||||||
/// The final destination the relay should send to
|
|
||||||
target: DHTKey,
|
|
||||||
/// An optional routing domain to require
|
|
||||||
routing_domain: Option<RoutingDomain>,
|
|
||||||
/// An optional safety route specification to send from for sender privacy
|
|
||||||
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
|
||||||
},
|
|
||||||
/// Send to private route (privateroute)
|
|
||||||
PrivateRoute {
|
|
||||||
/// A private route to send to
|
|
||||||
private_route: PrivateRoute,
|
|
||||||
/// An optional safety route specification to send from for sender privacy
|
|
||||||
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Destination {
|
|
||||||
pub fn direct(target: NodeRef) -> Self {
|
|
||||||
Self::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain: None,
|
|
||||||
safety_route_spec: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
|
|
||||||
Self::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain: None,
|
|
||||||
safety_route_spec: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn private_route(private_route: PrivateRoute) -> Self {
|
|
||||||
Self::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn
|
|
||||||
|
|
||||||
pub fn routing_domain(&self) -> Option<RoutingDomain> {
|
|
||||||
match self {
|
|
||||||
Destination::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => *routing_domain,
|
|
||||||
Destination::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => *routing_domain,
|
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec,
|
|
||||||
} => Some(RoutingDomain::PublicInternet),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn safety_route_spec(&self) -> Option<Arc<SafetyRouteSpec>> {
|
|
||||||
match self {
|
|
||||||
Destination::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => safety_route_spec.clone(),
|
|
||||||
Destination::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => safety_route_spec.clone(),
|
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec,
|
|
||||||
} => safety_route_spec.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn with_routing_domain(self, routing_domain: RoutingDomain) -> Self {
|
|
||||||
match self {
|
|
||||||
Destination::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain: _,
|
|
||||||
safety_route_spec,
|
|
||||||
} => Self::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain: Some(routing_domain),
|
|
||||||
safety_route_spec,
|
|
||||||
},
|
|
||||||
Destination::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain: _,
|
|
||||||
safety_route_spec,
|
|
||||||
} => Self::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain: Some(routing_domain),
|
|
||||||
safety_route_spec,
|
|
||||||
},
|
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route: _,
|
|
||||||
safety_route_spec: _,
|
|
||||||
} => panic!("Private route is only valid in PublicInternet routing domain"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn with_safety_route_spec(self, safety_route_spec: Arc<SafetyRouteSpec>) -> Self {
|
|
||||||
match self {
|
|
||||||
Destination::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec: _,
|
|
||||||
} => Self::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec: Some(safety_route_spec),
|
|
||||||
},
|
|
||||||
Destination::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec: _,
|
|
||||||
} => Self::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec: Some(safety_route_spec),
|
|
||||||
},
|
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec: _,
|
|
||||||
} => Self::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec: Some(safety_route_spec),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Destination {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Destination::Direct {
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => {
|
|
||||||
let rd = routing_domain
|
|
||||||
.map(|rd| format!("#{:?}", rd))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let sr = safety_route_spec
|
|
||||||
.map(|_sr| "+SR".to_owned())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
write!(f, "{:?}{}{}", target, rd, sr)
|
|
||||||
}
|
|
||||||
Destination::Relay {
|
|
||||||
relay,
|
|
||||||
target,
|
|
||||||
routing_domain,
|
|
||||||
safety_route_spec,
|
|
||||||
} => {
|
|
||||||
let rd = routing_domain
|
|
||||||
.map(|rd| format!("#{:?}", rd))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let sr = safety_route_spec
|
|
||||||
.map(|_sr| "+SR".to_owned())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
write!(f, "{:?}@{:?}{}{}", target.encode(), relay, rd, sr)
|
|
||||||
}
|
|
||||||
Destination::PrivateRoute {
|
|
||||||
private_route,
|
|
||||||
safety_route_spec,
|
|
||||||
} => {
|
|
||||||
let sr = safety_route_spec
|
|
||||||
.map(|_sr| "+SR".to_owned())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
write!(f, "{}{}", private_route, sr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The decoded header of an RPC message
|
/// The decoded header of an RPC message
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct RPCMessageHeader {
|
struct RPCMessageHeader {
|
||||||
@ -251,6 +51,8 @@ struct RPCMessageHeader {
|
|||||||
peer_noderef: NodeRef,
|
peer_noderef: NodeRef,
|
||||||
/// The connection from the peer sent the message (not the original sender)
|
/// The connection from the peer sent the message (not the original sender)
|
||||||
connection_descriptor: ConnectionDescriptor,
|
connection_descriptor: ConnectionDescriptor,
|
||||||
|
/// The routing domain the message was sent through
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -352,7 +154,6 @@ pub struct RPCProcessorInner {
|
|||||||
pub struct RPCProcessor {
|
pub struct RPCProcessor {
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
config: VeilidConfig,
|
config: VeilidConfig,
|
||||||
enable_local_peer_scope: bool,
|
|
||||||
inner: Arc<Mutex<RPCProcessorInner>>,
|
inner: Arc<Mutex<RPCProcessorInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,11 +176,6 @@ impl RPCProcessor {
|
|||||||
Self {
|
Self {
|
||||||
crypto: network_manager.crypto(),
|
crypto: network_manager.crypto(),
|
||||||
config: network_manager.config(),
|
config: network_manager.config(),
|
||||||
enable_local_peer_scope: network_manager
|
|
||||||
.config()
|
|
||||||
.get()
|
|
||||||
.network
|
|
||||||
.enable_local_peer_scope,
|
|
||||||
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
|
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,12 +198,8 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
fn filter_peer_scope(&self, node_info: &NodeInfo) -> bool {
|
/// Determine if a NodeInfo can be placed into the specified routing domain
|
||||||
// if local peer scope is enabled, then don't reject any peer info
|
fn filter_node_info(&self, routing_domain: RoutingDomain, node_info: &NodeInfo) -> bool {
|
||||||
if self.enable_local_peer_scope {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reject attempts to include non-public addresses in results
|
// reject attempts to include non-public addresses in results
|
||||||
for did in &node_info.dial_info_detail_list {
|
for did in &node_info.dial_info_detail_list {
|
||||||
if !did.dial_info.is_global() {
|
if !did.dial_info.is_global() {
|
||||||
@ -584,31 +376,6 @@ impl RPCProcessor {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a 'RespondTo::Sender' that contains either our dial info,
|
|
||||||
/// or None if the peer has seen our dial info before or our node info is not yet valid
|
|
||||||
/// because of an unknown network class
|
|
||||||
pub fn make_respond_to_sender(
|
|
||||||
&self,
|
|
||||||
routing_domain: RoutingDomain,
|
|
||||||
peer: NodeRef,
|
|
||||||
) -> RespondTo {
|
|
||||||
if peer.has_seen_our_node_info(routing_domain)
|
|
||||||
|| matches!(
|
|
||||||
self.network_manager()
|
|
||||||
.get_network_class(routing_domain)
|
|
||||||
.unwrap_or(NetworkClass::Invalid),
|
|
||||||
NetworkClass::Invalid
|
|
||||||
)
|
|
||||||
{
|
|
||||||
RespondTo::Sender(None)
|
|
||||||
} else {
|
|
||||||
let our_sni = self
|
|
||||||
.routing_table()
|
|
||||||
.get_own_signed_node_info(routing_domain);
|
|
||||||
RespondTo::Sender(Some(our_sni))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produce a byte buffer that represents the wire encoding of the entire
|
/// Produce a byte buffer that represents the wire encoding of the entire
|
||||||
/// unencrypted envelope body for a RPC message. This incorporates
|
/// unencrypted envelope body for a RPC message. This incorporates
|
||||||
/// wrapping a private and/or safety route if they are specified.
|
/// wrapping a private and/or safety route if they are specified.
|
||||||
@ -617,7 +384,7 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
operation: &RPCOperation,
|
operation: &RPCOperation,
|
||||||
) -> Result<RenderedOperation, RPCError> { xxx continue propagating safetyroutespec
|
) -> Result<RenderedOperation, RPCError> {
|
||||||
let out_node_id; // Envelope Node Id
|
let out_node_id; // Envelope Node Id
|
||||||
let mut out_node_ref: Option<NodeRef> = None; // Node to send envelope to
|
let mut out_node_ref: Option<NodeRef> = None; // Node to send envelope to
|
||||||
let out_hop_count: usize; // Total safety + private route hop count
|
let out_hop_count: usize; // Total safety + private route hop count
|
||||||
@ -634,12 +401,28 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// To where are we sending the request
|
// To where are we sending the request
|
||||||
match dest {
|
match dest {
|
||||||
Destination::Direct(ref node_ref) | Destination::Relay(ref node_ref, _) => {
|
Destination::Direct {
|
||||||
|
target: node_ref,
|
||||||
|
routing_domain,
|
||||||
|
safety_route_spec,
|
||||||
|
}
|
||||||
|
| Destination::Relay {
|
||||||
|
relay: node_ref,
|
||||||
|
target: _,
|
||||||
|
routing_domain,
|
||||||
|
safety_route_spec,
|
||||||
|
} => {
|
||||||
// Send to a node without a private route
|
// Send to a node without a private route
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
||||||
// Get the actual destination node id accounting for relays
|
// Get the actual destination node id accounting for relays
|
||||||
let (node_ref, node_id) = if let Destination::Relay(_, dht_key) = dest {
|
let (node_ref, node_id) = if let Destination::Relay {
|
||||||
|
relay: _,
|
||||||
|
target: dht_key,
|
||||||
|
routing_domain: _,
|
||||||
|
safety_route_spec: _,
|
||||||
|
} = dest
|
||||||
|
{
|
||||||
(node_ref.clone(), dht_key.clone())
|
(node_ref.clone(), dht_key.clone())
|
||||||
} else {
|
} else {
|
||||||
let node_id = node_ref.node_id();
|
let node_id = node_ref.node_id();
|
||||||
@ -676,7 +459,10 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Destination::PrivateRoute(private_route) => {
|
Destination::PrivateRoute {
|
||||||
|
private_route,
|
||||||
|
safety_route_spec,
|
||||||
|
} => {
|
||||||
// Send to private route
|
// Send to private route
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// Reply with 'route' operation
|
// Reply with 'route' operation
|
||||||
@ -723,12 +509,22 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Issue a question over the network, possibly using an anonymized route
|
// Issue a question over the network, possibly using an anonymized route
|
||||||
#[instrument(level = "debug", skip(self, question, safety_route_spec), err)]
|
#[instrument(level = "debug", skip(self, question), err)]
|
||||||
async fn question(
|
async fn question(
|
||||||
&self,
|
&self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
question: RPCQuestion,
|
question: RPCQuestion,
|
||||||
) -> Result<NetworkResult<WaitableReply>, RPCError> {
|
) -> Result<NetworkResult<WaitableReply>, RPCError> {
|
||||||
|
|
||||||
|
// Get sender info if we should send that
|
||||||
|
let opt_sender_info = if dest.safety_route_spec().is_none() && matches!(question.respond_to(), RespondTo::Sender) {
|
||||||
|
// Sender is not private, send sender info if needed
|
||||||
|
// Get the noderef of the eventual destination or first route hop
|
||||||
|
if let Some(target_nr) = self.routing_table().lookup_node_ref(dest.get_target_id()) {
|
||||||
|
if target_nr.has_seen_our_node_info(R)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap question in operation
|
// Wrap question in operation
|
||||||
let operation = RPCOperation::new_question(question);
|
let operation = RPCOperation::new_question(question);
|
||||||
let op_id = operation.op_id();
|
let op_id = operation.op_id();
|
||||||
@ -951,6 +747,10 @@ impl RPCProcessor {
|
|||||||
&self,
|
&self,
|
||||||
encoded_msg: RPCMessageEncoded,
|
encoded_msg: RPCMessageEncoded,
|
||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
|
|
||||||
|
// Get the routing domain
|
||||||
|
let routing_domain = encoded_msg.header.routing_domain;
|
||||||
|
|
||||||
// Decode the operation
|
// Decode the operation
|
||||||
let sender_node_id = encoded_msg.header.envelope.get_sender_id();
|
let sender_node_id = encoded_msg.header.envelope.get_sender_id();
|
||||||
|
|
||||||
@ -971,12 +771,13 @@ impl RPCProcessor {
|
|||||||
match q.respond_to() {
|
match q.respond_to() {
|
||||||
RespondTo::Sender(Some(sender_ni)) => {
|
RespondTo::Sender(Some(sender_ni)) => {
|
||||||
// Sender NodeInfo was specified, update our routing table with it
|
// Sender NodeInfo was specified, update our routing table with it
|
||||||
if !self.filter_peer_scope(&sender_ni.node_info) {
|
if !self.filter_node_info(&sender_ni.node_info) {
|
||||||
return Err(RPCError::invalid_format(
|
return Err(RPCError::invalid_format(
|
||||||
"respond_to_sender_signed_node_info has invalid peer scope",
|
"respond_to_sender_signed_node_info has invalid peer scope",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
opt_sender_nr = self.routing_table().register_node_with_signed_node_info(
|
opt_sender_nr = self.routing_table().register_node_with_signed_node_info(
|
||||||
|
routing_domain,
|
||||||
sender_node_id,
|
sender_node_id,
|
||||||
sender_ni.clone(),
|
sender_ni.clone(),
|
||||||
false,
|
false,
|
||||||
@ -1168,6 +969,7 @@ impl RPCProcessor {
|
|||||||
body: Vec<u8>,
|
body: Vec<u8>,
|
||||||
peer_noderef: NodeRef,
|
peer_noderef: NodeRef,
|
||||||
connection_descriptor: ConnectionDescriptor,
|
connection_descriptor: ConnectionDescriptor,
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
) -> EyreResult<()> {
|
) -> EyreResult<()> {
|
||||||
let msg = RPCMessageEncoded {
|
let msg = RPCMessageEncoded {
|
||||||
header: RPCMessageHeader {
|
header: RPCMessageHeader {
|
||||||
@ -1176,6 +978,7 @@ impl RPCProcessor {
|
|||||||
body_len: body.len() as u64,
|
body_len: body.len() as u64,
|
||||||
peer_noderef,
|
peer_noderef,
|
||||||
connection_descriptor,
|
connection_descriptor,
|
||||||
|
routing_domain,
|
||||||
},
|
},
|
||||||
data: RPCMessageData { contents: body },
|
data: RPCMessageData { contents: body },
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ impl RPCProcessor {
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
fn compile_safety_route(
|
fn compile_safety_route(
|
||||||
&self,
|
&self,
|
||||||
safety_route_spec: &SafetyRouteSpec,
|
safety_route_spec: Arc<SafetyRouteSpec>,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
) -> Result<SafetyRoute, RPCError> {
|
) -> Result<SafetyRoute, RPCError> {
|
||||||
// Ensure the total hop count isn't too long for our config
|
// Ensure the total hop count isn't too long for our config
|
||||||
@ -111,15 +111,15 @@ impl RPCProcessor {
|
|||||||
// Wrap an operation inside a route
|
// Wrap an operation inside a route
|
||||||
pub(super) fn wrap_with_route(
|
pub(super) fn wrap_with_route(
|
||||||
&self,
|
&self,
|
||||||
safety_route_spec: Option<&SafetyRouteSpec>,
|
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
|
||||||
private_route: PrivateRoute,
|
private_route: PrivateRoute,
|
||||||
message_data: Vec<u8>,
|
message_data: Vec<u8>,
|
||||||
) -> Result<Vec<u8>, RPCError> {
|
) -> Result<Vec<u8>, RPCError> {
|
||||||
// Encrypt routed operation
|
// Encrypt routed operation
|
||||||
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
||||||
let nonce = Crypto::get_random_nonce();
|
let nonce = Crypto::get_random_nonce();
|
||||||
let stub_safety_route_spec = SafetyRouteSpec::new();
|
let safety_route_spec =
|
||||||
let safety_route_spec = safety_route_spec.unwrap_or(&stub_safety_route_spec);
|
safety_route_spec.unwrap_or_else(|| Arc::new(SafetyRouteSpec::new()));
|
||||||
let dh_secret = self
|
let dh_secret = self
|
||||||
.crypto
|
.crypto
|
||||||
.cached_dh(&private_route.public_key, &safety_route_spec.secret_key)
|
.cached_dh(&private_route.public_key, &safety_route_spec.secret_key)
|
||||||
|
@ -8,15 +8,11 @@ impl RPCProcessor {
|
|||||||
self,
|
self,
|
||||||
dest: Destination,
|
dest: Destination,
|
||||||
key: DHTKey,
|
key: DHTKey,
|
||||||
safety_route: Option<&SafetyRouteSpec>,
|
|
||||||
respond_to: RespondTo,
|
|
||||||
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
|
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
|
||||||
let find_node_q = RPCOperationFindNodeQ { node_id: key };
|
let find_node_q = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ { node_id: key });
|
||||||
let question = RPCQuestion::new(respond_to, RPCQuestionDetail::FindNodeQ(find_node_q));
|
|
||||||
|
|
||||||
// Send the find_node request
|
// Send the find_node request
|
||||||
let waitable_reply =
|
let waitable_reply = network_result_try!(self.question(dest, find_node_q).await?);
|
||||||
network_result_try!(self.question(dest, question, safety_route).await?);
|
|
||||||
|
|
||||||
// Wait for reply
|
// Wait for reply
|
||||||
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
||||||
@ -35,7 +31,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Verify peers are in the correct peer scope
|
// Verify peers are in the correct peer scope
|
||||||
for peer_info in &find_node_a.peers {
|
for peer_info in &find_node_a.peers {
|
||||||
if !self.filter_peer_scope(&peer_info.signed_node_info.node_info) {
|
if !self.filter_node_info(&peer_info.signed_node_info.node_info) {
|
||||||
return Err(RPCError::invalid_format(
|
return Err(RPCError::invalid_format(
|
||||||
"find_node response has invalid peer scope",
|
"find_node response has invalid peer scope",
|
||||||
));
|
));
|
||||||
|
@ -2,20 +2,20 @@ use super::*;
|
|||||||
|
|
||||||
impl RPCProcessor {
|
impl RPCProcessor {
|
||||||
// Sends a our node info to another node
|
// Sends a our node info to another node
|
||||||
// Can be sent via all methods including relays and routes
|
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub async fn rpc_call_node_info_update(
|
pub async fn rpc_call_node_info_update(
|
||||||
self,
|
self,
|
||||||
target: NodeRef,
|
target: NodeRef,
|
||||||
routing_domain: RoutingDomain,
|
routing_domain: RoutingDomain,
|
||||||
) -> Result<NetworkResult<()>, RPCError> {
|
) -> Result<NetworkResult<()>, RPCError> {
|
||||||
|
// Get the signed node info for the desired routing domain to send update with
|
||||||
let signed_node_info = self
|
let signed_node_info = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.get_own_signed_node_info(routing_domain);
|
.get_own_signed_node_info(routing_domain);
|
||||||
let node_info_update = RPCOperationNodeInfoUpdate { signed_node_info };
|
let node_info_update = RPCOperationNodeInfoUpdate { signed_node_info };
|
||||||
let statement = RPCStatement::new(RPCStatementDetail::NodeInfoUpdate(node_info_update));
|
let statement = RPCStatement::new(RPCStatementDetail::NodeInfoUpdate(node_info_update));
|
||||||
|
|
||||||
// Send the node_info_update request
|
// Send the node_info_update request to the specific routing domain requested
|
||||||
network_result_try!(
|
network_result_try!(
|
||||||
self.statement(
|
self.statement(
|
||||||
Destination::direct(target).with_routing_domain(routing_domain),
|
Destination::direct(target).with_routing_domain(routing_domain),
|
||||||
@ -41,7 +41,7 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Update our routing table with signed node info
|
// Update our routing table with signed node info
|
||||||
if !self.filter_peer_scope(&node_info_update.signed_node_info.node_info) {
|
if !self.filter_node_info(&node_info_update.signed_node_info.node_info) {
|
||||||
log_rpc!(debug
|
log_rpc!(debug
|
||||||
"node_info_update has invalid peer scope from {}", sender_node_id
|
"node_info_update has invalid peer scope from {}", sender_node_id
|
||||||
);
|
);
|
||||||
|
@ -8,14 +8,21 @@ impl RPCProcessor {
|
|||||||
self,
|
self,
|
||||||
peer: NodeRef,
|
peer: NodeRef,
|
||||||
) -> Result<NetworkResult<Answer<SenderInfo>>, RPCError> {
|
) -> Result<NetworkResult<Answer<SenderInfo>>, RPCError> {
|
||||||
let node_status = self.network_manager().generate_node_status();
|
let routing_domain = match peer.best_routing_domain() {
|
||||||
|
Some(rd) => rd,
|
||||||
|
None => {
|
||||||
|
return Ok(NetworkResult::no_connection_other(
|
||||||
|
"no routing domain for peer",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let node_status = self.network_manager().generate_node_status(routing_domain);
|
||||||
let status_q = RPCOperationStatusQ { node_status };
|
let status_q = RPCOperationStatusQ { node_status };
|
||||||
let respond_to = self.make_respond_to_sender(peer.clone());
|
let question = RPCQuestion::new(RespondTo::Sender, RPCQuestionDetail::StatusQ(status_q));
|
||||||
let question = RPCQuestion::new(respond_to, RPCQuestionDetail::StatusQ(status_q));
|
|
||||||
|
|
||||||
// Send the info request
|
// Send the info request
|
||||||
let waitable_reply = network_result_try!(
|
let waitable_reply = network_result_try!(
|
||||||
self.question(Destination::Direct(peer.clone()), question, None)
|
self.question(Destination::direct(peer.clone()), question)
|
||||||
.await?
|
.await?
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -37,26 +44,48 @@ impl RPCProcessor {
|
|||||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ensure the returned node status is the kind for the routing domain we asked for
|
||||||
|
match routing_domain {
|
||||||
|
RoutingDomain::PublicInternet => {
|
||||||
|
if !matches!(status_a.node_status, NodeStatus::PublicInternet(_)) {
|
||||||
|
return Ok(NetworkResult::invalid_message(
|
||||||
|
"node status doesn't match PublicInternet routing domain",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RoutingDomain::LocalNetwork => {
|
||||||
|
if !matches!(status_a.node_status, NodeStatus::LocalNetwork(_)) {
|
||||||
|
return Ok(NetworkResult::invalid_message(
|
||||||
|
"node status doesn't match LocalNetwork routing domain",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update latest node status in routing table
|
// Update latest node status in routing table
|
||||||
peer.update_node_status(status_a.node_status.clone());
|
peer.update_node_status(status_a.node_status);
|
||||||
|
|
||||||
// Report sender_info IP addresses to network manager
|
// Report sender_info IP addresses to network manager
|
||||||
|
// Don't need to validate these addresses for the current routing domain
|
||||||
|
// the address itself is irrelevant, and the remote node can lie anyway
|
||||||
if let Some(socket_address) = status_a.sender_info.socket_address {
|
if let Some(socket_address) = status_a.sender_info.socket_address {
|
||||||
match send_data_kind {
|
match send_data_kind {
|
||||||
SendDataKind::Direct(connection_descriptor) => {
|
SendDataKind::Direct(connection_descriptor) => match routing_domain {
|
||||||
match connection_descriptor.peer_scope() {
|
RoutingDomain::PublicInternet => self
|
||||||
PeerScope::Global => self.network_manager().report_global_socket_address(
|
.network_manager()
|
||||||
|
.report_public_internet_socket_address(
|
||||||
socket_address,
|
socket_address,
|
||||||
connection_descriptor,
|
connection_descriptor,
|
||||||
peer,
|
peer,
|
||||||
),
|
),
|
||||||
PeerScope::Local => self.network_manager().report_local_socket_address(
|
RoutingDomain::LocalNetwork => {
|
||||||
|
self.network_manager().report_local_network_socket_address(
|
||||||
socket_address,
|
socket_address,
|
||||||
connection_descriptor,
|
connection_descriptor,
|
||||||
peer,
|
peer,
|
||||||
),
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
SendDataKind::Indirect => {
|
SendDataKind::Indirect => {
|
||||||
// Do nothing in this case, as the socket address returned here would be for any node other than ours
|
// Do nothing in this case, as the socket address returned here would be for any node other than ours
|
||||||
}
|
}
|
||||||
@ -75,6 +104,7 @@ 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 connection_descriptor = msg.header.connection_descriptor;
|
||||||
|
let routing_domain = msg.header.routing_domain;
|
||||||
|
|
||||||
// Get the question
|
// Get the question
|
||||||
let status_q = match msg.operation.kind() {
|
let status_q = match msg.operation.kind() {
|
||||||
@ -85,6 +115,24 @@ impl RPCProcessor {
|
|||||||
_ => panic!("not a question"),
|
_ => panic!("not a question"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ensure the node status from the question is the kind for the routing domain we received the request in
|
||||||
|
match routing_domain {
|
||||||
|
RoutingDomain::PublicInternet => {
|
||||||
|
if !matches!(status_a.node_status, NodeStatus::PublicInternet(_)) {
|
||||||
|
return Ok(NetworkResult::invalid_message(
|
||||||
|
"node status doesn't match PublicInternet routing domain",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RoutingDomain::LocalNetwork => {
|
||||||
|
if !matches!(status_a.node_status, NodeStatus::LocalNetwork(_)) {
|
||||||
|
return Ok(NetworkResult::invalid_message(
|
||||||
|
"node status doesn't match LocalNetwork routing domain",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// update node status for the requesting node to our routing table
|
// update node status for the requesting node to our routing table
|
||||||
if let Some(sender_nr) = msg.opt_sender_nr.clone() {
|
if let Some(sender_nr) = msg.opt_sender_nr.clone() {
|
||||||
// Update latest node status in routing table for the statusq sender
|
// Update latest node status in routing table for the statusq sender
|
||||||
@ -92,7 +140,7 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make status answer
|
// Make status answer
|
||||||
let node_status = self.network_manager().generate_node_status();
|
let node_status = self.network_manager().generate_node_status(routing_domain);
|
||||||
|
|
||||||
// Get the peer address in the returned sender info
|
// Get the peer address in the returned sender info
|
||||||
let sender_info = SenderInfo {
|
let sender_info = SenderInfo {
|
||||||
@ -106,11 +154,7 @@ impl RPCProcessor {
|
|||||||
|
|
||||||
// Send status answer
|
// Send status answer
|
||||||
let res = self
|
let res = self
|
||||||
.answer(
|
.answer(msg, RPCAnswer::new(RPCAnswerDetail::StatusA(status_a)))
|
||||||
msg,
|
|
||||||
RPCAnswer::new(RPCAnswerDetail::StatusA(status_a)),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
tracing::Span::current().record("res", &tracing::field::display(res));
|
tracing::Span::current().record("res", &tracing::field::display(res));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -224,7 +224,6 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
|||||||
"network.upnp" => Ok(Box::new(false)),
|
"network.upnp" => Ok(Box::new(false)),
|
||||||
"network.natpmp" => Ok(Box::new(false)),
|
"network.natpmp" => Ok(Box::new(false)),
|
||||||
"network.detect_address_changes" => Ok(Box::new(true)),
|
"network.detect_address_changes" => Ok(Box::new(true)),
|
||||||
"network.enable_local_peer_scope" => Ok(Box::new(false)),
|
|
||||||
"network.restricted_nat_retries" => Ok(Box::new(3u32)),
|
"network.restricted_nat_retries" => Ok(Box::new(3u32)),
|
||||||
"network.tls.certificate_path" => Ok(Box::new(get_certfile_path())),
|
"network.tls.certificate_path" => Ok(Box::new(get_certfile_path())),
|
||||||
"network.tls.private_key_path" => Ok(Box::new(get_keyfile_path())),
|
"network.tls.private_key_path" => Ok(Box::new(get_keyfile_path())),
|
||||||
@ -354,7 +353,6 @@ pub async fn test_config() {
|
|||||||
assert_eq!(inner.network.upnp, false);
|
assert_eq!(inner.network.upnp, false);
|
||||||
assert_eq!(inner.network.natpmp, false);
|
assert_eq!(inner.network.natpmp, false);
|
||||||
assert_eq!(inner.network.detect_address_changes, true);
|
assert_eq!(inner.network.detect_address_changes, true);
|
||||||
assert_eq!(inner.network.enable_local_peer_scope, false);
|
|
||||||
assert_eq!(inner.network.restricted_nat_retries, 3u32);
|
assert_eq!(inner.network.restricted_nat_retries, 3u32);
|
||||||
assert_eq!(inner.network.tls.certificate_path, get_certfile_path());
|
assert_eq!(inner.network.tls.certificate_path, get_certfile_path());
|
||||||
assert_eq!(inner.network.tls.private_key_path, get_keyfile_path());
|
assert_eq!(inner.network.tls.private_key_path, get_keyfile_path());
|
||||||
|
@ -45,6 +45,16 @@ fn get_address_type(text: &str) -> Option<AddressType> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn get_routing_domain(text: &str) -> Option<RoutingDomain> {
|
||||||
|
let lctext = text.to_ascii_lowercase();
|
||||||
|
if "publicinternet".starts_with(&lctext) {
|
||||||
|
Some(RoutingDomain::PublicInternet)
|
||||||
|
} else if "localnetwork".starts_with(&lctext) {
|
||||||
|
Some(RoutingDomain::LocalNetwork)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_debug_argument<T, G: FnOnce(&str) -> Option<T>>(
|
fn get_debug_argument<T, G: FnOnce(&str) -> Option<T>>(
|
||||||
value: &str,
|
value: &str,
|
||||||
@ -331,27 +341,40 @@ impl VeilidAPI {
|
|||||||
None => return Ok("Node id not found in routing table".to_owned()),
|
None => return Ok("Node id not found in routing table".to_owned()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.len() >= 2 {
|
let mut ai = 1;
|
||||||
let pt =
|
let mut routing_domain = None;
|
||||||
get_debug_argument_at(&args, 1, "debug_ping", "protocol_type", get_protocol_type)?;
|
while ai < args.len() {
|
||||||
nr.merge_filter(DialInfoFilter::all().with_protocol_type(pt));
|
if let Ok(pt) =
|
||||||
if args.len() >= 3 {
|
get_debug_argument_at(&args, ai, "debug_ping", "protocol_type", get_protocol_type)
|
||||||
let at = get_debug_argument_at(
|
{
|
||||||
&args,
|
nr.merge_filter(DialInfoFilter::all().with_protocol_type(pt));
|
||||||
2,
|
} else if let Ok(at) =
|
||||||
"debug_ping",
|
get_debug_argument_at(&args, ai, "debug_ping", "address_type", get_address_type)
|
||||||
"address_type",
|
{
|
||||||
get_address_type,
|
|
||||||
)?;
|
|
||||||
nr.merge_filter(DialInfoFilter::all().with_address_type(at));
|
nr.merge_filter(DialInfoFilter::all().with_address_type(at));
|
||||||
|
} else if let Ok(rd) = get_debug_argument_at(
|
||||||
|
&args,
|
||||||
|
ai,
|
||||||
|
"debug_ping",
|
||||||
|
"routing_domain",
|
||||||
|
get_routing_domain,
|
||||||
|
) {
|
||||||
|
if routing_domain.is_none() {
|
||||||
|
routing_domain = Some(rd);
|
||||||
|
} else {
|
||||||
|
return Ok("Multiple routing domains specified".to_owned());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(format!("Invalid argument specified: {}", args[ai]));
|
||||||
}
|
}
|
||||||
|
ai += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rpc = self.network_manager()?.rpc_processor();
|
let rpc = self.network_manager()?.rpc_processor();
|
||||||
|
|
||||||
// Dump routing table entry
|
// Dump routing table entry
|
||||||
let out = match rpc
|
let out = match rpc
|
||||||
.rpc_call_status(nr)
|
.rpc_call_status(routing_domain, nr)
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::internal)?
|
.map_err(VeilidAPIError::internal)?
|
||||||
{
|
{
|
||||||
@ -383,7 +406,7 @@ impl VeilidAPI {
|
|||||||
attach
|
attach
|
||||||
detach
|
detach
|
||||||
restart network
|
restart network
|
||||||
ping <node_id> [protocol_type [address_type]]
|
ping <node_id> [protocol_type][address_type][routing_domain]
|
||||||
contact <node_id> [protocol_type [address_type]]
|
contact <node_id> [protocol_type [address_type]]
|
||||||
"#
|
"#
|
||||||
.to_owned())
|
.to_owned())
|
||||||
|
@ -460,9 +460,31 @@ pub struct NodeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeInfo {
|
impl NodeInfo {
|
||||||
pub fn is_valid(&self) -> bool {
|
pub fn is_valid_in_routing_domain(
|
||||||
!matches!(self.network_class, NetworkClass::Invalid)
|
&self,
|
||||||
|
routing_table: RoutingTable,
|
||||||
|
routing_domain: RoutingDomain,
|
||||||
|
) -> bool {
|
||||||
|
// Should not be passing around nodeinfo with an invalid network class
|
||||||
|
if matches!(self.network_class, NetworkClass::Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Ensure all of the dial info works in this routing domain
|
||||||
|
for did in self.dial_info_detail_list {
|
||||||
|
if !routing_table.ensure_dial_info_is_valid(routing_domain, &did.dial_info) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure the relay is also valid in this routing domain if it is provided
|
||||||
|
if let Some(relay_peer_info) = self.relay_peer_info {
|
||||||
|
let relay_ni = &relay_peer_info.signed_node_info.node_info;
|
||||||
|
if !relay_ni.is_valid_in_routing_domain(routing_table, routing_domain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_filtered_dial_info_detail<F>(&self, filter: F) -> Option<DialInfoDetail>
|
pub fn first_filtered_dial_info_detail<F>(&self, filter: F) -> Option<DialInfoDetail>
|
||||||
where
|
where
|
||||||
F: Fn(&DialInfoDetail) -> bool,
|
F: Fn(&DialInfoDetail) -> bool,
|
||||||
@ -783,7 +805,7 @@ impl FromStr for SocketAddress {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct DialInfoFilter {
|
pub struct DialInfoFilter {
|
||||||
pub protocol_type_set: ProtocolTypeSet,
|
pub protocol_type_set: ProtocolTypeSet,
|
||||||
pub address_type_set: AddressTypeSet,
|
pub address_type_set: AddressTypeSet,
|
||||||
@ -1096,6 +1118,14 @@ impl DialInfo {
|
|||||||
pub fn address_type(&self) -> AddressType {
|
pub fn address_type(&self) -> AddressType {
|
||||||
self.socket_address().address_type()
|
self.socket_address().address_type()
|
||||||
}
|
}
|
||||||
|
pub fn address(&self) -> Address {
|
||||||
|
match self {
|
||||||
|
Self::UDP(di) => di.socket_address.address,
|
||||||
|
Self::TCP(di) => di.socket_address.address,
|
||||||
|
Self::WS(di) => di.socket_address.address,
|
||||||
|
Self::WSS(di) => di.socket_address.address,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn socket_address(&self) -> SocketAddress {
|
pub fn socket_address(&self) -> SocketAddress {
|
||||||
match self {
|
match self {
|
||||||
Self::UDP(di) => di.socket_address,
|
Self::UDP(di) => di.socket_address,
|
||||||
|
@ -137,7 +137,6 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub upnp: bool,
|
pub upnp: bool,
|
||||||
pub natpmp: bool,
|
pub natpmp: bool,
|
||||||
pub detect_address_changes: bool,
|
pub detect_address_changes: bool,
|
||||||
pub enable_local_peer_scope: bool,
|
|
||||||
pub restricted_nat_retries: u32,
|
pub restricted_nat_retries: u32,
|
||||||
pub tls: VeilidConfigTLS,
|
pub tls: VeilidConfigTLS,
|
||||||
pub application: VeilidConfigApplication,
|
pub application: VeilidConfigApplication,
|
||||||
@ -356,7 +355,6 @@ impl VeilidConfig {
|
|||||||
get_config!(inner.network.upnp);
|
get_config!(inner.network.upnp);
|
||||||
get_config!(inner.network.natpmp);
|
get_config!(inner.network.natpmp);
|
||||||
get_config!(inner.network.detect_address_changes);
|
get_config!(inner.network.detect_address_changes);
|
||||||
get_config!(inner.network.enable_local_peer_scope);
|
|
||||||
get_config!(inner.network.restricted_nat_retries);
|
get_config!(inner.network.restricted_nat_retries);
|
||||||
get_config!(inner.network.tls.certificate_path);
|
get_config!(inner.network.tls.certificate_path);
|
||||||
get_config!(inner.network.tls.private_key_path);
|
get_config!(inner.network.tls.private_key_path);
|
||||||
|
@ -215,3 +215,48 @@ pub fn ip_to_ipblock(ip6_prefix_size: usize, addr: IpAddr) -> IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ipaddr_apply_netmask(addr: IpAddr, netmask: IpAddr) -> IpAddr {
|
||||||
|
match addr {
|
||||||
|
IpAddr::V4(v4) => {
|
||||||
|
let v4mask = match netmask {
|
||||||
|
IpAddr::V4(v4mask) => v4mask,
|
||||||
|
IpAddr::V6(_) => {
|
||||||
|
panic!("netmask doesn't match ipv4 address");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let v4 = v4.octets();
|
||||||
|
let v4mask = v4mask.octets();
|
||||||
|
IpAddr::V4(Ipv4Addr::new(
|
||||||
|
v4[0] & v4mask[0],
|
||||||
|
v4[1] & v4mask[1],
|
||||||
|
v4[2] & v4mask[2],
|
||||||
|
v4[3] & v4mask[3],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
IpAddr::V6(v6) => {
|
||||||
|
let v6mask = match netmask {
|
||||||
|
IpAddr::V4(_) => {
|
||||||
|
panic!("netmask doesn't match ipv6 address");
|
||||||
|
}
|
||||||
|
IpAddr::V6(v6mask) => v6mask,
|
||||||
|
};
|
||||||
|
let v6 = v6.segments();
|
||||||
|
let v6mask = v6mask.segments();
|
||||||
|
IpAddr::V6(Ipv6Addr::new(
|
||||||
|
v6[0] & v6mask[0],
|
||||||
|
v6[1] & v6mask[1],
|
||||||
|
v6[2] & v6mask[2],
|
||||||
|
v6[3] & v6mask[3],
|
||||||
|
v6[4] & v6mask[4],
|
||||||
|
v6[5] & v6mask[5],
|
||||||
|
v6[6] & v6mask[6],
|
||||||
|
v6[7] & v6mask[7],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ipaddr_in_network(addr: IpAddr, netaddr: IpAddr, netmask: IpAddr) -> bool {
|
||||||
|
ipaddr_apply_netmask(netaddr, netmask) == ipaddr_apply_netmask(addr, netmask)
|
||||||
|
}
|
||||||
|
@ -85,7 +85,6 @@ Future<VeilidConfig> getDefaultVeilidConfig() async {
|
|||||||
upnp: true,
|
upnp: true,
|
||||||
natpmp: true,
|
natpmp: true,
|
||||||
detectAddressChanges: true,
|
detectAddressChanges: true,
|
||||||
enableLocalPeerScope: false,
|
|
||||||
restrictedNatRetries: 0,
|
restrictedNatRetries: 0,
|
||||||
tls: VeilidConfigTLS(
|
tls: VeilidConfigTLS(
|
||||||
certificatePath: "",
|
certificatePath: "",
|
||||||
|
@ -741,7 +741,6 @@ class VeilidConfigNetwork {
|
|||||||
bool upnp;
|
bool upnp;
|
||||||
bool natpmp;
|
bool natpmp;
|
||||||
bool detectAddressChanges;
|
bool detectAddressChanges;
|
||||||
bool enableLocalPeerScope;
|
|
||||||
int restrictedNatRetries;
|
int restrictedNatRetries;
|
||||||
VeilidConfigTLS tls;
|
VeilidConfigTLS tls;
|
||||||
VeilidConfigApplication application;
|
VeilidConfigApplication application;
|
||||||
@ -767,7 +766,6 @@ class VeilidConfigNetwork {
|
|||||||
required this.upnp,
|
required this.upnp,
|
||||||
required this.natpmp,
|
required this.natpmp,
|
||||||
required this.detectAddressChanges,
|
required this.detectAddressChanges,
|
||||||
required this.enableLocalPeerScope,
|
|
||||||
required this.restrictedNatRetries,
|
required this.restrictedNatRetries,
|
||||||
required this.tls,
|
required this.tls,
|
||||||
required this.application,
|
required this.application,
|
||||||
@ -795,7 +793,6 @@ class VeilidConfigNetwork {
|
|||||||
'upnp': upnp,
|
'upnp': upnp,
|
||||||
'natpmp': natpmp,
|
'natpmp': natpmp,
|
||||||
'detect_address_changes': detectAddressChanges,
|
'detect_address_changes': detectAddressChanges,
|
||||||
'enable_local_peer_scope': enableLocalPeerScope,
|
|
||||||
'restricted_nat_retries': restrictedNatRetries,
|
'restricted_nat_retries': restrictedNatRetries,
|
||||||
'tls': tls.json,
|
'tls': tls.json,
|
||||||
'application': application.json,
|
'application': application.json,
|
||||||
@ -826,7 +823,6 @@ class VeilidConfigNetwork {
|
|||||||
upnp = json['upnp'],
|
upnp = json['upnp'],
|
||||||
natpmp = json['natpmp'],
|
natpmp = json['natpmp'],
|
||||||
detectAddressChanges = json['detect_address_changes'],
|
detectAddressChanges = json['detect_address_changes'],
|
||||||
enableLocalPeerScope = json['enable_local_peer_scope'],
|
|
||||||
restrictedNatRetries = json['restricted_nat_retries'],
|
restrictedNatRetries = json['restricted_nat_retries'],
|
||||||
tls = VeilidConfigTLS.fromJson(json['tls']),
|
tls = VeilidConfigTLS.fromJson(json['tls']),
|
||||||
application = VeilidConfigApplication.fromJson(json['application']),
|
application = VeilidConfigApplication.fromJson(json['application']),
|
||||||
|
@ -130,11 +130,7 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
|||||||
.value_name("BOOTSTRAP_NODE_LIST")
|
.value_name("BOOTSTRAP_NODE_LIST")
|
||||||
.help("Specify a list of bootstrap node dialinfos to use"),
|
.help("Specify a list of bootstrap node dialinfos to use"),
|
||||||
)
|
)
|
||||||
.arg(
|
;
|
||||||
Arg::new("local")
|
|
||||||
.long("local")
|
|
||||||
.help("Enable local peer scope")
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let matches = matches.arg(
|
let matches = matches.arg(
|
||||||
@ -218,9 +214,6 @@ pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> {
|
|||||||
if matches.is_present("attach") {
|
if matches.is_present("attach") {
|
||||||
settingsrw.auto_attach = !matches!(matches.value_of("attach"), Some("true"));
|
settingsrw.auto_attach = !matches!(matches.value_of("attach"), Some("true"));
|
||||||
}
|
}
|
||||||
if matches.is_present("local") {
|
|
||||||
settingsrw.core.network.enable_local_peer_scope = true;
|
|
||||||
}
|
|
||||||
if matches.occurrences_of("delete-protected-store") != 0 {
|
if matches.occurrences_of("delete-protected-store") != 0 {
|
||||||
settingsrw.core.protected_store.delete = true;
|
settingsrw.core.protected_store.delete = true;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,6 @@ core:
|
|||||||
upnp: true
|
upnp: true
|
||||||
natpmp: false
|
natpmp: false
|
||||||
detect_address_changes: true
|
detect_address_changes: true
|
||||||
enable_local_peer_scope: false
|
|
||||||
restricted_nat_retries: 0
|
restricted_nat_retries: 0
|
||||||
tls:
|
tls:
|
||||||
certificate_path: '%CERTIFICATE_PATH%'
|
certificate_path: '%CERTIFICATE_PATH%'
|
||||||
@ -589,7 +588,6 @@ pub struct Network {
|
|||||||
pub upnp: bool,
|
pub upnp: bool,
|
||||||
pub natpmp: bool,
|
pub natpmp: bool,
|
||||||
pub detect_address_changes: bool,
|
pub detect_address_changes: bool,
|
||||||
pub enable_local_peer_scope: bool,
|
|
||||||
pub restricted_nat_retries: u32,
|
pub restricted_nat_retries: u32,
|
||||||
pub tls: Tls,
|
pub tls: Tls,
|
||||||
pub application: Application,
|
pub application: Application,
|
||||||
@ -976,7 +974,6 @@ impl Settings {
|
|||||||
set_config_value!(inner.core.network.upnp, value);
|
set_config_value!(inner.core.network.upnp, value);
|
||||||
set_config_value!(inner.core.network.natpmp, value);
|
set_config_value!(inner.core.network.natpmp, value);
|
||||||
set_config_value!(inner.core.network.detect_address_changes, value);
|
set_config_value!(inner.core.network.detect_address_changes, value);
|
||||||
set_config_value!(inner.core.network.enable_local_peer_scope, value);
|
|
||||||
set_config_value!(inner.core.network.restricted_nat_retries, value);
|
set_config_value!(inner.core.network.restricted_nat_retries, value);
|
||||||
set_config_value!(inner.core.network.tls.certificate_path, value);
|
set_config_value!(inner.core.network.tls.certificate_path, value);
|
||||||
set_config_value!(inner.core.network.tls.private_key_path, value);
|
set_config_value!(inner.core.network.tls.private_key_path, value);
|
||||||
@ -1177,9 +1174,6 @@ impl Settings {
|
|||||||
"network.detect_address_changes" => {
|
"network.detect_address_changes" => {
|
||||||
Ok(Box::new(inner.core.network.detect_address_changes))
|
Ok(Box::new(inner.core.network.detect_address_changes))
|
||||||
}
|
}
|
||||||
"network.enable_local_peer_scope" => {
|
|
||||||
Ok(Box::new(inner.core.network.enable_local_peer_scope))
|
|
||||||
}
|
|
||||||
"network.restricted_nat_retries" => {
|
"network.restricted_nat_retries" => {
|
||||||
Ok(Box::new(inner.core.network.restricted_nat_retries))
|
Ok(Box::new(inner.core.network.restricted_nat_retries))
|
||||||
}
|
}
|
||||||
@ -1503,7 +1497,6 @@ mod tests {
|
|||||||
assert_eq!(s.core.network.upnp, true);
|
assert_eq!(s.core.network.upnp, true);
|
||||||
assert_eq!(s.core.network.natpmp, false);
|
assert_eq!(s.core.network.natpmp, false);
|
||||||
assert_eq!(s.core.network.detect_address_changes, true);
|
assert_eq!(s.core.network.detect_address_changes, true);
|
||||||
assert_eq!(s.core.network.enable_local_peer_scope, false);
|
|
||||||
assert_eq!(s.core.network.restricted_nat_retries, 0u32);
|
assert_eq!(s.core.network.restricted_nat_retries, 0u32);
|
||||||
//
|
//
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
Loading…
Reference in New Issue
Block a user