mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-12-17 19:54:46 -05:00
route work
This commit is contained in:
parent
be55a42878
commit
d335b56571
@ -136,22 +136,22 @@ struct RouteHop {
|
|||||||
nodeId @0 :NodeID; # node id only for established routes
|
nodeId @0 :NodeID; # node id only for established routes
|
||||||
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: next hop in encrypted blob
|
nextHop @2 :RouteHopData; # Next hop in encrypted blob
|
||||||
# Null means no next hop, at destination (only used in private route, safety routes must enclose a stub private route)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PrivateRoute {
|
struct PrivateRoute {
|
||||||
publicKey @0 :RoutePublicKey; # private route public key (unique per private route)
|
publicKey @0 :RoutePublicKey; # private route public key (unique per private route)
|
||||||
hopCount @1 :UInt8; # Count of hops left in the private route
|
hopCount @1 :UInt8; # Count of hops left in the private route (for timeout calculation purposes only)
|
||||||
firstHop @2 :RouteHop; # Optional: first hop in the private route
|
firstHop @2 :RouteHop; # Optional: first hop in the private route, if empty, this is the last hop and payload should be decrypted and processed.
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SafetyRoute {
|
struct SafetyRoute {
|
||||||
publicKey @0 :RoutePublicKey; # safety route public key (unique per safety route)
|
publicKey @0 :RoutePublicKey; # safety route public key (unique per safety route)
|
||||||
hopCount @1 :UInt8; # Count of hops left in the safety route
|
hopCount @1 :UInt8; # Count of hops left in the safety route (for timeout calculation purposes only)
|
||||||
hops :union {
|
hops :union {
|
||||||
data @2 :RouteHopData; # safety route has more hops
|
data @2 :RouteHopData; # safety route has more hops
|
||||||
private @3 :PrivateRoute; # safety route has ended and private route follows
|
private @3 :PrivateRoute; # safety route has ended and private route follows
|
||||||
|
xxx find better representation for privateroute stub (going straight to node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ use super::*;
|
|||||||
use crate::veilid_api::*;
|
use crate::veilid_api::*;
|
||||||
use serde::*;
|
use serde::*;
|
||||||
|
|
||||||
|
|
||||||
/// Compiled route (safety route + private route)
|
/// Compiled route (safety route + private route)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CompiledRoute {
|
pub struct CompiledRoute {
|
||||||
@ -771,7 +770,7 @@ impl RouteSpecStore {
|
|||||||
RouteNode::PeerInfo(pi.unwrap())
|
RouteNode::PeerInfo(pi.unwrap())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
next_hop: Some(route_hop_data),
|
next_hop: route_hop_data,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make next blob from route hop
|
// Make next blob from route hop
|
||||||
|
@ -60,10 +60,10 @@ pub fn encode_route_hop(
|
|||||||
encode_peer_info(&pi, &mut pi_builder)?;
|
encode_peer_info(&pi, &mut pi_builder)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(rhd) = &route_hop.next_hop {
|
|
||||||
let mut rhd_builder = builder.reborrow().init_next_hop();
|
let mut rhd_builder = builder.reborrow().init_next_hop();
|
||||||
encode_route_hop_data(rhd, &mut rhd_builder)?;
|
encode_route_hop_data(&route_hop.next_hop, &mut rhd_builder)?;
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +83,10 @@ pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result<Rout
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_hop = if reader.has_next_hop() {
|
|
||||||
let rhd_reader = reader
|
let rhd_reader = reader
|
||||||
.get_next_hop()
|
.get_next_hop()
|
||||||
.map_err(RPCError::map_protocol("invalid next hop in route hop"))?;
|
.map_err(RPCError::map_protocol("invalid next hop in route hop"))?;
|
||||||
Some(decode_route_hop_data(&rhd_reader)?)
|
let next_hop = decode_route_hop_data(&rhd_reader)?;
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(RouteHop { node, next_hop })
|
Ok(RouteHop { node, next_hop })
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,241 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl RPCProcessor {
|
impl RPCProcessor {
|
||||||
// xxx do not process latency for routed messages
|
async fn process_route_safety_route_hop(
|
||||||
|
&self,
|
||||||
|
route: &RPCOperationRoute,
|
||||||
|
route_hop: RouteHop,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
// Get next hop node ref
|
||||||
|
let next_hop_nr = match route_hop.node {
|
||||||
|
RouteNode::NodeId(id) => {
|
||||||
|
//
|
||||||
|
self.routing_table
|
||||||
|
.lookup_node_ref(id.key)
|
||||||
|
.ok_or_else(|| RPCError::network(format!("node hop {} not found", id.key)))
|
||||||
|
}
|
||||||
|
RouteNode::PeerInfo(pi) => {
|
||||||
|
//
|
||||||
|
self.routing_table
|
||||||
|
.register_node_with_signed_node_info(
|
||||||
|
RoutingDomain::PublicInternet,
|
||||||
|
pi.node_id.key,
|
||||||
|
pi.signed_node_info,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
RPCError::network(format!(
|
||||||
|
"node hop {} could not be registered",
|
||||||
|
pi.node_id.key
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
// Pass along the route
|
||||||
|
let next_hop_route = RPCOperationRoute {
|
||||||
|
safety_route: SafetyRoute {
|
||||||
|
public_key: route.safety_route.public_key,
|
||||||
|
hop_count: route.safety_route.hop_count - 1,
|
||||||
|
hops: SafetyRouteHops::Data(route_hop.next_hop),
|
||||||
|
},
|
||||||
|
operation: route.operation,
|
||||||
|
};
|
||||||
|
let next_hop_route_stmt = RPCStatement::new(RPCStatementDetail::Route(next_hop_route));
|
||||||
|
|
||||||
|
// Send the next route statement
|
||||||
|
network_result_try!(
|
||||||
|
self.statement(Destination::direct(next_hop_nr), next_hop_route_stmt)
|
||||||
|
.await?
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn process_route_safety_route_private_route_hop(
|
||||||
|
&self,
|
||||||
|
route: &RPCOperationRoute,
|
||||||
|
private_route: &PrivateRoute,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
//
|
||||||
|
let route_hop = private_route.first_hop.unwrap();
|
||||||
|
|
||||||
|
// Pass along the route
|
||||||
|
let next_hop_route = RPCOperationRoute {
|
||||||
|
safety_route: SafetyRoute {
|
||||||
|
public_key: route.safety_route.public_key,
|
||||||
|
hop_count: 0,
|
||||||
|
hops: SafetyRouteHops::PrivateRoute(Private),
|
||||||
|
},
|
||||||
|
operation: route.operation,
|
||||||
|
};
|
||||||
|
let next_hop_route_stmt = RPCStatement::new(RPCStatementDetail::Route(next_hop_route));
|
||||||
|
|
||||||
|
// Send the next route statement
|
||||||
|
network_result_try!(
|
||||||
|
self.statement(Destination::direct(next_hop_nr), next_hop_route_stmt)
|
||||||
|
.await?
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn process_routed_operation(
|
||||||
|
&self,
|
||||||
|
route: &RPCOperationRoute,
|
||||||
|
private_route: &PrivateRoute,
|
||||||
|
) -> Result<(), RPCError> {
|
||||||
|
//
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
|
||||||
pub(crate) async fn process_route(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
pub(crate) async fn process_route(&self, msg: RPCMessage) -> Result<(), RPCError> {
|
||||||
// xxx do not process latency for routed messages
|
// xxx do not process latency for routed messages
|
||||||
// tracing::Span::current().record("res", &tracing::field::display(res));
|
// tracing::Span::current().record("res", &tracing::field::display(res));
|
||||||
|
|
||||||
xxx continue here
|
// Get the statement
|
||||||
|
let route = match msg.operation.kind() {
|
||||||
|
RPCOperationKind::Statement(s) => match s.detail() {
|
||||||
|
RPCStatementDetail::Route(s) => s,
|
||||||
|
_ => panic!("not a route statement"),
|
||||||
|
},
|
||||||
|
_ => panic!("not a statement"),
|
||||||
|
};
|
||||||
|
|
||||||
Err(RPCError::unimplemented("process_route"))
|
// See what kind of safety route we have going on here
|
||||||
|
match &route.safety_route.hops {
|
||||||
|
// There is a safety route hop
|
||||||
|
SafetyRouteHops::Data(d) => {
|
||||||
|
// See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop
|
||||||
|
let (blob_tag, blob_data) = if let Some(b) = d.blob.last() {
|
||||||
|
(*b, &d.blob[0..d.blob.len() - 1])
|
||||||
|
} else {
|
||||||
|
return Err(RPCError::protocol("no bytes in blob"));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
||||||
|
let node_id_secret = self.routing_table.node_id_secret();
|
||||||
|
let dh_secret = self
|
||||||
|
.crypto
|
||||||
|
.cached_dh(&route.safety_route.public_key, &node_id_secret)
|
||||||
|
.map_err(RPCError::protocol)?;
|
||||||
|
let dec_blob_data = Crypto::decrypt_aead(blob_data, &d.nonce, &dh_secret, None)
|
||||||
|
.map_err(RPCError::map_internal("encryption failed"))?;
|
||||||
|
let dec_blob_reader = capnp::message::Reader::new(
|
||||||
|
RPCMessageData {
|
||||||
|
contents: dec_blob_data,
|
||||||
|
},
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Decode the blob appropriately
|
||||||
|
if blob_tag == 0 {
|
||||||
|
// PrivateRoute
|
||||||
|
let private_route = {
|
||||||
|
let pr_reader = dec_blob_reader
|
||||||
|
.get_root::<veilid_capnp::private_route::Reader>()
|
||||||
|
.map_err(RPCError::protocol)?;
|
||||||
|
decode_private_route(&pr_reader)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if route.safety_route.hop_count as usize != 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Safety hop count should be zero if switched to private route",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next hop node ref
|
||||||
|
if private_route.first_hop.is_some() {
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if private_route.hop_count as usize
|
||||||
|
> self.unlocked_inner.max_route_hop_count
|
||||||
|
{
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count too high to process",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if private_route.hop_count == 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count should not be zero if there are more hops",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switching to private route from safety route
|
||||||
|
self.process_route_safety_route_private_route_hop(route, &private_route)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if private_route.hop_count != 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count should be zero if we are at the end",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private route was a stub, process routed operation
|
||||||
|
self.process_routed_operation(route, &private_route).await?;
|
||||||
|
}
|
||||||
|
} else if blob_tag == 1 {
|
||||||
|
// RouteHop
|
||||||
|
let route_hop = {
|
||||||
|
let rh_reader = dec_blob_reader
|
||||||
|
.get_root::<veilid_capnp::route_hop::Reader>()
|
||||||
|
.map_err(RPCError::protocol)?;
|
||||||
|
decode_route_hop(&rh_reader)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if route.safety_route.hop_count as usize
|
||||||
|
> self.unlocked_inner.max_route_hop_count
|
||||||
|
{
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Safety route hop count too high to process",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if route.safety_route.hop_count == 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Safety route hop count should not be zero if there are more hops",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.process_route_safety_route_hop(route, route_hop)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
return Err(RPCError::protocol("invalid blob tag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Safety route has ended, now do private route
|
||||||
|
SafetyRouteHops::Private(private_route) => {
|
||||||
|
if private_route.first_hop.is_some() {
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if private_route.hop_count as usize > self.unlocked_inner.max_route_hop_count {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count too high to process",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if private_route.hop_count == 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count should not be zero if there are more hops",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are some hops left
|
||||||
|
self.process_route_safety_route_private_route_hop(route, private_route)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
// Make sure hop count makes sense
|
||||||
|
if private_route.hop_count != 0 {
|
||||||
|
return Err(RPCError::protocol(
|
||||||
|
"Private route hop count should be zero if we are at the end",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// No hops left, time to process the routed operation
|
||||||
|
self.process_routed_operation(route, private_route).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ impl fmt::Display for RouteNode {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RouteHop {
|
pub struct RouteHop {
|
||||||
pub node: RouteNode,
|
pub node: RouteNode,
|
||||||
pub next_hop: Option<RouteHopData>,
|
pub next_hop: RouteHopData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -81,7 +81,9 @@ impl fmt::Display for PrivateRoute {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SafetyRouteHops {
|
pub enum SafetyRouteHops {
|
||||||
|
/// Has >= 1 safety route hops
|
||||||
Data(RouteHopData),
|
Data(RouteHopData),
|
||||||
|
/// Has 0 safety route hops
|
||||||
Private(PrivateRoute),
|
Private(PrivateRoute),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user