receipt fixes

This commit is contained in:
John Smith 2022-05-28 16:11:50 -04:00
parent 3c5274cddd
commit ad4b6328ac
7 changed files with 153 additions and 198 deletions

View File

@ -111,12 +111,12 @@ struct NodeDialInfo {
############################## ##############################
struct SignalInfoHolePunch { struct SignalInfoHolePunch {
receiptNonce @0 :Nonce; # receipt to return with hole punch receipt @0 :Data; # receipt to return with hole punch
peerInfo @1 :PeerInfo; # peer info of the signal sender for hole punch attempt peerInfo @1 :PeerInfo; # peer info of the signal sender for hole punch attempt
} }
struct SignalInfoReverseConnect { struct SignalInfoReverseConnect {
receiptNonce @0 :Nonce; # receipt to return with reverse connect receipt @0 :Data; # receipt to return with reverse connect
peerInfo @1 :PeerInfo; # peer info of the signal sender for reverse connect attempt peerInfo @1 :PeerInfo; # peer info of the signal sender for reverse connect attempt
} }
@ -240,15 +240,12 @@ struct OperationStatusA {
struct OperationValidateDialInfo { struct OperationValidateDialInfo {
dialInfo @0 :DialInfo; # dial info to use for the receipt dialInfo @0 :DialInfo; # dial info to use for the receipt
minVersion @1 :UInt8; # minimum version for the direct receipt receipt @1 :Data; # receipt to return to dial info to prove it is reachable
maxVersion @2 :UInt8; # maximum version for the direct receipt redirect @2 :Bool; # request a different node do the validate
receiptNonce @3 :Nonce; # receipt to return to dial info to prove it is reachable
redirect @4 :Bool; # request a different node do the validate
} }
struct OperationReturnReceipt { struct OperationReturnReceipt {
receiptNonce @0 :Nonce; # receipt being returned to its origin receipt @0 :Data; # receipt being returned to its origin
extraData @1 :Data; # extra data for receipt
} }
struct OperationFindNodeQ { struct OperationFindNodeQ {

View File

@ -423,41 +423,53 @@ impl NetworkManager {
} }
// Generates a multi-shot/normal receipt // Generates a multi-shot/normal receipt
pub fn generate_receipt( pub fn generate_receipt<D: AsRef<[u8]>>(
&self, &self,
expiration_us: u64, expiration_us: u64,
expected_returns: u32, expected_returns: u32,
extra_data: D,
callback: impl ReceiptCallback, callback: impl ReceiptCallback,
) -> Result<ReceiptNonce, String> { ) -> Result<Vec<u8>, String> {
let receipt_manager = self.receipt_manager(); let receipt_manager = self.receipt_manager();
let routing_table = self.routing_table();
// Generate receipt nonce // Generate receipt and serialized form to return
let receipt_nonce = Crypto::get_random_nonce(); let nonce = Crypto::get_random_nonce();
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
let out = receipt
.to_signed_data(&routing_table.node_id_secret())
.map_err(|_| "failed to generate signed receipt".to_owned())?;
// Record the receipt for later // Record the receipt for later
let exp_ts = intf::get_timestamp() + expiration_us; let exp_ts = intf::get_timestamp() + expiration_us;
receipt_manager.record_receipt(receipt_nonce, exp_ts, expected_returns, callback); receipt_manager.record_receipt(receipt, exp_ts, expected_returns, callback);
Ok(receipt_nonce) Ok(out)
} }
// Generates a single-shot/normal receipt // Generates a single-shot/normal receipt
pub fn generate_single_shot_receipt( pub fn generate_single_shot_receipt<D: AsRef<[u8]>>(
&self, &self,
expiration_us: u64, expiration_us: u64,
) -> Result<(ReceiptNonce, EventualValueFuture<ReceiptEvent>), String> { extra_data: D,
) -> Result<(Vec<u8>, EventualValueFuture<ReceiptEvent>), String> {
let receipt_manager = self.receipt_manager(); let receipt_manager = self.receipt_manager();
let routing_table = self.routing_table();
// Generate receipt nonce // Generate receipt and serialized form to return
let receipt_nonce = Crypto::get_random_nonce(); let nonce = Crypto::get_random_nonce();
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
let out = receipt
.to_signed_data(&routing_table.node_id_secret())
.map_err(|_| "failed to generate signed receipt".to_owned())?;
// Record the receipt for later // Record the receipt for later
let exp_ts = intf::get_timestamp() + expiration_us; let exp_ts = intf::get_timestamp() + expiration_us;
let eventual = SingleShotEventual::new(Some(ReceiptEvent::Cancelled)); let eventual = SingleShotEventual::new(Some(ReceiptEvent::Cancelled));
let instance = eventual.instance(); let instance = eventual.instance();
receipt_manager.record_single_shot_receipt(receipt_nonce, exp_ts, eventual); receipt_manager.record_single_shot_receipt(receipt, exp_ts, eventual);
Ok((receipt_nonce, instance)) Ok((out, instance))
} }
// Process a received out-of-band receipt // Process a received out-of-band receipt
@ -468,34 +480,31 @@ impl NetworkManager {
let receipt_manager = self.receipt_manager(); let receipt_manager = self.receipt_manager();
let receipt = Receipt::from_signed_data(receipt_data.as_ref()) let receipt = Receipt::from_signed_data(receipt_data.as_ref())
.map_err(|_| "failed to parse signed receipt".to_owned())?; .map_err(|_| "failed to parse signed out-of-band receipt".to_owned())?;
receipt_manager receipt_manager.handle_receipt(receipt, None).await
.handle_receipt(receipt.get_nonce(), receipt.get_extra_data().to_vec(), None)
.await
} }
// Process a received in-band receipt // Process a received in-band receipt
pub async fn handle_in_band_receipt( pub async fn handle_in_band_receipt<R: AsRef<[u8]>>(
&self, &self,
receipt_nonce: ReceiptNonce, receipt_data: R,
extra_data: Vec<u8>,
inbound_nr: NodeRef, inbound_nr: NodeRef,
) -> Result<(), String> { ) -> Result<(), String> {
let receipt_manager = self.receipt_manager(); let receipt_manager = self.receipt_manager();
let receipt = Receipt::from_signed_data(receipt_data.as_ref())
.map_err(|_| "failed to parse signed in-band receipt".to_owned())?;
receipt_manager receipt_manager
.handle_receipt(receipt_nonce, extra_data, Some(inbound_nr)) .handle_receipt(receipt, Some(inbound_nr))
.await .await
} }
// Process a received signal // Process a received signal
pub async fn handle_signal(&self, signal_info: SignalInfo) -> Result<(), String> { pub async fn handle_signal(&self, signal_info: SignalInfo) -> Result<(), String> {
match signal_info { match signal_info {
SignalInfo::ReverseConnect { SignalInfo::ReverseConnect { receipt, peer_info } => {
receipt_nonce,
peer_info,
} => {
let routing_table = self.routing_table(); let routing_table = self.routing_table();
let rpc = self.rpc_processor(); let rpc = self.rpc_processor();
@ -506,14 +515,11 @@ impl NetworkManager {
)?; )?;
// Make a reverse connection to the peer and send the receipt to it // Make a reverse connection to the peer and send the receipt to it
rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt_nonce, []) rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt)
.await .await
.map_err(map_to_string)?; .map_err(map_to_string)?;
} }
SignalInfo::HolePunch { SignalInfo::HolePunch { receipt, peer_info } => {
receipt_nonce,
peer_info,
} => {
let routing_table = self.routing_table(); let routing_table = self.routing_table();
let rpc = self.rpc_processor(); let rpc = self.rpc_processor();
@ -547,7 +553,7 @@ impl NetworkManager {
// XXX: do we need a delay here? or another hole punch packet? // XXX: do we need a delay here? or another hole punch packet?
// Return the receipt using the same dial info send the receipt to it // Return the receipt using the same dial info send the receipt to it
rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt_nonce, []) rpc.rpc_call_return_receipt(Destination::Direct(peer_nr), None, receipt)
.await .await
.map_err(map_to_string)?; .map_err(map_to_string)?;
} }
@ -634,21 +640,16 @@ impl NetworkManager {
} }
// Called by the RPC handler when we want to issue an direct receipt // Called by the RPC handler when we want to issue an direct receipt
pub async fn send_out_of_band_receipt<D: AsRef<[u8]>>( pub async fn send_out_of_band_receipt(
&self, &self,
dial_info: DialInfo, dial_info: DialInfo,
version: u8, rcpt_data: Vec<u8>,
receipt_nonce: Nonce,
extra_data: D,
) -> Result<(), String> { ) -> Result<(), String> {
let routing_table = self.routing_table(); // Do we need to validate the outgoing receipt? Probably not
let node_id = routing_table.node_id(); // because it is supposed to be opaque and the
let node_id_secret = routing_table.node_id_secret(); // recipient/originator does the validation
// Also, in the case of an old 'version', returning the receipt
let receipt = Receipt::try_new(version, receipt_nonce, node_id, extra_data)?; // should not be subject to our ability to decode it
let rcpt_data = receipt
.to_signed_data(&node_id_secret)
.map_err(|_| "failed to sign receipt".to_owned())?;
// Send receipt directly // Send receipt directly
self.net() self.net()
@ -785,8 +786,8 @@ impl NetworkManager {
// Build a return receipt for the signal // Build a return receipt for the signal
let receipt_timeout = let receipt_timeout =
ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms); ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms);
let (receipt_nonce, eventual_value) = self let (receipt, eventual_value) = self
.generate_single_shot_receipt(receipt_timeout) .generate_single_shot_receipt(receipt_timeout, [])
.map_err(map_to_string)?; .map_err(map_to_string)?;
// Get our peer info // Get our peer info
@ -797,23 +798,17 @@ impl NetworkManager {
rpc.rpc_call_signal( rpc.rpc_call_signal(
Destination::Relay(relay_nr.clone(), target_nr.node_id()), Destination::Relay(relay_nr.clone(), target_nr.node_id()),
None, None,
SignalInfo::ReverseConnect { SignalInfo::ReverseConnect { receipt, peer_info },
receipt_nonce,
peer_info,
},
) )
.await .await
.map_err(logthru_net!("failed to send signal to {:?}", relay_nr)) .map_err(logthru_net!("failed to send signal to {:?}", relay_nr))
.map_err(map_to_string)?; .map_err(map_to_string)?;
// Wait for the return receipt // Wait for the return receipt
let inbound_nr = match eventual_value.await.take_value().unwrap() { let inbound_nr = match eventual_value.await.take_value().unwrap() {
ReceiptEvent::ReturnedOutOfBand { extra_data: _ } => { ReceiptEvent::ReturnedOutOfBand => {
return Err("reverse connect receipt should be returned in-band".to_owned()); return Err("reverse connect receipt should be returned in-band".to_owned());
} }
ReceiptEvent::ReturnedInBand { ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef,
inbound_noderef,
extra_data: _,
} => inbound_noderef,
ReceiptEvent::Expired => { ReceiptEvent::Expired => {
return Err(format!( return Err(format!(
"reverse connect receipt expired from {:?}", "reverse connect receipt expired from {:?}",
@ -871,8 +866,8 @@ impl NetworkManager {
// Build a return receipt for the signal // Build a return receipt for the signal
let receipt_timeout = let receipt_timeout =
ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms); ms_to_us(self.config.get().network.reverse_connection_receipt_time_ms);
let (receipt_nonce, eventual_value) = self let (receipt, eventual_value) = self
.generate_single_shot_receipt(receipt_timeout) .generate_single_shot_receipt(receipt_timeout, [])
.map_err(map_to_string)?; .map_err(map_to_string)?;
// Get our peer info // Get our peer info
@ -894,10 +889,7 @@ impl NetworkManager {
rpc.rpc_call_signal( rpc.rpc_call_signal(
Destination::Relay(relay_nr.clone(), target_nr.node_id()), Destination::Relay(relay_nr.clone(), target_nr.node_id()),
None, None,
SignalInfo::HolePunch { SignalInfo::HolePunch { receipt, peer_info },
receipt_nonce,
peer_info,
},
) )
.await .await
.map_err(logthru_net!("failed to send signal to {:?}", relay_nr)) .map_err(logthru_net!("failed to send signal to {:?}", relay_nr))
@ -905,13 +897,10 @@ impl NetworkManager {
// Wait for the return receipt // Wait for the return receipt
let inbound_nr = match eventual_value.await.take_value().unwrap() { let inbound_nr = match eventual_value.await.take_value().unwrap() {
ReceiptEvent::ReturnedOutOfBand { extra_data: _ } => { ReceiptEvent::ReturnedOutOfBand => {
return Err("hole punch receipt should be returned in-band".to_owned()); return Err("hole punch receipt should be returned in-band".to_owned());
} }
ReceiptEvent::ReturnedInBand { ReceiptEvent::ReturnedInBand { inbound_noderef } => inbound_noderef,
inbound_noderef,
extra_data: _,
} => inbound_noderef,
ReceiptEvent::Expired => { ReceiptEvent::Expired => {
return Err(format!("hole punch receipt expired from {}", target_nr)); return Err(format!("hole punch receipt expired from {}", target_nr));
} }

View File

@ -8,13 +8,8 @@ use xx::*;
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum ReceiptEvent { pub enum ReceiptEvent {
ReturnedOutOfBand { ReturnedOutOfBand,
extra_data: Vec<u8>, ReturnedInBand { inbound_noderef: NodeRef },
},
ReturnedInBand {
inbound_noderef: NodeRef,
extra_data: Vec<u8>,
},
Expired, Expired,
Cancelled, Cancelled,
} }
@ -25,24 +20,24 @@ cfg_if! {
fn call( fn call(
&self, &self,
event: ReceiptEvent, event: ReceiptEvent,
nonce: ReceiptNonce, receipt: Receipt,
returns_so_far: u32, returns_so_far: u32,
expected_returns: u32, expected_returns: u32,
) -> SystemPinBoxFuture<()>; ) -> SystemPinBoxFuture<()>;
} }
impl<T, F> ReceiptCallback for T impl<T, F> ReceiptCallback for T
where where
T: Fn(ReceiptEvent, ReceiptNonce, u32, u32) -> F + 'static, T: Fn(ReceiptEvent, Receipt, u32, u32) -> F + 'static,
F: Future<Output = ()> + 'static, F: Future<Output = ()> + 'static,
{ {
fn call( fn call(
&self, &self,
event: ReceiptEvent, event: ReceiptEvent,
nonce: ReceiptNonce, receipt: Receipt,
returns_so_far: u32, returns_so_far: u32,
expected_returns: u32, expected_returns: u32,
) -> SystemPinBoxFuture<()> { ) -> SystemPinBoxFuture<()> {
Box::pin(self(event, nonce, returns_so_far, expected_returns)) Box::pin(self(event, receipt, returns_so_far, expected_returns))
} }
} }
} else { } else {
@ -50,24 +45,24 @@ cfg_if! {
fn call( fn call(
&self, &self,
event: ReceiptEvent, event: ReceiptEvent,
nonce: ReceiptNonce, receipt: Receipt,
returns_so_far: u32, returns_so_far: u32,
expected_returns: u32, expected_returns: u32,
) -> SystemPinBoxFuture<()>; ) -> SystemPinBoxFuture<()>;
} }
impl<F, T> ReceiptCallback for T impl<F, T> ReceiptCallback for T
where where
T: Fn(ReceiptEvent, ReceiptNonce, u32, u32) -> F + Send + 'static, T: Fn(ReceiptEvent, Receipt, u32, u32) -> F + Send + 'static,
F: Future<Output = ()> + Send + 'static F: Future<Output = ()> + Send + 'static
{ {
fn call( fn call(
&self, &self,
event: ReceiptEvent, event: ReceiptEvent,
nonce: ReceiptNonce, receipt: Receipt,
returns_so_far: u32, returns_so_far: u32,
expected_returns: u32, expected_returns: u32,
) -> SystemPinBoxFuture<()> { ) -> SystemPinBoxFuture<()> {
Box::pin(self(event, nonce, returns_so_far, expected_returns)) Box::pin(self(event, receipt, returns_so_far, expected_returns))
} }
} }
} }
@ -95,7 +90,7 @@ impl fmt::Debug for ReceiptRecordCallbackType {
pub struct ReceiptRecord { pub struct ReceiptRecord {
expiration_ts: u64, expiration_ts: u64,
nonce: ReceiptNonce, receipt: Receipt,
expected_returns: u32, expected_returns: u32,
returns_so_far: u32, returns_so_far: u32,
receipt_callback: ReceiptRecordCallbackType, receipt_callback: ReceiptRecordCallbackType,
@ -105,7 +100,7 @@ impl fmt::Debug for ReceiptRecord {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReceiptRecord") f.debug_struct("ReceiptRecord")
.field("expiration_ts", &self.expiration_ts) .field("expiration_ts", &self.expiration_ts)
.field("nonce", &self.nonce) .field("receipt", &self.receipt)
.field("expected_returns", &self.expected_returns) .field("expected_returns", &self.expected_returns)
.field("returns_so_far", &self.returns_so_far) .field("returns_so_far", &self.returns_so_far)
.field("receipt_callback", &self.receipt_callback) .field("receipt_callback", &self.receipt_callback)
@ -115,14 +110,14 @@ impl fmt::Debug for ReceiptRecord {
impl ReceiptRecord { impl ReceiptRecord {
pub fn new( pub fn new(
receipt_nonce: ReceiptNonce, receipt: Receipt,
expiration_ts: u64, expiration_ts: u64,
expected_returns: u32, expected_returns: u32,
receipt_callback: impl ReceiptCallback, receipt_callback: impl ReceiptCallback,
) -> Self { ) -> Self {
Self { Self {
expiration_ts, expiration_ts,
nonce: receipt_nonce, receipt,
expected_returns, expected_returns,
returns_so_far: 0u32, returns_so_far: 0u32,
receipt_callback: ReceiptRecordCallbackType::Normal(Box::new(receipt_callback)), receipt_callback: ReceiptRecordCallbackType::Normal(Box::new(receipt_callback)),
@ -130,13 +125,13 @@ impl ReceiptRecord {
} }
pub fn new_single_shot( pub fn new_single_shot(
receipt_nonce: ReceiptNonce, receipt: Receipt,
expiration_ts: u64, expiration_ts: u64,
eventual: ReceiptSingleShotType, eventual: ReceiptSingleShotType,
) -> Self { ) -> Self {
Self { Self {
expiration_ts, expiration_ts,
nonce: receipt_nonce, receipt,
returns_so_far: 0u32, returns_so_far: 0u32,
expected_returns: 1u32, expected_returns: 1u32,
receipt_callback: ReceiptRecordCallbackType::SingleShot(Some(eventual)), receipt_callback: ReceiptRecordCallbackType::SingleShot(Some(eventual)),
@ -223,7 +218,7 @@ impl ReceiptManager {
match &mut record_mut.receipt_callback { match &mut record_mut.receipt_callback {
ReceiptRecordCallbackType::Normal(callback) => Some(callback.call( ReceiptRecordCallbackType::Normal(callback) => Some(callback.call(
evt, evt,
record_mut.nonce, record_mut.receipt.clone(),
record_mut.returns_so_far, record_mut.returns_so_far,
record_mut.expected_returns, record_mut.expected_returns,
)), )),
@ -308,14 +303,15 @@ impl ReceiptManager {
pub fn record_receipt( pub fn record_receipt(
&self, &self,
receipt_nonce: ReceiptNonce, receipt: Receipt,
expiration: u64, expiration: u64,
expected_returns: u32, expected_returns: u32,
callback: impl ReceiptCallback, callback: impl ReceiptCallback,
) { ) {
let receipt_nonce = receipt.get_nonce();
log_rpc!(debug "== New Multiple Receipt ({}) {} ", expected_returns, receipt_nonce.encode()); log_rpc!(debug "== New Multiple Receipt ({}) {} ", expected_returns, receipt_nonce.encode());
let record = Arc::new(Mutex::new(ReceiptRecord::new( let record = Arc::new(Mutex::new(ReceiptRecord::new(
receipt_nonce, receipt,
expiration, expiration,
expected_returns, expected_returns,
callback, callback,
@ -328,16 +324,15 @@ impl ReceiptManager {
pub fn record_single_shot_receipt( pub fn record_single_shot_receipt(
&self, &self,
receipt_nonce: ReceiptNonce, receipt: Receipt,
expiration: u64, expiration: u64,
eventual: ReceiptSingleShotType, eventual: ReceiptSingleShotType,
) { ) {
let receipt_nonce = receipt.get_nonce();
log_rpc!(debug "== New SingleShot Receipt {}", receipt_nonce.encode()); log_rpc!(debug "== New SingleShot Receipt {}", receipt_nonce.encode());
let record = Arc::new(Mutex::new(ReceiptRecord::new_single_shot( let record = Arc::new(Mutex::new(ReceiptRecord::new_single_shot(
receipt_nonce, receipt, expiration, eventual,
expiration,
eventual,
))); )));
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
inner.records_by_nonce.insert(receipt_nonce, record); inner.records_by_nonce.insert(receipt_nonce, record);
@ -393,10 +388,12 @@ impl ReceiptManager {
pub async fn handle_receipt( pub async fn handle_receipt(
&self, &self,
receipt_nonce: ReceiptNonce, receipt: Receipt,
extra_data: Vec<u8>,
inbound_noderef: Option<NodeRef>, inbound_noderef: Option<NodeRef>,
) -> Result<(), String> { ) -> Result<(), String> {
let receipt_nonce = receipt.get_nonce();
let extra_data = receipt.get_extra_data();
log_rpc!(debug "<<== RECEIPT {} <- {}{}", log_rpc!(debug "<<== RECEIPT {} <- {}{}",
receipt_nonce.encode(), receipt_nonce.encode(),
if let Some(nr) = &inbound_noderef { if let Some(nr) = &inbound_noderef {
@ -427,12 +424,9 @@ impl ReceiptManager {
// Get the receipt event to return // Get the receipt event to return
let receipt_event = if let Some(inbound_noderef) = inbound_noderef { let receipt_event = if let Some(inbound_noderef) = inbound_noderef {
ReceiptEvent::ReturnedInBand { ReceiptEvent::ReturnedInBand { inbound_noderef }
inbound_noderef,
extra_data,
}
} else { } else {
ReceiptEvent::ReturnedOutOfBand { extra_data } ReceiptEvent::ReturnedOutOfBand
}; };
let callback_future = Self::perform_callback(receipt_event, &mut record_mut); let callback_future = Self::perform_callback(receipt_event, &mut record_mut);

View File

@ -6,23 +6,25 @@ pub fn encode_signal_info(
builder: &mut veilid_capnp::operation_signal::Builder, builder: &mut veilid_capnp::operation_signal::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
match signal_info { match signal_info {
SignalInfo::HolePunch { SignalInfo::HolePunch { receipt, peer_info } => {
receipt_nonce,
peer_info,
} => {
let mut hp_builder = builder.reborrow().init_hole_punch(); let mut hp_builder = builder.reborrow().init_hole_punch();
let mut rn_builder = hp_builder.reborrow().init_receipt_nonce(); let r_builder = hp_builder
encode_nonce(receipt_nonce, &mut rn_builder); .reborrow()
.init_receipt(receipt.len().try_into().map_err(map_error_protocol!(
"invalid receipt length in encode_signal_info"
))?);
r_builder.copy_from_slice(receipt);
let mut pi_builder = hp_builder.init_peer_info(); let mut pi_builder = hp_builder.init_peer_info();
encode_peer_info(peer_info, &mut pi_builder)?; encode_peer_info(peer_info, &mut pi_builder)?;
} }
SignalInfo::ReverseConnect { SignalInfo::ReverseConnect { receipt, peer_info } => {
receipt_nonce,
peer_info,
} => {
let mut rc_builder = builder.reborrow().init_reverse_connect(); let mut rc_builder = builder.reborrow().init_reverse_connect();
let mut rn_builder = rc_builder.reborrow().init_receipt_nonce(); let r_builder = rc_builder
encode_nonce(receipt_nonce, &mut rn_builder); .reborrow()
.init_receipt(receipt.len().try_into().map_err(map_error_protocol!(
"invalid receipt length in encode_signal_info"
))?);
r_builder.copy_from_slice(receipt);
let mut pi_builder = rc_builder.init_peer_info(); let mut pi_builder = rc_builder.init_peer_info();
encode_peer_info(peer_info, &mut pi_builder)?; encode_peer_info(peer_info, &mut pi_builder)?;
} }
@ -45,17 +47,18 @@ pub fn decode_signal_info(
Ok(r) => r, Ok(r) => r,
Err(_) => return Err(rpc_error_internal("invalid hole punch")), Err(_) => return Err(rpc_error_internal("invalid hole punch")),
}; };
let receipt_nonce = let receipt = r
decode_nonce(&r.get_receipt_nonce().map_err(map_error_capnp_error!())?); .get_receipt()
.map_err(map_error_protocol!(
"invalid receipt in hole punch signal info"
))?
.to_vec();
let pi_reader = r.get_peer_info().map_err(map_error_protocol!( let pi_reader = r.get_peer_info().map_err(map_error_protocol!(
"invalid peer info in hole punch signal info" "invalid peer info in hole punch signal info"
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, true)?; let peer_info = decode_peer_info(&pi_reader, true)?;
SignalInfo::HolePunch { SignalInfo::HolePunch { receipt, peer_info }
receipt_nonce,
peer_info,
}
} }
veilid_capnp::operation_signal::ReverseConnect(r) => { veilid_capnp::operation_signal::ReverseConnect(r) => {
// Extract reverse connect reader // Extract reverse connect reader
@ -63,17 +66,18 @@ pub fn decode_signal_info(
Ok(r) => r, Ok(r) => r,
Err(_) => return Err(rpc_error_internal("invalid reverse connect")), Err(_) => return Err(rpc_error_internal("invalid reverse connect")),
}; };
let receipt_nonce = let receipt = r
decode_nonce(&r.get_receipt_nonce().map_err(map_error_capnp_error!())?); .get_receipt()
.map_err(map_error_protocol!(
"invalid receipt in hole punch signal info"
))?
.to_vec();
let pi_reader = r.get_peer_info().map_err(map_error_protocol!( let pi_reader = r.get_peer_info().map_err(map_error_protocol!(
"invalid peer info in reverse connect signal info" "invalid peer info in reverse connect signal info"
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, true)?; let peer_info = decode_peer_info(&pi_reader, true)?;
SignalInfo::ReverseConnect { SignalInfo::ReverseConnect { receipt, peer_info }
receipt_nonce,
peer_info,
}
} }
}, },
) )

View File

@ -872,7 +872,7 @@ impl RPCProcessor {
rpcreader: RPCMessageReader, rpcreader: RPCMessageReader,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
// //
let (redirect, dial_info, receipt_nonce, min_version, max_version) = { let (redirect, dial_info, receipt) = {
let operation = rpcreader let operation = rpcreader
.reader .reader
.get_root::<veilid_capnp::operation::Reader>() .get_root::<veilid_capnp::operation::Reader>()
@ -893,20 +893,17 @@ impl RPCProcessor {
}; };
// Parse out fields // Parse out fields
let min_version = vdi_reader.get_min_version();
let max_version = vdi_reader.get_max_version();
let redirect = vdi_reader.get_redirect(); let redirect = vdi_reader.get_redirect();
let dial_info = decode_dial_info( let dial_info = decode_dial_info(
&vdi_reader &vdi_reader
.get_dial_info() .get_dial_info()
.map_err(map_error_internal!("no valid dial info"))?, .map_err(map_error_internal!("no valid dial info in process_validate_dial_info"))?,
)?; )?;
let rn_reader = vdi_reader let receipt = vdi_reader
.get_receipt_nonce() .get_receipt()
.map_err(map_error_internal!("no valid receipt nonce"))?; .map_err(map_error_internal!("no valid receipt in process_validate_dial_info"))?.to_vec();
let receipt_nonce = decode_nonce(&rn_reader);
(redirect, dial_info, receipt_nonce, min_version, max_version) (redirect, dial_info, receipt)
}; };
// Redirect this request if we are asked to // Redirect this request if we are asked to
@ -949,12 +946,12 @@ impl RPCProcessor {
let detail = question.reborrow().init_detail(); let detail = question.reborrow().init_detail();
let mut vdi_builder = detail.init_validate_dial_info(); let mut vdi_builder = detail.init_validate_dial_info();
vdi_builder.set_redirect(false); vdi_builder.set_redirect(false);
vdi_builder.set_min_version(min_version);
vdi_builder.set_max_version(max_version);
let mut di_builder = vdi_builder.reborrow().init_dial_info(); let mut di_builder = vdi_builder.reborrow().init_dial_info();
encode_dial_info(&dial_info, &mut di_builder)?; encode_dial_info(&dial_info, &mut di_builder)?;
let mut rn_builder = vdi_builder.reborrow().init_receipt_nonce(); let r_builder = vdi_builder.init_receipt(receipt.len().try_into().map_err(
encode_nonce(&receipt_nonce, &mut rn_builder); map_error_protocol!("invalid receipt length in process_validate_dial_info"),
)?);
r_builder.copy_from_slice(&receipt);
vdi_msg.into_reader() vdi_msg.into_reader()
}; };
@ -967,25 +964,13 @@ impl RPCProcessor {
// Otherwise send a return receipt directly // Otherwise send a return receipt directly
// Possibly from an alternate port // Possibly from an alternate port
let version = {
#[allow(clippy::absurd_extreme_comparisons)]
if min_version > MAX_VERSION || max_version < MIN_VERSION {
return Err(rpc_error_protocol(format!(
"can't send direct receipt to {} because version is unsupported: ({},{})",
dial_info, min_version, max_version
)))
.map_err(
logthru_rpc!(debug));
}
cmp::min(max_version, MAX_VERSION)
};
let network_manager = self.network_manager(); let network_manager = self.network_manager();
network_manager network_manager
.send_out_of_band_receipt(dial_info.clone(), version, receipt_nonce, []) .send_out_of_band_receipt(dial_info.clone(), receipt)
.await .await
.map_err(map_error_string!()) .map_err(map_error_string!())
.map_err( .map_err(
logthru_net!(error "failed to send direct receipt to dial info: {}, version={}", dial_info, version), logthru_net!(error "failed to send direct receipt to dial info: {}", dial_info),
)?; )?;
Ok(()) Ok(())
@ -1166,7 +1151,7 @@ impl RPCProcessor {
} }
async fn process_return_receipt(&self, rpcreader: RPCMessageReader) -> Result<(), RPCError> { async fn process_return_receipt(&self, rpcreader: RPCMessageReader) -> Result<(), RPCError> {
let (receipt_nonce, extra_data) = { let receipt = {
let operation = rpcreader let operation = rpcreader
.reader .reader
.get_root::<veilid_capnp::operation::Reader>() .get_root::<veilid_capnp::operation::Reader>()
@ -1186,24 +1171,16 @@ impl RPCProcessor {
_ => panic!("invalid operation type in process_return_receipt"), _ => panic!("invalid operation type in process_return_receipt"),
}; };
// Get receipt nonce // Get receipt
let rn_reader = rr_reader rr_reader
.get_receipt_nonce() .get_receipt()
.map_err(map_error_internal!("no valid receipt_nonce"))?; .map_err(map_error_internal!("no valid receipt in process_return_receipt"))?.to_vec()
let receipt_nonce = decode_nonce(&rn_reader);
// Get receipt extra data
let extra_data = rr_reader
.get_extra_data()
.map_err(map_error_internal!("no valid extra data"))?;
(receipt_nonce, extra_data.to_vec())
}; };
// Handle it // Handle it
let network_manager = self.network_manager(); let network_manager = self.network_manager();
network_manager network_manager
.handle_in_band_receipt(receipt_nonce, extra_data, rpcreader.header.peer_noderef) .handle_in_band_receipt(receipt, rpcreader.header.peer_noderef)
.await .await
.map_err(map_error_string!()) .map_err(map_error_string!())
} }
@ -1602,17 +1579,17 @@ impl RPCProcessor {
let mut vdi_builder = detail.init_validate_dial_info(); let mut vdi_builder = detail.init_validate_dial_info();
// Generate receipt and waitable eventual so we can see if we get the receipt back // Generate receipt and waitable eventual so we can see if we get the receipt back
let (receipt_nonce, eventual_value) = network_manager let (receipt, eventual_value) = network_manager
.generate_single_shot_receipt(receipt_time) .generate_single_shot_receipt(receipt_time, [])
.map_err(map_error_string!())?; .map_err(map_error_string!())?;
vdi_builder.set_redirect(redirect); vdi_builder.set_redirect(redirect);
vdi_builder.set_min_version(MIN_VERSION);
vdi_builder.set_max_version(MAX_VERSION);
let mut di_builder = vdi_builder.reborrow().init_dial_info(); let mut di_builder = vdi_builder.reborrow().init_dial_info();
encode_dial_info(&dial_info, &mut di_builder)?; encode_dial_info(&dial_info, &mut di_builder)?;
let mut rn_builder = vdi_builder.reborrow().init_receipt_nonce(); let r_builder = vdi_builder.init_receipt(receipt.len().try_into().map_err(
encode_nonce(&receipt_nonce, &mut rn_builder); map_error_protocol!("invalid receipt length in validate dial info"),
)?);
r_builder.copy_from_slice(&receipt);
(vdi_msg.into_reader(), eventual_value) (vdi_msg.into_reader(), eventual_value)
}; };
@ -1627,13 +1604,10 @@ impl RPCProcessor {
match eventual_value.await.take_value().unwrap() { match eventual_value.await.take_value().unwrap() {
ReceiptEvent::ReturnedInBand { ReceiptEvent::ReturnedInBand {
inbound_noderef: _, inbound_noderef: _,
extra_data:_
} => { } => {
Err(rpc_error_internal("validate_dial_info receipt should be returned out-of-band")) Err(rpc_error_internal("validate_dial_info receipt should be returned out-of-band"))
} }
ReceiptEvent::ReturnedOutOfBand { ReceiptEvent::ReturnedOutOfBand => {
extra_data:_
} => {
log_net!(debug "validate_dial_info receipt returned"); log_net!(debug "validate_dial_info receipt returned");
Ok(true) Ok(true)
} }
@ -1779,14 +1753,13 @@ impl RPCProcessor {
// Sends a unidirectional in-band return receipt // Sends a unidirectional in-band return receipt
// Can be sent via all methods including relays and routes // Can be sent via all methods including relays and routes
pub async fn rpc_call_return_receipt<B: AsRef<[u8]>>( pub async fn rpc_call_return_receipt<D: AsRef<[u8]>>(
&self, &self,
dest: Destination, dest: Destination,
safety_route: Option<&SafetyRouteSpec>, safety_route: Option<&SafetyRouteSpec>,
receipt_nonce: Nonce, receipt: D,
extra_data: B,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
let extra_data = extra_data.as_ref(); let receipt = receipt.as_ref();
let rr_msg = { let rr_msg = {
let mut rr_msg = ::capnp::message::Builder::new_default(); let mut rr_msg = ::capnp::message::Builder::new_default();
@ -1795,13 +1768,11 @@ impl RPCProcessor {
let mut respond_to = question.reborrow().init_respond_to(); let mut respond_to = question.reborrow().init_respond_to();
respond_to.set_none(()); respond_to.set_none(());
let detail = question.reborrow().init_detail(); let detail = question.reborrow().init_detail();
let mut rr_builder = detail.init_return_receipt(); let rr_builder = detail.init_return_receipt();
let mut rn_builder = rr_builder.reborrow().init_receipt_nonce(); let r_builder = rr_builder.init_receipt(receipt.len().try_into().map_err(
encode_nonce(&receipt_nonce, &mut rn_builder); map_error_protocol!("invalid receipt length in return receipt"),
let ed_builder = rr_builder.init_extra_data(extra_data.len().try_into().map_err(
map_error_protocol!("invalid extra data length in return receipt"),
)?); )?);
ed_builder.copy_from_slice(extra_data); r_builder.copy_from_slice(receipt);
rr_msg.into_reader() rr_msg.into_reader()
}; };

View File

@ -1482,13 +1482,13 @@ cfg_if! {
pub enum SignalInfo { pub enum SignalInfo {
HolePunch { HolePunch {
// UDP Hole Punch Request // UDP Hole Punch Request
receipt_nonce: ReceiptNonce, // Receipt to be returned after the hole punch receipt: Vec<u8>, // Receipt to be returned after the hole punch
peer_info: PeerInfo, // Sender's peer info peer_info: PeerInfo, // Sender's peer info
}, },
ReverseConnect { ReverseConnect {
// Reverse Connection Request // Reverse Connection Request
receipt_nonce: ReceiptNonce, // Receipt to be returned by the reverse connection receipt: Vec<u8>, // Receipt to be returned by the reverse connection
peer_info: PeerInfo, // Sender's peer info peer_info: PeerInfo, // Sender's peer info
}, },
// XXX: WebRTC // XXX: WebRTC
// XXX: App-level signalling // XXX: App-level signalling

View File

@ -91,11 +91,11 @@ core:
set_value_fanout: 5 set_value_fanout: 5
min_peer_count: 1 # 20 min_peer_count: 1 # 20
min_peer_refresh_time_ms: 2000 min_peer_refresh_time_ms: 2000
validate_dial_info_receipt_time_ms: 1000 validate_dial_info_receipt_time_ms: 2000
upnp: false upnp: false
natpmp: false natpmp: false
enable_local_peer_scope: false enable_local_peer_scope: false
restricted_nat_retries: 5 restricted_nat_retries: 0
tls: tls:
certificate_path: '%CERTIFICATE_DIRECTORY%/server.crt' certificate_path: '%CERTIFICATE_DIRECTORY%/server.crt'
private_key_path: '%PRIVATE_KEY_DIRECTORY%/server.key' private_key_path: '%PRIVATE_KEY_DIRECTORY%/server.key'