more dialinfodetail refactor
This commit is contained in:
parent
1156159748
commit
2d7cffee3d
@ -195,8 +195,8 @@ enum DialInfoClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DialInfoDetail {
|
struct DialInfoDetail {
|
||||||
dialInfo @0; :DialInfo;
|
dialInfo @0 :DialInfo;
|
||||||
class @1; :DialInfoClass;
|
class @1 :DialInfoClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeStatus {
|
struct NodeStatus {
|
||||||
@ -243,7 +243,6 @@ struct OperationReturnReceipt {
|
|||||||
|
|
||||||
struct OperationFindNodeQ {
|
struct OperationFindNodeQ {
|
||||||
nodeId @0 :NodeID; # node id to locate
|
nodeId @0 :NodeID; # node id to locate
|
||||||
senderNodeInfo @1 :NodeInfo; # dial info for the node asking the question
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfo {
|
struct PeerInfo {
|
||||||
|
@ -4,39 +4,62 @@ use crate::intf::*;
|
|||||||
use crate::routing_table::*;
|
use crate::routing_table::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
struct DiscoveryContextInner {
|
||||||
|
network_class: Option<NetworkClass>,
|
||||||
|
// per-protocol
|
||||||
|
intf_addrs: Option<Vec<SocketAddress>>,
|
||||||
|
protocol_type: Option<ProtocolType>,
|
||||||
|
address_type: Option<AddressType>,
|
||||||
|
low_level_protocol_type: Option<ProtocolType>,
|
||||||
|
external1_dial_info: Option<DialInfo>,
|
||||||
|
external1: Option<SocketAddress>,
|
||||||
|
node_b: Option<NodeRef>,
|
||||||
|
}
|
||||||
|
|
||||||
struct DiscoveryContext {
|
struct DiscoveryContext {
|
||||||
routing_table: RoutingTable,
|
routing_table: RoutingTable,
|
||||||
external_ipv4: Option<Ipv4Addr>,
|
net: Network,
|
||||||
external_ipv6: Option<Ipv6Addr>,
|
inner: Arc<Mutex<DiscoveryContextInner>>,
|
||||||
network_class: Option<NetworkClass>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiscoveryContext {
|
impl DiscoveryContext {
|
||||||
pub fn new(routing_table: RoutingTable) -> Self {
|
pub fn new(routing_table: RoutingTable, net: Network) -> Self {
|
||||||
Self {
|
Self {
|
||||||
routing_table,
|
routing_table,
|
||||||
external_ipv4: None,
|
net,
|
||||||
external_ipv6: None,
|
inner: Arc::new(Mutex::new(DiscoveryContextInner {
|
||||||
network_class: None,
|
network_class: None,
|
||||||
|
// per-protocol
|
||||||
|
intf_addrs: None,
|
||||||
|
protocol_type: None,
|
||||||
|
address_type: None,
|
||||||
|
low_level_protocol_type: None,
|
||||||
|
external1_dial_info: None,
|
||||||
|
external1: None,
|
||||||
|
node_b: None,
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn upgrade_network_class(&mut self, network_class: NetworkClass) {
|
|
||||||
if let Some(old_nc) = self.network_class {
|
///////
|
||||||
|
// Utilities
|
||||||
|
xxxx continue converting to async safe inner
|
||||||
|
// Pick the best network class we have seen so far
|
||||||
|
pub fn upgrade_network_class(&self, network_class: NetworkClass) {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
|
||||||
|
if let Some(old_nc) = inner.network_class {
|
||||||
if network_class < old_nc {
|
if network_class < old_nc {
|
||||||
self.network_class = Some(network_class);
|
inner.network_class = Some(network_class);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.network_class = Some(network_class);
|
inner.network_class = Some(network_class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Network {
|
|
||||||
// Ask for a public address check from a particular noderef
|
// Ask for a public address check from a particular noderef
|
||||||
async fn request_public_address(&self, node_ref: NodeRef) -> Option<SocketAddress> {
|
async fn request_public_address(&self, node_ref: NodeRef) -> Option<SocketAddress> {
|
||||||
let routing_table = self.routing_table();
|
let rpc = self.routing_table.rpc_processor();
|
||||||
let rpc = routing_table.rpc_processor();
|
|
||||||
rpc.rpc_call_info(node_ref.clone())
|
rpc.rpc_call_info(node_ref.clone())
|
||||||
.await
|
.await
|
||||||
.map_err(logthru_net!(
|
.map_err(logthru_net!(
|
||||||
@ -54,11 +77,10 @@ impl Network {
|
|||||||
address_type: AddressType,
|
address_type: AddressType,
|
||||||
ignore_node: Option<DHTKey>,
|
ignore_node: Option<DHTKey>,
|
||||||
) -> Option<(SocketAddress, NodeRef)> {
|
) -> Option<(SocketAddress, NodeRef)> {
|
||||||
let routing_table = self.routing_table();
|
|
||||||
let filter = DialInfoFilter::global()
|
let filter = DialInfoFilter::global()
|
||||||
.with_protocol_type(protocol_type)
|
.with_protocol_type(protocol_type)
|
||||||
.with_address_type(address_type);
|
.with_address_type(address_type);
|
||||||
let peers = routing_table.find_fast_public_nodes_filtered(&filter);
|
let peers = self.routing_table.find_fast_public_nodes_filtered(&filter);
|
||||||
if peers.is_empty() {
|
if peers.is_empty() {
|
||||||
log_net!("no peers of type '{:?}'", filter);
|
log_net!("no peers of type '{:?}'", filter);
|
||||||
return None;
|
return None;
|
||||||
@ -82,12 +104,10 @@ impl Network {
|
|||||||
protocol_type: ProtocolType,
|
protocol_type: ProtocolType,
|
||||||
address_type: AddressType,
|
address_type: AddressType,
|
||||||
) -> Vec<SocketAddress> {
|
) -> Vec<SocketAddress> {
|
||||||
let routing_table = self.routing_table();
|
|
||||||
|
|
||||||
let filter = DialInfoFilter::local()
|
let filter = DialInfoFilter::local()
|
||||||
.with_protocol_type(protocol_type)
|
.with_protocol_type(protocol_type)
|
||||||
.with_address_type(address_type);
|
.with_address_type(address_type);
|
||||||
routing_table
|
self.routing_table
|
||||||
.dial_info_details(RoutingDomain::LocalNetwork)
|
.dial_info_details(RoutingDomain::LocalNetwork)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|did| {
|
.filter_map(|did| {
|
||||||
@ -107,8 +127,7 @@ impl Network {
|
|||||||
redirect: bool,
|
redirect: bool,
|
||||||
alternate_port: bool,
|
alternate_port: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let routing_table = self.routing_table();
|
let rpc = self.routing_table.rpc_processor();
|
||||||
let rpc = routing_table.rpc_processor();
|
|
||||||
rpc.rpc_call_validate_dial_info(node_ref.clone(), dial_info, redirect, alternate_port)
|
rpc.rpc_call_validate_dial_info(node_ref.clone(), dial_info, redirect, alternate_port)
|
||||||
.await
|
.await
|
||||||
.map_err(logthru_net!(
|
.map_err(logthru_net!(
|
||||||
@ -118,241 +137,287 @@ impl Network {
|
|||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_port_mapping<I: AsRef<[SocketAddress]>>(
|
async fn try_port_mapping(&mut self) -> Option<DialInfo> {
|
||||||
&self,
|
|
||||||
_intf_addrs: I,
|
|
||||||
_protocol_type: ProtocolType,
|
|
||||||
_address_type: AddressType,
|
|
||||||
) -> Option<SocketAddress> {
|
|
||||||
//xxx
|
//xxx
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
xxx split this routine up into helper routines that can be used by different protocols too.
|
fn make_dial_info(&self, addr: SocketAddress, protocol_type: ProtocolType) -> DialInfo {
|
||||||
|
match protocol_type {
|
||||||
|
ProtocolType::UDP => DialInfo::udp(addr),
|
||||||
|
ProtocolType::TCP => DialInfo::tcp(addr),
|
||||||
|
ProtocolType::WS => {
|
||||||
|
let c = self.net.config.get();
|
||||||
|
DialInfo::try_ws(
|
||||||
|
addr,
|
||||||
|
format!("ws://{}/{}", addr, c.network.protocol.ws.path),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
ProtocolType::WSS => panic!("none of the discovery functions are used for wss"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_udpv4_dialinfo(
|
///////
|
||||||
|
// Per-protocol discovery routines
|
||||||
|
|
||||||
|
pub fn protocol_begin(&mut self, protocol_type: ProtocolType, address_type: AddressType) {
|
||||||
|
// Get our interface addresses
|
||||||
|
self.intf_addrs = Some(self.get_local_addresses(protocol_type, address_type));
|
||||||
|
self.protocol_type = Some(protocol_type);
|
||||||
|
self.address_type = Some(address_type);
|
||||||
|
self.low_level_protocol_type = Some(match protocol_type {
|
||||||
|
ProtocolType::UDP => ProtocolType::UDP,
|
||||||
|
ProtocolType::TCP => ProtocolType::TCP,
|
||||||
|
ProtocolType::WS => ProtocolType::TCP,
|
||||||
|
ProtocolType::WSS => ProtocolType::TCP,
|
||||||
|
});
|
||||||
|
self.external1_dial_info = None;
|
||||||
|
self.external1 = None;
|
||||||
|
self.node_b = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn protocol_get_external_address_1(&mut self) -> bool {
|
||||||
|
let protocol_type = self.protocol_type.unwrap();
|
||||||
|
let address_type = self.address_type.unwrap();
|
||||||
|
|
||||||
|
// Get our external address from some fast node, call it node B
|
||||||
|
let (external1, node_b) = match self
|
||||||
|
.discover_external_address(protocol_type, address_type, None)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
// If we can't get an external address, exit but don't throw an error so we can try again later
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
let external1_dial_info = self.make_dial_info(external1, protocol_type);
|
||||||
|
|
||||||
|
self.external1_dial_info = Some(external1_dial_info);
|
||||||
|
self.external1 = Some(external1);
|
||||||
|
self.node_b = Some(node_b);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn protocol_process_no_nat(&mut self) {
|
||||||
|
let node_b = self.node_b.as_ref().unwrap().clone();
|
||||||
|
let external1_dial_info = self.external1_dial_info.as_ref().unwrap().clone();
|
||||||
|
let external1 = self.external1.unwrap();
|
||||||
|
let protocol_type = self.protocol_type.unwrap();
|
||||||
|
let address_type = self.address_type.unwrap();
|
||||||
|
let intf_addrs = self.intf_addrs.as_ref().unwrap();
|
||||||
|
|
||||||
|
// Do a validate_dial_info on the external address from a redirected node
|
||||||
|
if self
|
||||||
|
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Add public dial info with Direct dialinfo class
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external1_dial_info,
|
||||||
|
DialInfoClass::Direct,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Attempt a UDP port mapping via all available and enabled mechanisms
|
||||||
|
else if let Some(external_mapped_dial_info) = self.try_port_mapping().await {
|
||||||
|
// Got a port mapping, let's use it
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external_mapped_dial_info,
|
||||||
|
DialInfoClass::Mapped,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Add public dial info with Blocked dialinfo class
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external1_dial_info,
|
||||||
|
DialInfoClass::Blocked,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.upgrade_network_class(NetworkClass::InboundCapable);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn protocol_process_nat(&mut self) -> bool {
|
||||||
|
let node_b = self.node_b.as_ref().unwrap().clone();
|
||||||
|
let external1_dial_info = self.external1_dial_info.as_ref().unwrap().clone();
|
||||||
|
let external1 = self.external1.unwrap();
|
||||||
|
let protocol_type = self.protocol_type.unwrap();
|
||||||
|
let address_type = self.address_type.unwrap();
|
||||||
|
let intf_addrs = self.intf_addrs.as_ref().unwrap();
|
||||||
|
|
||||||
|
// Attempt a UDP port mapping via all available and enabled mechanisms
|
||||||
|
if let Some(external_mapped_dial_info) = self.try_port_mapping().await {
|
||||||
|
// Got a port mapping, let's use it
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external_mapped_dial_info,
|
||||||
|
DialInfoClass::Mapped,
|
||||||
|
);
|
||||||
|
self.upgrade_network_class(NetworkClass::InboundCapable);
|
||||||
|
|
||||||
|
// No more retries
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port mapping was not possible, let's see what kind of NAT we have
|
||||||
|
|
||||||
|
// Does a redirected dial info validation find us?
|
||||||
|
if self
|
||||||
|
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Yes, another machine can use the dial info directly, so Full Cone
|
||||||
|
// Add public dial info with full cone NAT network class
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external1_dial_info,
|
||||||
|
DialInfoClass::FullConeNAT,
|
||||||
|
);
|
||||||
|
self.upgrade_network_class(NetworkClass::InboundCapable);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No, we are restricted, determine what kind of restriction
|
||||||
|
|
||||||
|
// Get our external address from some fast node, that is not node B, call it node D
|
||||||
|
let (external2, node_d) = match self
|
||||||
|
.discover_external_address(protocol_type, address_type, Some(node_b.node_id()))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
// If we can't get an external address, allow retry
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we have two different external addresses, then this is a symmetric NAT
|
||||||
|
if external2 != external1 {
|
||||||
|
// Symmetric NAT is outbound only, no public dial info will work
|
||||||
|
self.upgrade_network_class(NetworkClass::OutboundOnly);
|
||||||
|
|
||||||
|
// No more retries
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're going to end up as a restricted NAT of some sort
|
||||||
|
|
||||||
|
// Address is the same, so it's address or port restricted
|
||||||
|
let external2_dial_info = DialInfo::udp(external2);
|
||||||
|
// Do a validate_dial_info on the external address from a routed node
|
||||||
|
if self
|
||||||
|
.validate_dial_info(node_d.clone(), external2_dial_info.clone(), false, true)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Got a reply from a non-default port, which means we're only address restricted
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external1_dial_info,
|
||||||
|
DialInfoClass::AddressRestrictedNAT,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Didn't get a reply from a non-default port, which means we are also port restricted
|
||||||
|
self.routing_table.register_dial_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
external1_dial_info,
|
||||||
|
DialInfoClass::PortRestrictedNAT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.upgrade_network_class(NetworkClass::InboundCapable);
|
||||||
|
|
||||||
|
// Allow another retry because sometimes trying again will get us Full Cone NAT instead
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Network {
|
||||||
|
pub async fn update_ipv4_protocol_dialinfo(
|
||||||
&self,
|
&self,
|
||||||
context: &mut DiscoveryContext,
|
context: &mut DiscoveryContext,
|
||||||
|
protocol_type: ProtocolType,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
log_net!("looking for udpv4 public dial info");
|
|
||||||
let routing_table = self.routing_table();
|
|
||||||
|
|
||||||
let mut retry_count = {
|
let mut retry_count = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
c.network.restricted_nat_retries
|
c.network.restricted_nat_retries
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get our interface addresses
|
// Start doing ipv4 protocol
|
||||||
let intf_addrs = self.get_local_addresses(ProtocolType::UDP, AddressType::IPV4);
|
context.protocol_begin(protocol_type, AddressType::IPV4);
|
||||||
|
|
||||||
// Loop for restricted NAT retries
|
// Loop for restricted NAT retries
|
||||||
loop {
|
loop {
|
||||||
// Get our external address from some fast node, call it node B
|
// Get our external address from some fast node, call it node B
|
||||||
let (external1, node_b) = match self
|
if !context.protocol_get_external_address_1().await {
|
||||||
.discover_external_address(ProtocolType::UDP, AddressType::IPV4, None)
|
// If we couldn't get an external address, then we should just try the whole network class detection again later
|
||||||
.await
|
return Ok(());
|
||||||
{
|
}
|
||||||
None => {
|
|
||||||
// If we can't get an external address, exit but don't throw an error so we can try again later
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
Some(v) => v,
|
|
||||||
};
|
|
||||||
let external1_dial_info = DialInfo::udp(external1);
|
|
||||||
|
|
||||||
// If our local interface list contains external1 then there is no NAT in place
|
// If our local interface list contains external1 then there is no NAT in place
|
||||||
if intf_addrs.contains(&external1) {
|
if context
|
||||||
|
.intf_addrs
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.contains(&context.external1.as_ref().unwrap())
|
||||||
|
{
|
||||||
// No NAT
|
// No NAT
|
||||||
// Do a validate_dial_info on the external address from a redirected node
|
context.protocol_process_no_nat().await;
|
||||||
if self
|
|
||||||
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Add public dial info with Direct dialinfo class
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external1_dial_info,
|
|
||||||
DialInfoClass::Direct,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Attempt a UDP port mapping via all available and enabled mechanisms
|
|
||||||
else if let Some(external_mapped) = self
|
|
||||||
.try_port_mapping(&intf_addrs, ProtocolType::UDP, AddressType::IPV4)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Got a port mapping, let's use it
|
|
||||||
let external_mapped_dial_info = DialInfo::udp(external_mapped);
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external_mapped_dial_info,
|
|
||||||
DialInfoClass::Mapped,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Add public dial info with Blocked dialinfo class
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external1_dial_info,
|
|
||||||
DialInfoClass::Blocked,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
context.upgrade_network_class(NetworkClass::InboundCapable);
|
|
||||||
// No more retries
|
// No more retries
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
// There is -some NAT-
|
|
||||||
// Attempt a UDP port mapping via all available and enabled mechanisms
|
|
||||||
if let Some(external_mapped) = self
|
|
||||||
.try_port_mapping(&intf_addrs, ProtocolType::UDP, AddressType::IPV4)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Got a port mapping, let's use it
|
|
||||||
let external_mapped_dial_info = DialInfo::udp(external_mapped);
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external_mapped_dial_info,
|
|
||||||
DialInfoClass::Mapped,
|
|
||||||
);
|
|
||||||
context.upgrade_network_class(NetworkClass::InboundCapable);
|
|
||||||
|
|
||||||
// No more retries
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// Port mapping was not possible, let's see what kind of NAT we have
|
|
||||||
|
|
||||||
// Does a redirected dial info validation find us?
|
|
||||||
if self
|
|
||||||
.validate_dial_info(
|
|
||||||
node_b.clone(),
|
|
||||||
external1_dial_info.clone(),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Yes, another machine can use the dial info directly, so Full Cone
|
|
||||||
// Add public dial info with full cone NAT network class
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external1_dial_info,
|
|
||||||
DialInfoClass::FullConeNAT,
|
|
||||||
);
|
|
||||||
context.upgrade_network_class(NetworkClass::InboundCapable);
|
|
||||||
|
|
||||||
// No more retries
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// No, we are restricted, determine what kind of restriction
|
|
||||||
|
|
||||||
// Get our external address from some fast node, that is not node B, call it node D
|
|
||||||
let (external2, node_d) = match self
|
|
||||||
.discover_external_address(
|
|
||||||
ProtocolType::UDP,
|
|
||||||
AddressType::IPV4,
|
|
||||||
Some(node_b.node_id()),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
None => {
|
|
||||||
// If we can't get an external address, exit but don't throw an error so we can try again later
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
Some(v) => v,
|
|
||||||
};
|
|
||||||
// If we have two different external addresses, then this is a symmetric NAT
|
|
||||||
if external2 != external1 {
|
|
||||||
// Symmetric NAT is outbound only, no public dial info will work
|
|
||||||
context.upgrade_network_class(NetworkClass::OutboundOnly);
|
|
||||||
|
|
||||||
// No more retries
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// If we're going to end up as a restricted NAT of some sort
|
|
||||||
// we should go through our retries before we assign a dial info
|
|
||||||
if retry_count == 0 {
|
|
||||||
// Address is the same, so it's address or port restricted
|
|
||||||
let external2_dial_info = DialInfo::udp(external2);
|
|
||||||
// Do a validate_dial_info on the external address from a routed node
|
|
||||||
if self
|
|
||||||
.validate_dial_info(
|
|
||||||
node_d.clone(),
|
|
||||||
external2_dial_info.clone(),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Got a reply from a non-default port, which means we're only address restricted
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external1_dial_info,
|
|
||||||
DialInfoClass::AddressRestrictedNAT,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Didn't get a reply from a non-default port, which means we are also port restricted
|
|
||||||
routing_table.register_dial_info(
|
|
||||||
RoutingDomain::PublicInternet,
|
|
||||||
external1_dial_info,
|
|
||||||
DialInfoClass::PortRestrictedNAT,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
context.upgrade_network_class(NetworkClass::InboundCapable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if retry_count == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
retry_count -= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There is -some NAT-
|
||||||
|
if context.protocol_process_nat().await {
|
||||||
|
// We either got dial info or a network class without one
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we tried everything, break anyway after N attempts
|
||||||
|
if retry_count == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retry_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx should verify hole punch capable somehow and switch to outbound-only if hole punch can't work
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_tcpv4_dialinfo(
|
pub async fn update_ipv6_protocol_dialinfo(
|
||||||
&self,
|
&self,
|
||||||
context: &mut DiscoveryContext,
|
context: &mut DiscoveryContext,
|
||||||
|
protocol_type: ProtocolType,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
log_net!("looking for tcpv4 public dial info");
|
// Start doing ipv6 protocol
|
||||||
|
context.protocol_begin(protocol_type, AddressType::IPV6);
|
||||||
|
|
||||||
Ok(())
|
// Get our external address from some fast node, call it node B
|
||||||
}
|
if !context.protocol_get_external_address_1().await {
|
||||||
|
// If we couldn't get an external address, then we should just try the whole network class detection again later
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_wsv4_dialinfo(&self, context: &mut DiscoveryContext) -> Result<(), String> {
|
// If our local interface list doesn't contain external1 then there is an Ipv6 NAT in place
|
||||||
log_net!("looking for wsv4 public dial info");
|
if !context
|
||||||
// xxx
|
.intf_addrs
|
||||||
//Err("unimplemented".to_owned())
|
.as_ref()
|
||||||
Ok(())
|
.unwrap()
|
||||||
}
|
.contains(&context.external1.as_ref().unwrap())
|
||||||
|
{
|
||||||
|
// IPv6 NAT is not supported today
|
||||||
|
log_net!(warn
|
||||||
|
"IPv6 NAT is not supported for external address: {}",
|
||||||
|
context.external1.unwrap()
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_udpv6_dialinfo(
|
// No NAT
|
||||||
&self,
|
context.protocol_process_no_nat().await;
|
||||||
context: &mut DiscoveryContext,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
log_net!("looking for udpv6 public dial info");
|
|
||||||
// xxx
|
|
||||||
//Err("unimplemented".to_owned())
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_tcpv6_dialinfo(
|
|
||||||
&self,
|
|
||||||
context: &mut DiscoveryContext,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
log_net!("looking for tcpv6 public dial info");
|
|
||||||
// xxx
|
|
||||||
//Err("unimplemented".to_owned())
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_wsv6_dialinfo(&self, context: &mut DiscoveryContext) -> Result<(), String> {
|
|
||||||
log_net!("looking for wsv6 public dial info");
|
|
||||||
// xxx
|
|
||||||
//Err("unimplemented".to_owned())
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,21 +431,27 @@ impl Network {
|
|||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut context = DiscoveryContext::default();
|
let context = DiscoveryContext::new(self.routing_table(), self.clone());
|
||||||
|
|
||||||
if protocol_config.inbound.contains(ProtocolType::UDP) {
|
if protocol_config.inbound.contains(ProtocolType::UDP) {
|
||||||
self.update_udpv4_dialinfo(&mut context).await?;
|
self.update_ipv4_protocol_dialinfo(&mut context, ProtocolType::UDP)
|
||||||
self.update_udpv6_dialinfo(&mut context).await?;
|
.await?;
|
||||||
|
self.update_ipv6_protocol_dialinfo(&mut context, ProtocolType::UDP)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if protocol_config.inbound.contains(ProtocolType::TCP) {
|
if protocol_config.inbound.contains(ProtocolType::TCP) {
|
||||||
self.update_tcpv4_dialinfo(&mut context).await?;
|
self.update_ipv4_protocol_dialinfo(&mut context, ProtocolType::TCP)
|
||||||
self.update_tcpv6_dialinfo(&mut context).await?;
|
.await?;
|
||||||
|
self.update_ipv6_protocol_dialinfo(&mut context, ProtocolType::TCP)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if protocol_config.inbound.contains(ProtocolType::WS) {
|
if protocol_config.inbound.contains(ProtocolType::WS) {
|
||||||
self.update_wsv4_dialinfo(&mut context).await?;
|
self.update_ipv4_protocol_dialinfo(&mut context, ProtocolType::WS)
|
||||||
self.update_wsv6_dialinfo(&mut context).await?;
|
.await?;
|
||||||
|
self.update_ipv6_protocol_dialinfo(&mut context, ProtocolType::WS)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.lock().network_class = context.network_class;
|
self.inner.lock().network_class = context.network_class;
|
||||||
|
@ -299,7 +299,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
pdi.clone(),
|
pdi.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
|
|
||||||
// See if this public address is also a local interface address
|
// See if this public address is also a local interface address
|
||||||
@ -345,7 +345,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
DialInfo::udp_from_socketaddr(pdi_addr),
|
DialInfo::udp_from_socketaddr(pdi_addr),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
pdi.clone(),
|
pdi.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
pdi,
|
pdi,
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +469,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
local_di.clone(),
|
local_di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
}
|
}
|
||||||
@ -478,7 +478,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
local_di,
|
local_di,
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,7 +561,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
pdi.clone(),
|
pdi.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
|
|
||||||
@ -579,7 +579,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
pdi,
|
pdi,
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,7 +646,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
}
|
}
|
||||||
@ -654,7 +654,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
di.clone(),
|
di.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
registered_addresses.insert(socket_address.to_ip_addr());
|
registered_addresses.insert(socket_address.to_ip_addr());
|
||||||
}
|
}
|
||||||
@ -678,7 +678,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::PublicInternet,
|
RoutingDomain::PublicInternet,
|
||||||
pdi.clone(),
|
pdi.clone(),
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
static_public = true;
|
static_public = true;
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ impl Network {
|
|||||||
routing_table.register_dial_info(
|
routing_table.register_dial_info(
|
||||||
RoutingDomain::LocalNetwork,
|
RoutingDomain::LocalNetwork,
|
||||||
pdi,
|
pdi,
|
||||||
DialInfoOrigin::Static,
|
DialInfoClass::Direct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,13 +363,13 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Get our node's capabilities
|
// Get our node's capabilities
|
||||||
pub fn generate_node_status(&self) -> NodeStatus {
|
pub fn generate_node_status(&self) -> NodeStatus {
|
||||||
let network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
|
let peer_info = self.routing_table().get_own_peer_info();
|
||||||
|
|
||||||
let will_route = network_class.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
let will_route = peer_info.node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
|
||||||
let will_tunnel = network_class.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
let will_tunnel = peer_info.node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
|
||||||
let will_signal = network_class.can_signal();
|
let will_signal = peer_info.node_info.can_signal();
|
||||||
let will_relay = network_class.can_inbound_relay();
|
let will_relay = peer_info.node_info.can_inbound_relay();
|
||||||
let will_validate_dial_info = network_class.can_validate_dial_info();
|
let will_validate_dial_info = peer_info.node_info.can_validate_dial_info();
|
||||||
|
|
||||||
NodeStatus {
|
NodeStatus {
|
||||||
will_route,
|
will_route,
|
||||||
@ -500,20 +500,23 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// Get the udp direct dialinfo for the hole punch
|
// Get the udp direct dialinfo for the hole punch
|
||||||
peer_nr.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
|
peer_nr.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
|
||||||
let hole_punch_dial_info = peer_nr
|
let hole_punch_dial_info_detail = peer_nr
|
||||||
.first_filtered_dial_info()
|
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
||||||
.ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?;
|
.ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?;
|
||||||
|
|
||||||
// Do our half of the hole punch by sending an empty packet
|
// Do our half of the hole punch by sending an empty packet
|
||||||
// Both sides will do this and then the receipt will get sent over the punched hole
|
// Both sides will do this and then the receipt will get sent over the punched hole
|
||||||
self.net()
|
self.net()
|
||||||
.send_data_to_dial_info(hole_punch_dial_info.clone(), Vec::new())
|
.send_data_to_dial_info(
|
||||||
|
hole_punch_dial_info_detail.dial_info.clone(),
|
||||||
|
Vec::new(),
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// XXX: do we need a delay here? or another hole punch packet?
|
// XXX: do we need a delay here? or another hole punch packet?
|
||||||
|
|
||||||
// Return the receipt over the direct channel since we want to use exactly the same dial info
|
// Return the receipt over the direct channel since we want to use exactly the same dial info
|
||||||
self.send_direct_receipt(hole_punch_dial_info, receipt, false)
|
self.send_direct_receipt(hole_punch_dial_info_detail.dial_info, receipt, false)
|
||||||
.await
|
.await
|
||||||
.map_err(map_to_string)?;
|
.map_err(map_to_string)?;
|
||||||
}
|
}
|
||||||
@ -623,57 +626,88 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out how to reach a node
|
// Figure out how to reach a node
|
||||||
fn get_contact_method(&self, node_ref: NodeRef) -> Result<ContactMethod, String> {
|
fn get_contact_method(&self, target_node_ref: NodeRef) -> Result<ContactMethod, String> {
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
// Get our network class and protocol config
|
// Get our network class and protocol config
|
||||||
let our_network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
|
let our_network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
|
||||||
let our_protocol_config = self.get_protocol_config().unwrap();
|
let our_protocol_config = self.get_protocol_config().unwrap();
|
||||||
|
|
||||||
// Scope noderef down to protocols we can do outbound
|
// Scope noderef down to protocols we can do outbound
|
||||||
if !node_ref.filter_protocols(our_protocol_config.outbound) {
|
if !target_node_ref.filter_protocols(our_protocol_config.outbound) {
|
||||||
return Ok(ContactMethod::Unreachable);
|
return Ok(ContactMethod::Unreachable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the best matching direct dial info if we have it
|
// Get the best matching local direct dial info if we have it
|
||||||
let opt_direct_dial_info = node_ref.first_filtered_dial_info();
|
let opt_local_did =
|
||||||
|
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::LocalNetwork));
|
||||||
// See if this is a local node reachable directly
|
if let Some(local_did) = opt_local_did {
|
||||||
if let Some(direct_dial_info) = opt_direct_dial_info {
|
return Ok(ContactMethod::Direct(local_did.dial_info));
|
||||||
if direct_dial_info.is_local() {
|
|
||||||
return Ok(ContactMethod::Direct(direct_dial_info));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the best match internet dial info if we have it
|
||||||
|
let opt_public_did =
|
||||||
|
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet));
|
||||||
|
|
||||||
// Can the target node do inbound?
|
// Can the target node do inbound?
|
||||||
let target_network_class = node_ref.network_class();
|
let target_network_class = target_node_ref.network_class();
|
||||||
if target_network_class.inbound_capable() {
|
//if matches!(target_network_class, NetworkClass::InboundCapable) {
|
||||||
|
if let Some(public_did) = opt_public_did {
|
||||||
// Do we need to signal before going inbound?
|
// Do we need to signal before going inbound?
|
||||||
if target_network_class.inbound_requires_signal() {
|
if public_did.class.requires_signal() {
|
||||||
// Get the target's inbound relay, it must have one or it is not reachable
|
// Get the target's inbound relay, it must have one or it is not reachable
|
||||||
if let Some(inbound_relay_nr) = node_ref.relay() {
|
if let Some(inbound_relay_nr) = target_node_ref.relay() {
|
||||||
// Can we reach the inbound relay?
|
// Can we reach the inbound relay?
|
||||||
if inbound_relay_nr.first_filtered_dial_info().is_some() {
|
if inbound_relay_nr
|
||||||
|
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
// Can we receive anything inbound ever?
|
// Can we receive anything inbound ever?
|
||||||
if our_network_class.inbound_capable() {
|
if matches!(our_network_class, NetworkClass::InboundCapable) {
|
||||||
// Can we receive a direct reverse connection?
|
// Get the best match dial info for an reverse inbound connection
|
||||||
if !our_network_class.inbound_requires_signal() {
|
let reverse_dif = DialInfoFilter::global()
|
||||||
return Ok(ContactMethod::SignalReverse(
|
.with_protocol_set(target_node_ref.outbound_protocols());
|
||||||
inbound_relay_nr,
|
if let Some(reverse_did) = routing_table
|
||||||
node_ref,
|
.first_filtered_dial_info_detail(
|
||||||
));
|
RoutingDomain::PublicInternet,
|
||||||
}
|
&reverse_dif,
|
||||||
// Can we hole-punch?
|
)
|
||||||
else if our_protocol_config.inbound.contains(ProtocolType::UDP)
|
|
||||||
&& node_ref.outbound_protocols().contains(ProtocolType::UDP)
|
|
||||||
{
|
{
|
||||||
let udp_inbound_relay_nr = inbound_relay_nr.clone();
|
// Can we receive a direct reverse connection?
|
||||||
let udp_target_nr = node_ref.clone();
|
if !reverse_did.class.requires_signal() {
|
||||||
let can_reach_inbound_relay = udp_inbound_relay_nr
|
return Ok(ContactMethod::SignalReverse(
|
||||||
|
inbound_relay_nr,
|
||||||
|
target_node_ref,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does we and the target have outbound protocols to hole-punch?
|
||||||
|
if our_protocol_config.outbound.contains(ProtocolType::UDP)
|
||||||
|
&& target_node_ref
|
||||||
|
.outbound_protocols()
|
||||||
|
.contains(ProtocolType::UDP)
|
||||||
|
{
|
||||||
|
// Do the target and self nodes have a direct udp dialinfo
|
||||||
|
let udp_dif =
|
||||||
|
DialInfoFilter::global().with_protocol_type(ProtocolType::UDP);
|
||||||
|
let udp_target_nr = target_node_ref.clone();
|
||||||
|
udp_target_nr
|
||||||
.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
|
.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
|
||||||
let can_reach_target = udp_target_nr
|
let target_has_udp_dialinfo = target_node_ref
|
||||||
.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
|
.first_filtered_dial_info_detail(Some(
|
||||||
if can_reach_inbound_relay && can_reach_target {
|
RoutingDomain::PublicInternet,
|
||||||
|
))
|
||||||
|
.is_some();
|
||||||
|
let self_has_udp_dialinfo = routing_table
|
||||||
|
.first_filtered_dial_info_detail(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
&udp_dif,
|
||||||
|
)
|
||||||
|
.is_some();
|
||||||
|
if target_has_udp_dialinfo && self_has_udp_dialinfo {
|
||||||
return Ok(ContactMethod::SignalHolePunch(
|
return Ok(ContactMethod::SignalHolePunch(
|
||||||
udp_inbound_relay_nr,
|
inbound_relay_nr,
|
||||||
udp_target_nr,
|
udp_target_nr,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -688,15 +722,18 @@ impl NetworkManager {
|
|||||||
// Go direct without signaling
|
// Go direct without signaling
|
||||||
else {
|
else {
|
||||||
// If we have direct dial info we can use, do it
|
// If we have direct dial info we can use, do it
|
||||||
if let Some(ddi) = opt_direct_dial_info {
|
if let Some(did) = opt_public_did {
|
||||||
return Ok(ContactMethod::Direct(ddi));
|
return Ok(ContactMethod::Direct(did.dial_info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the other node is not inbound capable at all, it is using a full relay
|
// If the other node is not inbound capable at all, it is using a full relay
|
||||||
if let Some(target_inbound_relay_nr) = node_ref.relay() {
|
if let Some(target_inbound_relay_nr) = target_node_ref.relay() {
|
||||||
// Can we reach the full relay?
|
// Can we reach the full relay?
|
||||||
if target_inbound_relay_nr.first_filtered_dial_info().is_some() {
|
if target_inbound_relay_nr
|
||||||
|
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
return Ok(ContactMethod::InboundRelay(target_inbound_relay_nr));
|
return Ok(ContactMethod::InboundRelay(target_inbound_relay_nr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -806,14 +843,14 @@ impl NetworkManager {
|
|||||||
let peer_info = self.routing_table().get_own_peer_info();
|
let peer_info = self.routing_table().get_own_peer_info();
|
||||||
|
|
||||||
// Get the udp direct dialinfo for the hole punch
|
// Get the udp direct dialinfo for the hole punch
|
||||||
let hole_punch_dial_info = target_nr
|
let hole_punch_did = target_nr
|
||||||
.first_filtered_dial_info()
|
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
|
||||||
.ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?;
|
.ok_or_else(|| "No hole punch capable dialinfo found for node".to_owned())?;
|
||||||
|
|
||||||
// Do our half of the hole punch by sending an empty packet
|
// Do our half of the hole punch by sending an empty packet
|
||||||
// Both sides will do this and then the receipt will get sent over the punched hole
|
// Both sides will do this and then the receipt will get sent over the punched hole
|
||||||
self.net()
|
self.net()
|
||||||
.send_data_to_dial_info(hole_punch_dial_info, Vec::new())
|
.send_data_to_dial_info(hole_punch_did.dial_info, Vec::new())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Issue the signal
|
// Issue the signal
|
||||||
@ -1070,47 +1107,49 @@ impl NetworkManager {
|
|||||||
async fn relay_management_task_routine(self, _last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
async fn relay_management_task_routine(self, _last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
||||||
log_net!("--- network manager relay_management task");
|
log_net!("--- network manager relay_management task");
|
||||||
|
|
||||||
// Get our node's current network class and do the right thing
|
// Get our node's current node info and network class and do the right thing
|
||||||
|
let routing_table = self.routing_table();
|
||||||
|
let node_info = routing_table.get_own_peer_info().node_info;
|
||||||
let network_class = self.get_network_class();
|
let network_class = self.get_network_class();
|
||||||
|
|
||||||
// Do we know our network class yet?
|
// Do we know our network class yet?
|
||||||
if let Some(network_class) = network_class {
|
if let Some(network_class) = network_class {
|
||||||
let routing_table = self.routing_table();
|
|
||||||
|
|
||||||
// If we already have a relay, see if it is dead, or if we don't need it any more
|
// If we already have a relay, see if it is dead, or if we don't need it any more
|
||||||
{
|
{
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
if let Some(relay_node) = inner.relay_node.clone() {
|
if let Some(relay_node) = inner.relay_node.clone() {
|
||||||
let state = relay_node.operate(|e| e.state(cur_ts));
|
let state = relay_node.operate(|e| e.state(cur_ts));
|
||||||
if matches!(state, BucketEntryState::Dead) || !network_class.needs_relay() {
|
if matches!(state, BucketEntryState::Dead) || !node_info.requires_relay() {
|
||||||
// Relay node is dead or no longer needed
|
// Relay node is dead or no longer needed
|
||||||
inner.relay_node = None;
|
inner.relay_node = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we need an outbound relay?
|
// Do we need a relay?
|
||||||
if network_class.outbound_wants_relay() {
|
if node_info.requires_relay() {
|
||||||
// The outbound relay is the host of the PWA
|
// Do we need an outbound relay?
|
||||||
if let Some(outbound_relay_peerinfo) = intf::get_outbound_relay_peer().await {
|
if network_class.outbound_wants_relay() {
|
||||||
let mut inner = self.inner.lock();
|
// The outbound relay is the host of the PWA
|
||||||
|
if let Some(outbound_relay_peerinfo) = intf::get_outbound_relay_peer().await {
|
||||||
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
// Register new outbound relay
|
// Register new outbound relay
|
||||||
let nr = routing_table.register_node_with_node_info(
|
let nr = routing_table.register_node_with_node_info(
|
||||||
outbound_relay_peerinfo.node_id.key,
|
outbound_relay_peerinfo.node_id.key,
|
||||||
outbound_relay_peerinfo.node_info,
|
outbound_relay_peerinfo.node_info,
|
||||||
)?;
|
)?;
|
||||||
inner.relay_node = Some(nr);
|
inner.relay_node = Some(nr);
|
||||||
}
|
}
|
||||||
} else if network_class.needs_relay() {
|
// Otherwise we must need an inbound relay
|
||||||
// Find a node in our routing table that is an acceptable inbound relay
|
} else {
|
||||||
if let Some(nr) = routing_table.find_inbound_relay(cur_ts) {
|
// Find a node in our routing table that is an acceptable inbound relay
|
||||||
let mut inner = self.inner.lock();
|
if let Some(nr) = routing_table.find_inbound_relay(cur_ts) {
|
||||||
inner.relay_node = Some(nr);
|
let mut inner = self.inner.lock();
|
||||||
|
inner.relay_node = Some(nr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If we don't know our network class, we do nothing here and wait until we do
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1208,14 +1247,11 @@ impl NetworkManager {
|
|||||||
.global_address_check_cache
|
.global_address_check_cache
|
||||||
.insert(reporting_peer.node_id(), socket_address);
|
.insert(reporting_peer.node_id(), socket_address);
|
||||||
|
|
||||||
let network_class = inner
|
let net = inner.components.as_ref().unwrap().net.clone();
|
||||||
.components
|
|
||||||
.unwrap()
|
|
||||||
.net
|
|
||||||
.get_network_class()
|
|
||||||
.unwrap_or(NetworkClass::Invalid);
|
|
||||||
|
|
||||||
if network_class.inbound_capable() {
|
let network_class = net.get_network_class().unwrap_or(NetworkClass::Invalid);
|
||||||
|
|
||||||
|
if matches!(network_class, NetworkClass::InboundCapable) {
|
||||||
// If we are inbound capable, but start to see inconsistent socket addresses from multiple reporting peers
|
// If we are inbound capable, but start to see inconsistent socket addresses from multiple reporting peers
|
||||||
// then we zap the network class and re-detect it
|
// then we zap the network class and re-detect it
|
||||||
|
|
||||||
@ -1225,7 +1261,7 @@ impl NetworkManager {
|
|||||||
// If we are currently outbound only, we don't have any public dial info
|
// If we are currently outbound only, we don't have any public dial info
|
||||||
// but if we are starting to see consistent socket address from multiple reporting peers
|
// but if we are starting to see consistent socket address from multiple reporting peers
|
||||||
// then we may be become inbound capable, so zap the network class so we can re-detect it and any public dial info
|
// then we may be become inbound capable, so zap the network class so we can re-detect it and any public dial info
|
||||||
inner.components.unwrap().net.reset_network_class();
|
net.reset_network_class();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,8 +209,8 @@ impl RoutingTable {
|
|||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
|
|
||||||
if domain == None || domain == Some(RoutingDomain::Local) {
|
if domain == None || domain == Some(RoutingDomain::LocalNetwork) {
|
||||||
Self::with_routing_domain(&*inner, RoutingDomain::Local, |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) {
|
||||||
ret.push(did.clone());
|
ret.push(did.clone());
|
||||||
@ -261,6 +261,7 @@ impl RoutingTable {
|
|||||||
dial_info: dial_info.clone(),
|
dial_info: dial_info.clone(),
|
||||||
class,
|
class,
|
||||||
});
|
});
|
||||||
|
rd.dial_info_details.sort();
|
||||||
});
|
});
|
||||||
|
|
||||||
let domain_str = match domain {
|
let domain_str = match domain {
|
||||||
@ -520,7 +521,7 @@ impl RoutingTable {
|
|||||||
Destination::Direct(node_ref.clone()),
|
Destination::Direct(node_ref.clone()),
|
||||||
node_id,
|
node_id,
|
||||||
None,
|
None,
|
||||||
rpc_processor.get_respond_to_sender(node_ref.clone()),
|
rpc_processor.make_respond_to_sender(node_ref.clone()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
@ -613,7 +614,7 @@ impl RoutingTable {
|
|||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
.push(DialInfoDetail {
|
.push(DialInfoDetail {
|
||||||
dial_info: ndis.dial_info,
|
dial_info: ndis.dial_info,
|
||||||
class: DialInfoClass::Direct,
|
class: DialInfoClass::Direct, // Bootstraps are always directly reachable
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
log_rtab!(" bootstrap list: {:?}", bsmap);
|
log_rtab!(" bootstrap list: {:?}", bsmap);
|
||||||
@ -626,7 +627,7 @@ impl RoutingTable {
|
|||||||
.register_node_with_node_info(
|
.register_node_with_node_info(
|
||||||
k,
|
k,
|
||||||
NodeInfo {
|
NodeInfo {
|
||||||
network_class: NetworkClass::Server, // Bootstraps are always full servers
|
network_class: NetworkClass::InboundCapable, // Bootstraps are always inbound capable
|
||||||
outbound_protocols: ProtocolSet::empty(), // Bootstraps do not participate in relaying and will not make outbound requests
|
outbound_protocols: ProtocolSet::empty(), // Bootstraps do not participate in relaying and will not make outbound requests
|
||||||
dial_info_detail_list: v, // Dial info is as specified in the bootstrap list
|
dial_info_detail_list: v, // Dial info is as specified in the bootstrap list
|
||||||
relay_peer_info: None, // Bootstraps never require a relay themselves
|
relay_peer_info: None, // Bootstraps never require a relay themselves
|
||||||
|
@ -6,7 +6,7 @@ pub fn encode_dial_info_detail(
|
|||||||
builder: &mut veilid_capnp::dial_info_detail::Builder,
|
builder: &mut veilid_capnp::dial_info_detail::Builder,
|
||||||
) -> Result<(), RPCError> {
|
) -> Result<(), RPCError> {
|
||||||
let mut di_builder = builder.reborrow().init_dial_info();
|
let mut di_builder = builder.reborrow().init_dial_info();
|
||||||
encode_dial_info(&node_info.dial_info, &mut di_builder)?;
|
encode_dial_info(&dial_info_detail.dial_info, &mut di_builder)?;
|
||||||
|
|
||||||
builder.set_class(encode_dial_info_class(dial_info_detail.class));
|
builder.set_class(encode_dial_info_class(dial_info_detail.class));
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -22,7 +22,7 @@ pub fn decode_dial_info_detail(
|
|||||||
.map_err(map_error_capnp_error!())?,
|
.map_err(map_error_capnp_error!())?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let dial_info_class = decode_dial_info_class(
|
let class = decode_dial_info_class(
|
||||||
reader
|
reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_class()
|
.get_class()
|
||||||
|
@ -2,26 +2,17 @@ use crate::*;
|
|||||||
|
|
||||||
pub fn encode_network_class(network_class: NetworkClass) -> veilid_capnp::NetworkClass {
|
pub fn encode_network_class(network_class: NetworkClass) -> veilid_capnp::NetworkClass {
|
||||||
match network_class {
|
match network_class {
|
||||||
NetworkClass::Server => veilid_capnp::NetworkClass::Server,
|
NetworkClass::InboundCapable => veilid_capnp::NetworkClass::InboundCapable,
|
||||||
NetworkClass::Mapped => veilid_capnp::NetworkClass::Mapped,
|
|
||||||
NetworkClass::FullConeNAT => veilid_capnp::NetworkClass::FullConeNAT,
|
|
||||||
NetworkClass::AddressRestrictedNAT => veilid_capnp::NetworkClass::AddressRestrictedNAT,
|
|
||||||
NetworkClass::PortRestrictedNAT => veilid_capnp::NetworkClass::PortRestrictedNAT,
|
|
||||||
NetworkClass::OutboundOnly => veilid_capnp::NetworkClass::OutboundOnly,
|
NetworkClass::OutboundOnly => veilid_capnp::NetworkClass::OutboundOnly,
|
||||||
NetworkClass::WebApp => veilid_capnp::NetworkClass::WebApp,
|
NetworkClass::WebApp => veilid_capnp::NetworkClass::WebApp,
|
||||||
NetworkClass::Invalid => veilid_capnp::NetworkClass::Invalid,
|
NetworkClass::Invalid => panic!("invalid network class should not be encoded"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_network_class(network_class: veilid_capnp::NetworkClass) -> NetworkClass {
|
pub fn decode_network_class(network_class: veilid_capnp::NetworkClass) -> NetworkClass {
|
||||||
match network_class {
|
match network_class {
|
||||||
veilid_capnp::NetworkClass::Server => NetworkClass::Server,
|
veilid_capnp::NetworkClass::InboundCapable => NetworkClass::InboundCapable,
|
||||||
veilid_capnp::NetworkClass::Mapped => NetworkClass::Mapped,
|
|
||||||
veilid_capnp::NetworkClass::FullConeNAT => NetworkClass::FullConeNAT,
|
|
||||||
veilid_capnp::NetworkClass::AddressRestrictedNAT => NetworkClass::AddressRestrictedNAT,
|
|
||||||
veilid_capnp::NetworkClass::PortRestrictedNAT => NetworkClass::PortRestrictedNAT,
|
|
||||||
veilid_capnp::NetworkClass::OutboundOnly => NetworkClass::OutboundOnly,
|
veilid_capnp::NetworkClass::OutboundOnly => NetworkClass::OutboundOnly,
|
||||||
veilid_capnp::NetworkClass::WebApp => NetworkClass::WebApp,
|
veilid_capnp::NetworkClass::WebApp => NetworkClass::WebApp,
|
||||||
veilid_capnp::NetworkClass::Invalid => NetworkClass::Invalid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,14 +55,14 @@ pub fn decode_node_info(
|
|||||||
.reborrow()
|
.reborrow()
|
||||||
.get_dial_info_detail_list()
|
.get_dial_info_detail_list()
|
||||||
.map_err(map_error_capnp_error!())?;
|
.map_err(map_error_capnp_error!())?;
|
||||||
let mut dial_info_detail_list = Vec::<DialInfo>::with_capacity(
|
let mut dial_info_detail_list = Vec::<DialInfoDetail>::with_capacity(
|
||||||
didl_reader
|
didl_reader
|
||||||
.len()
|
.len()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(map_error_protocol!("too many dial info details"))?,
|
.map_err(map_error_protocol!("too many dial info details"))?,
|
||||||
);
|
);
|
||||||
for di in dil_reader.iter() {
|
for did in didl_reader.iter() {
|
||||||
dial_info_detail_list.push(decode_dial_info_detail(&di)?)
|
dial_info_detail_list.push(decode_dial_info_detail(&did)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
let relay_peer_info = if allow_relay_peer_info {
|
let relay_peer_info = if allow_relay_peer_info {
|
||||||
|
@ -204,26 +204,8 @@ impl RPCProcessor {
|
|||||||
return format!("(invalid node id: {})", e);
|
return format!("(invalid node id: {})", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sni_reader = match fnqr.reborrow().get_sender_node_info() {
|
|
||||||
Ok(snir) => snir,
|
|
||||||
Err(e) => {
|
|
||||||
return format!("(invalid sender node info: {})", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let sender_node_info = match decode_node_info(&sni_reader, true) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
return format!("(unable to decode node info: {})", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let node_id = decode_public_key(&nidr);
|
let node_id = decode_public_key(&nidr);
|
||||||
format!(
|
format!("FindNodeQ: node_id={}", node_id.encode(),)
|
||||||
"FindNodeQ: node_id={} sender_node_info={:#?}",
|
|
||||||
node_id.encode(),
|
|
||||||
sender_node_info
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
veilid_capnp::operation::detail::FindNodeA(d) => {
|
veilid_capnp::operation::detail::FindNodeA(d) => {
|
||||||
let fnar = match d {
|
let fnar = match d {
|
||||||
@ -236,7 +218,7 @@ impl RPCProcessor {
|
|||||||
let p_reader = match fnar.reborrow().get_peers() {
|
let p_reader = match fnar.reborrow().get_peers() {
|
||||||
Ok(pr) => pr,
|
Ok(pr) => pr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return format!("(invalid sender node info: {})", e);
|
return format!("(invalid peers: {})", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut peers = Vec::<PeerInfo>::with_capacity(match p_reader.len().try_into() {
|
let mut peers = Vec::<PeerInfo>::with_capacity(match p_reader.len().try_into() {
|
||||||
|
@ -213,22 +213,22 @@ impl RPCProcessor {
|
|||||||
get_random_u64()
|
get_random_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_peer_scope(&self, peer_info: &PeerInfo) -> bool {
|
fn filter_peer_scope(&self, node_info: &NodeInfo) -> bool {
|
||||||
// if local peer scope is enabled, then don't reject any peer info
|
// if local peer scope is enabled, then don't reject any peer info
|
||||||
if self.enable_local_peer_scope {
|
if self.enable_local_peer_scope {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject attempts to include non-public addresses in results
|
// reject attempts to include non-public addresses in results
|
||||||
for di in &peer_info.node_info.dial_info_list {
|
for did in &node_info.dial_info_detail_list {
|
||||||
if !di.is_global() {
|
if !did.dial_info.is_global() {
|
||||||
// non-public address causes rejection
|
// non-public address causes rejection
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(rpi) = &peer_info.node_info.relay_peer_info {
|
if let Some(rpi) = &node_info.relay_peer_info {
|
||||||
for di in &rpi.node_info.dial_info_list {
|
for did in &rpi.node_info.dial_info_detail_list {
|
||||||
if !di.is_global() {
|
if !did.dial_info.is_global() {
|
||||||
// non-public address causes rejection
|
// non-public address causes rejection
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -964,26 +964,8 @@ impl RPCProcessor {
|
|||||||
.map_err(logthru_rpc!())?,
|
.map_err(logthru_rpc!())?,
|
||||||
);
|
);
|
||||||
|
|
||||||
// get the sender NodeInfo of the requesting node
|
|
||||||
let sni_reader = fnq_reader
|
|
||||||
.reborrow()
|
|
||||||
.get_sender_node_info()
|
|
||||||
.map_err(map_error_capnp_error!())?;
|
|
||||||
let peer_info = PeerInfo {
|
|
||||||
node_id: NodeId::new(rpcreader.header.envelope.get_sender_id()),
|
|
||||||
node_info: decode_node_info(&sni_reader, true)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
// filter out attempts to pass non-public addresses in for peers
|
|
||||||
if !self.filter_peer_scope(&peer_info) {
|
|
||||||
return Err(RPCError::InvalidFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add node information for the requesting node to our routing table
|
// add node information for the requesting node to our routing table
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
let _requesting_node_ref = routing_table
|
|
||||||
.register_node_with_node_info(peer_info.node_id.key, peer_info.node_info)
|
|
||||||
.map_err(map_error_string!())?;
|
|
||||||
|
|
||||||
// find N nodes closest to the target node in our routing table
|
// find N nodes closest to the target node in our routing table
|
||||||
let own_peer_info = routing_table.get_own_peer_info();
|
let own_peer_info = routing_table.get_own_peer_info();
|
||||||
@ -1192,6 +1174,9 @@ impl RPCProcessor {
|
|||||||
opt_sender_nr =
|
opt_sender_nr =
|
||||||
if let Some(sender_ni) = self.get_respond_to_sender_node_info(&operation)? {
|
if let Some(sender_ni) = self.get_respond_to_sender_node_info(&operation)? {
|
||||||
// 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) {
|
||||||
|
return Err(RPCError::InvalidFormat);
|
||||||
|
}
|
||||||
let nr = self
|
let nr = self
|
||||||
.routing_table()
|
.routing_table()
|
||||||
.register_node_with_node_info(
|
.register_node_with_node_info(
|
||||||
@ -1544,11 +1529,6 @@ impl RPCProcessor {
|
|||||||
let mut node_id_builder = fnq.reborrow().init_node_id();
|
let mut node_id_builder = fnq.reborrow().init_node_id();
|
||||||
encode_public_key(&key, &mut node_id_builder)?;
|
encode_public_key(&key, &mut node_id_builder)?;
|
||||||
|
|
||||||
let own_peer_info = self.routing_table().get_own_peer_info();
|
|
||||||
|
|
||||||
let mut ni_builder = fnq.reborrow().init_sender_node_info();
|
|
||||||
encode_node_info(&own_peer_info.node_info, &mut ni_builder)?;
|
|
||||||
|
|
||||||
find_node_q_msg.into_reader()
|
find_node_q_msg.into_reader()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1590,7 +1570,7 @@ impl RPCProcessor {
|
|||||||
for p in peers_reader.iter() {
|
for p in peers_reader.iter() {
|
||||||
let peer_info = decode_peer_info(&p, true)?;
|
let peer_info = decode_peer_info(&p, true)?;
|
||||||
|
|
||||||
if !self.filter_peer_scope(&peer_info) {
|
if !self.filter_peer_scope(&peer_info.node_info) {
|
||||||
return Err(RPCError::InvalidFormat);
|
return Err(RPCError::InvalidFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ pub struct SenderInfo {
|
|||||||
pub socket_address: Option<SocketAddress>,
|
pub socket_address: Option<SocketAddress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep member order appropriate for sorting < preference
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub enum DialInfoClass {
|
pub enum DialInfoClass {
|
||||||
Direct = 0, // D = Directly reachable with public IP and no firewall, with statically configured port
|
Direct = 0, // D = Directly reachable with public IP and no firewall, with statically configured port
|
||||||
@ -268,10 +269,11 @@ impl DialInfoClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep member order appropriate for sorting < preference
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
pub struct DialInfoDetail {
|
pub struct DialInfoDetail {
|
||||||
pub dial_info: DialInfo,
|
|
||||||
pub class: DialInfoClass,
|
pub class: DialInfoClass,
|
||||||
|
pub dial_info: DialInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchesDialInfoFilter for DialInfoDetail {
|
impl MatchesDialInfoFilter for DialInfoDetail {
|
||||||
@ -445,7 +447,7 @@ impl LocalNodeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumSetType)]
|
#[derive(Debug, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumSetType)]
|
||||||
// The derived ordering here is the order of preference, lower is preferred for connections
|
// Keep member order appropriate for sorting < preference
|
||||||
// Must match DialInfo order
|
// Must match DialInfo order
|
||||||
pub enum ProtocolType {
|
pub enum ProtocolType {
|
||||||
UDP,
|
UDP,
|
||||||
@ -661,6 +663,10 @@ impl DialInfoFilter {
|
|||||||
self.protocol_set = ProtocolSet::only(protocol_type);
|
self.protocol_set = ProtocolSet::only(protocol_type);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn with_protocol_set(mut self, protocol_set: ProtocolSet) -> Self {
|
||||||
|
self.protocol_set = protocol_set;
|
||||||
|
self
|
||||||
|
}
|
||||||
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
|
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
|
||||||
self.address_type = Some(address_type);
|
self.address_type = Some(address_type);
|
||||||
self
|
self
|
||||||
@ -709,7 +715,7 @@ pub struct DialInfoWSS {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
// The derived ordering here is the order of preference, lower is preferred for connections
|
// Keep member order appropriate for sorting < preference
|
||||||
// Must match ProtocolType order
|
// Must match ProtocolType order
|
||||||
pub enum DialInfo {
|
pub enum DialInfo {
|
||||||
UDP(DialInfoUDP),
|
UDP(DialInfoUDP),
|
||||||
|
Loading…
Reference in New Issue
Block a user