2022-09-03 17:57:25 +00:00
use super ::* ;
2022-10-13 02:53:40 +00:00
/// Mechanism required to contact another node
#[ derive(Clone, Debug) ]
2022-11-02 01:05:48 +00:00
pub enum ContactMethod {
2022-10-13 02:53:40 +00:00
/// Node is not reachable by any means
Unreachable ,
/// Connection should have already existed
Existing ,
/// Contact the node directly
Direct ( DialInfo ) ,
/// Request via signal the node connect back directly (relay, target)
2023-02-11 20:54:55 +00:00
SignalReverse ( TypedKey , TypedKey ) ,
2023-02-22 23:29:07 +00:00
/// Request via signal the node negotiate a hole punch (relay, target)
2023-02-11 20:54:55 +00:00
SignalHolePunch ( TypedKey , TypedKey ) ,
2022-10-13 02:53:40 +00:00
/// Must use an inbound relay to reach the node
2023-02-11 20:54:55 +00:00
InboundRelay ( TypedKey ) ,
2022-10-13 02:53:40 +00:00
/// Must use outbound relay to reach the node
2023-02-11 20:54:55 +00:00
OutboundRelay ( TypedKey ) ,
2022-10-13 02:53:40 +00:00
}
2022-10-09 18:59:01 +00:00
#[ derive(Debug) ]
pub struct RoutingDomainDetailCommon {
routing_domain : RoutingDomain ,
network_class : Option < NetworkClass > ,
outbound_protocols : ProtocolTypeSet ,
inbound_protocols : ProtocolTypeSet ,
address_types : AddressTypeSet ,
2022-09-03 17:57:25 +00:00
relay_node : Option < NodeRef > ,
2023-07-14 18:21:00 +00:00
relay_node_last_keepalive : Option < Timestamp > ,
2023-07-04 04:24:55 +00:00
capabilities : Vec < Capability > ,
2022-09-03 17:57:25 +00:00
dial_info_details : Vec < DialInfoDetail > ,
2022-10-09 18:59:01 +00:00
// caches
cached_peer_info : Mutex < Option < PeerInfo > > ,
2022-09-03 17:57:25 +00:00
}
2022-10-09 18:59:01 +00:00
impl RoutingDomainDetailCommon {
pub fn new ( routing_domain : RoutingDomain ) -> Self {
Self {
routing_domain ,
network_class : Default ::default ( ) ,
outbound_protocols : Default ::default ( ) ,
inbound_protocols : Default ::default ( ) ,
address_types : Default ::default ( ) ,
relay_node : Default ::default ( ) ,
2023-07-14 18:21:00 +00:00
relay_node_last_keepalive : Default ::default ( ) ,
2023-07-04 04:24:55 +00:00
capabilities : Default ::default ( ) ,
2022-10-09 18:59:01 +00:00
dial_info_details : Default ::default ( ) ,
cached_peer_info : Mutex ::new ( Default ::default ( ) ) ,
}
}
// Set from network manager
pub ( super ) fn setup_network (
& mut self ,
outbound_protocols : ProtocolTypeSet ,
inbound_protocols : ProtocolTypeSet ,
address_types : AddressTypeSet ,
2023-07-04 04:24:55 +00:00
capabilities : Vec < Capability > ,
2022-10-09 18:59:01 +00:00
) {
self . outbound_protocols = outbound_protocols ;
self . inbound_protocols = inbound_protocols ;
self . address_types = address_types ;
2023-07-04 04:24:55 +00:00
self . capabilities = capabilities ;
2022-11-03 01:54:48 +00:00
self . clear_cache ( ) ;
2022-10-09 18:59:01 +00:00
}
pub ( super ) fn set_network_class ( & mut self , network_class : Option < NetworkClass > ) {
self . network_class = network_class ;
2022-11-03 01:54:48 +00:00
self . clear_cache ( ) ;
2022-10-09 18:59:01 +00:00
}
pub fn network_class ( & self ) -> Option < NetworkClass > {
self . network_class
2022-09-03 17:57:25 +00:00
}
2022-10-09 18:59:01 +00:00
pub fn outbound_protocols ( & self ) -> ProtocolTypeSet {
self . outbound_protocols
}
pub fn inbound_protocols ( & self ) -> ProtocolTypeSet {
self . inbound_protocols
}
pub fn address_types ( & self ) -> AddressTypeSet {
self . address_types
}
2023-07-04 04:24:55 +00:00
pub fn capabilities ( & self ) -> Vec < Capability > {
self . capabilities . clone ( )
}
2022-10-09 18:59:01 +00:00
pub fn relay_node ( & self ) -> Option < NodeRef > {
2022-09-03 17:57:25 +00:00
self . relay_node . clone ( )
}
2023-07-14 18:21:00 +00:00
pub fn relay_node_last_keepalive ( & self ) -> Option < Timestamp > {
self . relay_node_last_keepalive
}
2022-10-09 18:59:01 +00:00
pub ( super ) fn set_relay_node ( & mut self , opt_relay_node : Option < NodeRef > ) {
2022-09-04 18:17:28 +00:00
self . relay_node = opt_relay_node . map ( | nr | {
2022-10-09 18:59:01 +00:00
nr . filtered_clone ( NodeRefFilter ::new ( ) . with_routing_domain ( self . routing_domain ) )
2022-11-03 01:54:48 +00:00
} ) ;
2023-07-14 18:21:00 +00:00
self . relay_node_last_keepalive = None ;
2022-11-03 01:54:48 +00:00
self . clear_cache ( ) ;
2022-09-03 17:57:25 +00:00
}
2023-07-14 18:21:00 +00:00
pub ( super ) fn set_relay_node_last_keepalive ( & mut self , ts : Option < Timestamp > ) {
self . relay_node_last_keepalive = ts ;
}
2022-10-09 18:59:01 +00:00
pub fn dial_info_details ( & self ) -> & Vec < DialInfoDetail > {
2022-09-03 17:57:25 +00:00
& self . dial_info_details
}
2023-09-04 17:33:27 +00:00
pub ( super ) fn clear_dial_info_details ( & mut self , address_type : Option < AddressType > , protocol_type : Option < ProtocolType > ) {
self . dial_info_details . retain_mut ( | e | {
let mut remove = true ;
if let Some ( pt ) = protocol_type {
if pt ! = e . dial_info . protocol_type ( ) {
remove = false ;
}
}
if let Some ( at ) = address_type {
if at ! = e . dial_info . address_type ( ) {
remove = false ;
}
}
! remove
} ) ;
2022-11-03 01:54:48 +00:00
self . clear_cache ( ) ;
2022-09-03 17:57:25 +00:00
}
2022-10-09 18:59:01 +00:00
pub ( super ) fn add_dial_info_detail ( & mut self , did : DialInfoDetail ) {
2022-09-03 17:57:25 +00:00
self . dial_info_details . push ( did ) ;
self . dial_info_details . sort ( ) ;
2022-11-03 01:54:48 +00:00
self . clear_cache ( ) ;
2022-09-03 17:57:25 +00:00
}
2022-10-09 18:59:01 +00:00
2023-07-14 23:14:12 +00:00
pub fn has_valid_network_class ( & self ) -> bool {
2022-10-09 18:59:01 +00:00
self . network_class . unwrap_or ( NetworkClass ::Invalid ) ! = NetworkClass ::Invalid
}
2022-11-09 22:11:35 +00:00
fn make_peer_info ( & self , rti : & RoutingTableInner ) -> PeerInfo {
2023-05-29 19:24:57 +00:00
let node_info = NodeInfo ::new (
self . network_class . unwrap_or ( NetworkClass ::Invalid ) ,
self . outbound_protocols ,
self . address_types ,
VALID_ENVELOPE_VERSIONS . to_vec ( ) ,
VALID_CRYPTO_KINDS . to_vec ( ) ,
2023-07-04 04:24:55 +00:00
self . capabilities . clone ( ) ,
2023-05-29 19:24:57 +00:00
self . dial_info_details . clone ( )
) ;
2022-11-09 22:11:35 +00:00
2023-08-24 21:17:48 +00:00
// Check if any of our dialinfo require a relay for signaling
// FullConeNAT requires a relay but it does not have to be published because it does not require signaling
2023-08-24 22:59:33 +00:00
let mut publish_relay = node_info . network_class ( ) . inbound_wants_relay ( ) | | node_info . network_class ( ) . outbound_wants_relay ( ) ;
if ! publish_relay {
// Check the dialinfo to see if they might want to publish a relay for signalling specifically
for did in self . dial_info_details ( ) {
if did . class . requires_signal ( ) {
publish_relay = true ;
break ;
}
}
}
2023-08-24 21:17:48 +00:00
let relay_info = if publish_relay {
self
2022-11-09 22:11:35 +00:00
. relay_node
. as_ref ( )
2022-11-10 03:27:37 +00:00
. and_then ( | rn | {
let opt_relay_pi = rn . locked ( rti ) . make_peer_info ( self . routing_domain ) ;
if let Some ( relay_pi ) = opt_relay_pi {
2023-05-29 19:24:57 +00:00
let ( relay_ids , relay_sni ) = relay_pi . destructure ( ) ;
match relay_sni {
SignedNodeInfo ::Direct ( d ) = > Some ( ( relay_ids , d ) ) ,
2022-11-10 03:27:37 +00:00
SignedNodeInfo ::Relayed ( _ ) = > {
warn! ( " relay node should not have a relay itself! if this happens, a relay updated its signed node info and became a relay, which should cause the relay to be dropped " ) ;
None
} ,
}
} else {
None
}
2023-08-24 21:17:48 +00:00
} )
} else {
None
} ;
2022-11-09 22:11:35 +00:00
2022-11-10 03:27:37 +00:00
let signed_node_info = match relay_info {
2023-02-22 23:29:07 +00:00
Some ( ( relay_ids , relay_sdni ) ) = > SignedNodeInfo ::Relayed (
2023-02-08 02:44:50 +00:00
SignedRelayedNodeInfo ::make_signatures (
2023-02-22 23:29:07 +00:00
rti . unlocked_inner . crypto ( ) ,
rti . unlocked_inner . node_id_typed_key_pairs ( ) ,
2022-11-09 22:11:35 +00:00
node_info ,
2023-02-22 23:29:07 +00:00
relay_ids ,
2022-11-10 03:27:37 +00:00
relay_sdni ,
2022-11-09 22:11:35 +00:00
)
. unwrap ( ) ,
) ,
None = > SignedNodeInfo ::Direct (
2023-02-22 23:29:07 +00:00
SignedDirectNodeInfo ::make_signatures (
rti . unlocked_inner . crypto ( ) ,
rti . unlocked_inner . node_id_typed_key_pairs ( ) ,
2022-11-09 22:11:35 +00:00
node_info ,
)
2022-11-10 03:27:37 +00:00
. unwrap ( )
2022-11-09 22:11:35 +00:00
) ,
} ;
2023-02-22 23:29:07 +00:00
PeerInfo ::new ( rti . unlocked_inner . node_ids ( ) , signed_node_info )
2022-11-09 22:11:35 +00:00
}
2022-11-03 01:54:48 +00:00
pub fn with_peer_info < F , R > ( & self , rti : & RoutingTableInner , f : F ) -> R
2022-10-09 18:59:01 +00:00
where
F : FnOnce ( & PeerInfo ) -> R ,
{
2022-10-31 03:23:12 +00:00
let mut cpi = self . cached_peer_info . lock ( ) ;
2022-10-09 18:59:01 +00:00
if cpi . is_none ( ) {
// Regenerate peer info
2022-11-10 03:27:37 +00:00
let pi = self . make_peer_info ( rti ) ;
2022-10-09 18:59:01 +00:00
// Cache the peer info
* cpi = Some ( pi ) ;
}
f ( cpi . as_ref ( ) . unwrap ( ) )
}
pub fn inbound_dial_info_filter ( & self ) -> DialInfoFilter {
DialInfoFilter ::all ( )
. with_protocol_type_set ( self . inbound_protocols )
. with_address_type_set ( self . address_types )
}
pub fn outbound_dial_info_filter ( & self ) -> DialInfoFilter {
DialInfoFilter ::all ( )
. with_protocol_type_set ( self . outbound_protocols )
. with_address_type_set ( self . address_types )
}
pub ( super ) fn clear_cache ( & self ) {
* self . cached_peer_info . lock ( ) = None ;
}
}
/// General trait for all routing domains
pub trait RoutingDomainDetail {
// Common accessors
fn common ( & self ) -> & RoutingDomainDetailCommon ;
fn common_mut ( & mut self ) -> & mut RoutingDomainDetailCommon ;
2022-10-13 02:53:40 +00:00
/// Can this routing domain contain a particular address
2022-10-09 18:59:01 +00:00
fn can_contain_address ( & self , address : Address ) -> bool ;
2022-10-13 02:53:40 +00:00
/// Get the contact method required for node A to reach node B in this routing domain
/// Routing table must be locked for reading to use this function
fn get_contact_method (
& self ,
rti : & RoutingTableInner ,
2022-11-10 03:27:37 +00:00
peer_a : & PeerInfo ,
peer_b : & PeerInfo ,
2022-10-13 02:53:40 +00:00
dial_info_filter : DialInfoFilter ,
2022-10-21 14:35:03 +00:00
sequencing : Sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort : Option < Arc < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > > ,
2022-10-13 02:53:40 +00:00
) -> ContactMethod ;
2022-10-09 18:59:01 +00:00
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Public Internet routing domain internals
#[ derive(Debug) ]
pub struct PublicInternetRoutingDomainDetail {
/// Common implementation for all routing domains
common : RoutingDomainDetailCommon ,
}
impl Default for PublicInternetRoutingDomainDetail {
fn default ( ) -> Self {
Self {
common : RoutingDomainDetailCommon ::new ( RoutingDomain ::PublicInternet ) ,
}
}
}
2023-06-24 15:16:34 +00:00
fn first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
from_node : & NodeInfo ,
to_node : & NodeInfo ,
dial_info_filter : & DialInfoFilter ,
2022-10-22 01:27:07 +00:00
sequencing : Sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort : Option < Arc < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > >
2022-10-13 02:53:40 +00:00
) -> Option < DialInfoDetail > {
2022-10-22 01:27:07 +00:00
let dial_info_filter = dial_info_filter . clone ( ) . filtered (
2022-10-13 02:53:40 +00:00
& DialInfoFilter ::all ( )
2023-05-29 19:24:57 +00:00
. with_address_type_set ( from_node . address_types ( ) )
. with_protocol_type_set ( from_node . outbound_protocols ( ) ) ,
2022-10-13 02:53:40 +00:00
) ;
2023-06-24 15:16:34 +00:00
// Apply sequencing and get sort
2023-08-22 01:04:21 +00:00
// Include sorting by external dial info sort for rotating through dialinfo
// based on an external preference table, for example the one kept by
// AddressFilter to deprioritize dialinfo that have recently failed to connect
2023-06-24 15:16:34 +00:00
let ( ordered , dial_info_filter ) = dial_info_filter . with_sequencing ( sequencing ) ;
2023-08-22 01:04:21 +00:00
let sort : Option < Box < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > > = if ordered {
if let Some ( dif_sort ) = dif_sort {
Some ( Box ::new ( move | a , b | {
let mut ord = dif_sort ( a , b ) ;
if ord = = core ::cmp ::Ordering ::Equal {
ord = DialInfoDetail ::ordered_sequencing_sort ( a , b ) ;
}
ord
} ) )
} else {
Some ( Box ::new ( move | a , b | { DialInfoDetail ::ordered_sequencing_sort ( a , b ) } ) )
}
2023-06-24 15:16:34 +00:00
} else {
2023-08-22 01:04:21 +00:00
if let Some ( dif_sort ) = dif_sort {
Some ( Box ::new ( move | a , b | { dif_sort ( a , b ) } ) )
} else {
None
}
2022-10-13 02:53:40 +00:00
} ;
2023-06-24 15:16:34 +00:00
2022-10-22 01:27:07 +00:00
// If the filter is dead then we won't be able to connect
if dial_info_filter . is_dead ( ) {
return None ;
}
2022-10-13 02:53:40 +00:00
// Get the best match dial info for node B if we have it
2023-06-24 15:16:34 +00:00
let direct_filter = | did : & DialInfoDetail | did . matches_filter ( & dial_info_filter ) ;
2022-10-13 02:53:40 +00:00
to_node . first_filtered_dial_info_detail ( sort , direct_filter )
}
2022-10-09 18:59:01 +00:00
impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
fn common ( & self ) -> & RoutingDomainDetailCommon {
& self . common
}
fn common_mut ( & mut self ) -> & mut RoutingDomainDetailCommon {
& mut self . common
}
fn can_contain_address ( & self , address : Address ) -> bool {
address . is_global ( )
}
2022-10-13 02:53:40 +00:00
fn get_contact_method (
& self ,
_rti : & RoutingTableInner ,
2022-11-10 03:27:37 +00:00
peer_a : & PeerInfo ,
peer_b : & PeerInfo ,
2022-10-13 02:53:40 +00:00
dial_info_filter : DialInfoFilter ,
2022-10-22 01:27:07 +00:00
sequencing : Sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort : Option < Arc < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > > ,
2022-10-13 02:53:40 +00:00
) -> ContactMethod {
2022-11-10 03:27:37 +00:00
// Get the nodeinfos for convenience
2023-05-29 19:24:57 +00:00
let node_a = peer_a . signed_node_info ( ) . node_info ( ) ;
let node_b = peer_b . signed_node_info ( ) . node_info ( ) ;
2023-02-22 23:29:07 +00:00
// Get the node ids that would be used between these peers
2023-05-29 19:24:57 +00:00
let cck = common_crypto_kinds ( & peer_a . node_ids ( ) . kinds ( ) , & peer_b . node_ids ( ) . kinds ( ) ) ;
2023-02-22 23:29:07 +00:00
let Some ( best_ck ) = cck . first ( ) . copied ( ) else {
// No common crypto kinds between these nodes, can't contact
return ContactMethod ::Unreachable ;
} ;
2023-03-01 02:11:26 +00:00
2023-05-29 19:24:57 +00:00
//let node_a_id = peer_a.node_ids().get(best_ck).unwrap();
let node_b_id = peer_b . node_ids ( ) . get ( best_ck ) . unwrap ( ) ;
2023-02-22 23:29:07 +00:00
2022-10-13 02:53:40 +00:00
// Get the best match dial info for node B if we have it
if let Some ( target_did ) =
2023-08-22 01:04:21 +00:00
first_filtered_dial_info_detail_between_nodes ( node_a , node_b , & dial_info_filter , sequencing , dif_sort . clone ( ) )
2022-10-13 02:53:40 +00:00
{
// Do we need to signal before going inbound?
if ! target_did . class . requires_signal ( ) {
// Go direct without signaling
return ContactMethod ::Direct ( target_did . dial_info ) ;
}
// Get the target's inbound relay, it must have one or it is not reachable
2023-05-29 19:24:57 +00:00
if let Some ( node_b_relay ) = peer_b . signed_node_info ( ) . relay_info ( ) {
2022-12-17 18:02:39 +00:00
2022-10-13 02:53:40 +00:00
// Note that relay_peer_info could be node_a, in which case a connection already exists
2022-12-17 18:02:39 +00:00
// and we only get here if the connection had dropped, in which case node_a is unreachable until
// it gets a new relay connection up
2023-05-29 19:24:57 +00:00
if peer_b . signed_node_info ( ) . relay_ids ( ) . contains_any ( peer_a . node_ids ( ) ) {
2022-10-13 02:53:40 +00:00
return ContactMethod ::Existing ;
}
2023-02-22 23:29:07 +00:00
// Get best node id to contact relay with
2023-05-29 19:24:57 +00:00
let Some ( node_b_relay_id ) = peer_b . signed_node_info ( ) . relay_ids ( ) . get ( best_ck ) else {
2023-02-22 23:29:07 +00:00
// No best relay id
return ContactMethod ::Unreachable ;
} ;
2022-10-13 02:53:40 +00:00
// Can node A reach the inbound relay directly?
2023-06-24 15:16:34 +00:00
if first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
node_a ,
2022-11-10 03:27:37 +00:00
node_b_relay ,
2022-10-13 02:53:40 +00:00
& dial_info_filter ,
2022-10-22 01:27:07 +00:00
sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort . clone ( ) ,
2022-10-13 02:53:40 +00:00
)
. is_some ( )
{
// Can node A receive anything inbound ever?
2023-05-29 19:24:57 +00:00
if matches! ( node_a . network_class ( ) , NetworkClass ::InboundCapable ) {
2022-10-13 02:53:40 +00:00
///////// Reverse connection
// Get the best match dial info for an reverse inbound connection from node B to node A
2023-06-24 15:16:34 +00:00
if let Some ( reverse_did ) = first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
node_b ,
node_a ,
& dial_info_filter ,
2022-10-22 01:27:07 +00:00
sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort . clone ( )
2022-10-13 02:53:40 +00:00
) {
// Ensure we aren't on the same public IP address (no hairpin nat)
if reverse_did . dial_info . to_ip_addr ( )
! = target_did . dial_info . to_ip_addr ( )
{
// Can we receive a direct reverse connection?
if ! reverse_did . class . requires_signal ( ) {
return ContactMethod ::SignalReverse (
2023-02-22 23:29:07 +00:00
node_b_relay_id ,
node_b_id ,
2022-10-13 02:53:40 +00:00
) ;
}
}
}
///////// UDP hole-punch
// Does node B have a direct udp dialinfo node A can reach?
let udp_dial_info_filter = dial_info_filter
. clone ( )
. filtered ( & DialInfoFilter ::all ( ) . with_protocol_type ( ProtocolType ::UDP ) ) ;
2023-06-24 15:16:34 +00:00
if let Some ( target_udp_did ) = first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
node_a ,
node_b ,
& udp_dial_info_filter ,
2022-10-22 01:27:07 +00:00
sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort . clone ( )
2022-10-13 02:53:40 +00:00
) {
// Does node A have a direct udp dialinfo that node B can reach?
2023-06-24 15:16:34 +00:00
if let Some ( reverse_udp_did ) = first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
node_b ,
node_a ,
& udp_dial_info_filter ,
2022-10-22 01:27:07 +00:00
sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort . clone ( ) ,
2022-10-13 02:53:40 +00:00
) {
// Ensure we aren't on the same public IP address (no hairpin nat)
if reverse_udp_did . dial_info . to_ip_addr ( )
! = target_udp_did . dial_info . to_ip_addr ( )
{
// The target and ourselves have a udp dialinfo that they can reach
return ContactMethod ::SignalHolePunch (
2023-02-22 23:29:07 +00:00
node_b_relay_id ,
node_b_id ,
2022-10-13 02:53:40 +00:00
) ;
}
}
}
// Otherwise we have to inbound relay
}
2023-02-22 23:29:07 +00:00
return ContactMethod ::InboundRelay ( node_b_relay_id ) ;
2022-10-13 02:53:40 +00:00
}
}
}
// If the node B has no direct dial info, it needs to have an inbound relay
2023-05-29 19:24:57 +00:00
else if let Some ( node_b_relay ) = peer_b . signed_node_info ( ) . relay_info ( ) {
2023-02-22 23:29:07 +00:00
2022-12-17 18:02:39 +00:00
// Note that relay_peer_info could be node_a, in which case a connection already exists
2023-07-19 18:44:58 +00:00
// and we only get here if the connection had dropped, in which case node_b is unreachable until
2022-12-17 18:02:39 +00:00
// it gets a new relay connection up
2023-05-29 19:24:57 +00:00
if peer_b . signed_node_info ( ) . relay_ids ( ) . contains_any ( peer_a . node_ids ( ) ) {
2022-12-17 18:02:39 +00:00
return ContactMethod ::Existing ;
}
2022-11-10 03:27:37 +00:00
2023-02-22 23:29:07 +00:00
// Get best node id to contact relay with
2023-05-29 19:24:57 +00:00
let Some ( node_b_relay_id ) = peer_b . signed_node_info ( ) . relay_ids ( ) . get ( best_ck ) else {
2023-02-22 23:29:07 +00:00
// No best relay id
return ContactMethod ::Unreachable ;
} ;
2022-10-13 02:53:40 +00:00
// Can we reach the full relay?
2023-06-24 15:16:34 +00:00
if first_filtered_dial_info_detail_between_nodes (
2022-10-13 02:53:40 +00:00
node_a ,
2022-11-10 03:27:37 +00:00
& node_b_relay ,
2022-10-13 02:53:40 +00:00
& dial_info_filter ,
2022-10-22 01:27:07 +00:00
sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort . clone ( )
2022-10-13 02:53:40 +00:00
)
. is_some ( )
{
2023-02-22 23:29:07 +00:00
return ContactMethod ::InboundRelay ( node_b_relay_id ) ;
2022-10-13 02:53:40 +00:00
}
}
// If node A can't reach the node by other means, it may need to use its own relay
2023-07-19 18:44:58 +00:00
if peer_a . signed_node_info ( ) . node_info ( ) . network_class ( ) . outbound_wants_relay ( ) {
if let Some ( node_a_relay_id ) = peer_a . signed_node_info ( ) . relay_ids ( ) . get ( best_ck ) {
// Ensure it's not our relay we're trying to reach
if node_a_relay_id ! = node_b_id {
return ContactMethod ::OutboundRelay ( node_a_relay_id ) ;
}
2023-07-13 23:54:08 +00:00
}
2022-10-13 02:53:40 +00:00
}
ContactMethod ::Unreachable
}
2022-09-03 17:57:25 +00:00
}
/// Local Network routing domain internals
2022-10-09 18:59:01 +00:00
#[ derive(Debug) ]
pub struct LocalNetworkRoutingDomainDetail {
2022-09-03 17:57:25 +00:00
/// The local networks this domain will communicate with
local_networks : Vec < ( IpAddr , IpAddr ) > ,
2022-10-09 18:59:01 +00:00
/// Common implementation for all routing domains
common : RoutingDomainDetailCommon ,
}
impl Default for LocalNetworkRoutingDomainDetail {
fn default ( ) -> Self {
Self {
local_networks : Default ::default ( ) ,
common : RoutingDomainDetailCommon ::new ( RoutingDomain ::LocalNetwork ) ,
}
}
2022-09-03 17:57:25 +00:00
}
2022-10-09 18:59:01 +00:00
impl LocalNetworkRoutingDomainDetail {
2022-09-04 19:40:35 +00:00
pub fn set_local_networks ( & mut self , mut local_networks : Vec < ( IpAddr , IpAddr ) > ) -> bool {
2022-09-03 17:57:25 +00:00
local_networks . sort ( ) ;
if local_networks = = self . local_networks {
return false ;
}
self . local_networks = local_networks ;
true
}
}
2022-10-09 18:59:01 +00:00
impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
fn common ( & self ) -> & RoutingDomainDetailCommon {
& self . common
}
fn common_mut ( & mut self ) -> & mut RoutingDomainDetailCommon {
& mut self . common
}
2022-09-03 17:57:25 +00:00
fn can_contain_address ( & self , address : Address ) -> bool {
let ip = address . to_ip_addr ( ) ;
2022-09-04 19:40:35 +00:00
for localnet in & self . local_networks {
2022-09-03 17:57:25 +00:00
if ipaddr_in_network ( ip , localnet . 0 , localnet . 1 ) {
return true ;
}
}
false
}
2022-10-13 02:53:40 +00:00
fn get_contact_method (
& self ,
_rti : & RoutingTableInner ,
2022-11-10 03:27:37 +00:00
peer_a : & PeerInfo ,
peer_b : & PeerInfo ,
2022-10-13 02:53:40 +00:00
dial_info_filter : DialInfoFilter ,
2022-10-22 01:27:07 +00:00
sequencing : Sequencing ,
2023-08-22 01:04:21 +00:00
dif_sort : Option < Arc < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > > ,
2022-10-13 02:53:40 +00:00
) -> ContactMethod {
// Scope the filter down to protocols node A can do outbound
let dial_info_filter = dial_info_filter . filtered (
& DialInfoFilter ::all ( )
2023-05-29 19:24:57 +00:00
. with_address_type_set ( peer_a . signed_node_info ( ) . node_info ( ) . address_types ( ) )
. with_protocol_type_set ( peer_a . signed_node_info ( ) . node_info ( ) . outbound_protocols ( ) ) ,
2022-10-13 02:53:40 +00:00
) ;
2022-11-10 03:27:37 +00:00
2023-08-22 01:04:21 +00:00
// Apply sequencing and get sort
// Include sorting by external dial info sort for rotating through dialinfo
// based on an external preference table, for example the one kept by
// AddressFilter to deprioritize dialinfo that have recently failed to connect
let ( ordered , dial_info_filter ) = dial_info_filter . with_sequencing ( sequencing ) ;
let sort : Option < Box < dyn Fn ( & DialInfoDetail , & DialInfoDetail ) -> core ::cmp ::Ordering > > = if ordered {
if let Some ( dif_sort ) = dif_sort {
Some ( Box ::new ( move | a , b | {
let mut ord = dif_sort ( a , b ) ;
if ord = = core ::cmp ::Ordering ::Equal {
ord = DialInfoDetail ::ordered_sequencing_sort ( a , b ) ;
}
ord
} ) )
} else {
Some ( Box ::new ( move | a , b | { DialInfoDetail ::ordered_sequencing_sort ( a , b ) } ) )
}
} else {
if let Some ( dif_sort ) = dif_sort {
Some ( Box ::new ( move | a , b | { dif_sort ( a , b ) } ) )
} else {
None
}
2022-10-22 01:27:07 +00:00
} ;
2023-08-22 01:04:21 +00:00
2022-10-13 02:53:40 +00:00
// If the filter is dead then we won't be able to connect
if dial_info_filter . is_dead ( ) {
return ContactMethod ::Unreachable ;
}
let filter = | did : & DialInfoDetail | did . matches_filter ( & dial_info_filter ) ;
2023-05-29 19:24:57 +00:00
let opt_target_did = peer_b . signed_node_info ( ) . node_info ( ) . first_filtered_dial_info_detail ( sort , filter ) ;
2022-10-13 02:53:40 +00:00
if let Some ( target_did ) = opt_target_did {
return ContactMethod ::Direct ( target_did . dial_info ) ;
}
ContactMethod ::Unreachable
}
2022-09-03 17:57:25 +00:00
}