more refactor
This commit is contained in:
parent
f11dc8aaac
commit
8f9b9b58d5
@ -134,7 +134,7 @@ struct RouteHopData @0x8ce231f9d1b7adf2 {
|
|||||||
|
|
||||||
struct RouteHop @0xf8f672d75cce0c3b {
|
struct RouteHop @0xf8f672d75cce0c3b {
|
||||||
node :union {
|
node :union {
|
||||||
nodeId @0 :TypedKey; # node id only for established routes
|
nodeId @0 :PublicKey; # node id key only for established routes (kind is the same as the pr or sr it is part of)
|
||||||
peerInfo @1 :PeerInfo; # full peer info for this hop to establish the route
|
peerInfo @1 :PeerInfo; # full peer info for this hop to establish the route
|
||||||
}
|
}
|
||||||
nextHop @2 :RouteHopData; # optional: If this the end of a private route, this field will not exist
|
nextHop @2 :RouteHopData; # optional: If this the end of a private route, this field will not exist
|
||||||
|
@ -36,9 +36,14 @@ pub fn best_crypto_kind() -> CryptoKind {
|
|||||||
VALID_CRYPTO_KINDS[0]
|
VALID_CRYPTO_KINDS[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Envelope versions in order of preference, best envelope version is the first one, worst is the last one
|
// Version number of envelope format
|
||||||
pub type EnvelopeVersion = u8;
|
pub type EnvelopeVersion = u8;
|
||||||
|
|
||||||
|
/// Envelope versions in order of preference, best envelope version is the first one, worst is the last one
|
||||||
pub const VALID_ENVELOPE_VERSIONS: [EnvelopeVersion; 1] = [0u8];
|
pub const VALID_ENVELOPE_VERSIONS: [EnvelopeVersion; 1] = [0u8];
|
||||||
|
/// Number of envelope versions to keep on structures if many are present beyond the ones we consider valid
|
||||||
|
pub const MAX_ENVELOPE_VERSIONS: usize = 3;
|
||||||
|
/// Return the best envelope version we support
|
||||||
pub fn best_envelope_version() -> EnvelopeVersion {
|
pub fn best_envelope_version() -> EnvelopeVersion {
|
||||||
VALID_ENVELOPE_VERSIONS[0]
|
VALID_ENVELOPE_VERSIONS[0]
|
||||||
}
|
}
|
||||||
@ -218,17 +223,19 @@ impl Crypto {
|
|||||||
node_ids: &[TypedKey],
|
node_ids: &[TypedKey],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
typed_signatures: &[TypedSignature],
|
typed_signatures: &[TypedSignature],
|
||||||
) -> Result<(), VeilidAPIError> {
|
) -> Result<Vec<CryptoKind>, VeilidAPIError> {
|
||||||
|
let mut out = Vec::with_capacity(node_ids.len());
|
||||||
for sig in typed_signatures {
|
for sig in typed_signatures {
|
||||||
for nid in node_ids {
|
for nid in node_ids {
|
||||||
if nid.kind == sig.kind {
|
if nid.kind == sig.kind {
|
||||||
if let Some(vcrypto) = self.get(sig.kind) {
|
if let Some(vcrypto) = self.get(sig.kind) {
|
||||||
vcrypto.verify(&nid.key, data, &sig.signature)?;
|
vcrypto.verify(&nid.key, data, &sig.signature)?;
|
||||||
|
out.push(nid.kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signature set generation
|
/// Signature set generation
|
||||||
|
@ -27,6 +27,17 @@ pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Intersection of crypto kind vectors
|
||||||
|
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for ack in a {
|
||||||
|
if b.contains(ack) {
|
||||||
|
out.push(*ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Copy,
|
Copy,
|
||||||
@ -42,7 +53,7 @@ pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
pub secret: SecretKey,
|
pub secret: SecretKey,
|
||||||
@ -67,7 +78,7 @@ impl KeyPair {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct TypedKey {
|
pub struct TypedKey {
|
||||||
pub kind: CryptoKind,
|
pub kind: CryptoKind,
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
@ -126,7 +137,7 @@ impl FromStr for TypedKey {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct TypedKeySet {
|
pub struct TypedKeySet {
|
||||||
items: Vec<TypedKey>,
|
items: Vec<TypedKey>,
|
||||||
}
|
}
|
||||||
@ -178,6 +189,11 @@ impl TypedKeySet {
|
|||||||
self.items.remove(idx);
|
self.items.remove(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn remove_all(&self, kinds: &[CryptoKind]) {
|
||||||
|
for k in kinds {
|
||||||
|
self.remove(*k);
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn best(&self) -> Option<TypedKey> {
|
pub fn best(&self) -> Option<TypedKey> {
|
||||||
self.items.first().copied()
|
self.items.first().copied()
|
||||||
}
|
}
|
||||||
@ -255,7 +271,7 @@ impl FromStr for TypedKeySet {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct TypedKeyPair {
|
pub struct TypedKeyPair {
|
||||||
pub kind: CryptoKind,
|
pub kind: CryptoKind,
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
@ -329,7 +345,7 @@ impl FromStr for TypedKeyPair {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct TypedSignature {
|
pub struct TypedSignature {
|
||||||
pub kind: CryptoKind,
|
pub kind: CryptoKind,
|
||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
@ -399,7 +415,7 @@ impl FromStr for TypedSignature {
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
pub struct TypedKeySignature {
|
pub struct TypedKeySignature {
|
||||||
pub kind: CryptoKind,
|
pub kind: CryptoKind,
|
||||||
pub key: PublicKey,
|
pub key: PublicKey,
|
||||||
|
@ -893,7 +893,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// We expect the inbound noderef to be the same as the target noderef
|
// We expect the inbound noderef to be the same as the target noderef
|
||||||
// if they aren't the same, we should error on this and figure out what then hell is up
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
||||||
if target_nr.node_id() != inbound_nr.node_id() {
|
if !target_nr.same_entry(&inbound_nr) {
|
||||||
bail!("unexpected noderef mismatch on reverse connect");
|
bail!("unexpected noderef mismatch on reverse connect");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -998,7 +998,7 @@ impl NetworkManager {
|
|||||||
|
|
||||||
// We expect the inbound noderef to be the same as the target noderef
|
// We expect the inbound noderef to be the same as the target noderef
|
||||||
// if they aren't the same, we should error on this and figure out what then hell is up
|
// if they aren't the same, we should error on this and figure out what then hell is up
|
||||||
if target_nr.node_id() != inbound_nr.node_id() {
|
if !target_nr.same_entry(&inbound_nr) {
|
||||||
bail!(
|
bail!(
|
||||||
"unexpected noderef mismatch on hole punch {}, expected {}",
|
"unexpected noderef mismatch on hole punch {}, expected {}",
|
||||||
inbound_nr,
|
inbound_nr,
|
||||||
|
@ -133,6 +133,15 @@ impl BucketEntryInner {
|
|||||||
self.node_ids.best().unwrap()
|
self.node_ids.best().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crypto kinds
|
||||||
|
pub fn crypto_kinds(&self) -> Vec<CryptoKind> {
|
||||||
|
self.node_ids.kinds()
|
||||||
|
}
|
||||||
|
pub fn common_crypto_kinds(&self, other: &[CryptoKind]) -> Vec<CryptoKind> {
|
||||||
|
common_crypto_kinds(&self.node_ids.kinds(), other)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Less is faster
|
// Less is faster
|
||||||
pub fn cmp_fastest(e1: &Self, e2: &Self) -> std::cmp::Ordering {
|
pub fn cmp_fastest(e1: &Self, e2: &Self) -> std::cmp::Ordering {
|
||||||
// Lower latency to the front
|
// Lower latency to the front
|
||||||
|
@ -20,6 +20,14 @@ pub trait NodeRefBase: Sized {
|
|||||||
fn common(&self) -> &NodeRefBaseCommon;
|
fn common(&self) -> &NodeRefBaseCommon;
|
||||||
fn common_mut(&mut self) -> &mut NodeRefBaseCommon;
|
fn common_mut(&mut self) -> &mut NodeRefBaseCommon;
|
||||||
|
|
||||||
|
// Comparators
|
||||||
|
fn same_entry<T: NodeRefBase>(&self, other: &T) -> bool {
|
||||||
|
Arc::ptr_eq(&self.common().entry, &other.common().entry)
|
||||||
|
}
|
||||||
|
fn same_bucket_entry(&self, entry: &Arc<BucketEntry>) -> bool {
|
||||||
|
Arc::ptr_eq(&self.common().entry, entry)
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation-specific operators
|
// Implementation-specific operators
|
||||||
fn operate<T, F>(&self, f: F) -> T
|
fn operate<T, F>(&self, f: F) -> T
|
||||||
where
|
where
|
||||||
|
@ -20,18 +20,6 @@ pub enum RouteNode {
|
|||||||
/// Route node with full contact method information to ensure the peer is reachable
|
/// Route node with full contact method information to ensure the peer is reachable
|
||||||
PeerInfo(PeerInfo),
|
PeerInfo(PeerInfo),
|
||||||
}
|
}
|
||||||
impl fmt::Display for RouteNode {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
match self {
|
|
||||||
RouteNode::NodeId(x) => x.key.encode(),
|
|
||||||
RouteNode::PeerInfo(pi) => pi.node_id.key.encode(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An unencrypted private/safety route hop
|
/// An unencrypted private/safety route hop
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -221,7 +221,7 @@ impl RouteSpecDetail {
|
|||||||
#[archive_attr(repr(C, align(8)), derive(CheckBytes))]
|
#[archive_attr(repr(C, align(8)), derive(CheckBytes))]
|
||||||
pub struct RouteSpecStoreContent {
|
pub struct RouteSpecStoreContent {
|
||||||
/// All of the routes we have allocated so far
|
/// All of the routes we have allocated so far
|
||||||
details: HashMap<PublicKey, RouteSpecDetail>,
|
details: HashMap<TypedKey, RouteSpecDetail>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What remote private routes have seen
|
/// What remote private routes have seen
|
||||||
@ -250,19 +250,19 @@ impl RemotePrivateRouteInfo {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouteSpecStoreCache {
|
pub struct RouteSpecStoreCache {
|
||||||
/// How many times nodes have been used
|
/// How many times nodes have been used
|
||||||
used_nodes: HashMap<PublicKey, usize>,
|
used_nodes: HashMap<TypedKey, usize>,
|
||||||
/// How many times nodes have been used at the terminal point of a route
|
/// How many times nodes have been used at the terminal point of a route
|
||||||
used_end_nodes: HashMap<PublicKey, usize>,
|
used_end_nodes: HashMap<TypedKey, usize>,
|
||||||
/// Route spec hop cache, used to quickly disqualify routes
|
/// Route spec hop cache, used to quickly disqualify routes
|
||||||
hop_cache: HashSet<Vec<u8>>,
|
hop_cache: HashSet<Vec<u8>>,
|
||||||
/// Has a remote private route responded to a question and when
|
/// Has a remote private route responded to a question and when
|
||||||
remote_private_route_cache: LruCache<PublicKey, RemotePrivateRouteInfo>,
|
remote_private_route_cache: LruCache<TypedKey, RemotePrivateRouteInfo>,
|
||||||
/// Compiled route cache
|
/// Compiled route cache
|
||||||
compiled_route_cache: LruCache<CompiledRouteCacheKey, SafetyRoute>,
|
compiled_route_cache: LruCache<CompiledRouteCacheKey, SafetyRoute>,
|
||||||
/// List of dead allocated routes
|
/// List of dead allocated routes
|
||||||
dead_routes: Vec<PublicKey>,
|
dead_routes: Vec<TypedKey>,
|
||||||
/// List of dead remote routes
|
/// List of dead remote routes
|
||||||
dead_remote_routes: Vec<PublicKey>,
|
dead_remote_routes: Vec<TypedKey>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RouteSpecStoreCache {
|
impl Default for RouteSpecStoreCache {
|
||||||
@ -577,15 +577,15 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
fn detail<'a>(
|
fn detail<'a>(
|
||||||
inner: &'a RouteSpecStoreInner,
|
inner: &'a RouteSpecStoreInner,
|
||||||
public_key: &PublicKey,
|
route_spec_key: &TypedKey,
|
||||||
) -> Option<&'a RouteSpecDetail> {
|
) -> Option<&'a RouteSpecDetail> {
|
||||||
inner.content.details.get(public_key)
|
inner.content.details.get(route_spec_key)
|
||||||
}
|
}
|
||||||
fn detail_mut<'a>(
|
fn detail_mut<'a>(
|
||||||
inner: &'a mut RouteSpecStoreInner,
|
inner: &'a mut RouteSpecStoreInner,
|
||||||
public_key: &PublicKey,
|
route_spec_key: &TypedKey,
|
||||||
) -> Option<&'a mut RouteSpecDetail> {
|
) -> Option<&'a mut RouteSpecDetail> {
|
||||||
inner.content.details.get_mut(public_key)
|
inner.content.details.get_mut(route_spec_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Purge the route spec store
|
/// Purge the route spec store
|
||||||
@ -605,12 +605,13 @@ impl RouteSpecStore {
|
|||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub fn allocate_route(
|
pub fn allocate_route(
|
||||||
&self,
|
&self,
|
||||||
|
crypto_kinds: &[CryptoKind],
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
sequencing: Sequencing,
|
sequencing: Sequencing,
|
||||||
hop_count: usize,
|
hop_count: usize,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
avoid_node_ids: &[PublicKey],
|
avoid_nodes: &[TypedKey],
|
||||||
) -> EyreResult<Option<PublicKey>> {
|
) -> EyreResult<Option<TypedKeySet>> {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let routing_table = self.unlocked_inner.routing_table.clone();
|
let routing_table = self.unlocked_inner.routing_table.clone();
|
||||||
let rti = &mut *routing_table.inner.write();
|
let rti = &mut *routing_table.inner.write();
|
||||||
@ -618,11 +619,12 @@ impl RouteSpecStore {
|
|||||||
self.allocate_route_inner(
|
self.allocate_route_inner(
|
||||||
inner,
|
inner,
|
||||||
rti,
|
rti,
|
||||||
|
crypto_kinds,
|
||||||
stability,
|
stability,
|
||||||
sequencing,
|
sequencing,
|
||||||
hop_count,
|
hop_count,
|
||||||
directions,
|
directions,
|
||||||
avoid_node_ids,
|
avoid_nodes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,12 +633,13 @@ impl RouteSpecStore {
|
|||||||
&self,
|
&self,
|
||||||
inner: &mut RouteSpecStoreInner,
|
inner: &mut RouteSpecStoreInner,
|
||||||
rti: &RoutingTableInner,
|
rti: &RoutingTableInner,
|
||||||
|
crypto_kinds: &[CryptoKind],
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
sequencing: Sequencing,
|
sequencing: Sequencing,
|
||||||
hop_count: usize,
|
hop_count: usize,
|
||||||
directions: DirectionSet,
|
directions: DirectionSet,
|
||||||
avoid_node_ids: &[PublicKey],
|
avoid_nodes: &[TypedKey],
|
||||||
) -> EyreResult<Option<PublicKey>> {
|
) -> EyreResult<Option<TypedKeySet>> {
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
if hop_count < 1 {
|
if hop_count < 1 {
|
||||||
@ -651,52 +654,60 @@ impl RouteSpecStore {
|
|||||||
bail!("Can't allocate route until we have our own peer info");
|
bail!("Can't allocate route until we have our own peer info");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get relay node id if we have one
|
// Get relay node if we have one
|
||||||
let opt_relay_id = rti
|
let opt_own_relay_nr = rti.relay_node(RoutingDomain::PublicInternet).map(|nr| nr.locked(rti));
|
||||||
.relay_node(RoutingDomain::PublicInternet)
|
|
||||||
.map(|nr| nr.node_id());
|
|
||||||
|
|
||||||
// Get list of all nodes, and sort them for selection
|
// Get list of all nodes, and sort them for selection
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
let filter = Box::new(
|
let filter = Box::new(
|
||||||
move |rti: &RoutingTableInner, k: PublicKey, v: Option<Arc<BucketEntry>>| -> bool {
|
move |rti: &RoutingTableInner, entry: Option<Arc<BucketEntry>>| -> bool {
|
||||||
// Exclude our own node from routes
|
// Exclude our own node from routes
|
||||||
if v.is_none() {
|
if entry.is_none() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let v = v.unwrap();
|
let entry = entry.unwrap();
|
||||||
|
|
||||||
// Exclude our relay if we have one
|
// Exclude our relay if we have one
|
||||||
if let Some(own_relay_id) = opt_relay_id {
|
if let Some(own_relay_nr) = opt_own_relay_nr {
|
||||||
if k == own_relay_id {
|
if own_relay_nr.same_bucket_entry(&entry) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude nodes we have specifically chosen to avoid
|
|
||||||
if avoid_node_ids.contains(&k) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process node info exclusions
|
// Process node info exclusions
|
||||||
let keep = v.with(rti, |_rti, e| {
|
let keep = entry.with(rti, |_rti, e| {
|
||||||
|
|
||||||
|
// Exclude nodes that don't have our requested crypto kinds
|
||||||
|
let common_ck = e.common_crypto_kinds(crypto_kinds);
|
||||||
|
if common_ck.len() != crypto_kinds.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude nodes we have specifically chosen to avoid
|
||||||
|
if e.node_ids().contains_any(avoid_nodes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Exclude nodes on our local network
|
// Exclude nodes on our local network
|
||||||
if e.node_info(RoutingDomain::LocalNetwork).is_some() {
|
if e.node_info(RoutingDomain::LocalNetwork).is_some() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude nodes that have no publicinternet signednodeinfo
|
// Exclude nodes that have no publicinternet signednodeinfo
|
||||||
let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) else {
|
let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Relay check
|
// Relay check
|
||||||
if let Some(relay_id) = sni.relay_id() {
|
let relay_ids = sni.relay_ids();
|
||||||
|
if relay_ids.len() != 0 {
|
||||||
// Exclude nodes whose relays we have chosen to avoid
|
// Exclude nodes whose relays we have chosen to avoid
|
||||||
if avoid_node_ids.contains(&relay_id.key) {
|
if relay_ids.contains_any(avoid_nodes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Exclude nodes whose relay is our own relay if we have one
|
// Exclude nodes whose relay is our own relay if we have one
|
||||||
if let Some(own_relay_id) = opt_relay_id {
|
if let Some(own_relay_nr) = opt_own_relay_nr {
|
||||||
if own_relay_id == relay_id.key {
|
if relay_ids.contains_any(&own_relay_nr.node_ids()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -708,7 +719,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
// Exclude nodes with no publicinternet nodeinfo, or incompatible nodeinfo or node status won't route
|
||||||
v.with(rti, move |_rti, e| {
|
entry.with(rti, |_rti, e| {
|
||||||
let node_info_ok =
|
let node_info_ok =
|
||||||
if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) {
|
if let Some(sni) = e.signed_node_info(RoutingDomain::PublicInternet) {
|
||||||
sni.has_sequencing_matched_dial_info(sequencing)
|
sni.has_sequencing_matched_dial_info(sequencing)
|
||||||
@ -728,9 +739,14 @@ impl RouteSpecStore {
|
|||||||
) as RoutingTableEntryFilter;
|
) as RoutingTableEntryFilter;
|
||||||
let filters = VecDeque::from([filter]);
|
let filters = VecDeque::from([filter]);
|
||||||
let compare = |rti: &RoutingTableInner,
|
let compare = |rti: &RoutingTableInner,
|
||||||
v1: &(PublicKey, Option<Arc<BucketEntry>>),
|
entry1: &Option<Arc<BucketEntry>>,
|
||||||
v2: &(PublicKey, Option<Arc<BucketEntry>>)|
|
entry2: &Option<Arc<BucketEntry>>|
|
||||||
-> Ordering {
|
-> Ordering {
|
||||||
|
|
||||||
|
|
||||||
|
// xxx also sort my most overlapping crypto kinds
|
||||||
|
|
||||||
|
|
||||||
// deprioritize nodes that we have already used as end points
|
// deprioritize nodes that we have already used as end points
|
||||||
let e1_used_end = inner
|
let e1_used_end = inner
|
||||||
.cache
|
.cache
|
||||||
@ -1031,7 +1047,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
async fn test_allocated_route(&self, key: &PublicKey) -> EyreResult<bool> {
|
async fn test_allocated_route(&self, key: &TypedKey) -> EyreResult<bool> {
|
||||||
// Make loopback route to test with
|
// Make loopback route to test with
|
||||||
let dest = {
|
let dest = {
|
||||||
let private_route = self.assemble_private_route(key, None)?;
|
let private_route = self.assemble_private_route(key, None)?;
|
||||||
@ -1074,7 +1090,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
async fn test_remote_route(&self, key: &PublicKey) -> EyreResult<bool> {
|
async fn test_remote_route(&self, key: &TypedKey) -> EyreResult<bool> {
|
||||||
// Make private route test
|
// Make private route test
|
||||||
let dest = {
|
let dest = {
|
||||||
// Get the route to test
|
// Get the route to test
|
||||||
@ -1114,7 +1130,7 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Test an allocated route for continuity
|
/// Test an allocated route for continuity
|
||||||
#[instrument(level = "trace", skip(self), ret, err)]
|
#[instrument(level = "trace", skip(self), ret, err)]
|
||||||
pub async fn test_route(&self, key: &PublicKey) -> EyreResult<bool> {
|
pub async fn test_route(&self, key: &[TypedKey]) -> EyreResult<bool> {
|
||||||
let is_remote = {
|
let is_remote = {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
@ -1574,8 +1590,8 @@ impl RouteSpecStore {
|
|||||||
rti: &RoutingTableInner,
|
rti: &RoutingTableInner,
|
||||||
safety_spec: &SafetySpec,
|
safety_spec: &SafetySpec,
|
||||||
direction: DirectionSet,
|
direction: DirectionSet,
|
||||||
avoid_node_ids: &[PublicKey],
|
avoid_nodes: &[TypedKey],
|
||||||
) -> EyreResult<Option<PublicKey>> {
|
) -> EyreResult<Option<TypedKeySet>> {
|
||||||
// Ensure the total hop count isn't too long for our config
|
// Ensure the total hop count isn't too long for our config
|
||||||
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||||
if safety_spec.hop_count == 0 {
|
if safety_spec.hop_count == 0 {
|
||||||
@ -1634,8 +1650,8 @@ impl RouteSpecStore {
|
|||||||
pub fn get_private_route_for_safety_spec(
|
pub fn get_private_route_for_safety_spec(
|
||||||
&self,
|
&self,
|
||||||
safety_spec: &SafetySpec,
|
safety_spec: &SafetySpec,
|
||||||
avoid_node_ids: &[PublicKey],
|
avoid_nodes: &[TypedKey],
|
||||||
) -> EyreResult<Option<PublicKey>> {
|
) -> EyreResult<Option<TypedKey>> {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let routing_table = self.unlocked_inner.routing_table.clone();
|
let routing_table = self.unlocked_inner.routing_table.clone();
|
||||||
let rti = &*routing_table.inner.read();
|
let rti = &*routing_table.inner.read();
|
||||||
@ -1645,7 +1661,7 @@ impl RouteSpecStore {
|
|||||||
rti,
|
rti,
|
||||||
safety_spec,
|
safety_spec,
|
||||||
Direction::Inbound.into(),
|
Direction::Inbound.into(),
|
||||||
avoid_node_ids,
|
avoid_nodes,
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1742,7 +1758,7 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Import a remote private route for compilation
|
/// Import a remote private route for compilation
|
||||||
#[instrument(level = "trace", skip(self, blob), ret, err)]
|
#[instrument(level = "trace", skip(self, blob), ret, err)]
|
||||||
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<PublicKey> {
|
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<TypedKey> {
|
||||||
// decode the pr blob
|
// decode the pr blob
|
||||||
let private_route = RouteSpecStore::blob_to_private_route(blob)?;
|
let private_route = RouteSpecStore::blob_to_private_route(blob)?;
|
||||||
|
|
||||||
@ -1767,7 +1783,7 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Release a remote private route that is no longer in use
|
/// Release a remote private route that is no longer in use
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn release_remote_private_route(&self, key: &PublicKey) -> bool {
|
fn release_remote_private_route(&self, key: &TypedKey) -> bool {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
if inner.cache.remote_private_route_cache.remove(key).is_some() {
|
if inner.cache.remote_private_route_cache.remove(key).is_some() {
|
||||||
// Mark it as dead for the update
|
// Mark it as dead for the update
|
||||||
@ -1779,7 +1795,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve an imported remote private route by its public key
|
/// Retrieve an imported remote private route by its public key
|
||||||
pub fn get_remote_private_route(&self, key: &PublicKey) -> Option<PrivateRoute> {
|
pub fn get_remote_private_route(&self, key: &TypedKey) -> Option<PrivateRoute> {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
Self::with_get_remote_private_route(inner, cur_ts, key, |r| {
|
Self::with_get_remote_private_route(inner, cur_ts, key, |r| {
|
||||||
@ -1788,7 +1804,7 @@ impl RouteSpecStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve an imported remote private route by its public key but don't 'touch' it
|
/// Retrieve an imported remote private route by its public key but don't 'touch' it
|
||||||
pub fn peek_remote_private_route(&self, key: &PublicKey) -> Option<PrivateRoute> {
|
pub fn peek_remote_private_route(&self, key: &TypedKey) -> Option<PrivateRoute> {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
Self::with_peek_remote_private_route(inner, cur_ts, key, |r| {
|
Self::with_peek_remote_private_route(inner, cur_ts, key, |r| {
|
||||||
@ -1849,7 +1865,7 @@ impl RouteSpecStore {
|
|||||||
fn with_get_remote_private_route<F, R>(
|
fn with_get_remote_private_route<F, R>(
|
||||||
inner: &mut RouteSpecStoreInner,
|
inner: &mut RouteSpecStoreInner,
|
||||||
cur_ts: Timestamp,
|
cur_ts: Timestamp,
|
||||||
key: &PublicKey,
|
remote_private_route: &TypedKey,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Option<R>
|
) -> Option<R>
|
||||||
where
|
where
|
||||||
@ -1869,7 +1885,7 @@ impl RouteSpecStore {
|
|||||||
fn with_peek_remote_private_route<F, R>(
|
fn with_peek_remote_private_route<F, R>(
|
||||||
inner: &mut RouteSpecStoreInner,
|
inner: &mut RouteSpecStoreInner,
|
||||||
cur_ts: Timestamp,
|
cur_ts: Timestamp,
|
||||||
key: &PublicKey,
|
remote_private_route: &TypedKey,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Option<R>
|
) -> Option<R>
|
||||||
where
|
where
|
||||||
@ -1891,7 +1907,7 @@ impl RouteSpecStore {
|
|||||||
|
|
||||||
/// Check to see if this remote (not ours) private route has seen our current node info yet
|
/// Check to see if this remote (not ours) private route has seen our current node info yet
|
||||||
/// This happens when you communicate with a private route without a safety route
|
/// This happens when you communicate with a private route without a safety route
|
||||||
pub fn has_remote_private_route_seen_our_node_info(&self, key: &PublicKey) -> bool {
|
pub fn has_remote_private_route_seen_our_node_info(&self, remote_private_route: &TypedKey) -> bool {
|
||||||
let our_node_info_ts = {
|
let our_node_info_ts = {
|
||||||
let rti = &*self.unlocked_inner.routing_table.inner.read();
|
let rti = &*self.unlocked_inner.routing_table.inner.read();
|
||||||
let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else {
|
let Some(ts) = rti.get_own_node_info_ts(RoutingDomain::PublicInternet) else {
|
||||||
@ -1903,7 +1919,7 @@ impl RouteSpecStore {
|
|||||||
let opt_rpr_node_info_ts = {
|
let opt_rpr_node_info_ts = {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
Self::with_peek_remote_private_route(inner, cur_ts, key, |rpr| {
|
Self::with_peek_remote_private_route(inner, cur_ts, remote_private_route, |rpr| {
|
||||||
rpr.last_seen_our_node_info_ts
|
rpr.last_seen_our_node_info_ts
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -506,9 +506,9 @@ impl RoutingTableInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_nodes(&self, outer_self: RoutingTable, cur_ts: Timestamp) -> Vec<NodeRef> {
|
pub fn get_all_nodes(&self, outer_self: RoutingTable, cur_ts: Timestamp) -> Vec<NodeRef> {
|
||||||
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count);
|
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count());
|
||||||
self.with_entries(cur_ts, BucketEntryState::Unreliable, |_rti, k, v| {
|
self.with_entries(cur_ts, BucketEntryState::Unreliable, |_rti, entry| {
|
||||||
node_refs.push(NodeRef::new(outer_self.clone(), k, v, None));
|
node_refs.push(NodeRef::new(outer_self.clone(), entry, None));
|
||||||
Option::<()>::None
|
Option::<()>::None
|
||||||
});
|
});
|
||||||
node_refs
|
node_refs
|
||||||
@ -525,7 +525,7 @@ impl RoutingTableInner {
|
|||||||
) -> Option<NodeRef>
|
) -> Option<NodeRef>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner),
|
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner),
|
||||||
{
|
{xxx continue here
|
||||||
// Ensure someone isn't trying register this node itself
|
// Ensure someone isn't trying register this node itself
|
||||||
if self.unlocked_inner.matches_own_node_id(node_ids) {
|
if self.unlocked_inner.matches_own_node_id(node_ids) {
|
||||||
log_rtab!(debug "can't register own node");
|
log_rtab!(debug "can't register own node");
|
||||||
|
@ -25,7 +25,6 @@ impl RoutingTable {
|
|||||||
|
|
||||||
// Get the PublicInternet relay if we are using one
|
// Get the PublicInternet relay if we are using one
|
||||||
let opt_relay_nr = self.relay_node(RoutingDomain::PublicInternet);
|
let opt_relay_nr = self.relay_node(RoutingDomain::PublicInternet);
|
||||||
let opt_relay_id = opt_relay_nr.map(|nr| nr.node_id());
|
|
||||||
|
|
||||||
// Get our publicinternet dial info
|
// Get our publicinternet dial info
|
||||||
let dids = self.all_filtered_dial_info_details(
|
let dids = self.all_filtered_dial_info_details(
|
||||||
@ -35,9 +34,10 @@ impl RoutingTable {
|
|||||||
|
|
||||||
// For all nodes needing pings, figure out how many and over what protocols
|
// For all nodes needing pings, figure out how many and over what protocols
|
||||||
for nr in node_refs {
|
for nr in node_refs {
|
||||||
// If this is a relay, let's check for NAT keepalives
|
// If this is our relay, let's check for NAT keepalives
|
||||||
let mut did_pings = false;
|
let mut did_pings = false;
|
||||||
if Some(nr.node_id()) == opt_relay_id {
|
if let Some(relay_nr) = opt_relay_nr {
|
||||||
|
if nr.same_entry(&relay_nr) {
|
||||||
// Relay nodes get pinged over all protocols we have inbound dialinfo for
|
// Relay nodes get pinged over all protocols we have inbound dialinfo for
|
||||||
// This is so we can preserve the inbound NAT mappings at our router
|
// This is so we can preserve the inbound NAT mappings at our router
|
||||||
for did in &dids {
|
for did in &dids {
|
||||||
@ -62,7 +62,9 @@ impl RoutingTable {
|
|||||||
nr.filtered_clone(NodeRefFilter::new().with_dial_info_filter(dif));
|
nr.filtered_clone(NodeRefFilter::new().with_dial_info_filter(dif));
|
||||||
log_net!("--> Keepalive ping to {:?}", nr_filtered);
|
log_net!("--> Keepalive ping to {:?}", nr_filtered);
|
||||||
unord.push(
|
unord.push(
|
||||||
async move { rpc.rpc_call_status(Destination::direct(nr_filtered)).await }
|
async move {
|
||||||
|
rpc.rpc_call_status(Destination::direct(nr_filtered)).await
|
||||||
|
}
|
||||||
.instrument(Span::current())
|
.instrument(Span::current())
|
||||||
.boxed(),
|
.boxed(),
|
||||||
);
|
);
|
||||||
@ -70,6 +72,7 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Just do a single ping with the best protocol for all the other nodes,
|
// Just do a single ping with the best protocol for all the other nodes,
|
||||||
// ensuring that we at least ping a relay with -something- even if we didnt have
|
// ensuring that we at least ping a relay with -something- even if we didnt have
|
||||||
// any mapped ports to preserve
|
// any mapped ports to preserve
|
||||||
|
@ -79,6 +79,21 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
.map(|s| s.to_vec())
|
.map(|s| s.to_vec())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// Ensure envelope versions are not duplicated
|
||||||
|
// Unsorted is okay, some nodes may have a different envelope order preference
|
||||||
|
// But nothing should show up more than once
|
||||||
|
let mut eversions = envelope_support.clone();
|
||||||
|
eversions.dedup();
|
||||||
|
if eversions.len() != envelope_support.len() {
|
||||||
|
return Err(RPCError::protocol("duplicate envelope versions"));
|
||||||
|
}
|
||||||
|
if envelope_support.len() > MAX_ENVELOPE_VERSIONS {
|
||||||
|
return Err(RPCError::protocol("too many envelope versions"));
|
||||||
|
}
|
||||||
|
if envelope_support.len() == 0 {
|
||||||
|
return Err(RPCError::protocol("no envelope versions"));
|
||||||
|
}
|
||||||
|
|
||||||
let crypto_support: Vec<CryptoKind> = reader
|
let crypto_support: Vec<CryptoKind> = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_crypto_support()
|
.get_crypto_support()
|
||||||
@ -87,6 +102,21 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
|||||||
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// Ensure crypto kinds are not duplicated
|
||||||
|
// Unsorted is okay, some nodes may have a different crypto order preference
|
||||||
|
// But nothing should show up more than once
|
||||||
|
let mut ckinds = crypto_support.clone();
|
||||||
|
ckinds.dedup();
|
||||||
|
if ckinds.len() != crypto_support.len() {
|
||||||
|
return Err(RPCError::protocol("duplicate crypto kinds"));
|
||||||
|
}
|
||||||
|
if crypto_support.len() > MAX_CRYPTO_KINDS {
|
||||||
|
return Err(RPCError::protocol("too many crypto kinds"));
|
||||||
|
}
|
||||||
|
if crypto_support.len() == 0 {
|
||||||
|
return Err(RPCError::protocol("no crypto kinds"));
|
||||||
|
}
|
||||||
|
|
||||||
let didl_reader = reader
|
let didl_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
.get_dial_info_detail_list()
|
.get_dial_info_detail_list()
|
||||||
|
@ -43,8 +43,10 @@ pub fn decode_peer_info(
|
|||||||
for nid_reader in nids_reader.iter() {
|
for nid_reader in nids_reader.iter() {
|
||||||
node_ids.add(decode_typed_key(&nid_reader)?);
|
node_ids.add(decode_typed_key(&nid_reader)?);
|
||||||
}
|
}
|
||||||
let signed_node_info = decode_signed_node_info(&sni_reader, crypto, &node_ids)?;
|
let signed_node_info = decode_signed_node_info(&sni_reader, crypto, &mut node_ids)?;
|
||||||
|
if node_ids.len() == 0 {
|
||||||
|
return Err(RPCError::protocol("no verified node ids"));
|
||||||
|
}
|
||||||
Ok(PeerInfo {
|
Ok(PeerInfo {
|
||||||
node_ids,
|
node_ids,
|
||||||
signed_node_info,
|
signed_node_info,
|
||||||
|
@ -35,7 +35,7 @@ pub fn encode_signed_direct_node_info(
|
|||||||
pub fn decode_signed_direct_node_info(
|
pub fn decode_signed_direct_node_info(
|
||||||
reader: &veilid_capnp::signed_direct_node_info::Reader,
|
reader: &veilid_capnp::signed_direct_node_info::Reader,
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
node_ids: &[TypedKey],
|
node_ids: &mut TypedKeySet,
|
||||||
) -> Result<SignedDirectNodeInfo, RPCError> {
|
) -> Result<SignedDirectNodeInfo, RPCError> {
|
||||||
let ni_reader = reader
|
let ni_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
|
@ -21,7 +21,7 @@ pub fn encode_signed_node_info(
|
|||||||
pub fn decode_signed_node_info(
|
pub fn decode_signed_node_info(
|
||||||
reader: &veilid_capnp::signed_node_info::Reader,
|
reader: &veilid_capnp::signed_node_info::Reader,
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
node_ids: &[TypedKey],
|
node_ids: &mut TypedKeySet,
|
||||||
) -> Result<SignedNodeInfo, RPCError> {
|
) -> Result<SignedNodeInfo, RPCError> {
|
||||||
match reader
|
match reader
|
||||||
.which()
|
.which()
|
||||||
|
@ -55,7 +55,7 @@ pub fn encode_signed_relayed_node_info(
|
|||||||
pub fn decode_signed_relayed_node_info(
|
pub fn decode_signed_relayed_node_info(
|
||||||
reader: &veilid_capnp::signed_relayed_node_info::Reader,
|
reader: &veilid_capnp::signed_relayed_node_info::Reader,
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
node_ids: &[TypedKey],
|
node_ids: &mut TypedKeySet,
|
||||||
) -> Result<SignedRelayedNodeInfo, RPCError> {
|
) -> Result<SignedRelayedNodeInfo, RPCError> {
|
||||||
let ni_reader = reader
|
let ni_reader = reader
|
||||||
.reborrow()
|
.reborrow()
|
||||||
@ -81,7 +81,20 @@ pub fn decode_signed_relayed_node_info(
|
|||||||
.reborrow()
|
.reborrow()
|
||||||
.get_relay_info()
|
.get_relay_info()
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
let relay_info = decode_signed_direct_node_info(&ri_reader, crypto, &relay_ids)?;
|
let relay_info = decode_signed_direct_node_info(&ri_reader, crypto, &mut relay_ids)?;
|
||||||
|
|
||||||
|
// Ensure the relay info for the node has a superset of the crypto kinds of the node it is relaying
|
||||||
|
if common_crypto_kinds(
|
||||||
|
&node_info.crypto_support,
|
||||||
|
&relay_info.node_info.crypto_support,
|
||||||
|
)
|
||||||
|
.len()
|
||||||
|
!= node_info.crypto_support.len()
|
||||||
|
{
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"relay should have superset of node crypto kinds",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let timestamp = reader.reborrow().get_timestamp().into();
|
let timestamp = reader.reborrow().get_timestamp().into();
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ pub enum Destination {
|
|||||||
/// The relay to send to
|
/// The relay to send to
|
||||||
relay: NodeRef,
|
relay: NodeRef,
|
||||||
/// The final destination the relay should send to
|
/// The final destination the relay should send to
|
||||||
target: TypedKey,
|
target: NodeRef,
|
||||||
/// Require safety route or not
|
/// Require safety route or not
|
||||||
safety_selection: SafetySelection,
|
safety_selection: SafetySelection,
|
||||||
},
|
},
|
||||||
@ -36,7 +36,7 @@ impl Destination {
|
|||||||
safety_selection: SafetySelection::Unsafe(sequencing),
|
safety_selection: SafetySelection::Unsafe(sequencing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn relay(relay: NodeRef, target: TypedKey) -> Self {
|
pub fn relay(relay: NodeRef, target: NodeRef) -> Self {
|
||||||
let sequencing = relay.sequencing();
|
let sequencing = relay.sequencing();
|
||||||
Self::Relay {
|
Self::Relay {
|
||||||
relay,
|
relay,
|
||||||
@ -124,7 +124,7 @@ impl fmt::Display for Destination {
|
|||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "{}@{}{}", target.encode(), relay, sr)
|
write!(f, "{}@{}{}", target, relay, sr)
|
||||||
}
|
}
|
||||||
Destination::PrivateRoute {
|
Destination::PrivateRoute {
|
||||||
private_route,
|
private_route,
|
||||||
@ -163,7 +163,7 @@ impl RPCProcessor {
|
|||||||
SafetySelection::Safe(safety_spec) => {
|
SafetySelection::Safe(safety_spec) => {
|
||||||
// Sent directly but with a safety route, respond to private route
|
// Sent directly but with a safety route, respond to private route
|
||||||
let Some(pr_key) = rss
|
let Some(pr_key) = rss
|
||||||
.get_private_route_for_safety_spec(safety_spec, &[target.node_id()])
|
.get_private_route_for_safety_spec(safety_spec, &target.node_ids())
|
||||||
.map_err(RPCError::internal)? else {
|
.map_err(RPCError::internal)? else {
|
||||||
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
||||||
};
|
};
|
||||||
@ -187,8 +187,10 @@ impl RPCProcessor {
|
|||||||
}
|
}
|
||||||
SafetySelection::Safe(safety_spec) => {
|
SafetySelection::Safe(safety_spec) => {
|
||||||
// Sent via a relay but with a safety route, respond to private route
|
// Sent via a relay but with a safety route, respond to private route
|
||||||
|
let mut avoid_nodes = relay.node_ids();
|
||||||
|
avoid_nodes.add_all(&target.node_ids());
|
||||||
let Some(pr_key) = rss
|
let Some(pr_key) = rss
|
||||||
.get_private_route_for_safety_spec(safety_spec, &[relay.node_id(), *target])
|
.get_private_route_for_safety_spec(safety_spec, &avoid_nodes)
|
||||||
.map_err(RPCError::internal)? else {
|
.map_err(RPCError::internal)? else {
|
||||||
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
return Ok(NetworkResult::no_connection_other("no private route for response at this time"));
|
||||||
};
|
};
|
||||||
@ -209,6 +211,8 @@ impl RPCProcessor {
|
|||||||
return Err(RPCError::internal("destination private route must have first hop"));
|
return Err(RPCError::internal("destination private route must have first hop"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let crypto_kind = private_route.public_key.kind;
|
||||||
|
|
||||||
match safety_selection {
|
match safety_selection {
|
||||||
SafetySelection::Unsafe(_) => {
|
SafetySelection::Unsafe(_) => {
|
||||||
// Sent to a private route with no safety route, use a stub safety route for the response
|
// Sent to a private route with no safety route, use a stub safety route for the response
|
||||||
@ -221,7 +225,7 @@ impl RPCProcessor {
|
|||||||
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
||||||
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
|
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
|
||||||
}
|
}
|
||||||
RouteNode::NodeId(NodeId::new(routing_table.node_id()))
|
RouteNode::NodeId(routing_table.node_id(crypto_kind))
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
let Some(own_peer_info) =
|
let Some(own_peer_info) =
|
||||||
@ -233,7 +237,7 @@ impl RPCProcessor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(NetworkResult::value(RespondTo::PrivateRoute(
|
Ok(NetworkResult::value(RespondTo::PrivateRoute(
|
||||||
PrivateRoute::new_stub(routing_table.node_id(), route_node),
|
PrivateRoute::new_stub(routing_table.node_id(crypto_kind), route_node),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
SafetySelection::Safe(safety_spec) => {
|
SafetySelection::Safe(safety_spec) => {
|
||||||
|
@ -167,17 +167,22 @@ impl VeilidAPI {
|
|||||||
// Private route allocation
|
// Private route allocation
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn new_private_route(&self) -> Result<(TypedKey, Vec<u8>), VeilidAPIError> {
|
pub async fn new_private_route(&self) -> Result<(TypedKeySet, Vec<u8>), VeilidAPIError> {
|
||||||
self.new_custom_private_route(Stability::default(), Sequencing::default())
|
self.new_custom_private_route(
|
||||||
|
&VALID_CRYPTO_KINDS,
|
||||||
|
Stability::default(),
|
||||||
|
Sequencing::default(),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn new_custom_private_route(
|
pub async fn new_custom_private_route(
|
||||||
&self,
|
&self,
|
||||||
|
crypto_kinds: &[CryptoKind],
|
||||||
stability: Stability,
|
stability: Stability,
|
||||||
sequencing: Sequencing,
|
sequencing: Sequencing,
|
||||||
) -> Result<(TypedKey, Vec<u8>), VeilidAPIError> {
|
) -> Result<(TypedKeySet, Vec<u8>), VeilidAPIError> {
|
||||||
let default_route_hop_count: usize = {
|
let default_route_hop_count: usize = {
|
||||||
let config = self.config()?;
|
let config = self.config()?;
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
@ -187,6 +192,7 @@ impl VeilidAPI {
|
|||||||
let rss = self.routing_table()?.route_spec_store();
|
let rss = self.routing_table()?.route_spec_store();
|
||||||
let r = rss
|
let r = rss
|
||||||
.allocate_route(
|
.allocate_route(
|
||||||
|
&crypto_kinds,
|
||||||
stability,
|
stability,
|
||||||
sequencing,
|
sequencing,
|
||||||
default_route_hop_count,
|
default_route_hop_count,
|
||||||
@ -194,7 +200,7 @@ impl VeilidAPI {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.map_err(VeilidAPIError::internal)?;
|
.map_err(VeilidAPIError::internal)?;
|
||||||
let Some(pr_pubkey) = r else {
|
let Some(pr_keys) = r else {
|
||||||
apibail_generic!("unable to allocate route");
|
apibail_generic!("unable to allocate route");
|
||||||
};
|
};
|
||||||
if !rss
|
if !rss
|
||||||
|
@ -35,7 +35,7 @@ pub type ValueSchema = FourCC;
|
|||||||
RkyvSerialize,
|
RkyvSerialize,
|
||||||
RkyvDeserialize,
|
RkyvDeserialize,
|
||||||
)]
|
)]
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq))]
|
#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq, Hash))]
|
||||||
pub struct FourCC(pub [u8; 4]);
|
pub struct FourCC(pub [u8; 4]);
|
||||||
|
|
||||||
impl From<[u8; 4]> for FourCC {
|
impl From<[u8; 4]> for FourCC {
|
||||||
@ -513,7 +513,7 @@ impl SafetySelection {
|
|||||||
#[archive_attr(repr(C), derive(CheckBytes))]
|
#[archive_attr(repr(C), derive(CheckBytes))]
|
||||||
pub struct SafetySpec {
|
pub struct SafetySpec {
|
||||||
/// preferred safety route if it still exists
|
/// preferred safety route if it still exists
|
||||||
pub preferred_route: Option<PublicKey>,
|
pub preferred_route: Option<TypedKey>,
|
||||||
/// must be greater than 0
|
/// must be greater than 0
|
||||||
pub hop_count: usize,
|
pub hop_count: usize,
|
||||||
/// prefer reliability over speed
|
/// prefer reliability over speed
|
||||||
@ -1853,7 +1853,7 @@ pub struct SignedDirectNodeInfo {
|
|||||||
impl SignedDirectNodeInfo {
|
impl SignedDirectNodeInfo {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
node_ids: &[TypedKey],
|
node_ids: &mut TypedKeySet,
|
||||||
node_info: NodeInfo,
|
node_info: NodeInfo,
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
typed_signatures: Vec<TypedSignature>,
|
typed_signatures: Vec<TypedSignature>,
|
||||||
@ -1861,7 +1861,13 @@ impl SignedDirectNodeInfo {
|
|||||||
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
||||||
|
|
||||||
// Verify the signatures that we can
|
// Verify the signatures that we can
|
||||||
|
let valid_crypto_kinds =
|
||||||
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
||||||
|
node_ids.remove_all(&valid_crypto_kinds);
|
||||||
|
if node_ids.len() == 0 {
|
||||||
|
apibail_generic!("no valid node ids in direct node info");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
node_info,
|
node_info,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -1933,7 +1939,7 @@ pub struct SignedRelayedNodeInfo {
|
|||||||
impl SignedRelayedNodeInfo {
|
impl SignedRelayedNodeInfo {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
node_ids: &[TypedKey],
|
node_ids: &mut TypedKeySet,
|
||||||
node_info: NodeInfo,
|
node_info: NodeInfo,
|
||||||
relay_ids: TypedKeySet,
|
relay_ids: TypedKeySet,
|
||||||
relay_info: SignedDirectNodeInfo,
|
relay_info: SignedDirectNodeInfo,
|
||||||
@ -1942,7 +1948,14 @@ impl SignedRelayedNodeInfo {
|
|||||||
) -> Result<Self, VeilidAPIError> {
|
) -> Result<Self, VeilidAPIError> {
|
||||||
let node_info_bytes =
|
let node_info_bytes =
|
||||||
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
||||||
|
let valid_crypto_kinds =
|
||||||
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
|
||||||
|
|
||||||
|
node_ids.remove_all(&valid_crypto_kinds);
|
||||||
|
if node_ids.len() == 0 {
|
||||||
|
apibail_generic!("no valid node ids in relayed node info");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
node_info,
|
node_info,
|
||||||
relay_ids,
|
relay_ids,
|
||||||
@ -2113,6 +2126,7 @@ pub struct PeerInfo {
|
|||||||
|
|
||||||
impl PeerInfo {
|
impl PeerInfo {
|
||||||
pub fn new(node_ids: TypedKeySet, signed_node_info: SignedNodeInfo) -> Self {
|
pub fn new(node_ids: TypedKeySet, signed_node_info: SignedNodeInfo) -> Self {
|
||||||
|
assert!(node_ids.len() > 0 && node_ids.len() <= MAX_CRYPTO_KINDS);
|
||||||
Self {
|
Self {
|
||||||
node_ids,
|
node_ids,
|
||||||
signed_node_info,
|
signed_node_info,
|
||||||
|
Loading…
Reference in New Issue
Block a user