keepalive work
This commit is contained in:
@@ -4,6 +4,14 @@ use crate::dht::*;
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
|
||||
pub type LowLevelProtocolPorts = BTreeSet<(LowLevelProtocolType, AddressType, u16)>;
|
||||
pub type ProtocolToPortMapping = BTreeMap<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MappedPortInfo {
|
||||
pub low_level_protocol_ports: LowLevelProtocolPorts,
|
||||
pub protocol_to_port: ProtocolToPortMapping,
|
||||
}
|
||||
|
||||
impl RoutingTable {
|
||||
// Makes a filter that finds nodes with a matching inbound dialinfo
|
||||
pub fn make_inbound_dial_info_entry_filter(
|
||||
@@ -383,12 +391,46 @@ impl RoutingTable {
|
||||
out
|
||||
}
|
||||
|
||||
// Build a map of protocols to low level ports
|
||||
// This way we can get the set of protocols required to keep our NAT mapping alive for keepalive pings
|
||||
// Only one protocol per low level protocol/port combination is required
|
||||
// For example, if WS/WSS and TCP protocols are on the same low-level TCP port, only TCP keepalives will be required
|
||||
// and we do not need to do WS/WSS keepalive as well. If they are on different ports, then we will need WS/WSS keepalives too.
|
||||
pub fn get_mapped_port_info(&self) -> MappedPortInfo {
|
||||
let mut low_level_protocol_ports =
|
||||
BTreeSet::<(LowLevelProtocolType, AddressType, u16)>::new();
|
||||
let mut protocol_to_port =
|
||||
BTreeMap::<(ProtocolType, AddressType), (LowLevelProtocolType, u16)>::new();
|
||||
let our_dids = self.all_filtered_dial_info_details(
|
||||
Some(RoutingDomain::PublicInternet),
|
||||
&DialInfoFilter::all(),
|
||||
);
|
||||
for did in our_dids {
|
||||
low_level_protocol_ports.insert((
|
||||
did.dial_info.protocol_type().low_level_protocol_type(),
|
||||
did.dial_info.address_type(),
|
||||
did.dial_info.socket_address().port(),
|
||||
));
|
||||
protocol_to_port.insert(
|
||||
(did.dial_info.protocol_type(), did.dial_info.address_type()),
|
||||
(
|
||||
did.dial_info.protocol_type().low_level_protocol_type(),
|
||||
did.dial_info.socket_address().port(),
|
||||
),
|
||||
);
|
||||
}
|
||||
MappedPortInfo {
|
||||
low_level_protocol_ports,
|
||||
protocol_to_port,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_relay_node_filter(&self) -> impl Fn(&BucketEntryInner) -> bool {
|
||||
// Get all our outbound protocol/address types
|
||||
let protocol_config = self.network_manager().get_protocol_config();
|
||||
let outbound_dif = self
|
||||
.network_manager()
|
||||
.get_outbound_dial_info_filter(RoutingDomain::PublicInternet);
|
||||
let mapped_port_info = self.get_mapped_port_info();
|
||||
|
||||
move |e: &BucketEntryInner| {
|
||||
// Ensure this node is not on our local network
|
||||
@@ -400,29 +442,24 @@ impl RoutingTable {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disqualify nodes that don't have all our outbound protocol types
|
||||
// Disqualify nodes that don't cover all our inbound ports for tcp and udp
|
||||
// as we need to be able to use the relay for keepalives for all nat mappings
|
||||
let mut low_level_protocol_ports = mapped_port_info.low_level_protocol_ports.clone();
|
||||
|
||||
let can_serve_as_relay = e
|
||||
.node_info()
|
||||
.map(|n| {
|
||||
let dids =
|
||||
n.all_filtered_dial_info_details(|did| did.matches_filter(&outbound_dif));
|
||||
for pt in protocol_config.outbound {
|
||||
for at in protocol_config.family_global {
|
||||
let mut found = false;
|
||||
for did in &dids {
|
||||
if did.dial_info.protocol_type() == pt
|
||||
&& did.dial_info.address_type() == at
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false;
|
||||
}
|
||||
for did in &dids {
|
||||
let pt = did.dial_info.protocol_type();
|
||||
let at = did.dial_info.address_type();
|
||||
if let Some((llpt, port)) = mapped_port_info.protocol_to_port.get(&(pt, at))
|
||||
{
|
||||
low_level_protocol_ports.remove(&(*llpt, at, *port));
|
||||
}
|
||||
}
|
||||
true
|
||||
low_level_protocol_ports.is_empty()
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if !can_serve_as_relay {
|
||||
|
Reference in New Issue
Block a user