checkpoint

This commit is contained in:
John Smith 2022-07-04 22:44:04 -04:00
parent 9214bcf9a4
commit 8b5fc96c8c
7 changed files with 197 additions and 252 deletions

View File

@ -85,7 +85,7 @@ impl DiscoveryContext {
node_ref
))
.map(|sa| {
let ret = sa.sender_info.socket_address;
let ret = sa.answer.socket_address;
log_net!("request_public_address: {:?}", ret);
ret
})

View File

@ -2,13 +2,21 @@ use crate::*;
use rpc_processor::*;
#[derive(Debug, Clone)]
struct RoutedOperation {
pub struct RoutedOperation {
pub signatures: Vec<DHTSignature>,
pub nonce: Nonce,
pub data: Vec<u8>,
}
impl RoutedOperation {
pub fn new(nonce: Nonce, data: Vec<u8>) -> Self {
Self {
signatures: Vec::new(),
nonce,
data,
}
}
pub fn decode(
reader: &veilid_capnp::routed_operation::Reader,
) -> Result<RoutedOperation, RPCError> {

View File

@ -61,9 +61,9 @@ pub fn encode_full_tunnel(
) -> Result<(), RPCError> {
builder.set_id(full_tunnel.id);
builder.set_timeout(full_tunnel.timeout);
let l_builder = builder.init_local();
let mut l_builder = builder.reborrow().init_local();
encode_tunnel_endpoint(&full_tunnel.local, &mut l_builder)?;
let r_builder = builder.init_remote();
let mut r_builder = builder.reborrow().init_remote();
encode_tunnel_endpoint(&full_tunnel.remote, &mut r_builder)?;
Ok(())
}
@ -92,7 +92,7 @@ pub fn encode_partial_tunnel(
) -> Result<(), RPCError> {
builder.set_id(partial_tunnel.id);
builder.set_timeout(partial_tunnel.timeout);
let l_builder = builder.init_local();
let mut l_builder = builder.reborrow().init_local();
encode_tunnel_endpoint(&partial_tunnel.local, &mut l_builder)?;
Ok(())
}

View File

@ -86,29 +86,3 @@ macro_rules! map_error_panic {
|_| panic!("oops")
};
}
impl RPCProcessor {
pub(super) fn get_rpc_message_debug_info<T: capnp::message::ReaderSegments>(
&self,
message: &capnp::message::Reader<T>,
) -> String {
let operation = match message.get_root::<veilid_capnp::operation::Reader>() {
Ok(v) => v,
Err(e) => {
return format!("invalid operation: {}", e);
}
};
let op_id = operation.get_op_id();
let detail = match operation.get_detail().which() {
Ok(v) => v,
Err(e) => {
return format!("(operation detail not in schema: {})", e);
}
};
format!(
"#{} {}",
op_id,
Self::get_rpc_operation_detail_debug_info(&detail)
)
}
}

View File

@ -140,10 +140,10 @@ impl<T> Answer<T> {
}
struct RenderedOperation {
out: Vec<u8>, // The rendered operation bytes
out_node_id: DHTKey, // Node id we're sending to
out_noderef: Option<NodeRef>, // Node to send envelope to (may not be destination node id in case of relay)
hopcount: usize, // Total safety + private route hop count
message: Vec<u8>, // The rendered operation bytes
node_id: DHTKey, // Node id we're sending to
node_ref: Option<NodeRef>, // Node to send envelope to (may not be destination node id in case of relay)
hop_count: usize, // Total safety + private route hop count
}
/////////////////////////////////////////////////////////////////////
@ -400,6 +400,9 @@ impl RPCProcessor {
}
}
// 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.
#[instrument(level = "debug", skip(self, operation, safety_route_spec), err)]
fn render_operation(
&self,
@ -407,110 +410,108 @@ impl RPCProcessor {
operation: &RPCOperation,
safety_route_spec: Option<&SafetyRouteSpec>,
) -> Result<RenderedOperation, RPCError> {
// Encode message to a builder and make a message reader for it
let mut msg_builder = ::capnp::message::Builder::new_default();
let mut op_builder = msg_builder.init_root::<veilid_capnp::operation::Builder>();
operation.encode(&mut op_builder)?;
// Create envelope data
let out_node_id; // Envelope Node Id
let mut out_noderef: Option<NodeRef> = None; // Node to send envelope to
let hopcount: usize; // Total safety + private route hop count
let out = {
let out; // Envelope data
let mut out_node_ref: Option<NodeRef> = None; // Node to send envelope to
let out_hop_count: usize; // Total safety + private route hop count
let out_message; // Envelope data
// To where are we sending the request
match dest {
Destination::Direct(node_ref) | Destination::Relay(node_ref, _) => {
// Send to a node without a private route
// --------------------------------------
// Encode message to a builder and make a message reader for it
// Then produce the message as an unencrypted byte buffer
let message_vec = {
let mut msg_builder = ::capnp::message::Builder::new_default();
let mut op_builder = msg_builder.init_root::<veilid_capnp::operation::Builder>();
operation.encode(&mut op_builder)?;
builder_to_vec(msg_builder)?
};
// Get the actual destination node id accounting for relays
let (node_ref, node_id) = if let Destination::Relay(_, dht_key) = dest {
(node_ref.clone(), dht_key.clone())
} else {
let node_id = node_ref.node_id();
(node_ref.clone(), node_id)
};
// To where are we sending the request
match dest {
Destination::Direct(node_ref) | Destination::Relay(node_ref, _) => {
// Send to a node without a private route
// --------------------------------------
// Handle the existence of safety route
match safety_route_spec {
None => {
// If no safety route is being used, and we're not sending to a private
// route, we can use a direct envelope instead of routing
out = builder_to_vec(msg_builder)?;
// Get the actual destination node id accounting for relays
let (node_ref, node_id) = if let Destination::Relay(_, dht_key) = dest {
(node_ref.clone(), dht_key.clone())
} else {
let node_id = node_ref.node_id();
(node_ref.clone(), node_id)
};
// Message goes directly to the node
out_node_id = node_id;
out_noderef = Some(node_ref);
hopcount = 1;
}
Some(sr) => {
// No private route was specified for the request
// but we are using a safety route, so we must create an empty private route
let mut pr_builder = ::capnp::message::Builder::new_default();
let private_route = PrivateRoute::new_stub(node_id);
// Handle the existence of safety route
match safety_route_spec {
None => {
// If no safety route is being used, and we're not sending to a private
// route, we can use a direct envelope instead of routing
out_message = message_vec;
let message_vec = builder_to_vec(msg_builder)?;
// first
out_node_id = sr
.hops
.first()
.ok_or_else(|| rpc_error_internal("no hop in safety route"))?
.dial_info
.node_id
.key;
out = self.wrap_with_route(Some(sr), private_route, message_vec)?;
hopcount = 1 + sr.hops.len();
}
};
}
Destination::PrivateRoute(private_route) => {
// Send to private route
// ---------------------
// Reply with 'route' operation
let message_vec = builder_to_vec(msg_builder)?;
out_node_id = match safety_route_spec {
None => {
// If no safety route, the first node is the first hop of the private route
hopcount = private_route.hop_count as usize;
let out_node_id = match &private_route.hops {
Some(rh) => rh.dial_info.node_id.key,
_ => return Err(rpc_error_internal("private route has no hops")),
};
out = self.wrap_with_route(None, private_route, message_vec)?;
out_node_id
}
Some(sr) => {
// If safety route is in use, first node is the first hop of the safety route
hopcount = 1 + sr.hops.len() + (private_route.hop_count as usize);
let out_node_id = sr
.hops
.first()
.ok_or_else(|| rpc_error_internal("no hop in safety route"))?
.dial_info
.node_id
.key;
out = self.wrap_with_route(Some(sr), private_route, message_vec)?;
out_node_id
}
// Message goes directly to the node
out_node_id = node_id;
out_node_ref = Some(node_ref);
out_hop_count = 1;
}
Some(sr) => {
// No private route was specified for the request
// but we are using a safety route, so we must create an empty private route
let mut pr_builder = ::capnp::message::Builder::new_default();
let private_route = PrivateRoute::new_stub(node_id);
// first
out_node_id = sr
.hops
.first()
.ok_or_else(|| rpc_error_internal("no hop in safety route"))?
.dial_info
.node_id
.key;
out_message = self.wrap_with_route(Some(sr), private_route, message_vec)?;
out_hop_count = 1 + sr.hops.len();
}
};
}
Destination::PrivateRoute(private_route) => {
// Send to private route
// ---------------------
// Reply with 'route' operation
out_node_id = match safety_route_spec {
None => {
// If no safety route, the first node is the first hop of the private route
out_hop_count = private_route.hop_count as usize;
let out_node_id = match &private_route.hops {
Some(rh) => rh.dial_info.node_id.key,
_ => return Err(rpc_error_internal("private route has no hops")),
};
out_message = self.wrap_with_route(None, private_route, message_vec)?;
out_node_id
}
Some(sr) => {
// If safety route is in use, first node is the first hop of the safety route
out_hop_count = 1 + sr.hops.len() + (private_route.hop_count as usize);
let out_node_id = sr
.hops
.first()
.ok_or_else(|| rpc_error_internal("no hop in safety route"))?
.dial_info
.node_id
.key;
out_message = self.wrap_with_route(Some(sr), private_route, message_vec)?;
out_node_id
}
}
}
out
};
}
// Verify hop count isn't larger than out maximum routed hop count
if hopcount > self.inner.lock().max_route_hop_count {
if out_hop_count > self.inner.lock().max_route_hop_count {
return Err(rpc_error_internal("hop count too long for route"))
.map_err(logthru_rpc!(warn));
}
Ok(RenderedOperation {
out,
out_node_id,
out_noderef,
hopcount,
message: out_message,
node_id: out_node_id,
node_ref: out_node_ref,
hop_count: out_hop_count,
})
}
@ -531,21 +532,17 @@ impl RPCProcessor {
// Produce rendered operation
let RenderedOperation {
out,
out_node_id,
out_noderef,
hopcount,
message,
node_id,
node_ref,
hop_count,
} = self.render_operation(dest, &operation, safety_route_spec)?;
// Calculate answer timeout
// Timeout is number of hops times the timeout per hop
let timeout = self.inner.lock().timeout * (hopcount as u64);
// If we need to resolve the first hop, do it
let node_ref = match out_noderef {
let node_ref = match node_ref {
None => {
// resolve node
self.resolve_node(out_node_id)
self.resolve_node(node_id)
.await
.map_err(logthru_rpc!(error))?
}
@ -555,15 +552,19 @@ impl RPCProcessor {
}
};
// Calculate answer timeout
// Timeout is number of hops times the timeout per hop
let timeout = self.inner.lock().timeout * (hop_count as u64);
// Set up op id eventual
let eventual = self.add_op_id_waiter(op_id);
// Send question
let bytes = out.len() as u64;
let bytes = message.len() as u64;
let send_ts = intf::get_timestamp();
let send_data_kind = match self
.network_manager()
.send_envelope(node_ref.clone(), Some(out_node_id), out)
.send_envelope(node_ref.clone(), Some(node_id), message)
.await
.map_err(RPCError::Internal)
{
@ -610,21 +611,17 @@ impl RPCProcessor {
// Produce rendered operation
let RenderedOperation {
out,
out_node_id,
out_noderef,
hopcount,
message,
node_id,
node_ref,
hop_count,
} = self.render_operation(dest, &operation, safety_route_spec)?;
// Calculate answer timeout
// Timeout is number of hops times the timeout per hop
let timeout = self.inner.lock().timeout * (hopcount as u64);
// If we need to resolve the first hop, do it
let node_ref = match out_noderef {
let node_ref = match node_ref {
None => {
// resolve node
self.resolve_node(out_node_id)
self.resolve_node(node_id)
.await
.map_err(logthru_rpc!(error))?
}
@ -634,12 +631,16 @@ impl RPCProcessor {
}
};
// Calculate answer timeout
// Timeout is number of hops times the timeout per hop
let timeout = self.inner.lock().timeout * (hop_count as u64);
// Send statement
let bytes = out.len() as u64;
let bytes = message.len() as u64;
let send_ts = intf::get_timestamp();
let send_data_kind = match self
.network_manager()
.send_envelope(node_ref.clone(), Some(out_node_id), out)
.send_envelope(node_ref.clone(), Some(node_id), message)
.await
.map_err(RPCError::Internal)
{
@ -709,17 +710,17 @@ impl RPCProcessor {
// Produce rendered operation
let RenderedOperation {
out,
out_node_id,
out_noderef,
hopcount,
message,
node_id,
node_ref,
hop_count,
} = self.render_operation(dest, &operation, safety_route_spec)?;
// If we need to resolve the first hop, do it
let node_ref = match out_noderef {
let node_ref = match node_ref {
None => {
// resolve node
self.resolve_node(out_node_id).await?
self.resolve_node(node_id).await?
}
Some(nr) => {
// got the node in the routing table already
@ -728,10 +729,10 @@ impl RPCProcessor {
};
// Send the reply
let bytes = out.len() as u64;
let bytes = message.len() as u64;
let send_ts = intf::get_timestamp();
self.network_manager()
.send_envelope(node_ref.clone(), Some(out_node_id), out)
.send_envelope(node_ref.clone(), Some(node_id), message)
.await
.map_err(RPCError::Internal)
.map_err(|e| {

View File

@ -15,33 +15,17 @@ impl RPCProcessor {
return Err(rpc_error_internal("hop count too long for route"));
}
// Build the safety route
let mut sr_pk = builder.reborrow().init_public_key();
encode_public_key(&safety_route_spec.public_key, &mut sr_pk)?;
builder.set_hop_count(
u8::try_from(sr_hopcount)
.map_err(map_error_internal!("hop count too large for safety route"))?,
);
// Build all the hops in the safety route
let mut hops_builder = builder.reborrow().init_hops();
if sr_hopcount == 0 {
hops_builder
.set_private(private_route)
.map_err(map_error_internal!(
"invalid private route while encoding safety route"
))?;
// Create hops
let hops = if sr_hopcount == 0 {
SafetyRouteHops::Private(private_route)
} else {
// start last blob-to-encrypt data off as private route
let mut blob_data = {
let mut pr_message = ::capnp::message::Builder::new_default();
pr_message
.set_root_canonical(private_route)
.map_err(map_error_internal!(
"invalid private route while encoding safety route"
))?;
let mut pr_builder = pr_message.init_root::<veilid_capnp::private_route::Builder>();
encode_private_route(&private_route, &mut pr_builder)?;
let mut blob_data = builder_to_vec(pr_message)?;
// append the private route tag so we know how to decode it later
blob_data.push(1u8);
blob_data
@ -56,16 +40,6 @@ impl RPCProcessor {
for h in (1..sr_hopcount).rev() {
// Get blob to encrypt for next hop
blob_data = {
// RouteHop
let mut rh_message = ::capnp::message::Builder::new_default();
let mut rh_builder = rh_message.init_root::<veilid_capnp::route_hop::Builder>();
let mut di_builder = rh_builder.reborrow().init_dial_info();
encode_node_dial_info(&safety_route_spec.hops[h].dial_info, &mut di_builder)?;
// RouteHopData
let mut rhd_builder = rh_builder.init_next_hop();
// Add the nonce
let mut rhd_nonce = rhd_builder.reborrow().init_nonce();
encode_nonce(&nonce, &mut rhd_nonce);
// Encrypt the previous blob ENC(nonce, DH(PKhop,SKsr))
let dh_secret = self
.crypto
@ -78,21 +52,34 @@ impl RPCProcessor {
Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
.map_err(map_error_internal!("encryption failed"))?;
rhd_builder.set_blob(enc_msg_data.as_slice());
// Make route hop data
let route_hop_data = RouteHopData {
nonce,
blob: enc_msg_data,
};
// Make route hop
let route_hop = RouteHop {
dial_info: safety_route_spec.hops[h].dial_info.clone(),
next_hop: Some(route_hop_data),
};
// Make next blob from route hop
let mut rh_message = ::capnp::message::Builder::new_default();
let mut rh_builder = rh_message.init_root::<veilid_capnp::route_hop::Builder>();
encode_route_hop(&route_hop, &mut rh_builder)?;
let mut blob_data = builder_to_vec(rh_message)?;
// append the route hop tag so we know how to decode it later
// Append the route hop tag so we know how to decode it later
blob_data.push(0u8);
blob_data
};
// Make another nonce for the next hop
nonce = Crypto::get_random_nonce();
}
// Encode first RouteHopData
let mut first_rhd_builder = hops_builder.init_data();
let mut first_rhd_nonce = first_rhd_builder.reborrow().init_nonce();
encode_nonce(&nonce, &mut first_rhd_nonce);
let dh_secret = self
.crypto
.cached_dh(
@ -103,86 +90,61 @@ impl RPCProcessor {
let enc_msg_data = Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
.map_err(map_error_internal!("encryption failed"))?;
first_rhd_builder.set_blob(enc_msg_data.as_slice());
}
let route_hop_data = RouteHopData {
nonce,
blob: enc_msg_data,
};
Ok(())
SafetyRouteHops::Data(route_hop_data)
};
// Build safety route
let safety_route = SafetyRoute {
public_key: safety_route_spec.public_key,
hop_count: safety_route_spec.hops.len() as u8,
hops,
};
Ok(safety_route)
}
// Wrap an operation inside a route
pub(super) fn wrap_with_route(
&self,
safety_route: Option<&SafetyRouteSpec>,
safety_route_spec: Option<&SafetyRouteSpec>,
private_route: PrivateRoute,
message_data: Vec<u8>,
) -> Result<Vec<u8>, RPCError> {
// Encode the private route
let mut pr_msg_builder = ::capnp::message::Builder::new_default();
let mut pr_builder = pr_msg_builder.init_root::<veilid_capnp::private_route::Builder>();
encode_private_route(&private_route, &mut pr_builder)?;
let pr_reader = pr_builder.into_reader();
// Get stuff before we lock inner
let op_id = intf::get_random_u64();
// Encrypt routed operation
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
let nonce = Crypto::get_random_nonce();
let pr_pk_reader = private_route
.get_public_key()
.map_err(map_error_internal!("public key is invalid"))?;
let pr_pk = decode_public_key(&pr_pk_reader);
let stub_safety_route = SafetyRouteSpec::new();
let sr = safety_route.unwrap_or(&stub_safety_route);
let stub_safety_route_spec = SafetyRouteSpec::new();
let safety_route_spec = safety_route_spec.unwrap_or(&stub_safety_route_spec);
let dh_secret = self
.crypto
.cached_dh(&pr_pk, &sr.secret_key)
.cached_dh(&private_route.public_key, &safety_route_spec.secret_key)
.map_err(map_error_internal!("dh failed"))?;
let enc_msg_data = Crypto::encrypt_aead(&message_data, &nonce, &dh_secret, None)
.map_err(map_error_internal!("encryption failed"))?;
// Compile the safety route with the private route
let safety_route = self.compile_safety_route(safety_route_spec, private_route)?;
// Make the routed operation
let operation = RoutedOperation::new(nonce, enc_msg_data);
// Prepare route operation
let route = RPCOperationRoute {
safety_route: todo!(),
operation: todo!(),
};
let route_msg = {
let mut route_msg = ::capnp::message::Builder::new_default();
let mut route_operation = route_msg.init_root::<veilid_capnp::operation::Builder>();
// Doesn't matter what this op id because there's no answer
// but it shouldn't conflict with any other op id either
route_operation.set_op_id(op_id);
// Answers don't get a 'respond'
let mut respond_to = route_operation.reborrow().init_respond_to();
respond_to.set_none(());
// Set up 'route' operation
let mut route = route_operation.reborrow().init_detail().init_route();
// Set the safety route we've constructed
let mut msg_sr = route.reborrow().init_safety_route();
self.encode_safety_route(sr, private_route, &mut msg_sr)?;
// Put in the encrypted operation we're routing
let mut msg_operation = route.init_operation();
msg_operation.reborrow().init_signatures(0);
let mut route_nonce = msg_operation.reborrow().init_nonce();
encode_nonce(&nonce, &mut route_nonce);
let data = msg_operation.reborrow().init_data(
enc_msg_data
.len()
.try_into()
.map_err(map_error_internal!("data too large"))?,
);
data.copy_from_slice(enc_msg_data.as_slice());
route_msg
safety_route,
operation,
};
let operation =
RPCOperation::new_statement(RPCStatement::new(RPCStatementDetail::Route(route)));
// Convert message to bytes and return it
let mut route_msg = ::capnp::message::Builder::new_default();
let mut route_operation = route_msg.init_root::<veilid_capnp::operation::Builder>();
operation.encode(&mut route_operation)?;
let out = builder_to_vec(route_msg)?;
Ok(out)
}

View File

@ -1581,13 +1581,13 @@ pub enum SignalInfo {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
pub enum TunnelMode {
Raw,
Turn,
}
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
pub enum TunnelError {
BadId, // Tunnel ID was rejected
NoEndpoint, // Endpoint was unreachable