filtering cleanup

This commit is contained in:
John Smith 2022-08-01 21:06:31 -04:00
parent 4fd8a562ba
commit 54f8676340
14 changed files with 487 additions and 235 deletions

View File

@ -207,20 +207,26 @@ struct NodeStatus {
willValidateDialInfo @4 :Bool;
}
struct ProtocolSet {
struct ProtocolTypeSet {
udp @0 :Bool;
tcp @1 :Bool;
ws @2 :Bool;
wss @3 :Bool;
}
struct AddressTypeSet {
ipv4 @0 :Bool;
ipv6 @1 :Bool;
}
struct NodeInfo {
networkClass @0 :NetworkClass; # network class of this node
outboundProtocols @1 :ProtocolSet; # protocols that can go outbound
minVersion @2 :UInt8; # minimum protocol version for rpc
maxVersion @3 :UInt8; # maximum protocol version for rpc
dialInfoDetailList @4 :List(DialInfoDetail); # inbound dial info details for this node
relayPeerInfo @5 :PeerInfo; # (optional) relay peer info for this node
outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound
addressTypes @2 :AddressTypeSet; # address types supported
minVersion @3 :UInt8; # minimum protocol version for rpc
maxVersion @4 :UInt8; # maximum protocol version for rpc
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
relayPeerInfo @6 :PeerInfo; # (optional) relay peer info for this node
}
struct SignedNodeInfo {

View File

@ -413,7 +413,7 @@ impl PlatformSupportApple {
}
// Ask for all the addresses we have
let ifaddrs = IfAddrs::new().map_err(map_to_string)?;
let ifaddrs = IfAddrs::new().wrap_err("failed to get interface addresses")?;
for ifaddr in ifaddrs.iter() {
// Get the interface name
let ifname = unsafe { CStr::from_ptr(ifaddr.ifa_name) }

View File

@ -56,8 +56,10 @@ pub type BootstrapRecordMap = BTreeMap<DHTKey, BootstrapRecord>;
#[derive(Copy, Clone, Debug, Default)]
pub struct ProtocolConfig {
pub outbound: ProtocolSet,
pub inbound: ProtocolSet,
pub outbound: ProtocolTypeSet,
pub inbound: ProtocolTypeSet,
pub family_global: AddressTypeSet,
pub family_local: AddressTypeSet,
}
// Things we get when we start up and go away when we shut down
@ -135,6 +137,11 @@ struct NetworkManagerInner {
client_whitelist: LruCache<DHTKey, ClientWhitelistEntry>,
relay_node: Option<NodeRef>,
public_address_check_cache: LruCache<DHTKey, SocketAddress>,
protocol_config: Option<ProtocolConfig>,
public_inbound_dial_info_filter: Option<DialInfoFilter>,
local_inbound_dial_info_filter: Option<DialInfoFilter>,
public_outbound_dial_info_filter: Option<DialInfoFilter>,
local_outbound_dial_info_filter: Option<DialInfoFilter>,
}
struct NetworkManagerUnlockedInner {
@ -166,6 +173,11 @@ impl NetworkManager {
client_whitelist: LruCache::new_unbounded(),
relay_node: None,
public_address_check_cache: LruCache::new(8),
protocol_config: None,
public_inbound_dial_info_filter: None,
local_inbound_dial_info_filter: None,
public_outbound_dial_info_filter: None,
local_outbound_dial_info_filter: None,
}
}
fn new_unlocked_inner(config: VeilidConfig) -> NetworkManagerUnlockedInner {
@ -343,6 +355,41 @@ impl NetworkManager {
return Err(e);
}
// Store copy of protocol config and dial info filters
{
let mut inner = self.inner.lock();
let pc = inner
.components
.as_ref()
.unwrap()
.net
.get_protocol_config()
.unwrap();
inner.public_inbound_dial_info_filter = Some(
DialInfoFilter::global()
.with_protocol_type_set(pc.inbound)
.with_address_type_set(pc.family_global),
);
inner.local_inbound_dial_info_filter = Some(
DialInfoFilter::local()
.with_protocol_type_set(pc.inbound)
.with_address_type_set(pc.family_local),
);
inner.public_outbound_dial_info_filter = Some(
DialInfoFilter::global()
.with_protocol_type_set(pc.outbound)
.with_address_type_set(pc.family_global),
);
inner.local_outbound_dial_info_filter = Some(
DialInfoFilter::local()
.with_protocol_type_set(pc.outbound)
.with_address_type_set(pc.family_local),
);
inner.protocol_config = Some(pc);
}
// Inform routing table entries that our dial info has changed
self.send_node_info_updates(true).await;
@ -405,6 +452,11 @@ impl NetworkManager {
let mut inner = self.inner.lock();
inner.components = None;
inner.relay_node = None;
inner.public_inbound_dial_info_filter = None;
inner.local_inbound_dial_info_filter = None;
inner.public_outbound_dial_info_filter = None;
inner.local_outbound_dial_info_filter = None;
inner.protocol_config = None;
}
// send update
@ -544,11 +596,42 @@ impl NetworkManager {
}
// Return what protocols we have enabled
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
if let Some(components) = &self.inner.lock().components {
components.net.get_protocol_config()
} else {
None
pub fn get_protocol_config(&self) -> ProtocolConfig {
let inner = self.inner.lock();
inner.protocol_config.as_ref().unwrap().clone()
}
// Return a dial info filter for what we can receive
pub fn get_inbound_dial_info_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter {
let inner = self.inner.lock();
match routing_domain {
RoutingDomain::PublicInternet => inner
.public_inbound_dial_info_filter
.as_ref()
.unwrap()
.clone(),
RoutingDomain::LocalNetwork => inner
.local_inbound_dial_info_filter
.as_ref()
.unwrap()
.clone(),
}
}
// Return a dial info filter for what we can send out
pub fn get_outbound_dial_info_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter {
let inner = self.inner.lock();
match routing_domain {
RoutingDomain::PublicInternet => inner
.public_outbound_dial_info_filter
.as_ref()
.unwrap()
.clone(),
RoutingDomain::LocalNetwork => inner
.local_outbound_dial_info_filter
.as_ref()
.unwrap()
.clone(),
}
}
@ -692,15 +775,18 @@ impl NetworkManager {
};
// Get the udp direct dialinfo for the hole punch
peer_nr.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
let outbound_dif = self
.get_outbound_dial_info_filter(RoutingDomain::PublicInternet)
.with_protocol_type(ProtocolType::UDP);
peer_nr.set_filter(Some(outbound_dif));
let hole_punch_dial_info_detail = peer_nr
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
.ok_or_else(|| eyre!("No hole punch capable dialinfo found for node"))?;
// Now that we picked a specific dialinfo, further restrict the noderef to the specific address type
let mut filter = peer_nr.take_filter().unwrap();
filter.peer_scope = PeerScope::Global;
filter.address_type = Some(hole_punch_dial_info_detail.dial_info.address_type());
let filter = peer_nr.take_filter().unwrap();
let filter =
filter.with_address_type(hole_punch_dial_info_detail.dial_info.address_type());
peer_nr.set_filter(Some(filter));
// Do our half of the hole punch by sending an empty packet
@ -827,26 +913,11 @@ impl NetworkManager {
Ok(())
}
// Figure out how to reach a node
#[instrument(level = "trace", skip(self), ret)]
fn get_contact_method(&self, mut target_node_ref: NodeRef) -> ContactMethod {
let routing_table = self.routing_table();
// Get our network class and protocol config and node id
let our_network_class = self.get_network_class().unwrap_or(NetworkClass::Invalid);
let our_protocol_config = self.get_protocol_config().unwrap();
fn get_contact_method_public(&self, target_node_ref: NodeRef) -> ContactMethod {
// Scope noderef down to protocols we can do outbound
if !target_node_ref.filter_protocols(our_protocol_config.outbound) {
return ContactMethod::Unreachable;
}
// Get the best matching local direct dial info if we have it
let opt_target_local_did =
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::LocalNetwork));
if let Some(target_local_did) = opt_target_local_did {
return ContactMethod::Direct(target_local_did.dial_info);
}
let public_outbound_dif = self.get_outbound_dial_info_filter(RoutingDomain::PublicInternet);
let target_node_ref = target_node_ref.filtered_clone(public_outbound_dif.clone());
// Get the best match internet dial info if we have it
let opt_target_public_did =
@ -861,17 +932,25 @@ impl NetworkManager {
// Get the target's inbound relay, it must have one or it is not reachable
// Note that .relay() never returns our own node. We can't relay to ourselves.
if let Some(inbound_relay_nr) = target_node_ref.relay() {
// Scope down to protocols we can do outbound
let inbound_relay_nr = inbound_relay_nr.filtered_clone(public_outbound_dif.clone());
// Can we reach the inbound relay?
if inbound_relay_nr
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
.is_some()
{
// Can we receive anything inbound ever?
let our_network_class =
self.get_network_class().unwrap_or(NetworkClass::Invalid);
if matches!(our_network_class, NetworkClass::InboundCapable) {
let routing_table = self.routing_table();
///////// Reverse connection
// Get the best match dial info for an reverse inbound connection
let reverse_dif = DialInfoFilter::global().with_protocol_set(
target_node_ref.outbound_protocols().unwrap_or_default(),
);
let reverse_dif = self
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
.filtered(target_node_ref.node_info_outbound_filter());
if let Some(reverse_did) = routing_table.first_filtered_dial_info_detail(
Some(RoutingDomain::PublicInternet),
&reverse_dif,
@ -885,35 +964,33 @@ impl NetworkManager {
}
}
// Does we and the target have outbound protocols to hole-punch?
if our_protocol_config.outbound.contains(ProtocolType::UDP)
&& target_node_ref
.outbound_protocols()
.unwrap_or_default()
.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 mut udp_target_nr = target_node_ref.clone();
udp_target_nr.filter_protocols(ProtocolSet::only(ProtocolType::UDP));
let target_has_udp_dialinfo = target_node_ref
.first_filtered_dial_info_detail(Some(
RoutingDomain::PublicInternet,
))
.is_some();
let self_has_udp_dialinfo = routing_table
.first_filtered_dial_info_detail(
Some(RoutingDomain::PublicInternet),
&udp_dif,
)
.is_some();
if target_has_udp_dialinfo && self_has_udp_dialinfo {
return ContactMethod::SignalHolePunch(
inbound_relay_nr,
udp_target_nr,
);
}
///////// UDP hole-punch
// Does the target have a direct udp dialinfo we can reach?
let udp_target_nr = target_node_ref.filtered_clone(
DialInfoFilter::global().with_protocol_type(ProtocolType::UDP),
);
let target_has_udp_dialinfo = udp_target_nr
.first_filtered_dial_info_detail(Some(RoutingDomain::PublicInternet))
.is_some();
// Does the self node have a direct udp dialinfo the target can reach?
let inbound_udp_dif = self
.get_inbound_dial_info_filter(RoutingDomain::PublicInternet)
.filtered(target_node_ref.node_info_outbound_filter())
.filtered(
DialInfoFilter::global().with_protocol_type(ProtocolType::UDP),
);
let self_has_udp_dialinfo = routing_table
.first_filtered_dial_info_detail(
Some(RoutingDomain::PublicInternet),
&inbound_udp_dif,
)
.is_some();
// Does the target and ourselves have a udp dialinfo that they can reach?
if target_has_udp_dialinfo && self_has_udp_dialinfo {
return ContactMethod::SignalHolePunch(inbound_relay_nr, udp_target_nr);
}
// Otherwise we have to inbound relay
}
@ -922,7 +999,7 @@ impl NetworkManager {
}
}
}
// 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 needs to have an inbound relay
else if let Some(target_inbound_relay_nr) = target_node_ref.relay() {
// Can we reach the full relay?
if target_inbound_relay_nr
@ -933,10 +1010,48 @@ impl NetworkManager {
}
}
ContactMethod::Unreachable
}
#[instrument(level = "trace", skip(self), ret)]
fn get_contact_method_local(&self, target_node_ref: NodeRef) -> ContactMethod {
// Scope noderef down to protocols we can do outbound
let local_outbound_dif = self.get_outbound_dial_info_filter(RoutingDomain::LocalNetwork);
let target_node_ref = target_node_ref.filtered_clone(local_outbound_dif);
// Get the best matching local direct dial info if we have it
// ygjghhtiygiukuymyg
if target_node_ref.is_filter_dead() {
return ContactMethod::Unreachable;
}
let opt_target_local_did =
target_node_ref.first_filtered_dial_info_detail(Some(RoutingDomain::LocalNetwork));
if let Some(target_local_did) = opt_target_local_did {
return ContactMethod::Direct(target_local_did.dial_info);
}
return ContactMethod::Unreachable;
}
// Figure out how to reach a node
#[instrument(level = "trace", skip(self), ret)]
fn get_contact_method(&self, target_node_ref: NodeRef) -> ContactMethod {
// Try local first
let out = self.get_contact_method_local(target_node_ref.clone());
if !matches!(out, ContactMethod::Unreachable) {
return out;
}
// Try public next
let out = self.get_contact_method_public(target_node_ref.clone());
if !matches!(out, ContactMethod::Unreachable) {
return out;
}
// If we can't reach the node by other means, try our outbound relay if we have one
if let Some(relay_node) = self.relay_node() {
return ContactMethod::OutboundRelay(relay_node);
}
// Otherwise, we can't reach this node
debug!("unable to reach node {:?}", target_node_ref);
ContactMethod::Unreachable
@ -1020,7 +1135,7 @@ impl NetworkManager {
// Ensure we are filtered down to UDP (the only hole punch protocol supported today)
assert!(target_nr
.filter_ref()
.map(|dif| dif.protocol_set == ProtocolSet::only(ProtocolType::UDP))
.map(|dif| dif.protocol_set == ProtocolTypeSet::only(ProtocolType::UDP))
.unwrap_or_default());
// Build a return receipt for the signal
@ -1118,11 +1233,13 @@ impl NetworkManager {
.await?
{
None => {
return Ok(if descriptor.matches_peer_scope(PeerScope::Local) {
NetworkResult::value(SendDataKind::LocalDirect)
} else {
NetworkResult::value(SendDataKind::GlobalDirect)
});
return Ok(
if descriptor.matches_peer_scope(PeerScopeSet::only(PeerScope::Local)) {
NetworkResult::value(SendDataKind::LocalDirect)
} else {
NetworkResult::value(SendDataKind::GlobalDirect)
},
);
}
Some(d) => d,
}

View File

@ -35,7 +35,7 @@ struct NetworkInner {
network_started: bool,
network_needs_restart: bool,
protocol_config: Option<ProtocolConfig>,
static_public_dialinfo: ProtocolSet,
static_public_dialinfo: ProtocolTypeSet,
network_class: Option<NetworkClass>,
join_handles: Vec<MustJoinHandle<()>>,
stop_source: Option<StopSource>,
@ -43,6 +43,9 @@ struct NetworkInner {
tcp_port: u16,
ws_port: u16,
wss_port: u16,
enable_ipv4: bool,
enable_ipv6_global: bool,
enable_ipv6_local: bool,
// udp
bound_first_udp: BTreeMap<u16, Option<(socket2::Socket, socket2::Socket)>>,
inbound_udp_protocol_handlers: BTreeMap<SocketAddr, RawUdpProtocolHandler>,
@ -79,7 +82,7 @@ impl Network {
network_started: false,
network_needs_restart: false,
protocol_config: None,
static_public_dialinfo: ProtocolSet::empty(),
static_public_dialinfo: ProtocolTypeSet::empty(),
network_class: None,
join_handles: Vec::new(),
stop_source: None,
@ -87,6 +90,9 @@ impl Network {
tcp_port: 0u16,
ws_port: 0u16,
wss_port: 0u16,
enable_ipv4: true,
enable_ipv6_global: true,
enable_ipv6_local: true,
bound_first_udp: BTreeMap::new(),
inbound_udp_protocol_handlers: BTreeMap::new(),
outbound_udpv4_protocol_handler: None,
@ -540,6 +546,24 @@ impl Network {
// initialize interfaces
self.unlocked_inner.interfaces.refresh().await?;
// determine if we have ipv4/ipv6 addresses
{
let mut inner = self.inner.lock();
for addr in self.unlocked_inner.interfaces.best_addresses() {
if addr.is_ipv4() {
inner.enable_ipv4 = true;
} else if addr.is_ipv6() {
let address = crate::Address::from_ip_addr(addr);
if address.is_global() {
inner.enable_ipv6_global = true;
} else if address.is_local() {
inner.enable_ipv6_local = true;
}
}
}
}
// Build our protocol config to share it with other nodes
let protocol_config = {
let mut inner = self.inner.lock();
@ -549,7 +573,7 @@ impl Network {
// get protocol config
let protocol_config = {
let c = self.config.get();
let mut inbound = ProtocolSet::new();
let mut inbound = ProtocolTypeSet::new();
if c.network.protocol.udp.enabled && c.capabilities.protocol_udp {
inbound.insert(ProtocolType::UDP);
@ -564,7 +588,7 @@ impl Network {
inbound.insert(ProtocolType::WSS);
}
let mut outbound = ProtocolSet::new();
let mut outbound = ProtocolTypeSet::new();
if c.network.protocol.udp.enabled && c.capabilities.protocol_udp {
outbound.insert(ProtocolType::UDP);
}
@ -578,7 +602,25 @@ impl Network {
outbound.insert(ProtocolType::WSS);
}
ProtocolConfig { inbound, outbound }
let mut family_global = AddressTypeSet::new();
let mut family_local = AddressTypeSet::new();
if inner.enable_ipv4 {
family_global.insert(AddressType::IPV4);
family_local.insert(AddressType::IPV4);
}
if inner.enable_ipv6_global {
family_global.insert(AddressType::IPV6);
}
if inner.enable_ipv6_local {
family_local.insert(AddressType::IPV6);
}
ProtocolConfig {
inbound,
outbound,
family_global,
family_local,
}
};
inner.protocol_config = Some(protocol_config);
protocol_config

View File

@ -280,7 +280,8 @@ impl NetworkManager {
k,
SignedNodeInfo::with_no_signature(NodeInfo {
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: ProtocolTypeSet::only(ProtocolType::UDP), // Bootstraps do not participate in relaying and will not make outbound requests, but will have UDP enabled
address_types: AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable
min_version: v.min_version, // Minimum protocol version specified in txt record
max_version: v.max_version, // Maximum protocol version specified in txt record
dial_info_detail_list: v.dial_info_details, // Dial info is as specified in the bootstrap list

View File

@ -231,7 +231,11 @@ impl Network {
outbound.insert(ProtocolType::WSS);
}
ProtocolConfig { inbound, outbound }
// XXX: See issue #92
let family_global = AddressSet::all();
let family_local = AddressSet::all();
ProtocolConfig { inbound, outbound, family_global, family_local }
});
self.inner.lock().network_started = true;

View File

@ -126,9 +126,11 @@ impl RoutingTable {
pub fn get_own_node_info(&self) -> NodeInfo {
let netman = self.network_manager();
let relay_node = netman.relay_node();
let pc = netman.get_protocol_config();
NodeInfo {
network_class: netman.get_network_class().unwrap_or(NetworkClass::Invalid),
outbound_protocols: netman.get_protocol_config().unwrap_or_default().outbound,
outbound_protocols: pc.outbound,
address_types: pc.family_global,
min_version: MIN_VERSION,
max_version: MAX_VERSION,
dial_info_detail_list: self.dial_info_details(RoutingDomain::PublicInternet),

View File

@ -50,19 +50,41 @@ impl NodeRef {
self.filter = filter
}
// Returns true if some protocols can still pass the filter and false if no protocols remain
pub fn filter_protocols(&mut self, protocol_set: ProtocolSet) -> bool {
if protocol_set != ProtocolSet::all() {
let mut dif = self.filter.clone().unwrap_or_default();
dif.protocol_set &= protocol_set;
self.filter = Some(dif);
pub fn merge_filter(&mut self, filter: DialInfoFilter) {
if let Some(self_filter) = self.filter.take() {
self.filter = Some(self_filter.filtered(filter));
} else {
self.filter = Some(filter);
}
self.filter
.as_ref()
.map(|f| !f.protocol_set.is_empty())
.unwrap_or(true)
}
pub fn filtered_clone(&self, filter: DialInfoFilter) -> Self {
let mut out = self.clone();
out.merge_filter(filter);
out
}
pub fn is_filter_dead(&self) -> bool {
if let Some(filter) = &self.filter {
filter.is_dead()
} else {
false
}
}
// Returns true if some protocols can still pass the filter and false if no protocols remain
// pub fn filter_protocols(&mut self, protocol_set: ProtocolSet) -> bool {
// if protocol_set != ProtocolSet::all() {
// let mut dif = self.filter.clone().unwrap_or_default();
// dif.protocol_set &= protocol_set;
// self.filter = Some(dif);
// }
// self.filter
// .as_ref()
// .map(|f| !f.protocol_set.is_empty())
// .unwrap_or(true)
// }
pub fn operate<T, F>(&self, f: F) -> T
where
F: FnOnce(&BucketEntryInner) -> T,
@ -89,9 +111,23 @@ impl NodeRef {
pub fn network_class(&self) -> Option<NetworkClass> {
self.operate(|e| e.node_info().map(|n| n.network_class))
}
pub fn outbound_protocols(&self) -> Option<ProtocolSet> {
pub fn outbound_protocols(&self) -> Option<ProtocolTypeSet> {
self.operate(|e| e.node_info().map(|n| n.outbound_protocols))
}
pub fn address_types(&self) -> Option<AddressTypeSet> {
self.operate(|e| e.node_info().map(|n| n.address_types))
}
pub fn node_info_outbound_filter(&self) -> DialInfoFilter {
let mut dif = DialInfoFilter::all();
if let Some(outbound_protocols) = self.outbound_protocols() {
dif = dif.with_protocol_type_set(outbound_protocols);
}
if let Some(address_types) = self.address_types() {
dif = dif.with_address_type_set(address_types);
}
dif
}
pub fn relay(&self) -> Option<NodeRef> {
let target_rpi = self.operate(|e| e.node_info().map(|n| n.relay_peer_info))?;
target_rpi.and_then(|t| {
@ -116,15 +152,7 @@ impl NodeRef {
) -> Option<DialInfoDetail> {
self.operate(|e| {
// Prefer local dial info first unless it is filtered out
if (routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork))
&& matches!(
self.filter
.as_ref()
.map(|f| f.peer_scope)
.unwrap_or(PeerScope::All),
PeerScope::All | PeerScope::Local
)
{
if routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork) {
e.local_node_info().and_then(|l| {
l.first_filtered_dial_info(|di| {
if let Some(filter) = self.filter.as_ref() {
@ -142,15 +170,7 @@ impl NodeRef {
None
}
.or_else(|| {
if (routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet))
&& matches!(
self.filter
.as_ref()
.map(|f| f.peer_scope)
.unwrap_or(PeerScope::All),
PeerScope::All | PeerScope::Global
)
{
if routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet) {
e.node_info().and_then(|n| {
n.first_filtered_dial_info_detail(|did| {
if let Some(filter) = self.filter.as_ref() {
@ -174,15 +194,7 @@ impl NodeRef {
let mut out = Vec::new();
self.operate(|e| {
// Prefer local dial info first unless it is filtered out
if (routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork))
&& matches!(
self.filter
.as_ref()
.map(|f| f.peer_scope)
.unwrap_or(PeerScope::All),
PeerScope::All | PeerScope::Local
)
{
if routing_domain == None || routing_domain == Some(RoutingDomain::LocalNetwork) {
if let Some(lni) = e.local_node_info() {
for di in lni.all_filtered_dial_info(|di| {
if let Some(filter) = self.filter.as_ref() {
@ -198,15 +210,7 @@ impl NodeRef {
}
}
}
if (routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet))
&& matches!(
self.filter
.as_ref()
.map(|f| f.peer_scope)
.unwrap_or(PeerScope::All),
PeerScope::All | PeerScope::Global
)
{
if routing_domain == None || routing_domain == Some(RoutingDomain::PublicInternet) {
if let Some(ni) = e.node_info() {
out.append(&mut ni.all_filtered_dial_info_details(|did| {
if let Some(filter) = self.filter.as_ref() {

View File

@ -0,0 +1,25 @@
use crate::*;
use rpc_processor::*;
pub fn encode_address_type_set(
address_type_set: &AddressTypeSet,
builder: &mut veilid_capnp::address_type_set::Builder,
) -> Result<(), RPCError> {
builder.set_ipv4(address_type_set.contains(AddressType::IPV4));
builder.set_ipv6(address_type_set.contains(AddressType::IPV6));
Ok(())
}
pub fn decode_address_type_set(
reader: &veilid_capnp::address_type_set::Reader,
) -> Result<AddressTypeSet, RPCError> {
let mut out = AddressTypeSet::new();
if reader.reborrow().get_ipv4() {
out.insert(AddressType::IPV4);
}
if reader.reborrow().get_ipv6() {
out.insert(AddressType::IPV6);
}
Ok(out)
}

View File

@ -1,4 +1,5 @@
mod address;
mod address_type_set;
mod block_id;
mod dial_info;
mod dial_info_class;
@ -11,7 +12,7 @@ mod nonce;
mod operations;
mod peer_info;
mod private_safety_route;
mod protocol_set;
mod protocol_type_set;
mod public_key;
mod sender_info;
mod signal_info;
@ -23,6 +24,7 @@ mod value_data;
mod value_key;
pub use address::*;
pub use address_type_set::*;
pub use block_id::*;
pub use dial_info::*;
pub use dial_info_class::*;
@ -35,7 +37,7 @@ pub use nonce::*;
pub use operations::*;
pub use peer_info::*;
pub use private_safety_route::*;
pub use protocol_set::*;
pub use protocol_type_set::*;
pub use public_key::*;
pub use sender_info::*;
pub use signal_info::*;

View File

@ -8,7 +8,10 @@ pub fn encode_node_info(
builder.set_network_class(encode_network_class(node_info.network_class));
let mut ps_builder = builder.reborrow().init_outbound_protocols();
encode_protocol_set(&node_info.outbound_protocols, &mut ps_builder)?;
encode_protocol_type_set(&node_info.outbound_protocols, &mut ps_builder)?;
let mut ats_builder = builder.reborrow().init_address_types();
encode_address_type_set(&node_info.address_types, &mut ats_builder)?;
builder.set_min_version(node_info.min_version);
builder.set_max_version(node_info.max_version);
@ -47,13 +50,20 @@ pub fn decode_node_info(
.map_err(RPCError::protocol)?,
);
let outbound_protocols = decode_protocol_set(
let outbound_protocols = decode_protocol_type_set(
&reader
.reborrow()
.get_outbound_protocols()
.map_err(RPCError::protocol)?,
)?;
let address_types = decode_address_type_set(
&reader
.reborrow()
.get_address_types()
.map_err(RPCError::protocol)?,
)?;
let min_version = reader.reborrow().get_min_version();
let max_version = reader.reborrow().get_max_version();
@ -90,6 +100,7 @@ pub fn decode_node_info(
Ok(NodeInfo {
network_class,
outbound_protocols,
address_types,
min_version,
max_version,
dial_info_detail_list,

View File

@ -1,33 +0,0 @@
use crate::*;
use rpc_processor::*;
pub fn encode_protocol_set(
protocol_set: &ProtocolSet,
builder: &mut veilid_capnp::protocol_set::Builder,
) -> Result<(), RPCError> {
builder.set_udp(protocol_set.contains(ProtocolType::UDP));
builder.set_tcp(protocol_set.contains(ProtocolType::TCP));
builder.set_ws(protocol_set.contains(ProtocolType::WS));
builder.set_wss(protocol_set.contains(ProtocolType::WSS));
Ok(())
}
pub fn decode_protocol_set(
reader: &veilid_capnp::protocol_set::Reader,
) -> Result<ProtocolSet, RPCError> {
let mut out = ProtocolSet::new();
if reader.reborrow().get_udp() {
out.insert(ProtocolType::UDP);
}
if reader.reborrow().get_tcp() {
out.insert(ProtocolType::TCP);
}
if reader.reborrow().get_ws() {
out.insert(ProtocolType::WS);
}
if reader.reborrow().get_wss() {
out.insert(ProtocolType::WSS);
}
Ok(out)
}

View File

@ -0,0 +1,33 @@
use crate::*;
use rpc_processor::*;
pub fn encode_protocol_type_set(
protocol_type_set: &ProtocolTypeSet,
builder: &mut veilid_capnp::protocol_type_set::Builder,
) -> Result<(), RPCError> {
builder.set_udp(protocol_type_set.contains(ProtocolType::UDP));
builder.set_tcp(protocol_type_set.contains(ProtocolType::TCP));
builder.set_ws(protocol_type_set.contains(ProtocolType::WS));
builder.set_wss(protocol_type_set.contains(ProtocolType::WSS));
Ok(())
}
pub fn decode_protocol_type_set(
reader: &veilid_capnp::protocol_type_set::Reader,
) -> Result<ProtocolTypeSet, RPCError> {
let mut out = ProtocolTypeSet::new();
if reader.reborrow().get_udp() {
out.insert(ProtocolType::UDP);
}
if reader.reborrow().get_tcp() {
out.insert(ProtocolType::TCP);
}
if reader.reborrow().get_ws() {
out.insert(ProtocolType::WS);
}
if reader.reborrow().get_wss() {
out.insert(ProtocolType::WSS);
}
Ok(out)
}

View File

@ -402,7 +402,8 @@ pub struct NodeStatus {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeInfo {
pub network_class: NetworkClass,
pub outbound_protocols: ProtocolSet,
pub outbound_protocols: ProtocolTypeSet,
pub address_types: AddressTypeSet,
pub min_version: u8,
pub max_version: u8,
pub dial_info_detail_list: Vec<DialInfoDetail>,
@ -557,14 +558,23 @@ impl ProtocolType {
)
}
}
pub type ProtocolTypeSet = EnumSet<ProtocolType>;
pub type ProtocolSet = EnumSet<ProtocolType>;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Debug, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumSetType)]
pub enum AddressType {
IPV4,
IPV6,
}
pub type AddressTypeSet = EnumSet<AddressType>;
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Debug, Ord, PartialOrd, Hash, Serialize, Deserialize, EnumSetType)]
pub enum PeerScope {
Global,
Local,
}
pub type PeerScopeSet = EnumSet<PeerScope>;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
pub enum Address {
@ -585,6 +595,12 @@ impl Address {
SocketAddr::V6(v6) => Address::IPV6(*v6.ip()),
}
}
pub fn from_ip_addr(addr: IpAddr) -> Address {
match addr {
IpAddr::V4(v4) => Address::IPV4(v4),
IpAddr::V6(v6) => Address::IPV6(v6),
}
}
pub fn address_type(&self) -> AddressType {
match self {
Address::IPV4(_) => AddressType::IPV4,
@ -715,17 +731,17 @@ impl FromStr for SocketAddress {
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct DialInfoFilter {
pub peer_scope: PeerScope,
pub protocol_set: ProtocolSet,
pub address_type: Option<AddressType>,
pub peer_scope_set: PeerScopeSet,
pub protocol_set: ProtocolTypeSet,
pub address_set: AddressTypeSet,
}
impl Default for DialInfoFilter {
fn default() -> Self {
Self {
peer_scope: PeerScope::All,
protocol_set: ProtocolSet::all(),
address_type: None,
peer_scope_set: PeerScopeSet::all(),
protocol_set: ProtocolTypeSet::all(),
address_set: AddressTypeSet::all(),
}
}
}
@ -733,55 +749,72 @@ impl Default for DialInfoFilter {
impl DialInfoFilter {
pub fn all() -> Self {
Self {
peer_scope: PeerScope::All,
protocol_set: ProtocolSet::all(),
address_type: None,
peer_scope_set: PeerScopeSet::all(),
protocol_set: ProtocolTypeSet::all(),
address_set: AddressTypeSet::all(),
}
}
pub fn global() -> Self {
Self {
peer_scope: PeerScope::Global,
protocol_set: ProtocolSet::all(),
address_type: None,
peer_scope_set: PeerScopeSet::only(PeerScope::Global),
protocol_set: ProtocolTypeSet::all(),
address_set: AddressTypeSet::all(),
}
}
pub fn local() -> Self {
Self {
peer_scope: PeerScope::Local,
protocol_set: ProtocolSet::all(),
address_type: None,
peer_scope_set: PeerScopeSet::only(PeerScope::Local),
protocol_set: ProtocolTypeSet::all(),
address_set: AddressTypeSet::all(),
}
}
pub fn scoped(peer_scope: PeerScope) -> Self {
Self {
peer_scope,
protocol_set: ProtocolSet::all(),
address_type: None,
peer_scope_set: PeerScopeSet::only(peer_scope),
protocol_set: ProtocolTypeSet::all(),
address_set: AddressTypeSet::all(),
}
}
pub fn with_protocol_type(mut self, protocol_type: ProtocolType) -> Self {
self.protocol_set = ProtocolSet::only(protocol_type);
self.protocol_set = ProtocolTypeSet::only(protocol_type);
self
}
pub fn with_protocol_set(mut self, protocol_set: ProtocolSet) -> Self {
pub fn with_protocol_type_set(mut self, protocol_set: ProtocolTypeSet) -> Self {
self.protocol_set = protocol_set;
self
}
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
self.address_type = Some(address_type);
self.address_set = AddressTypeSet::only(address_type);
self
}
pub fn with_address_type_set(mut self, address_set: AddressTypeSet) -> Self {
self.address_set = address_set;
self
}
pub fn filtered(mut self, other_dif: DialInfoFilter) -> Self {
self.peer_scope_set &= other_dif.peer_scope_set;
self.protocol_set &= other_dif.protocol_set;
self.address_set &= other_dif.address_set;
self
}
pub fn is_dead(&self) -> bool {
self.peer_scope_set.is_empty()
|| self.protocol_set.is_empty()
|| self.address_set.is_empty()
}
}
impl fmt::Debug for DialInfoFilter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
let mut out = String::new();
out += &format!("{:?}", self.peer_scope);
if self.protocol_set != ProtocolSet::all() {
if self.peer_scope_set != PeerScopeSet::all() {
out += &format!("+{:?}", self.peer_scope_set);
}
if self.protocol_set != ProtocolTypeSet::all() {
out += &format!("+{:?}", self.protocol_set);
}
if let Some(at) = self.address_type {
out += &format!("+{:?}", at);
if self.address_set != AddressTypeSet::all() {
out += &format!("+{:?}", self.address_set);
}
write!(f, "[{}]", out)
}
@ -1107,28 +1140,39 @@ impl DialInfo {
let port = socket_address.port();
(address.is_global() || address.is_local()) && port > 0
}
pub fn matches_peer_scope(&self, scope: PeerScope) -> bool {
match scope {
PeerScope::All => true,
PeerScope::Global => self.is_global(),
PeerScope::Local => self.is_local(),
pub fn peer_scope(&self) -> Option<PeerScope> {
let addr = self.socket_address().address();
if addr.is_global() {
return Some(PeerScope::Global);
}
if addr.is_local() {
return Some(PeerScope::Local);
}
None
}
pub fn matches_peer_scope(&self, scope: PeerScopeSet) -> bool {
if let Some(ps) = self.peer_scope() {
scope.contains(ps)
} else {
false
}
}
pub fn make_filter(&self, scoped: bool) -> DialInfoFilter {
DialInfoFilter {
peer_scope: if scoped {
peer_scope_set: if scoped {
if self.is_global() {
PeerScope::Global
PeerScopeSet::only(PeerScope::Global)
} else if self.is_local() {
PeerScope::Local
PeerScopeSet::only(PeerScope::Local)
} else {
PeerScope::All
PeerScopeSet::empty()
}
} else {
PeerScope::All
PeerScopeSet::all()
},
protocol_set: ProtocolSet::only(self.protocol_type()),
address_type: Some(self.address_type()),
protocol_set: ProtocolTypeSet::only(self.protocol_type()),
address_set: AddressTypeSet::only(self.address_type()),
}
}
@ -1313,16 +1357,14 @@ impl DialInfo {
impl MatchesDialInfoFilter for DialInfo {
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
if !self.matches_peer_scope(filter.peer_scope) {
if !self.matches_peer_scope(filter.peer_scope_set) {
return false;
}
if !filter.protocol_set.contains(self.protocol_type()) {
return false;
}
if let Some(at) = filter.address_type {
if self.address_type() != at {
return false;
}
if !filter.address_set.contains(self.address_type()) {
return false;
}
true
}
@ -1330,18 +1372,6 @@ impl MatchesDialInfoFilter for DialInfo {
//////////////////////////////////////////////////////////////////////////
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum PeerScope {
All,
Global,
Local,
}
impl Default for PeerScope {
fn default() -> Self {
PeerScope::All
}
}
// Signed NodeInfo that can be passed around amongst peers and verifiable
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SignedNodeInfo {
@ -1487,27 +1517,35 @@ impl ConnectionDescriptor {
pub fn address_type(&self) -> AddressType {
self.remote.address_type()
}
pub fn matches_peer_scope(&self, scope: PeerScope) -> bool {
match scope {
PeerScope::All => true,
PeerScope::Global => self.remote.socket_address.address().is_global(),
PeerScope::Local => self.remote.socket_address.address().is_local(),
pub fn peer_scope(&self) -> Option<PeerScope> {
let addr = self.remote.socket_address.address();
if addr.is_global() {
return Some(PeerScope::Global);
}
if addr.is_local() {
return Some(PeerScope::Local);
}
None
}
pub fn matches_peer_scope(&self, scope: PeerScopeSet) -> bool {
if let Some(ps) = self.peer_scope() {
scope.contains(ps)
} else {
false
}
}
}
impl MatchesDialInfoFilter for ConnectionDescriptor {
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
if !self.matches_peer_scope(filter.peer_scope) {
if !self.matches_peer_scope(filter.peer_scope_set) {
return false;
}
if !filter.protocol_set.contains(self.protocol_type()) {
return false;
}
if let Some(at) = filter.address_type {
if self.address_type() != at {
return false;
}
if !filter.address_set.contains(self.address_type()) {
return false;
}
true
}