refactor checkpoint

This commit is contained in:
John Smith
2022-09-03 13:57:25 -04:00
parent 9966d25672
commit e0a5b1bd69
30 changed files with 1274 additions and 838 deletions

View File

@@ -1,9 +1,9 @@
use crate::*;
use rpc_processor::*;
pub fn encode_node_status(
node_status: &NodeStatus,
builder: &mut veilid_capnp::node_status::Builder,
pub fn encode_public_internet_node_status(
public_internet_node_status: &PublicInternetNodeStatus,
builder: &mut veilid_capnp::public_internet_node_status::Builder,
) -> Result<(), RPCError> {
builder.set_will_route(node_status.will_route);
builder.set_will_tunnel(node_status.will_tunnel);
@@ -14,10 +14,10 @@ pub fn encode_node_status(
Ok(())
}
pub fn decode_node_status(
reader: &veilid_capnp::node_status::Reader,
) -> Result<NodeStatus, RPCError> {
Ok(NodeStatus {
pub fn decode_public_internet_node_status(
reader: &veilid_capnp::public_internet_node_status::Reader,
) -> Result<PublicInternetNodeStatus, RPCError> {
Ok(PublicInternetNodeStatus {
will_route: reader.reborrow().get_will_route(),
will_tunnel: reader.reborrow().get_will_tunnel(),
will_signal: reader.reborrow().get_will_signal(),
@@ -25,3 +25,62 @@ pub fn decode_node_status(
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
})
}
pub fn encode_local_network_node_status(
local_network_node_status: &LocalNetworkNodeStatus,
builder: &mut veilid_capnp::local_network_node_status::Builder,
) -> Result<(), RPCError> {
builder.set_will_relay(node_status.will_relay);
builder.set_will_validate_dial_info(node_status.will_validate_dial_info);
Ok(())
}
pub fn decode_local_network_node_status(
reader: &veilid_capnp::local_network_node_status::Reader,
) -> Result<LocalNetworkNodeStatus, RPCError> {
Ok(NodeStatus {
will_relay: reader.reborrow().get_will_relay(),
will_validate_dial_info: reader.reborrow().get_will_validate_dial_info(),
})
}
pub fn encode_node_status(
node_status: &NodeStatus,
builder: &mut veilid_capnp::node_status::Builder,
) -> Result<(), RPCError> {
match node_status {
NodeStatus::PublicInternetNodeStatus(ns) => {
let mut pi_builder = builder.reborrow().init_public_internet();
encode_public_internet_node_status(&ns, &mut pi_builder)
}
NodeStatus::LocalNetworkNodeStatus(ns) => {
let mut ln_builder = builder.reborrow().init_local_network();
encode_local_network_node_status(&ns, &mut ln_builder)
}
}
Ok(())
}
pub fn decode_node_status(
reader: &veilid_capnp::node_status::Reader,
) -> Result<NodeStatus, RPCError> {
Ok(
match reader
.which()
.map_err(RPCError::map_internal("invalid node status"))?
{
veilid_capnp::node_status::PublicInternet(pi) => {
let r = r.map_err(RPCError::protocol)?;
let pins = decode_public_internet_node_status(&r)?;
NodeStatus::PublicInternet(pins)
}
veilid_capnp::node_status::LocalNetwork(ln) => {
let r = ln.map_err(RPCError::protocol)?;
let lnns = decode_local_network_node_status(&r)?;
NodeStatus::LocalNetwork(lnns)
}
},
)
}

View File

@@ -58,26 +58,34 @@ impl RPCOperationKind {
#[derive(Debug, Clone)]
pub struct RPCOperation {
op_id: u64,
sender_info: Option<SignedNodeInfo>,
kind: RPCOperationKind,
}
impl RPCOperation {
pub fn new_question(question: RPCQuestion) -> Self {
pub fn new_question(question: RPCQuestion, sender_info: Option<SignedNodeInfo>) -> Self {
Self {
op_id: intf::get_random_u64(),
sender_info,
kind: RPCOperationKind::Question(question),
}
}
pub fn new_statement(statement: RPCStatement) -> Self {
pub fn new_statement(statement: RPCStatement, sender_info: Option<SignedNodeInfo>) -> Self {
Self {
op_id: intf::get_random_u64(),
sender_info,
kind: RPCOperationKind::Statement(statement),
}
}
pub fn new_answer(request: &RPCOperation, answer: RPCAnswer) -> Self {
pub fn new_answer(
request: &RPCOperation,
answer: RPCAnswer,
sender_info: Option<SignedNodeInfo>,
) -> Self {
Self {
op_id: request.op_id,
sender_info,
kind: RPCOperationKind::Answer(answer),
}
}
@@ -86,6 +94,10 @@ impl RPCOperation {
self.op_id
}
pub fn sender_info(&self) -> Option<&SignedNodeInfo> {
self.sender_info.as_ref()
}
pub fn kind(&self) -> &RPCOperationKind {
&self.kind
}
@@ -100,16 +112,32 @@ impl RPCOperation {
) -> Result<Self, RPCError> {
let op_id = operation_reader.get_op_id();
let sender_info = if operation_reader.has_sender_info() {
let sni_reader = operation_reader.get_sender_info();
let sni = decode_signed_node_info(&sni_reader, sender_node_id, true)?;
Some(sni)
} else {
None
};
let kind_reader = operation_reader.get_kind();
let kind = RPCOperationKind::decode(&kind_reader, sender_node_id)?;
Ok(RPCOperation { op_id, kind })
Ok(RPCOperation {
op_id,
sender_info,
kind,
})
}
pub fn encode(&self, builder: &mut veilid_capnp::operation::Builder) -> Result<(), RPCError> {
builder.set_op_id(self.op_id);
let mut k_builder = builder.reborrow().init_kind();
self.kind.encode(&mut k_builder)?;
if let Some(sender_info) = self.sender_info {
let si_builder = builder.reborrow().init_sender_info();
encode_signed_node_info(&self.sender_info, &mut si_builder)?;
}
Ok(())
}
}

View File

@@ -18,12 +18,6 @@ impl RPCQuestion {
pub fn detail(&self) -> &RPCQuestionDetail {
&self.detail
}
// pub fn into_detail(self) -> RPCQuestionDetail {
// self.detail
// }
// pub fn into_respond_to_detail(self) -> (RespondTo, RPCQuestionDetail) {
// (self.respond_to, self.detail)
// }
pub fn desc(&self) -> &'static str {
self.detail.desc()
}
@@ -32,7 +26,7 @@ impl RPCQuestion {
sender_node_id: &DHTKey,
) -> Result<RPCQuestion, RPCError> {
let rt_reader = reader.get_respond_to();
let respond_to = RespondTo::decode(&rt_reader, sender_node_id)?;
let respond_to = RespondTo::decode(&rt_reader)?;
let d_reader = reader.get_detail();
let detail = RPCQuestionDetail::decode(&d_reader)?;
Ok(RPCQuestion { respond_to, detail })

View File

@@ -3,7 +3,7 @@ use rpc_processor::*;
#[derive(Debug, Clone)]
pub enum RespondTo {
Sender(Option<SignedNodeInfo>),
Sender,
PrivateRoute(PrivateRoute),
}
@@ -13,11 +13,7 @@ impl RespondTo {
builder: &mut veilid_capnp::question::respond_to::Builder,
) -> Result<(), RPCError> {
match self {
Self::Sender(Some(sni)) => {
let mut sni_builder = builder.reborrow().init_sender_with_info();
encode_signed_node_info(sni, &mut sni_builder)?;
}
Self::Sender(None) => {
Self::Sender => {
builder.reborrow().set_sender(());
}
Self::PrivateRoute(pr) => {
@@ -28,17 +24,9 @@ impl RespondTo {
Ok(())
}
pub fn decode(
reader: &veilid_capnp::question::respond_to::Reader,
sender_node_id: &DHTKey,
) -> Result<Self, RPCError> {
pub fn decode(reader: &veilid_capnp::question::respond_to::Reader) -> Result<Self, RPCError> {
let respond_to = match reader.which().map_err(RPCError::protocol)? {
veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender(None),
veilid_capnp::question::respond_to::SenderWithInfo(sender_ni_reader) => {
let sender_ni_reader = sender_ni_reader.map_err(RPCError::protocol)?;
let sni = decode_signed_node_info(&sender_ni_reader, sender_node_id, true)?;
RespondTo::Sender(Some(sni))
}
veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender,
veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => {
let pr_reader = pr_reader.map_err(RPCError::protocol)?;
let pr = decode_private_route(&pr_reader)?;

View File

@@ -0,0 +1,135 @@
use super::*;
/// Where to send an RPC message
#[derive(Debug, Clone)]
pub enum Destination {
/// Send to node directly
Direct {
/// The node to send to
target: NodeRef,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to node for relay purposes
Relay {
/// The relay to send to
relay: NodeRef,
/// The final destination the relay should send to
target: DHTKey,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to private route (privateroute)
PrivateRoute {
/// A private route to send to
private_route: PrivateRoute,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
}
impl Destination {
pub fn direct(target: NodeRef) -> Self {
Self::Direct {
target,
safety_route_spec: None,
}
}
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
Self::Relay {
relay,
target,
safety_route_spec: None,
}
}
pub fn private_route(private_route: PrivateRoute) -> Self {
Self::PrivateRoute {
private_route,
safety_route_spec: None,
}
}
pub fn safety_route_spec(&self) -> Option<Arc<SafetyRouteSpec>> {
match self {
Destination::Direct {
target,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::Relay {
relay,
target,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => safety_route_spec.clone(),
}
}
pub fn with_safety_route_spec(self, safety_route_spec: Arc<SafetyRouteSpec>) -> Self {
match self {
Destination::Direct {
target,
safety_route_spec: _,
} => Self::Direct {
target,
safety_route_spec: Some(safety_route_spec),
},
Destination::Relay {
relay,
target,
safety_route_spec: _,
} => Self::Relay {
relay,
target,
safety_route_spec: Some(safety_route_spec),
},
Destination::PrivateRoute {
private_route,
safety_route_spec: _,
} => Self::PrivateRoute {
private_route,
safety_route_spec: Some(safety_route_spec),
},
}
}
}
impl fmt::Display for Destination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => {
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}{}", target, sr)
}
Destination::Relay {
relay,
target,
safety_route_spec,
} => {
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}@{:?}{}", target.encode(), relay, sr)
}
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => {
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{}{}", private_route, sr)
}
}
}
}

View File

@@ -1,4 +1,5 @@
mod coders;
mod destination;
mod private_route;
mod rpc_cancel_tunnel;
mod rpc_complete_tunnel;
@@ -18,6 +19,7 @@ mod rpc_validate_dial_info;
mod rpc_value_changed;
mod rpc_watch_value;
pub use destination::*;
pub use private_route::*;
pub use rpc_error::*;
@@ -36,208 +38,6 @@ use stop_token::future::FutureExt;
type OperationId = u64;
/// Where to send an RPC message
#[derive(Debug, Clone)]
pub enum Destination {
/// Send to node directly
Direct {
/// The node to send to
target: NodeRef,
/// An optional routing domain to require
routing_domain: Option<RoutingDomain>,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to node for relay purposes
Relay {
/// The relay to send to
relay: NodeRef,
/// The final destination the relay should send to
target: DHTKey,
/// An optional routing domain to require
routing_domain: Option<RoutingDomain>,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
/// Send to private route (privateroute)
PrivateRoute {
/// A private route to send to
private_route: PrivateRoute,
/// An optional safety route specification to send from for sender privacy
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
},
}
impl Destination {
pub fn direct(target: NodeRef) -> Self {
Self::Direct {
target,
routing_domain: None,
safety_route_spec: None,
}
}
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
Self::Relay {
relay,
target,
routing_domain: None,
safety_route_spec: None,
}
}
pub fn private_route(private_route: PrivateRoute) -> Self {
Self::PrivateRoute {
private_route,
safety_route_spec: None,
}
}
pub fn
pub fn routing_domain(&self) -> Option<RoutingDomain> {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => *routing_domain,
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => *routing_domain,
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => Some(RoutingDomain::PublicInternet),
}
}
pub fn safety_route_spec(&self) -> Option<Arc<SafetyRouteSpec>> {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => safety_route_spec.clone(),
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => safety_route_spec.clone(),
}
}
pub fn with_routing_domain(self, routing_domain: RoutingDomain) -> Self {
match self {
Destination::Direct {
target,
routing_domain: _,
safety_route_spec,
} => Self::Direct {
target,
routing_domain: Some(routing_domain),
safety_route_spec,
},
Destination::Relay {
relay,
target,
routing_domain: _,
safety_route_spec,
} => Self::Relay {
relay,
target,
routing_domain: Some(routing_domain),
safety_route_spec,
},
Destination::PrivateRoute {
private_route: _,
safety_route_spec: _,
} => panic!("Private route is only valid in PublicInternet routing domain"),
}
}
pub fn with_safety_route_spec(self, safety_route_spec: Arc<SafetyRouteSpec>) -> Self {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec: _,
} => Self::Direct {
target,
routing_domain,
safety_route_spec: Some(safety_route_spec),
},
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec: _,
} => Self::Relay {
relay,
target,
routing_domain,
safety_route_spec: Some(safety_route_spec),
},
Destination::PrivateRoute {
private_route,
safety_route_spec: _,
} => Self::PrivateRoute {
private_route,
safety_route_spec: Some(safety_route_spec),
},
}
}
}
impl fmt::Display for Destination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Destination::Direct {
target,
routing_domain,
safety_route_spec,
} => {
let rd = routing_domain
.map(|rd| format!("#{:?}", rd))
.unwrap_or_default();
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}{}{}", target, rd, sr)
}
Destination::Relay {
relay,
target,
routing_domain,
safety_route_spec,
} => {
let rd = routing_domain
.map(|rd| format!("#{:?}", rd))
.unwrap_or_default();
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{:?}@{:?}{}{}", target.encode(), relay, rd, sr)
}
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => {
let sr = safety_route_spec
.map(|_sr| "+SR".to_owned())
.unwrap_or_default();
write!(f, "{}{}", private_route, sr)
}
}
}
}
/// The decoded header of an RPC message
#[derive(Debug, Clone)]
struct RPCMessageHeader {
@@ -251,6 +51,8 @@ struct RPCMessageHeader {
peer_noderef: NodeRef,
/// The connection from the peer sent the message (not the original sender)
connection_descriptor: ConnectionDescriptor,
/// The routing domain the message was sent through
routing_domain: RoutingDomain,
}
#[derive(Debug)]
@@ -352,7 +154,6 @@ pub struct RPCProcessorInner {
pub struct RPCProcessor {
crypto: Crypto,
config: VeilidConfig,
enable_local_peer_scope: bool,
inner: Arc<Mutex<RPCProcessorInner>>,
}
@@ -375,11 +176,6 @@ impl RPCProcessor {
Self {
crypto: network_manager.crypto(),
config: network_manager.config(),
enable_local_peer_scope: network_manager
.config()
.get()
.network
.enable_local_peer_scope,
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
}
}
@@ -402,12 +198,8 @@ impl RPCProcessor {
//////////////////////////////////////////////////////////////////////
fn filter_peer_scope(&self, node_info: &NodeInfo) -> bool {
// if local peer scope is enabled, then don't reject any peer info
if self.enable_local_peer_scope {
return true;
}
/// Determine if a NodeInfo can be placed into the specified routing domain
fn filter_node_info(&self, routing_domain: RoutingDomain, node_info: &NodeInfo) -> bool {
// reject attempts to include non-public addresses in results
for did in &node_info.dial_info_detail_list {
if !did.dial_info.is_global() {
@@ -584,31 +376,6 @@ impl RPCProcessor {
out
}
/// Gets a 'RespondTo::Sender' that contains either our dial info,
/// or None if the peer has seen our dial info before or our node info is not yet valid
/// because of an unknown network class
pub fn make_respond_to_sender(
&self,
routing_domain: RoutingDomain,
peer: NodeRef,
) -> RespondTo {
if peer.has_seen_our_node_info(routing_domain)
|| matches!(
self.network_manager()
.get_network_class(routing_domain)
.unwrap_or(NetworkClass::Invalid),
NetworkClass::Invalid
)
{
RespondTo::Sender(None)
} else {
let our_sni = self
.routing_table()
.get_own_signed_node_info(routing_domain);
RespondTo::Sender(Some(our_sni))
}
}
/// Produce a byte buffer that represents the wire encoding of the entire
/// unencrypted envelope body for a RPC message. This incorporates
/// wrapping a private and/or safety route if they are specified.
@@ -617,7 +384,7 @@ impl RPCProcessor {
&self,
dest: Destination,
operation: &RPCOperation,
) -> Result<RenderedOperation, RPCError> { xxx continue propagating safetyroutespec
) -> Result<RenderedOperation, RPCError> {
let out_node_id; // Envelope Node Id
let mut out_node_ref: Option<NodeRef> = None; // Node to send envelope to
let out_hop_count: usize; // Total safety + private route hop count
@@ -634,12 +401,28 @@ impl RPCProcessor {
// To where are we sending the request
match dest {
Destination::Direct(ref node_ref) | Destination::Relay(ref node_ref, _) => {
Destination::Direct {
target: node_ref,
routing_domain,
safety_route_spec,
}
| Destination::Relay {
relay: node_ref,
target: _,
routing_domain,
safety_route_spec,
} => {
// Send to a node without a private route
// --------------------------------------
// Get the actual destination node id accounting for relays
let (node_ref, node_id) = if let Destination::Relay(_, dht_key) = dest {
let (node_ref, node_id) = if let Destination::Relay {
relay: _,
target: dht_key,
routing_domain: _,
safety_route_spec: _,
} = dest
{
(node_ref.clone(), dht_key.clone())
} else {
let node_id = node_ref.node_id();
@@ -676,7 +459,10 @@ impl RPCProcessor {
}
};
}
Destination::PrivateRoute(private_route) => {
Destination::PrivateRoute {
private_route,
safety_route_spec,
} => {
// Send to private route
// ---------------------
// Reply with 'route' operation
@@ -723,12 +509,22 @@ impl RPCProcessor {
}
// Issue a question over the network, possibly using an anonymized route
#[instrument(level = "debug", skip(self, question, safety_route_spec), err)]
#[instrument(level = "debug", skip(self, question), err)]
async fn question(
&self,
dest: Destination,
question: RPCQuestion,
) -> Result<NetworkResult<WaitableReply>, RPCError> {
// Get sender info if we should send that
let opt_sender_info = if dest.safety_route_spec().is_none() && matches!(question.respond_to(), RespondTo::Sender) {
// Sender is not private, send sender info if needed
// Get the noderef of the eventual destination or first route hop
if let Some(target_nr) = self.routing_table().lookup_node_ref(dest.get_target_id()) {
if target_nr.has_seen_our_node_info(R)
}
}
// Wrap question in operation
let operation = RPCOperation::new_question(question);
let op_id = operation.op_id();
@@ -951,6 +747,10 @@ impl RPCProcessor {
&self,
encoded_msg: RPCMessageEncoded,
) -> Result<(), RPCError> {
// Get the routing domain
let routing_domain = encoded_msg.header.routing_domain;
// Decode the operation
let sender_node_id = encoded_msg.header.envelope.get_sender_id();
@@ -971,12 +771,13 @@ impl RPCProcessor {
match q.respond_to() {
RespondTo::Sender(Some(sender_ni)) => {
// Sender NodeInfo was specified, update our routing table with it
if !self.filter_peer_scope(&sender_ni.node_info) {
if !self.filter_node_info(&sender_ni.node_info) {
return Err(RPCError::invalid_format(
"respond_to_sender_signed_node_info has invalid peer scope",
));
}
opt_sender_nr = self.routing_table().register_node_with_signed_node_info(
routing_domain,
sender_node_id,
sender_ni.clone(),
false,
@@ -1168,6 +969,7 @@ impl RPCProcessor {
body: Vec<u8>,
peer_noderef: NodeRef,
connection_descriptor: ConnectionDescriptor,
routing_domain: RoutingDomain,
) -> EyreResult<()> {
let msg = RPCMessageEncoded {
header: RPCMessageHeader {
@@ -1176,6 +978,7 @@ impl RPCProcessor {
body_len: body.len() as u64,
peer_noderef,
connection_descriptor,
routing_domain,
},
data: RPCMessageData { contents: body },
};

View File

@@ -4,7 +4,7 @@ impl RPCProcessor {
//////////////////////////////////////////////////////////////////////
fn compile_safety_route(
&self,
safety_route_spec: &SafetyRouteSpec,
safety_route_spec: Arc<SafetyRouteSpec>,
private_route: PrivateRoute,
) -> Result<SafetyRoute, RPCError> {
// Ensure the total hop count isn't too long for our config
@@ -111,15 +111,15 @@ impl RPCProcessor {
// Wrap an operation inside a route
pub(super) fn wrap_with_route(
&self,
safety_route_spec: Option<&SafetyRouteSpec>,
safety_route_spec: Option<Arc<SafetyRouteSpec>>,
private_route: PrivateRoute,
message_data: Vec<u8>,
) -> Result<Vec<u8>, RPCError> {
// Encrypt routed operation
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
let nonce = Crypto::get_random_nonce();
let stub_safety_route_spec = SafetyRouteSpec::new();
let safety_route_spec = safety_route_spec.unwrap_or(&stub_safety_route_spec);
let safety_route_spec =
safety_route_spec.unwrap_or_else(|| Arc::new(SafetyRouteSpec::new()));
let dh_secret = self
.crypto
.cached_dh(&private_route.public_key, &safety_route_spec.secret_key)

View File

@@ -8,15 +8,11 @@ impl RPCProcessor {
self,
dest: Destination,
key: DHTKey,
safety_route: Option<&SafetyRouteSpec>,
respond_to: RespondTo,
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
let find_node_q = RPCOperationFindNodeQ { node_id: key };
let question = RPCQuestion::new(respond_to, RPCQuestionDetail::FindNodeQ(find_node_q));
let find_node_q = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ { node_id: key });
// Send the find_node request
let waitable_reply =
network_result_try!(self.question(dest, question, safety_route).await?);
let waitable_reply = network_result_try!(self.question(dest, find_node_q).await?);
// Wait for reply
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
@@ -35,7 +31,7 @@ impl RPCProcessor {
// Verify peers are in the correct peer scope
for peer_info in &find_node_a.peers {
if !self.filter_peer_scope(&peer_info.signed_node_info.node_info) {
if !self.filter_node_info(&peer_info.signed_node_info.node_info) {
return Err(RPCError::invalid_format(
"find_node response has invalid peer scope",
));

View File

@@ -2,20 +2,20 @@ use super::*;
impl RPCProcessor {
// Sends a our node info to another node
// Can be sent via all methods including relays and routes
#[instrument(level = "trace", skip(self), ret, err)]
pub async fn rpc_call_node_info_update(
self,
target: NodeRef,
routing_domain: RoutingDomain,
) -> Result<NetworkResult<()>, RPCError> {
// Get the signed node info for the desired routing domain to send update with
let signed_node_info = self
.routing_table()
.get_own_signed_node_info(routing_domain);
let node_info_update = RPCOperationNodeInfoUpdate { signed_node_info };
let statement = RPCStatement::new(RPCStatementDetail::NodeInfoUpdate(node_info_update));
// Send the node_info_update request
// Send the node_info_update request to the specific routing domain requested
network_result_try!(
self.statement(
Destination::direct(target).with_routing_domain(routing_domain),
@@ -41,7 +41,7 @@ impl RPCProcessor {
};
// Update our routing table with signed node info
if !self.filter_peer_scope(&node_info_update.signed_node_info.node_info) {
if !self.filter_node_info(&node_info_update.signed_node_info.node_info) {
log_rpc!(debug
"node_info_update has invalid peer scope from {}", sender_node_id
);

View File

@@ -8,14 +8,21 @@ impl RPCProcessor {
self,
peer: NodeRef,
) -> Result<NetworkResult<Answer<SenderInfo>>, RPCError> {
let node_status = self.network_manager().generate_node_status();
let routing_domain = match peer.best_routing_domain() {
Some(rd) => rd,
None => {
return Ok(NetworkResult::no_connection_other(
"no routing domain for peer",
))
}
};
let node_status = self.network_manager().generate_node_status(routing_domain);
let status_q = RPCOperationStatusQ { node_status };
let respond_to = self.make_respond_to_sender(peer.clone());
let question = RPCQuestion::new(respond_to, RPCQuestionDetail::StatusQ(status_q));
let question = RPCQuestion::new(RespondTo::Sender, RPCQuestionDetail::StatusQ(status_q));
// Send the info request
let waitable_reply = network_result_try!(
self.question(Destination::Direct(peer.clone()), question, None)
self.question(Destination::direct(peer.clone()), question)
.await?
);
@@ -37,26 +44,48 @@ impl RPCProcessor {
_ => return Err(RPCError::invalid_format("not an answer")),
};
// Ensure the returned node status is the kind for the routing domain we asked for
match routing_domain {
RoutingDomain::PublicInternet => {
if !matches!(status_a.node_status, NodeStatus::PublicInternet(_)) {
return Ok(NetworkResult::invalid_message(
"node status doesn't match PublicInternet routing domain",
));
}
}
RoutingDomain::LocalNetwork => {
if !matches!(status_a.node_status, NodeStatus::LocalNetwork(_)) {
return Ok(NetworkResult::invalid_message(
"node status doesn't match LocalNetwork routing domain",
));
}
}
}
// Update latest node status in routing table
peer.update_node_status(status_a.node_status.clone());
peer.update_node_status(status_a.node_status);
// Report sender_info IP addresses to network manager
// Don't need to validate these addresses for the current routing domain
// the address itself is irrelevant, and the remote node can lie anyway
if let Some(socket_address) = status_a.sender_info.socket_address {
match send_data_kind {
SendDataKind::Direct(connection_descriptor) => {
match connection_descriptor.peer_scope() {
PeerScope::Global => self.network_manager().report_global_socket_address(
SendDataKind::Direct(connection_descriptor) => match routing_domain {
RoutingDomain::PublicInternet => self
.network_manager()
.report_public_internet_socket_address(
socket_address,
connection_descriptor,
peer,
),
PeerScope::Local => self.network_manager().report_local_socket_address(
RoutingDomain::LocalNetwork => {
self.network_manager().report_local_network_socket_address(
socket_address,
connection_descriptor,
peer,
),
)
}
}
},
SendDataKind::Indirect => {
// Do nothing in this case, as the socket address returned here would be for any node other than ours
}
@@ -75,6 +104,7 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id, res), err)]
pub(crate) async fn process_status_q(&self, msg: RPCMessage) -> Result<(), RPCError> {
let connection_descriptor = msg.header.connection_descriptor;
let routing_domain = msg.header.routing_domain;
// Get the question
let status_q = match msg.operation.kind() {
@@ -85,6 +115,24 @@ impl RPCProcessor {
_ => panic!("not a question"),
};
// Ensure the node status from the question is the kind for the routing domain we received the request in
match routing_domain {
RoutingDomain::PublicInternet => {
if !matches!(status_a.node_status, NodeStatus::PublicInternet(_)) {
return Ok(NetworkResult::invalid_message(
"node status doesn't match PublicInternet routing domain",
));
}
}
RoutingDomain::LocalNetwork => {
if !matches!(status_a.node_status, NodeStatus::LocalNetwork(_)) {
return Ok(NetworkResult::invalid_message(
"node status doesn't match LocalNetwork routing domain",
));
}
}
}
// update node status for the requesting node to our routing table
if let Some(sender_nr) = msg.opt_sender_nr.clone() {
// Update latest node status in routing table for the statusq sender
@@ -92,7 +140,7 @@ impl RPCProcessor {
}
// Make status answer
let node_status = self.network_manager().generate_node_status();
let node_status = self.network_manager().generate_node_status(routing_domain);
// Get the peer address in the returned sender info
let sender_info = SenderInfo {
@@ -106,11 +154,7 @@ impl RPCProcessor {
// Send status answer
let res = self
.answer(
msg,
RPCAnswer::new(RPCAnswerDetail::StatusA(status_a)),
None,
)
.answer(msg, RPCAnswer::new(RPCAnswerDetail::StatusA(status_a)))
.await?;
tracing::Span::current().record("res", &tracing::field::display(res));
Ok(())