removing dev branch, many changes
This commit is contained in:
@@ -19,11 +19,12 @@ mod signature512;
|
||||
mod signed_direct_node_info;
|
||||
mod signed_node_info;
|
||||
mod signed_relayed_node_info;
|
||||
mod signed_value_data;
|
||||
mod signed_value_descriptor;
|
||||
mod socket_address;
|
||||
mod tunnel;
|
||||
mod typed_key;
|
||||
mod typed_signature;
|
||||
mod value_data;
|
||||
|
||||
pub use address::*;
|
||||
pub use address_type_set::*;
|
||||
@@ -46,10 +47,24 @@ pub use signature512::*;
|
||||
pub use signed_direct_node_info::*;
|
||||
pub use signed_node_info::*;
|
||||
pub use signed_relayed_node_info::*;
|
||||
pub use signed_value_data::*;
|
||||
pub use signed_value_descriptor::*;
|
||||
pub use socket_address::*;
|
||||
pub use tunnel::*;
|
||||
pub use typed_key::*;
|
||||
pub use typed_signature::*;
|
||||
pub use value_data::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum QuestionContext {
|
||||
GetValue(ValidateGetValueContext),
|
||||
SetValue(ValidateSetValueContext),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RPCValidateContext {
|
||||
pub crypto: Crypto,
|
||||
pub rpc_processor: RPCProcessor,
|
||||
pub question_context: Option<QuestionContext>,
|
||||
}
|
||||
|
||||
@@ -4,27 +4,27 @@ pub fn encode_node_info(
|
||||
node_info: &NodeInfo,
|
||||
builder: &mut veilid_capnp::node_info::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
builder.set_network_class(encode_network_class(node_info.network_class));
|
||||
builder.set_network_class(encode_network_class(node_info.network_class()));
|
||||
|
||||
let mut ps_builder = builder.reborrow().init_outbound_protocols();
|
||||
encode_protocol_type_set(&node_info.outbound_protocols, &mut ps_builder)?;
|
||||
encode_protocol_type_set(&node_info.outbound_protocols(), &mut ps_builder)?;
|
||||
|
||||
let mut ats_builder = builder.reborrow().init_address_types();
|
||||
encode_address_type_set(&node_info.address_types, &mut ats_builder)?;
|
||||
encode_address_type_set(&node_info.address_types(), &mut ats_builder)?;
|
||||
|
||||
let mut es_builder = builder
|
||||
.reborrow()
|
||||
.init_envelope_support(node_info.envelope_support.len() as u32);
|
||||
.init_envelope_support(node_info.envelope_support().len() as u32);
|
||||
if let Some(s) = es_builder.as_slice() {
|
||||
s.clone_from_slice(&node_info.envelope_support);
|
||||
s.clone_from_slice(&node_info.envelope_support());
|
||||
}
|
||||
|
||||
let mut cs_builder = builder
|
||||
.reborrow()
|
||||
.init_crypto_support(node_info.crypto_support.len() as u32);
|
||||
.init_crypto_support(node_info.crypto_support().len() as u32);
|
||||
if let Some(s) = cs_builder.as_slice() {
|
||||
let csvec: Vec<u32> = node_info
|
||||
.crypto_support
|
||||
.crypto_support()
|
||||
.iter()
|
||||
.map(|x| u32::from_be_bytes(x.0))
|
||||
.collect();
|
||||
@@ -33,7 +33,7 @@ pub fn encode_node_info(
|
||||
|
||||
let mut didl_builder = builder.reborrow().init_dial_info_detail_list(
|
||||
node_info
|
||||
.dial_info_detail_list
|
||||
.dial_info_detail_list()
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_protocol(
|
||||
@@ -41,9 +41,9 @@ pub fn encode_node_info(
|
||||
))?,
|
||||
);
|
||||
|
||||
for idx in 0..node_info.dial_info_detail_list.len() {
|
||||
for idx in 0..node_info.dial_info_detail_list().len() {
|
||||
let mut did_builder = didl_builder.reborrow().get(idx as u32);
|
||||
encode_dial_info_detail(&node_info.dial_info_detail_list[idx], &mut did_builder)?;
|
||||
encode_dial_info_detail(&node_info.dial_info_detail_list()[idx], &mut did_builder)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -131,12 +131,12 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
|
||||
dial_info_detail_list.push(decode_dial_info_detail(&did)?)
|
||||
}
|
||||
|
||||
Ok(NodeInfo {
|
||||
Ok(NodeInfo::new(
|
||||
network_class,
|
||||
outbound_protocols,
|
||||
address_types,
|
||||
envelope_support,
|
||||
crypto_support,
|
||||
dial_info_detail_list,
|
||||
})
|
||||
))
|
||||
}
|
||||
|
||||
@@ -9,18 +9,18 @@ impl RPCAnswer {
|
||||
pub fn new(detail: RPCAnswerDetail) -> Self {
|
||||
Self { detail }
|
||||
}
|
||||
pub fn into_detail(self) -> RPCAnswerDetail {
|
||||
self.detail
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
self.detail.validate(validate_context)
|
||||
}
|
||||
pub fn desc(&self) -> &'static str {
|
||||
self.detail.desc()
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::answer::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCAnswer, RPCError> {
|
||||
pub fn destructure(self) -> RPCAnswerDetail {
|
||||
self.detail
|
||||
}
|
||||
pub fn decode(reader: &veilid_capnp::answer::Reader) -> Result<RPCAnswer, RPCError> {
|
||||
let d_reader = reader.get_detail();
|
||||
let detail = RPCAnswerDetail::decode(&d_reader, crypto)?;
|
||||
let detail = RPCAnswerDetail::decode(&d_reader)?;
|
||||
Ok(RPCAnswer { detail })
|
||||
}
|
||||
pub fn encode(&self, builder: &mut veilid_capnp::answer::Builder) -> Result<(), RPCError> {
|
||||
@@ -60,10 +60,23 @@ impl RPCAnswerDetail {
|
||||
RPCAnswerDetail::CancelTunnelA(_) => "CancelTunnelA",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCAnswerDetail::StatusA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::FindNodeA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::AppCallA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::GetValueA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::SetValueA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::WatchValueA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::SupplyBlockA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::FindBlockA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::StartTunnelA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::CompleteTunnelA(r) => r.validate(validate_context),
|
||||
RPCAnswerDetail::CancelTunnelA(r) => r.validate(validate_context),
|
||||
}
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::answer::detail::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCAnswerDetail, RPCError> {
|
||||
let which_reader = reader.which().map_err(RPCError::protocol)?;
|
||||
let out = match which_reader {
|
||||
@@ -74,7 +87,7 @@ impl RPCAnswerDetail {
|
||||
}
|
||||
veilid_capnp::answer::detail::FindNodeA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationFindNodeA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationFindNodeA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::FindNodeA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::AppCallA(r) => {
|
||||
@@ -84,27 +97,27 @@ impl RPCAnswerDetail {
|
||||
}
|
||||
veilid_capnp::answer::detail::GetValueA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationGetValueA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationGetValueA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::GetValueA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::SetValueA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationSetValueA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationSetValueA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::SetValueA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::WatchValueA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationWatchValueA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationWatchValueA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::WatchValueA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::SupplyBlockA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationSupplyBlockA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationSupplyBlockA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::SupplyBlockA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::FindBlockA(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationFindBlockA::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationFindBlockA::decode(&op_reader)?;
|
||||
RPCAnswerDetail::FindBlockA(out)
|
||||
}
|
||||
veilid_capnp::answer::detail::StartTunnelA(r) => {
|
||||
|
||||
@@ -16,25 +16,30 @@ impl RPCOperationKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
kind_reader: &veilid_capnp::operation::kind::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<Self, RPCError> {
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationKind::Question(r) => r.validate(validate_context),
|
||||
RPCOperationKind::Statement(r) => r.validate(validate_context),
|
||||
RPCOperationKind::Answer(r) => r.validate(validate_context),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode(kind_reader: &veilid_capnp::operation::kind::Reader) -> Result<Self, RPCError> {
|
||||
let which_reader = kind_reader.which().map_err(RPCError::protocol)?;
|
||||
let out = match which_reader {
|
||||
veilid_capnp::operation::kind::Which::Question(r) => {
|
||||
let q_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCQuestion::decode(&q_reader, crypto)?;
|
||||
let out = RPCQuestion::decode(&q_reader)?;
|
||||
RPCOperationKind::Question(out)
|
||||
}
|
||||
veilid_capnp::operation::kind::Which::Statement(r) => {
|
||||
let q_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCStatement::decode(&q_reader, crypto)?;
|
||||
let out = RPCStatement::decode(&q_reader)?;
|
||||
RPCOperationKind::Statement(out)
|
||||
}
|
||||
veilid_capnp::operation::kind::Which::Answer(r) => {
|
||||
let q_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCAnswer::decode(&q_reader, crypto)?;
|
||||
let out = RPCAnswer::decode(&q_reader)?;
|
||||
RPCOperationKind::Answer(out)
|
||||
}
|
||||
};
|
||||
@@ -93,6 +98,17 @@ impl RPCOperation {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
// Validate sender peer info
|
||||
if let Some(sender_peer_info) = &self.opt_sender_peer_info {
|
||||
sender_peer_info
|
||||
.validate(validate_context.crypto.clone())
|
||||
.map_err(RPCError::protocol)?;
|
||||
}
|
||||
// Validate operation kind
|
||||
self.kind.validate(validate_context)
|
||||
}
|
||||
|
||||
pub fn op_id(&self) -> OperationId {
|
||||
self.op_id
|
||||
}
|
||||
@@ -108,21 +124,23 @@ impl RPCOperation {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn into_kind(self) -> RPCOperationKind {
|
||||
self.kind
|
||||
pub fn destructure(self) -> (OperationId, Option<PeerInfo>, Timestamp, RPCOperationKind) {
|
||||
(
|
||||
self.op_id,
|
||||
self.opt_sender_peer_info,
|
||||
self.target_node_info_ts,
|
||||
self.kind,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
operation_reader: &veilid_capnp::operation::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<Self, RPCError> {
|
||||
pub fn decode(operation_reader: &veilid_capnp::operation::Reader) -> Result<Self, RPCError> {
|
||||
let op_id = OperationId::new(operation_reader.get_op_id());
|
||||
|
||||
let sender_peer_info = if operation_reader.has_sender_peer_info() {
|
||||
let pi_reader = operation_reader
|
||||
.get_sender_peer_info()
|
||||
.map_err(RPCError::protocol)?;
|
||||
let pi = decode_peer_info(&pi_reader, crypto.clone())?;
|
||||
let pi = decode_peer_info(&pi_reader)?;
|
||||
Some(pi)
|
||||
} else {
|
||||
None
|
||||
@@ -131,7 +149,7 @@ impl RPCOperation {
|
||||
let target_node_info_ts = Timestamp::new(operation_reader.get_target_node_info_ts());
|
||||
|
||||
let kind_reader = operation_reader.get_kind();
|
||||
let kind = RPCOperationKind::decode(&kind_reader, crypto)?;
|
||||
let kind = RPCOperationKind::decode(&kind_reader)?;
|
||||
|
||||
Ok(RPCOperation {
|
||||
op_id,
|
||||
|
||||
@@ -1,16 +1,40 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_APP_CALL_Q_MESSAGE_LEN: usize = 32768;
|
||||
const MAX_APP_CALL_A_MESSAGE_LEN: usize = 32768;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationAppCallQ {
|
||||
pub message: Vec<u8>,
|
||||
message: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RPCOperationAppCallQ {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_app_call_q::Reader,
|
||||
) -> Result<RPCOperationAppCallQ, RPCError> {
|
||||
let message = reader.get_message().map_err(RPCError::protocol)?.to_vec();
|
||||
Ok(RPCOperationAppCallQ { message })
|
||||
pub fn new(message: Vec<u8>) -> Result<Self, RPCError> {
|
||||
if message.len() > MAX_APP_CALL_Q_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppCallQ message too long to set"));
|
||||
}
|
||||
Ok(Self { message })
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn message(&self) -> &[u8] {
|
||||
// &self.message
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> Vec<u8> {
|
||||
self.message
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_app_call_q::Reader) -> Result<Self, RPCError> {
|
||||
let mr = reader.get_message().map_err(RPCError::protocol)?;
|
||||
if mr.len() > MAX_APP_CALL_Q_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppCallQ message too long to set"));
|
||||
}
|
||||
Ok(Self {
|
||||
message: mr.to_vec(),
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -23,15 +47,37 @@ impl RPCOperationAppCallQ {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationAppCallA {
|
||||
pub message: Vec<u8>,
|
||||
message: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RPCOperationAppCallA {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_app_call_a::Reader,
|
||||
) -> Result<RPCOperationAppCallA, RPCError> {
|
||||
let message = reader.get_message().map_err(RPCError::protocol)?.to_vec();
|
||||
Ok(RPCOperationAppCallA { message })
|
||||
pub fn new(message: Vec<u8>) -> Result<Self, RPCError> {
|
||||
if message.len() > MAX_APP_CALL_A_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppCallA message too long to set"));
|
||||
}
|
||||
Ok(Self { message })
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn message(&self) -> &[u8] {
|
||||
// &self.message
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> Vec<u8> {
|
||||
self.message
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_app_call_a::Reader) -> Result<Self, RPCError> {
|
||||
let mr = reader.get_message().map_err(RPCError::protocol)?;
|
||||
if mr.len() > MAX_APP_CALL_A_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppCallA message too long to set"));
|
||||
}
|
||||
Ok(Self {
|
||||
message: mr.to_vec(),
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -1,16 +1,39 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_APP_MESSAGE_MESSAGE_LEN: usize = 32768;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationAppMessage {
|
||||
pub message: Vec<u8>,
|
||||
message: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RPCOperationAppMessage {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_app_message::Reader,
|
||||
) -> Result<RPCOperationAppMessage, RPCError> {
|
||||
let message = reader.get_message().map_err(RPCError::protocol)?.to_vec();
|
||||
Ok(RPCOperationAppMessage { message })
|
||||
pub fn new(message: Vec<u8>) -> Result<Self, RPCError> {
|
||||
if message.len() > MAX_APP_MESSAGE_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppMessage message too long to set"));
|
||||
}
|
||||
Ok(Self { message })
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn message(&self) -> &[u8] {
|
||||
// &self.message
|
||||
// }
|
||||
pub fn destructure(self) -> Vec<u8> {
|
||||
self.message
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_app_message::Reader) -> Result<Self, RPCError> {
|
||||
let mr = reader.get_message().map_err(RPCError::protocol)?;
|
||||
if mr.len() > MAX_APP_MESSAGE_MESSAGE_LEN {
|
||||
return Err(RPCError::protocol("AppMessage message too long to set"));
|
||||
}
|
||||
Ok(Self {
|
||||
message: mr.to_vec(),
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -2,16 +2,30 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationCancelTunnelQ {
|
||||
pub id: TunnelId,
|
||||
id: TunnelId,
|
||||
}
|
||||
|
||||
impl RPCOperationCancelTunnelQ {
|
||||
pub fn new(id: TunnelId) -> Self {
|
||||
Self { id }
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> TunnelId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn destructure(self) -> TunnelId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_cancel_tunnel_q::Reader,
|
||||
) -> Result<RPCOperationCancelTunnelQ, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let id = TunnelId::new(reader.get_id());
|
||||
|
||||
Ok(RPCOperationCancelTunnelQ { id })
|
||||
Ok(Self { id })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -30,16 +44,25 @@ pub enum RPCOperationCancelTunnelA {
|
||||
}
|
||||
|
||||
impl RPCOperationCancelTunnelA {
|
||||
pub fn new_tunnel(id: TunnelId) -> Self {
|
||||
Self::Tunnel(id)
|
||||
}
|
||||
pub fn new_error(error: TunnelError) -> Self {
|
||||
Self::Error(error)
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_cancel_tunnel_a::Reader,
|
||||
) -> Result<RPCOperationCancelTunnelA, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_cancel_tunnel_a::Which::Tunnel(r) => {
|
||||
Ok(RPCOperationCancelTunnelA::Tunnel(TunnelId::new(r)))
|
||||
Ok(Self::Tunnel(TunnelId::new(r)))
|
||||
}
|
||||
veilid_capnp::operation_cancel_tunnel_a::Which::Error(r) => {
|
||||
let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?);
|
||||
Ok(RPCOperationCancelTunnelA::Error(tunnel_error))
|
||||
Ok(Self::Error(tunnel_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,10 +71,10 @@ impl RPCOperationCancelTunnelA {
|
||||
builder: &mut veilid_capnp::operation_cancel_tunnel_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationCancelTunnelA::Tunnel(p) => {
|
||||
Self::Tunnel(p) => {
|
||||
builder.set_tunnel(p.as_u64());
|
||||
}
|
||||
RPCOperationCancelTunnelA::Error(e) => {
|
||||
Self::Error(e) => {
|
||||
builder.set_error(encode_tunnel_error(*e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,45 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationCompleteTunnelQ {
|
||||
pub id: TunnelId,
|
||||
pub local_mode: TunnelMode,
|
||||
pub depth: u8,
|
||||
pub endpoint: TunnelEndpoint,
|
||||
id: TunnelId,
|
||||
local_mode: TunnelMode,
|
||||
depth: u8,
|
||||
endpoint: TunnelEndpoint,
|
||||
}
|
||||
|
||||
impl RPCOperationCompleteTunnelQ {
|
||||
pub fn new(id: TunnelId, local_mode: TunnelMode, depth: u8, endpoint: TunnelEndpoint) -> Self {
|
||||
Self {
|
||||
id,
|
||||
local_mode,
|
||||
depth,
|
||||
endpoint,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> TunnelId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn local_mode(&self) -> TunnelMode {
|
||||
self.local_mode
|
||||
}
|
||||
pub fn depth(&self) -> u8 {
|
||||
self.depth
|
||||
}
|
||||
pub fn endpoint(&self) -> &TunnelEndpoint {
|
||||
&self.endpoint
|
||||
}
|
||||
pub fn destructure(self) -> (TunnelId, TunnelMode, u8, TunnelEndpoint) {
|
||||
(self.id, self.local_mode, self.depth, self.endpoint)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_complete_tunnel_q::Reader,
|
||||
) -> Result<RPCOperationCompleteTunnelQ, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let id = TunnelId::new(reader.get_id());
|
||||
let local_mode = match reader.get_local_mode().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::TunnelEndpointMode::Raw => TunnelMode::Raw,
|
||||
@@ -21,7 +50,7 @@ impl RPCOperationCompleteTunnelQ {
|
||||
let te_reader = reader.get_endpoint().map_err(RPCError::protocol)?;
|
||||
let endpoint = decode_tunnel_endpoint(&te_reader)?;
|
||||
|
||||
Ok(RPCOperationCompleteTunnelQ {
|
||||
Ok(Self {
|
||||
id,
|
||||
local_mode,
|
||||
depth,
|
||||
@@ -52,18 +81,28 @@ pub enum RPCOperationCompleteTunnelA {
|
||||
}
|
||||
|
||||
impl RPCOperationCompleteTunnelA {
|
||||
pub fn new_tunnel(tunnel: FullTunnel) -> Self {
|
||||
Self::Tunnel(tunnel)
|
||||
}
|
||||
pub fn new_error(error: TunnelError) -> Self {
|
||||
Self::Error(error)
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_complete_tunnel_a::Reader,
|
||||
) -> Result<RPCOperationCompleteTunnelA, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_complete_tunnel_a::Which::Tunnel(r) => {
|
||||
let ft_reader = r.map_err(RPCError::protocol)?;
|
||||
let full_tunnel = decode_full_tunnel(&ft_reader)?;
|
||||
Ok(RPCOperationCompleteTunnelA::Tunnel(full_tunnel))
|
||||
Ok(Self::Tunnel(full_tunnel))
|
||||
}
|
||||
veilid_capnp::operation_complete_tunnel_a::Which::Error(r) => {
|
||||
let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?);
|
||||
Ok(RPCOperationCompleteTunnelA::Error(tunnel_error))
|
||||
Ok(Self::Error(tunnel_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,10 +111,10 @@ impl RPCOperationCompleteTunnelA {
|
||||
builder: &mut veilid_capnp::operation_complete_tunnel_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationCompleteTunnelA::Tunnel(p) => {
|
||||
Self::Tunnel(p) => {
|
||||
encode_full_tunnel(p, &mut builder.reborrow().init_tunnel())?;
|
||||
}
|
||||
RPCOperationCompleteTunnelA::Error(e) => {
|
||||
Self::Error(e) => {
|
||||
builder.set_error(encode_tunnel_error(*e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_FIND_BLOCK_A_DATA_LEN: usize = 32768;
|
||||
const MAX_FIND_BLOCK_A_SUPPLIERS_LEN: usize = 10;
|
||||
const MAX_FIND_BLOCK_A_PEERS_LEN: usize = 10;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationFindBlockQ {
|
||||
pub block_id: TypedKey,
|
||||
block_id: TypedKey,
|
||||
}
|
||||
|
||||
impl RPCOperationFindBlockQ {
|
||||
pub fn new(block_id: TypedKey) -> Self {
|
||||
Self { block_id }
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn block_id(&self) -> TypedKey {
|
||||
self.block_id
|
||||
}
|
||||
|
||||
pub fn destructure(self) -> TypedKey {
|
||||
self.block_id
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_find_block_q::Reader,
|
||||
) -> Result<RPCOperationFindBlockQ, RPCError> {
|
||||
let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?;
|
||||
let block_id = decode_typed_key(&bi_reader)?;
|
||||
|
||||
Ok(RPCOperationFindBlockQ { block_id })
|
||||
Ok(Self { block_id })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -27,19 +46,68 @@ impl RPCOperationFindBlockQ {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationFindBlockA {
|
||||
pub data: Vec<u8>,
|
||||
pub suppliers: Vec<PeerInfo>,
|
||||
pub peers: Vec<PeerInfo>,
|
||||
data: Vec<u8>,
|
||||
suppliers: Vec<PeerInfo>,
|
||||
peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationFindBlockA {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_find_block_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationFindBlockA, RPCError> {
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
|
||||
pub fn new(
|
||||
data: Vec<u8>,
|
||||
suppliers: Vec<PeerInfo>,
|
||||
peers: Vec<PeerInfo>,
|
||||
) -> Result<Self, RPCError> {
|
||||
if data.len() > MAX_FIND_BLOCK_A_DATA_LEN {
|
||||
return Err(RPCError::protocol("find block data length too long"));
|
||||
}
|
||||
if suppliers.len() > MAX_FIND_BLOCK_A_SUPPLIERS_LEN {
|
||||
return Err(RPCError::protocol("find block suppliers length too long"));
|
||||
}
|
||||
if peers.len() > MAX_FIND_BLOCK_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("find block peers length too long"));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
data,
|
||||
suppliers,
|
||||
peers,
|
||||
})
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
PeerInfo::validate_vec(&mut self.suppliers, validate_context.crypto.clone());
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
pub fn suppliers(&self) -> &[PeerInfo] {
|
||||
&self.suppliers
|
||||
}
|
||||
pub fn peers(&self) -> &[PeerInfo] {
|
||||
&self.peers
|
||||
}
|
||||
|
||||
pub fn destructure(self) -> (Vec<u8>, Vec<PeerInfo>, Vec<PeerInfo>) {
|
||||
(self.data, self.suppliers, self.peers)
|
||||
}
|
||||
pub fn decode(reader: &veilid_capnp::operation_find_block_a::Reader) -> Result<Self, RPCError> {
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?;
|
||||
if data.len() > MAX_FIND_BLOCK_A_DATA_LEN {
|
||||
return Err(RPCError::protocol("find block data length too long"));
|
||||
}
|
||||
|
||||
let suppliers_reader = reader.get_suppliers().map_err(RPCError::protocol)?;
|
||||
if suppliers_reader.len() as usize > MAX_FIND_BLOCK_A_SUPPLIERS_LEN {
|
||||
return Err(RPCError::protocol("find block suppliers length too long"));
|
||||
}
|
||||
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
if peers_reader.len() as usize > MAX_FIND_BLOCK_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("find block peers length too long"));
|
||||
}
|
||||
|
||||
let mut suppliers = Vec::<PeerInfo>::with_capacity(
|
||||
suppliers_reader
|
||||
.len()
|
||||
@@ -47,11 +115,10 @@ impl RPCOperationFindBlockA {
|
||||
.map_err(RPCError::map_internal("too many suppliers"))?,
|
||||
);
|
||||
for s in suppliers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&s, crypto.clone())?;
|
||||
let peer_info = decode_peer_info(&s)?;
|
||||
suppliers.push(peer_info);
|
||||
}
|
||||
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
@@ -59,12 +126,12 @@ impl RPCOperationFindBlockA {
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(RPCOperationFindBlockA {
|
||||
data,
|
||||
Ok(Self {
|
||||
data: data.to_vec(),
|
||||
suppliers,
|
||||
peers,
|
||||
})
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_FIND_NODE_A_PEERS_LEN: usize = 20;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationFindNodeQ {
|
||||
pub node_id: TypedKey,
|
||||
node_id: TypedKey,
|
||||
}
|
||||
|
||||
impl RPCOperationFindNodeQ {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_find_node_q::Reader,
|
||||
) -> Result<RPCOperationFindNodeQ, RPCError> {
|
||||
pub fn new(node_id: TypedKey) -> Self {
|
||||
Self { node_id }
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn node_id(&self) -> &TypedKey {
|
||||
// &self.node_id
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> TypedKey {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_find_node_q::Reader) -> Result<Self, RPCError> {
|
||||
let ni_reader = reader.get_node_id().map_err(RPCError::protocol)?;
|
||||
let node_id = decode_typed_key(&ni_reader)?;
|
||||
Ok(RPCOperationFindNodeQ { node_id })
|
||||
Ok(Self { node_id })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -25,15 +40,40 @@ impl RPCOperationFindNodeQ {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationFindNodeA {
|
||||
pub peers: Vec<PeerInfo>,
|
||||
peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationFindNodeA {
|
||||
pub fn new(peers: Vec<PeerInfo>) -> Result<Self, RPCError> {
|
||||
if peers.len() > MAX_FIND_NODE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("find node peers length too long"));
|
||||
}
|
||||
|
||||
Ok(Self { peers })
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn peers(&self) -> &[PeerInfo] {
|
||||
// &self.peers
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> Vec<PeerInfo> {
|
||||
self.peers
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_find_node_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationFindNodeA, RPCError> {
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
|
||||
if peers_reader.len() as usize > MAX_FIND_NODE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("find node peers length too long"));
|
||||
}
|
||||
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
@@ -41,11 +81,11 @@ impl RPCOperationFindNodeA {
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(RPCOperationFindNodeA { peers })
|
||||
Ok(Self { peers })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -1,19 +1,67 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::{SignedValueData, SignedValueDescriptor};
|
||||
|
||||
const MAX_GET_VALUE_A_PEERS_LEN: usize = 20;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValidateGetValueContext {
|
||||
pub last_descriptor: Option<SignedValueDescriptor>,
|
||||
pub subkey: ValueSubkey,
|
||||
pub vcrypto: CryptoSystemVersion,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValidateGetValueContext {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ValidateGetValueContext")
|
||||
.field("last_descriptor", &self.last_descriptor)
|
||||
.field("subkey", &self.subkey)
|
||||
.field("vcrypto", &self.vcrypto.kind().to_string())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationGetValueQ {
|
||||
pub key: TypedKey,
|
||||
pub subkey: ValueSubkey,
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
want_descriptor: bool,
|
||||
}
|
||||
|
||||
impl RPCOperationGetValueQ {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_get_value_q::Reader,
|
||||
) -> Result<RPCOperationGetValueQ, RPCError> {
|
||||
let k_reader = reader.get_key().map_err(RPCError::protocol)?;
|
||||
pub fn new(key: TypedKey, subkey: ValueSubkey, want_descriptor: bool) -> Self {
|
||||
Self {
|
||||
key,
|
||||
subkey,
|
||||
want_descriptor,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn key(&self) -> &TypedKey {
|
||||
// &self.key
|
||||
// }
|
||||
// pub fn subkey(&self) -> ValueSubkey {
|
||||
// self.subkey
|
||||
// }
|
||||
// pub fn want_descriptor(&self) -> bool {
|
||||
// self.want_descriptor
|
||||
// }
|
||||
pub fn destructure(self) -> (TypedKey, ValueSubkey, bool) {
|
||||
(self.key, self.subkey, self.want_descriptor)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_get_value_q::Reader) -> Result<Self, RPCError> {
|
||||
let k_reader = reader.reborrow().get_key().map_err(RPCError::protocol)?;
|
||||
let key = decode_typed_key(&k_reader)?;
|
||||
let subkey = reader.get_subkey();
|
||||
Ok(RPCOperationGetValueQ { key, subkey })
|
||||
let subkey = reader.reborrow().get_subkey();
|
||||
let want_descriptor = reader.reborrow().get_want_descriptor();
|
||||
Ok(Self {
|
||||
key,
|
||||
subkey,
|
||||
want_descriptor,
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -22,64 +70,171 @@ impl RPCOperationGetValueQ {
|
||||
let mut k_builder = builder.reborrow().init_key();
|
||||
encode_typed_key(&self.key, &mut k_builder);
|
||||
builder.set_subkey(self.subkey);
|
||||
builder.set_want_descriptor(self.want_descriptor);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RPCOperationGetValueA {
|
||||
Data(ValueData),
|
||||
Peers(Vec<PeerInfo>),
|
||||
pub struct RPCOperationGetValueA {
|
||||
value: Option<SignedValueData>,
|
||||
peers: Vec<PeerInfo>,
|
||||
descriptor: Option<SignedValueDescriptor>,
|
||||
}
|
||||
|
||||
impl RPCOperationGetValueA {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_get_value_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationGetValueA, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_get_value_a::Which::Data(r) => {
|
||||
let data = decode_value_data(&r.map_err(RPCError::protocol)?)?;
|
||||
Ok(RPCOperationGetValueA::Data(data))
|
||||
}
|
||||
veilid_capnp::operation_get_value_a::Which::Peers(r) => {
|
||||
let peers_reader = r.map_err(RPCError::protocol)?;
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
pub fn new(
|
||||
value: Option<SignedValueData>,
|
||||
peers: Vec<PeerInfo>,
|
||||
descriptor: Option<SignedValueDescriptor>,
|
||||
) -> Result<Self, RPCError> {
|
||||
if peers.len() > MAX_GET_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("GetValueA peers length too long"));
|
||||
}
|
||||
if descriptor.is_some() && !value.is_some() {
|
||||
return Err(RPCError::protocol(
|
||||
"GetValueA should not return descriptor without value",
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
value,
|
||||
peers,
|
||||
descriptor,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(RPCOperationGetValueA::Peers(peers))
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
let question_context = validate_context
|
||||
.question_context
|
||||
.as_ref()
|
||||
.expect("GetValueA requires question context");
|
||||
let QuestionContext::GetValue(get_value_context) = question_context else {
|
||||
panic!("Wrong context type for GetValueA");
|
||||
};
|
||||
|
||||
if let Some(value) = &self.value {
|
||||
// Get descriptor to validate with
|
||||
let descriptor = if let Some(descriptor) = &self.descriptor {
|
||||
if let Some(last_descriptor) = &get_value_context.last_descriptor {
|
||||
if descriptor.cmp_no_sig(last_descriptor) != cmp::Ordering::Equal {
|
||||
return Err(RPCError::protocol(
|
||||
"getvalue descriptor does not match last descriptor",
|
||||
));
|
||||
}
|
||||
}
|
||||
descriptor
|
||||
} else {
|
||||
let Some(descriptor) = &get_value_context.last_descriptor else {
|
||||
return Err(RPCError::protocol(
|
||||
"no last descriptor, requires a descriptor",
|
||||
));
|
||||
};
|
||||
descriptor
|
||||
};
|
||||
// Ensure the descriptor itself validates
|
||||
descriptor
|
||||
.validate(get_value_context.vcrypto.clone())
|
||||
.map_err(RPCError::protocol)?;
|
||||
|
||||
// And the signed value data
|
||||
value
|
||||
.validate(
|
||||
descriptor.owner(),
|
||||
get_value_context.subkey,
|
||||
get_value_context.vcrypto.clone(),
|
||||
)
|
||||
.map_err(RPCError::protocol)?;
|
||||
} else {
|
||||
// No value, should not have descriptor
|
||||
if self.descriptor.is_some() {
|
||||
return Err(RPCError::protocol("descriptor returned without a value"));
|
||||
}
|
||||
}
|
||||
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn value(&self) -> Option<&SignedValueData> {
|
||||
// self.value.as_ref()
|
||||
// }
|
||||
// pub fn peers(&self) -> &[PeerInfo] {
|
||||
// &self.peers
|
||||
// }
|
||||
// pub fn descriptor(&self) -> Option<&SignedValueDescriptor> {
|
||||
// self.descriptor.as_ref()
|
||||
// }
|
||||
pub fn destructure(
|
||||
self,
|
||||
) -> (
|
||||
Option<SignedValueData>,
|
||||
Vec<PeerInfo>,
|
||||
Option<SignedValueDescriptor>,
|
||||
) {
|
||||
(self.value, self.peers, self.descriptor)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_get_value_a::Reader) -> Result<Self, RPCError> {
|
||||
let value = if reader.has_value() {
|
||||
let value_reader = reader.get_value().map_err(RPCError::protocol)?;
|
||||
let value = decode_signed_value_data(&value_reader)?;
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
if peers_reader.len() as usize > MAX_GET_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("GetValueA peers length too long"));
|
||||
}
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
let descriptor = if reader.has_descriptor() {
|
||||
let d_reader = reader.get_descriptor().map_err(RPCError::protocol)?;
|
||||
let descriptor = decode_signed_value_descriptor(&d_reader)?;
|
||||
Some(descriptor)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
value,
|
||||
peers,
|
||||
descriptor,
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
builder: &mut veilid_capnp::operation_get_value_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationGetValueA::Data(data) => {
|
||||
let mut d_builder = builder.reborrow().init_data();
|
||||
encode_value_data(&data, &mut d_builder)?;
|
||||
}
|
||||
RPCOperationGetValueA::Peers(peers) => {
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
}
|
||||
if let Some(value) = &self.value {
|
||||
let mut v_builder = builder.reborrow().init_value();
|
||||
encode_signed_value_data(value, &mut v_builder)?;
|
||||
}
|
||||
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
self.peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in self.peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
|
||||
if let Some(descriptor) = &self.descriptor {
|
||||
let mut d_builder = builder.reborrow().init_descriptor();
|
||||
encode_signed_value_descriptor(descriptor, &mut d_builder)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -2,17 +2,46 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationReturnReceipt {
|
||||
pub receipt: Vec<u8>,
|
||||
receipt: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RPCOperationReturnReceipt {
|
||||
pub fn new(receipt: Vec<u8>) -> Result<Self, RPCError> {
|
||||
if receipt.len() < MIN_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol("ReturnReceipt receipt too short to set"));
|
||||
}
|
||||
if receipt.len() > MAX_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol("ReturnReceipt receipt too long to set"));
|
||||
}
|
||||
|
||||
Ok(Self { receipt })
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn receipt(&self) -> &[u8] {
|
||||
// &self.receipt
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> Vec<u8> {
|
||||
self.receipt
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_return_receipt::Reader,
|
||||
) -> Result<RPCOperationReturnReceipt, RPCError> {
|
||||
let rcpt_reader = reader.get_receipt().map_err(RPCError::protocol)?;
|
||||
let receipt = rcpt_reader.to_vec();
|
||||
) -> Result<Self, RPCError> {
|
||||
let rr = reader.get_receipt().map_err(RPCError::protocol)?;
|
||||
if rr.len() < MIN_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol("ReturnReceipt receipt too short to set"));
|
||||
}
|
||||
if rr.len() > MAX_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol("ReturnReceipt receipt too long to set"));
|
||||
}
|
||||
|
||||
Ok(RPCOperationReturnReceipt { receipt })
|
||||
Ok(Self {
|
||||
receipt: rr.to_vec(),
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -2,10 +2,10 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RoutedOperation {
|
||||
pub sequencing: Sequencing,
|
||||
pub signatures: Vec<Signature>,
|
||||
pub nonce: Nonce,
|
||||
pub data: Vec<u8>,
|
||||
sequencing: Sequencing,
|
||||
signatures: Vec<Signature>,
|
||||
nonce: Nonce,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RoutedOperation {
|
||||
@@ -17,10 +17,33 @@ impl RoutedOperation {
|
||||
data,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
//xxx
|
||||
Ok(())
|
||||
}
|
||||
pub fn sequencing(&self) -> Sequencing {
|
||||
self.sequencing
|
||||
}
|
||||
pub fn signatures(&self) -> &[Signature] {
|
||||
&self.signatures
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::routed_operation::Reader,
|
||||
) -> Result<RoutedOperation, RPCError> {
|
||||
pub fn add_signature(&mut self, signature: Signature) {
|
||||
self.signatures.push(signature);
|
||||
}
|
||||
|
||||
pub fn nonce(&self) -> &Nonce {
|
||||
&self.nonce
|
||||
}
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn destructure(self) -> (Sequencing, Vec<Signature>, Nonce, Vec<u8>) {
|
||||
(self.sequencing, self.signatures, self.nonce, self.data)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::routed_operation::Reader) -> Result<Self, RPCError> {
|
||||
let sigs_reader = reader.get_signatures().map_err(RPCError::protocol)?;
|
||||
let mut signatures = Vec::<Signature>::with_capacity(
|
||||
sigs_reader
|
||||
@@ -36,13 +59,13 @@ impl RoutedOperation {
|
||||
let sequencing = decode_sequencing(reader.get_sequencing().map_err(RPCError::protocol)?);
|
||||
let n_reader = reader.get_nonce().map_err(RPCError::protocol)?;
|
||||
let nonce = decode_nonce(&n_reader);
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?;
|
||||
|
||||
Ok(RoutedOperation {
|
||||
Ok(Self {
|
||||
sequencing,
|
||||
signatures,
|
||||
nonce,
|
||||
data,
|
||||
data: data.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -73,22 +96,39 @@ impl RoutedOperation {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationRoute {
|
||||
pub safety_route: SafetyRoute,
|
||||
pub operation: RoutedOperation,
|
||||
safety_route: SafetyRoute,
|
||||
operation: RoutedOperation,
|
||||
}
|
||||
|
||||
impl RPCOperationRoute {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_route::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationRoute, RPCError> {
|
||||
pub fn new(safety_route: SafetyRoute, operation: RoutedOperation) -> Self {
|
||||
Self {
|
||||
safety_route,
|
||||
operation,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
self.operation.validate(validate_context)
|
||||
}
|
||||
|
||||
pub fn safety_route(&self) -> &SafetyRoute {
|
||||
&self.safety_route
|
||||
}
|
||||
pub fn operation(&self) -> &RoutedOperation {
|
||||
&self.operation
|
||||
}
|
||||
pub fn destructure(self) -> (SafetyRoute, RoutedOperation) {
|
||||
(self.safety_route, self.operation)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_route::Reader) -> Result<Self, RPCError> {
|
||||
let sr_reader = reader.get_safety_route().map_err(RPCError::protocol)?;
|
||||
let safety_route = decode_safety_route(&sr_reader, crypto)?;
|
||||
let safety_route = decode_safety_route(&sr_reader)?;
|
||||
|
||||
let o_reader = reader.get_operation().map_err(RPCError::protocol)?;
|
||||
let operation = RoutedOperation::decode(&o_reader)?;
|
||||
|
||||
Ok(RPCOperationRoute {
|
||||
Ok(Self {
|
||||
safety_route,
|
||||
operation,
|
||||
})
|
||||
|
||||
@@ -1,22 +1,96 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::{SignedValueData, SignedValueDescriptor};
|
||||
|
||||
const MAX_SET_VALUE_A_PEERS_LEN: usize = 20;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValidateSetValueContext {
|
||||
pub descriptor: SignedValueDescriptor,
|
||||
pub subkey: ValueSubkey,
|
||||
pub vcrypto: CryptoSystemVersion,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValidateSetValueContext {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("ValidateSetValueContext")
|
||||
.field("descriptor", &self.descriptor)
|
||||
.field("subkey", &self.subkey)
|
||||
.field("vcrypto", &self.vcrypto.kind().to_string())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationSetValueQ {
|
||||
pub key: TypedKey,
|
||||
pub subkey: ValueSubkey,
|
||||
pub value: ValueData,
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
value: SignedValueData,
|
||||
descriptor: Option<SignedValueDescriptor>,
|
||||
}
|
||||
|
||||
impl RPCOperationSetValueQ {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_set_value_q::Reader,
|
||||
) -> Result<RPCOperationSetValueQ, RPCError> {
|
||||
pub fn new(
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
value: SignedValueData,
|
||||
descriptor: Option<SignedValueDescriptor>,
|
||||
) -> Self {
|
||||
Self {
|
||||
key,
|
||||
subkey,
|
||||
value,
|
||||
descriptor,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn key(&self) -> &TypedKey {
|
||||
// &self.key
|
||||
// }
|
||||
|
||||
// pub fn subkey(&self) -> ValueSubkey {
|
||||
// self.subkey
|
||||
// }
|
||||
|
||||
// pub fn value(&self) -> &SignedValueData {
|
||||
// &self.value
|
||||
// }
|
||||
|
||||
// pub fn descriptor(&self) -> Option<&SignedValueDescriptor> {
|
||||
// self.descriptor.as_ref()
|
||||
// }
|
||||
pub fn destructure(
|
||||
self,
|
||||
) -> (
|
||||
TypedKey,
|
||||
ValueSubkey,
|
||||
SignedValueData,
|
||||
Option<SignedValueDescriptor>,
|
||||
) {
|
||||
(self.key, self.subkey, self.value, self.descriptor)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_set_value_q::Reader) -> Result<Self, RPCError> {
|
||||
let k_reader = reader.get_key().map_err(RPCError::protocol)?;
|
||||
let key = decode_typed_key(&k_reader)?;
|
||||
let subkey = reader.get_subkey();
|
||||
let v_reader = reader.get_value().map_err(RPCError::protocol)?;
|
||||
let value = decode_value_data(&v_reader)?;
|
||||
Ok(RPCOperationSetValueQ { key, subkey, value })
|
||||
let value = decode_signed_value_data(&v_reader)?;
|
||||
let descriptor = if reader.has_descriptor() {
|
||||
let d_reader = reader.get_descriptor().map_err(RPCError::protocol)?;
|
||||
let descriptor = decode_signed_value_descriptor(&d_reader)?;
|
||||
Some(descriptor)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Self {
|
||||
key,
|
||||
subkey,
|
||||
value,
|
||||
descriptor,
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -26,65 +100,123 @@ impl RPCOperationSetValueQ {
|
||||
encode_typed_key(&self.key, &mut k_builder);
|
||||
builder.set_subkey(self.subkey);
|
||||
let mut v_builder = builder.reborrow().init_value();
|
||||
encode_value_data(&self.value, &mut v_builder)?;
|
||||
encode_signed_value_data(&self.value, &mut v_builder)?;
|
||||
if let Some(descriptor) = &self.descriptor {
|
||||
let mut d_builder = builder.reborrow().init_descriptor();
|
||||
encode_signed_value_descriptor(descriptor, &mut d_builder)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RPCOperationSetValueA {
|
||||
Data(ValueData),
|
||||
Peers(Vec<PeerInfo>),
|
||||
pub struct RPCOperationSetValueA {
|
||||
set: bool,
|
||||
value: Option<SignedValueData>,
|
||||
peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationSetValueA {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_set_value_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationSetValueA, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_set_value_a::Which::Data(r) => {
|
||||
let data = decode_value_data(&r.map_err(RPCError::protocol)?)?;
|
||||
Ok(RPCOperationSetValueA::Data(data))
|
||||
}
|
||||
veilid_capnp::operation_set_value_a::Which::Peers(r) => {
|
||||
let peers_reader = r.map_err(RPCError::protocol)?;
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(RPCOperationSetValueA::Peers(peers))
|
||||
}
|
||||
pub fn new(
|
||||
set: bool,
|
||||
value: Option<SignedValueData>,
|
||||
peers: Vec<PeerInfo>,
|
||||
) -> Result<Self, RPCError> {
|
||||
if peers.len() as usize > MAX_SET_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("SetValueA peers length too long"));
|
||||
}
|
||||
Ok(Self { set, value, peers })
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
let question_context = validate_context
|
||||
.question_context
|
||||
.as_ref()
|
||||
.expect("SetValueA requires question context");
|
||||
let QuestionContext::SetValue(set_value_context) = question_context else {
|
||||
panic!("Wrong context type for SetValueA");
|
||||
};
|
||||
|
||||
if let Some(value) = &self.value {
|
||||
// Ensure the descriptor itself validates
|
||||
set_value_context
|
||||
.descriptor
|
||||
.validate(set_value_context.vcrypto.clone())
|
||||
.map_err(RPCError::protocol)?;
|
||||
|
||||
// And the signed value data
|
||||
value
|
||||
.validate(
|
||||
set_value_context.descriptor.owner(),
|
||||
set_value_context.subkey,
|
||||
set_value_context.vcrypto.clone(),
|
||||
)
|
||||
.map_err(RPCError::protocol)?;
|
||||
}
|
||||
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn set(&self) -> bool {
|
||||
// self.set
|
||||
// }
|
||||
// pub fn value(&self) -> Option<&SignedValueData> {
|
||||
// self.value.as_ref()
|
||||
// }
|
||||
// pub fn peers(&self) -> &[PeerInfo] {
|
||||
// &self.peers
|
||||
// }
|
||||
pub fn destructure(self) -> (bool, Option<SignedValueData>, Vec<PeerInfo>) {
|
||||
(self.set, self.value, self.peers)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_set_value_a::Reader) -> Result<Self, RPCError> {
|
||||
let set = reader.get_set();
|
||||
let value = if reader.has_value() {
|
||||
let v_reader = reader.get_value().map_err(RPCError::protocol)?;
|
||||
let value = decode_signed_value_data(&v_reader)?;
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
if peers_reader.len() as usize > MAX_SET_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("SetValueA peers length too long"));
|
||||
}
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(Self { set, value, peers })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
builder: &mut veilid_capnp::operation_set_value_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationSetValueA::Data(data) => {
|
||||
let mut d_builder = builder.reborrow().init_data();
|
||||
encode_value_data(&data, &mut d_builder)?;
|
||||
}
|
||||
RPCOperationSetValueA::Peers(peers) => {
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
}
|
||||
builder.set_set(self.set);
|
||||
|
||||
if let Some(value) = &self.value {
|
||||
let mut v_builder = builder.reborrow().init_value();
|
||||
encode_signed_value_data(value, &mut v_builder)?;
|
||||
}
|
||||
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
self.peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in self.peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -2,16 +2,26 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationSignal {
|
||||
pub signal_info: SignalInfo,
|
||||
signal_info: SignalInfo,
|
||||
}
|
||||
|
||||
impl RPCOperationSignal {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_signal::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationSignal, RPCError> {
|
||||
let signal_info = decode_signal_info(reader, crypto)?;
|
||||
Ok(RPCOperationSignal { signal_info })
|
||||
pub fn new(signal_info: SignalInfo) -> Self {
|
||||
Self { signal_info }
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
self.signal_info.validate(validate_context.crypto.clone())
|
||||
}
|
||||
// pub fn signal_info(&self) -> &SignalInfo {
|
||||
// &self.signal_info
|
||||
// }
|
||||
pub fn destructure(self) -> SignalInfo {
|
||||
self.signal_info
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_signal::Reader) -> Result<Self, RPCError> {
|
||||
let signal_info = decode_signal_info(reader)?;
|
||||
Ok(Self { signal_info })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -2,15 +2,40 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationStartTunnelQ {
|
||||
pub id: TunnelId,
|
||||
pub local_mode: TunnelMode,
|
||||
pub depth: u8,
|
||||
id: TunnelId,
|
||||
local_mode: TunnelMode,
|
||||
depth: u8,
|
||||
}
|
||||
|
||||
impl RPCOperationStartTunnelQ {
|
||||
pub fn new(id: TunnelId, local_mode: TunnelMode, depth: u8) -> Self {
|
||||
Self {
|
||||
id,
|
||||
local_mode,
|
||||
depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> TunnelId {
|
||||
self.id
|
||||
}
|
||||
pub fn local_mode(&self) -> TunnelMode {
|
||||
self.local_mode
|
||||
}
|
||||
pub fn depth(&self) -> u8 {
|
||||
self.depth
|
||||
}
|
||||
pub fn destructure(self) -> (TunnelId, TunnelMode, u8) {
|
||||
(self.id, self.local_mode, self.depth)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_start_tunnel_q::Reader,
|
||||
) -> Result<RPCOperationStartTunnelQ, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let id = TunnelId::new(reader.get_id());
|
||||
let local_mode = match reader.get_local_mode().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::TunnelEndpointMode::Raw => TunnelMode::Raw,
|
||||
@@ -18,7 +43,7 @@ impl RPCOperationStartTunnelQ {
|
||||
};
|
||||
let depth = reader.get_depth();
|
||||
|
||||
Ok(RPCOperationStartTunnelQ {
|
||||
Ok(Self {
|
||||
id,
|
||||
local_mode,
|
||||
depth,
|
||||
@@ -46,18 +71,28 @@ pub enum RPCOperationStartTunnelA {
|
||||
}
|
||||
|
||||
impl RPCOperationStartTunnelA {
|
||||
pub fn new_partial(partial_tunnel: PartialTunnel) -> Self {
|
||||
Self::Partial(partial_tunnel)
|
||||
}
|
||||
pub fn new_error(tunnel_error: TunnelError) -> Self {
|
||||
Self::Error(tunnel_error)
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_start_tunnel_a::Reader,
|
||||
) -> Result<RPCOperationStartTunnelA, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_start_tunnel_a::Which::Partial(r) => {
|
||||
let pt_reader = r.map_err(RPCError::protocol)?;
|
||||
let partial_tunnel = decode_partial_tunnel(&pt_reader)?;
|
||||
Ok(RPCOperationStartTunnelA::Partial(partial_tunnel))
|
||||
Ok(Self::Partial(partial_tunnel))
|
||||
}
|
||||
veilid_capnp::operation_start_tunnel_a::Which::Error(r) => {
|
||||
let tunnel_error = decode_tunnel_error(r.map_err(RPCError::protocol)?);
|
||||
Ok(RPCOperationStartTunnelA::Error(tunnel_error))
|
||||
Ok(Self::Error(tunnel_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,10 +101,10 @@ impl RPCOperationStartTunnelA {
|
||||
builder: &mut veilid_capnp::operation_start_tunnel_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationStartTunnelA::Partial(p) => {
|
||||
Self::Partial(p) => {
|
||||
encode_partial_tunnel(p, &mut builder.reborrow().init_partial())?;
|
||||
}
|
||||
RPCOperationStartTunnelA::Error(e) => {
|
||||
Self::Error(e) => {
|
||||
builder.set_error(encode_tunnel_error(*e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,25 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationStatusQ {
|
||||
pub node_status: Option<NodeStatus>,
|
||||
node_status: Option<NodeStatus>,
|
||||
}
|
||||
|
||||
impl RPCOperationStatusQ {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_status_q::Reader,
|
||||
) -> Result<RPCOperationStatusQ, RPCError> {
|
||||
pub fn new(node_status: Option<NodeStatus>) -> Self {
|
||||
Self { node_status }
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn node_status(&self) -> Option<&NodeStatus> {
|
||||
// self.node_status.as_ref()
|
||||
// }
|
||||
pub fn destructure(self) -> Option<NodeStatus> {
|
||||
self.node_status
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_status_q::Reader) -> Result<Self, RPCError> {
|
||||
let node_status = if reader.has_node_status() {
|
||||
let ns_reader = reader.get_node_status().map_err(RPCError::protocol)?;
|
||||
let node_status = decode_node_status(&ns_reader)?;
|
||||
@@ -16,7 +28,7 @@ impl RPCOperationStatusQ {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(RPCOperationStatusQ { node_status })
|
||||
Ok(Self { node_status })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -32,14 +44,33 @@ impl RPCOperationStatusQ {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationStatusA {
|
||||
pub node_status: Option<NodeStatus>,
|
||||
pub sender_info: Option<SenderInfo>,
|
||||
node_status: Option<NodeStatus>,
|
||||
sender_info: Option<SenderInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationStatusA {
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_status_a::Reader,
|
||||
) -> Result<RPCOperationStatusA, RPCError> {
|
||||
pub fn new(node_status: Option<NodeStatus>, sender_info: Option<SenderInfo>) -> Self {
|
||||
Self {
|
||||
node_status,
|
||||
sender_info,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn node_status(&self) -> Option<&NodeStatus> {
|
||||
// self.node_status.as_ref()
|
||||
// }
|
||||
// pub fn sender_info(&self) -> Option<&SenderInfo> {
|
||||
// self.sender_info.as_ref()
|
||||
// }
|
||||
pub fn destructure(self) -> (Option<NodeStatus>, Option<SenderInfo>) {
|
||||
(self.node_status, self.sender_info)
|
||||
}
|
||||
|
||||
pub fn decode(reader: &veilid_capnp::operation_status_a::Reader) -> Result<Self, RPCError> {
|
||||
let node_status = if reader.has_node_status() {
|
||||
let ns_reader = reader.get_node_status().map_err(RPCError::protocol)?;
|
||||
let node_status = decode_node_status(&ns_reader)?;
|
||||
@@ -56,7 +87,7 @@ impl RPCOperationStatusA {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(RPCOperationStatusA {
|
||||
Ok(Self {
|
||||
node_status,
|
||||
sender_info,
|
||||
})
|
||||
|
||||
@@ -1,18 +1,35 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_SUPPLY_BLOCK_A_PEERS_LEN: usize = 20;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationSupplyBlockQ {
|
||||
pub block_id: TypedKey,
|
||||
block_id: TypedKey,
|
||||
}
|
||||
|
||||
impl RPCOperationSupplyBlockQ {
|
||||
pub fn new(block_id: TypedKey) -> Self {
|
||||
Self { block_id }
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn block_id(&self) -> &TypedKey {
|
||||
&self.block_id
|
||||
}
|
||||
|
||||
pub fn destructure(self) -> TypedKey {
|
||||
self.block_id
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_supply_block_q::Reader,
|
||||
) -> Result<RPCOperationSupplyBlockQ, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?;
|
||||
let block_id = decode_typed_key(&bi_reader)?;
|
||||
|
||||
Ok(RPCOperationSupplyBlockQ { block_id })
|
||||
Ok(Self { block_id })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -26,57 +43,68 @@ impl RPCOperationSupplyBlockQ {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RPCOperationSupplyBlockA {
|
||||
Expiration(u64),
|
||||
Peers(Vec<PeerInfo>),
|
||||
pub struct RPCOperationSupplyBlockA {
|
||||
expiration: u64,
|
||||
peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationSupplyBlockA {
|
||||
pub fn new(expiration: u64, peers: Vec<PeerInfo>) -> Result<Self, RPCError> {
|
||||
if peers.len() > MAX_SUPPLY_BLOCK_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("SupplyBlockA peers length too long"));
|
||||
}
|
||||
Ok(Self { expiration, peers })
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
pub fn expiration(&self) -> u64 {
|
||||
self.expiration
|
||||
}
|
||||
pub fn peers(&self) -> &[PeerInfo] {
|
||||
&self.peers
|
||||
}
|
||||
pub fn destructure(self) -> (u64, Vec<PeerInfo>) {
|
||||
(self.expiration, self.peers)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_supply_block_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationSupplyBlockA, RPCError> {
|
||||
match reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::operation_supply_block_a::Which::Expiration(r) => {
|
||||
Ok(RPCOperationSupplyBlockA::Expiration(r))
|
||||
}
|
||||
veilid_capnp::operation_supply_block_a::Which::Peers(r) => {
|
||||
let peers_reader = r.map_err(RPCError::protocol)?;
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
) -> Result<Self, RPCError> {
|
||||
let expiration = reader.get_expiration();
|
||||
|
||||
Ok(RPCOperationSupplyBlockA::Peers(peers))
|
||||
}
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
if peers_reader.len() as usize > MAX_SUPPLY_BLOCK_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("SupplyBlockA peers length too long"));
|
||||
}
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(Self { expiration, peers })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
builder: &mut veilid_capnp::operation_supply_block_a::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCOperationSupplyBlockA::Expiration(e) => {
|
||||
builder.set_expiration(*e);
|
||||
}
|
||||
RPCOperationSupplyBlockA::Peers(peers) => {
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
}
|
||||
builder.set_expiration(self.expiration);
|
||||
let mut peers_builder = builder.reborrow().init_peers(
|
||||
self.peers
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_internal("invalid peers list length"))?,
|
||||
);
|
||||
for (i, peer) in self.peers.iter().enumerate() {
|
||||
let mut pi_builder = peers_builder.reborrow().get(i as u32);
|
||||
encode_peer_info(peer, &mut pi_builder)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -2,22 +2,68 @@ use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationValidateDialInfo {
|
||||
pub dial_info: DialInfo,
|
||||
pub receipt: Vec<u8>,
|
||||
pub redirect: bool,
|
||||
dial_info: DialInfo,
|
||||
receipt: Vec<u8>,
|
||||
redirect: bool,
|
||||
}
|
||||
|
||||
impl RPCOperationValidateDialInfo {
|
||||
pub fn new(dial_info: DialInfo, receipt: Vec<u8>, redirect: bool) -> Result<Self, RPCError> {
|
||||
if receipt.len() < MIN_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol(
|
||||
"ValidateDialInfo receipt too short to set",
|
||||
));
|
||||
}
|
||||
if receipt.len() > MAX_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol(
|
||||
"ValidateDialInfo receipt too long to set",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
dial_info,
|
||||
receipt,
|
||||
redirect,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
}
|
||||
// pub fn dial_info(&self) -> &DialInfo {
|
||||
// &self.dial_info
|
||||
// }
|
||||
// pub fn receipt(&self) -> &[u8] {
|
||||
// &self.receipt
|
||||
// }
|
||||
// pub fn redirect(&self) -> bool {
|
||||
// self.redirect
|
||||
// }
|
||||
pub fn destructure(self) -> (DialInfo, Vec<u8>, bool) {
|
||||
(self.dial_info, self.receipt, self.redirect)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_validate_dial_info::Reader,
|
||||
) -> Result<RPCOperationValidateDialInfo, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let di_reader = reader.get_dial_info().map_err(RPCError::protocol)?;
|
||||
let dial_info = decode_dial_info(&di_reader)?;
|
||||
let rcpt_reader = reader.get_receipt().map_err(RPCError::protocol)?;
|
||||
if rcpt_reader.len() < MIN_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol(
|
||||
"ValidateDialInfo receipt too short to set",
|
||||
));
|
||||
}
|
||||
if rcpt_reader.len() > MAX_RECEIPT_SIZE {
|
||||
return Err(RPCError::protocol(
|
||||
"ValidateDialInfo receipt too long to set",
|
||||
));
|
||||
}
|
||||
|
||||
let receipt = rcpt_reader.to_vec();
|
||||
let redirect = reader.get_redirect();
|
||||
|
||||
Ok(RPCOperationValidateDialInfo {
|
||||
Ok(Self {
|
||||
dial_info,
|
||||
receipt,
|
||||
redirect,
|
||||
|
||||
@@ -1,17 +1,53 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::SignedValueData;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationValueChanged {
|
||||
pub key: TypedKey,
|
||||
pub subkeys: Vec<ValueSubkeyRange>,
|
||||
pub count: u32,
|
||||
pub value: ValueData,
|
||||
key: TypedKey,
|
||||
subkeys: Vec<ValueSubkeyRange>,
|
||||
count: u32,
|
||||
value: SignedValueData,
|
||||
}
|
||||
|
||||
impl RPCOperationValueChanged {
|
||||
pub fn new(
|
||||
key: TypedKey,
|
||||
subkeys: Vec<ValueSubkeyRange>,
|
||||
count: u32,
|
||||
value: SignedValueData,
|
||||
) -> Self {
|
||||
Self {
|
||||
key,
|
||||
subkeys,
|
||||
count,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
// validation must be done by storage manager as this is more complicated
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn key(&self) -> &TypedKey {
|
||||
&self.key
|
||||
}
|
||||
pub fn subkeys(&self) -> &[ValueSubkeyRange] {
|
||||
&self.subkeys
|
||||
}
|
||||
pub fn count(&self) -> u32 {
|
||||
self.count
|
||||
}
|
||||
pub fn value(&self) -> &SignedValueData {
|
||||
&self.value
|
||||
}
|
||||
pub fn destructure(self) -> (TypedKey, Vec<ValueSubkeyRange>, u32, SignedValueData) {
|
||||
(self.key, self.subkeys, self.count, self.value)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_value_changed::Reader,
|
||||
) -> Result<RPCOperationValueChanged, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let k_reader = reader.get_key().map_err(RPCError::protocol)?;
|
||||
let key = decode_typed_key(&k_reader)?;
|
||||
|
||||
@@ -38,8 +74,8 @@ impl RPCOperationValueChanged {
|
||||
}
|
||||
let count = reader.get_count();
|
||||
let v_reader = reader.get_value().map_err(RPCError::protocol)?;
|
||||
let value = decode_value_data(&v_reader)?;
|
||||
Ok(RPCOperationValueChanged {
|
||||
let value = decode_signed_value_data(&v_reader)?;
|
||||
Ok(Self {
|
||||
key,
|
||||
subkeys,
|
||||
count,
|
||||
@@ -68,7 +104,7 @@ impl RPCOperationValueChanged {
|
||||
builder.set_count(self.count);
|
||||
|
||||
let mut v_builder = builder.reborrow().init_value();
|
||||
encode_value_data(&self.value, &mut v_builder)?;
|
||||
encode_signed_value_data(&self.value, &mut v_builder)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,117 @@
|
||||
use super::*;
|
||||
|
||||
const MAX_WATCH_VALUE_Q_SUBKEYS_LEN: usize = 512;
|
||||
const MAX_WATCH_VALUE_A_PEERS_LEN: usize = 20;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationWatchValueQ {
|
||||
pub key: TypedKey,
|
||||
pub subkeys: Vec<ValueSubkeyRange>,
|
||||
pub expiration: u64,
|
||||
pub count: u32,
|
||||
key: TypedKey,
|
||||
subkeys: Vec<ValueSubkeyRange>,
|
||||
expiration: u64,
|
||||
count: u32,
|
||||
watcher: PublicKey,
|
||||
signature: Signature,
|
||||
}
|
||||
|
||||
impl RPCOperationWatchValueQ {
|
||||
pub fn new(
|
||||
key: TypedKey,
|
||||
subkeys: Vec<ValueSubkeyRange>,
|
||||
expiration: u64,
|
||||
count: u32,
|
||||
watcher: PublicKey,
|
||||
signature: Signature,
|
||||
) -> Result<Self, RPCError> {
|
||||
if subkeys.len() > MAX_WATCH_VALUE_Q_SUBKEYS_LEN {
|
||||
return Err(RPCError::protocol("WatchValueQ subkeys length too long"));
|
||||
}
|
||||
Ok(Self {
|
||||
key,
|
||||
subkeys,
|
||||
expiration,
|
||||
count,
|
||||
watcher,
|
||||
signature,
|
||||
})
|
||||
}
|
||||
|
||||
// signature covers: key, subkeys, expiration, count, using watcher key
|
||||
fn make_signature_data(&self) -> Vec<u8> {
|
||||
let mut sig_data =
|
||||
Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + (self.subkeys.len() * 8) + 8 + 4);
|
||||
sig_data.extend_from_slice(&self.key.kind.0);
|
||||
sig_data.extend_from_slice(&self.key.value.bytes);
|
||||
for sk in &self.subkeys {
|
||||
sig_data.extend_from_slice(&sk.0.to_le_bytes());
|
||||
sig_data.extend_from_slice(&sk.1.to_le_bytes());
|
||||
}
|
||||
sig_data.extend_from_slice(&self.expiration.to_le_bytes());
|
||||
sig_data.extend_from_slice(&self.count.to_le_bytes());
|
||||
sig_data
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
let Some(vcrypto) = validate_context.crypto.get(self.key.kind) else {
|
||||
return Err(RPCError::protocol("unsupported cryptosystem"));
|
||||
};
|
||||
|
||||
let sig_data = self.make_signature_data();
|
||||
vcrypto
|
||||
.verify(&self.watcher, &sig_data, &self.signature)
|
||||
.map_err(RPCError::protocol)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn key(&self) -> &TypedKey {
|
||||
&self.key
|
||||
}
|
||||
pub fn subkeys(&self) -> &[ValueSubkeyRange] {
|
||||
&self.subkeys
|
||||
}
|
||||
pub fn expiration(&self) -> u64 {
|
||||
self.expiration
|
||||
}
|
||||
pub fn count(&self) -> u32 {
|
||||
self.count
|
||||
}
|
||||
pub fn watcher(&self) -> &PublicKey {
|
||||
&self.watcher
|
||||
}
|
||||
pub fn signature(&self) -> &Signature {
|
||||
&self.signature
|
||||
}
|
||||
|
||||
pub fn destructure(
|
||||
self,
|
||||
) -> (
|
||||
TypedKey,
|
||||
Vec<ValueSubkeyRange>,
|
||||
u64,
|
||||
u32,
|
||||
PublicKey,
|
||||
Signature,
|
||||
) {
|
||||
(
|
||||
self.key,
|
||||
self.subkeys,
|
||||
self.expiration,
|
||||
self.count,
|
||||
self.watcher,
|
||||
self.signature,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_watch_value_q::Reader,
|
||||
) -> Result<RPCOperationWatchValueQ, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let k_reader = reader.get_key().map_err(RPCError::protocol)?;
|
||||
let key = decode_typed_key(&k_reader)?;
|
||||
|
||||
let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?;
|
||||
if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEYS_LEN {
|
||||
return Err(RPCError::protocol("WatchValueQ subkeys length too long"));
|
||||
}
|
||||
let mut subkeys = Vec::<ValueSubkeyRange>::with_capacity(
|
||||
sk_reader
|
||||
.len()
|
||||
@@ -40,13 +136,22 @@ impl RPCOperationWatchValueQ {
|
||||
let expiration = reader.get_expiration();
|
||||
let count = reader.get_count();
|
||||
|
||||
Ok(RPCOperationWatchValueQ {
|
||||
let w_reader = reader.get_watcher().map_err(RPCError::protocol)?;
|
||||
let watcher = decode_key256(&w_reader);
|
||||
|
||||
let s_reader = reader.get_signature().map_err(RPCError::protocol)?;
|
||||
let signature = decode_signature512(&s_reader);
|
||||
|
||||
Ok(Self {
|
||||
key,
|
||||
subkeys,
|
||||
expiration,
|
||||
count,
|
||||
watcher,
|
||||
signature,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode(
|
||||
&self,
|
||||
builder: &mut veilid_capnp::operation_watch_value_q::Builder,
|
||||
@@ -67,23 +172,54 @@ impl RPCOperationWatchValueQ {
|
||||
}
|
||||
builder.set_expiration(self.expiration);
|
||||
builder.set_count(self.count);
|
||||
|
||||
let mut w_builder = builder.reborrow().init_watcher();
|
||||
encode_key256(&self.watcher, &mut w_builder);
|
||||
|
||||
let mut s_builder = builder.reborrow().init_signature();
|
||||
encode_signature512(&self.signature, &mut s_builder);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationWatchValueA {
|
||||
pub expiration: u64,
|
||||
pub peers: Vec<PeerInfo>,
|
||||
expiration: u64,
|
||||
peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCOperationWatchValueA {
|
||||
pub fn new(expiration: u64, peers: Vec<PeerInfo>) -> Result<Self, RPCError> {
|
||||
if peers.len() > MAX_WATCH_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("WatchValueA peers length too long"));
|
||||
}
|
||||
Ok(Self { expiration, peers })
|
||||
}
|
||||
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn expiration(&self) -> u64 {
|
||||
self.expiration
|
||||
}
|
||||
pub fn peers(&self) -> &[PeerInfo] {
|
||||
&self.peers
|
||||
}
|
||||
pub fn destructure(self) -> (u64, Vec<PeerInfo>) {
|
||||
(self.expiration, self.peers)
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::operation_watch_value_a::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCOperationWatchValueA, RPCError> {
|
||||
) -> Result<Self, RPCError> {
|
||||
let expiration = reader.get_expiration();
|
||||
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
|
||||
if peers_reader.len() as usize > MAX_WATCH_VALUE_A_PEERS_LEN {
|
||||
return Err(RPCError::protocol("WatchValueA peers length too long"));
|
||||
}
|
||||
let mut peers = Vec::<PeerInfo>::with_capacity(
|
||||
peers_reader
|
||||
.len()
|
||||
@@ -91,11 +227,11 @@ impl RPCOperationWatchValueA {
|
||||
.map_err(RPCError::map_internal("too many peers"))?,
|
||||
);
|
||||
for p in peers_reader.iter() {
|
||||
let peer_info = decode_peer_info(&p, crypto.clone())?;
|
||||
let peer_info = decode_peer_info(&p)?;
|
||||
peers.push(peer_info);
|
||||
}
|
||||
|
||||
Ok(RPCOperationWatchValueA { expiration, peers })
|
||||
Ok(Self { expiration, peers })
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
|
||||
@@ -10,6 +10,10 @@ impl RPCQuestion {
|
||||
pub fn new(respond_to: RespondTo, detail: RPCQuestionDetail) -> Self {
|
||||
Self { respond_to, detail }
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
self.respond_to.validate(validate_context.crypto.clone())?;
|
||||
self.detail.validate(validate_context)
|
||||
}
|
||||
pub fn respond_to(&self) -> &RespondTo {
|
||||
&self.respond_to
|
||||
}
|
||||
@@ -19,12 +23,12 @@ impl RPCQuestion {
|
||||
pub fn desc(&self) -> &'static str {
|
||||
self.detail.desc()
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::question::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCQuestion, RPCError> {
|
||||
pub fn destructure(self) -> (RespondTo, RPCQuestionDetail) {
|
||||
(self.respond_to, self.detail)
|
||||
}
|
||||
pub fn decode(reader: &veilid_capnp::question::Reader) -> Result<RPCQuestion, RPCError> {
|
||||
let rt_reader = reader.get_respond_to();
|
||||
let respond_to = RespondTo::decode(&rt_reader, crypto)?;
|
||||
let respond_to = RespondTo::decode(&rt_reader)?;
|
||||
let d_reader = reader.get_detail();
|
||||
let detail = RPCQuestionDetail::decode(&d_reader)?;
|
||||
Ok(RPCQuestion { respond_to, detail })
|
||||
@@ -68,6 +72,21 @@ impl RPCQuestionDetail {
|
||||
RPCQuestionDetail::CancelTunnelQ(_) => "CancelTunnelQ",
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCQuestionDetail::StatusQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::FindNodeQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::AppCallQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::GetValueQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::SetValueQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::WatchValueQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::SupplyBlockQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::FindBlockQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::StartTunnelQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::CompleteTunnelQ(r) => r.validate(validate_context),
|
||||
RPCQuestionDetail::CancelTunnelQ(r) => r.validate(validate_context),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::question::detail::Reader,
|
||||
|
||||
@@ -7,6 +7,13 @@ pub enum RespondTo {
|
||||
}
|
||||
|
||||
impl RespondTo {
|
||||
pub fn validate(&mut self, crypto: Crypto) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RespondTo::Sender => Ok(()),
|
||||
RespondTo::PrivateRoute(pr) => pr.validate(crypto).map_err(RPCError::protocol),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode(
|
||||
&self,
|
||||
builder: &mut veilid_capnp::question::respond_to::Builder,
|
||||
@@ -23,15 +30,12 @@ impl RespondTo {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::question::respond_to::Reader,
|
||||
crypto: Crypto,
|
||||
) -> 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,
|
||||
veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => {
|
||||
let pr_reader = pr_reader.map_err(RPCError::protocol)?;
|
||||
let pr = decode_private_route(&pr_reader, crypto)?;
|
||||
let pr = decode_private_route(&pr_reader)?;
|
||||
RespondTo::PrivateRoute(pr)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,21 +9,21 @@ impl RPCStatement {
|
||||
pub fn new(detail: RPCStatementDetail) -> Self {
|
||||
Self { detail }
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
self.detail.validate(validate_context)
|
||||
}
|
||||
pub fn detail(&self) -> &RPCStatementDetail {
|
||||
&self.detail
|
||||
}
|
||||
pub fn into_detail(self) -> RPCStatementDetail {
|
||||
self.detail
|
||||
}
|
||||
pub fn desc(&self) -> &'static str {
|
||||
self.detail.desc()
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::statement::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCStatement, RPCError> {
|
||||
pub fn destructure(self) -> RPCStatementDetail {
|
||||
self.detail
|
||||
}
|
||||
pub fn decode(reader: &veilid_capnp::statement::Reader) -> Result<RPCStatement, RPCError> {
|
||||
let d_reader = reader.get_detail();
|
||||
let detail = RPCStatementDetail::decode(&d_reader, crypto)?;
|
||||
let detail = RPCStatementDetail::decode(&d_reader)?;
|
||||
Ok(RPCStatement { detail })
|
||||
}
|
||||
pub fn encode(&self, builder: &mut veilid_capnp::statement::Builder) -> Result<(), RPCError> {
|
||||
@@ -53,9 +53,18 @@ impl RPCStatementDetail {
|
||||
RPCStatementDetail::AppMessage(_) => "AppMessage",
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
match self {
|
||||
RPCStatementDetail::ValidateDialInfo(r) => r.validate(validate_context),
|
||||
RPCStatementDetail::Route(r) => r.validate(validate_context),
|
||||
RPCStatementDetail::ValueChanged(r) => r.validate(validate_context),
|
||||
RPCStatementDetail::Signal(r) => r.validate(validate_context),
|
||||
RPCStatementDetail::ReturnReceipt(r) => r.validate(validate_context),
|
||||
RPCStatementDetail::AppMessage(r) => r.validate(validate_context),
|
||||
}
|
||||
}
|
||||
pub fn decode(
|
||||
reader: &veilid_capnp::statement::detail::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RPCStatementDetail, RPCError> {
|
||||
let which_reader = reader.which().map_err(RPCError::protocol)?;
|
||||
let out = match which_reader {
|
||||
@@ -66,7 +75,7 @@ impl RPCStatementDetail {
|
||||
}
|
||||
veilid_capnp::statement::detail::Route(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationRoute::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationRoute::decode(&op_reader)?;
|
||||
RPCStatementDetail::Route(out)
|
||||
}
|
||||
veilid_capnp::statement::detail::ValueChanged(r) => {
|
||||
@@ -76,7 +85,7 @@ impl RPCStatementDetail {
|
||||
}
|
||||
veilid_capnp::statement::detail::Signal(r) => {
|
||||
let op_reader = r.map_err(RPCError::protocol)?;
|
||||
let out = RPCOperationSignal::decode(&op_reader, crypto)?;
|
||||
let out = RPCOperationSignal::decode(&op_reader)?;
|
||||
RPCStatementDetail::Signal(out)
|
||||
}
|
||||
veilid_capnp::statement::detail::ReturnReceipt(r) => {
|
||||
|
||||
@@ -7,12 +7,12 @@ pub fn encode_peer_info(
|
||||
//
|
||||
let mut nids_builder = builder.reborrow().init_node_ids(
|
||||
peer_info
|
||||
.node_ids
|
||||
.node_ids()
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_invalid_format("out of bound error"))?,
|
||||
);
|
||||
for (i, nid) in peer_info.node_ids.iter().enumerate() {
|
||||
for (i, nid) in peer_info.node_ids().iter().enumerate() {
|
||||
encode_typed_key(
|
||||
nid,
|
||||
&mut nids_builder.reborrow().get(
|
||||
@@ -22,15 +22,12 @@ pub fn encode_peer_info(
|
||||
);
|
||||
}
|
||||
let mut sni_builder = builder.reborrow().init_signed_node_info();
|
||||
encode_signed_node_info(&peer_info.signed_node_info, &mut sni_builder)?;
|
||||
encode_signed_node_info(peer_info.signed_node_info(), &mut sni_builder)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_peer_info(
|
||||
reader: &veilid_capnp::peer_info::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<PeerInfo, RPCError> {
|
||||
pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<PeerInfo, RPCError> {
|
||||
let nids_reader = reader
|
||||
.reborrow()
|
||||
.get_node_ids()
|
||||
@@ -43,12 +40,9 @@ pub fn decode_peer_info(
|
||||
for nid_reader in nids_reader.iter() {
|
||||
node_ids.add(decode_typed_key(&nid_reader)?);
|
||||
}
|
||||
let signed_node_info = decode_signed_node_info(&sni_reader, crypto, &mut node_ids)?;
|
||||
let signed_node_info = decode_signed_node_info(&sni_reader)?;
|
||||
if node_ids.len() == 0 {
|
||||
return Err(RPCError::protocol("no verified node ids"));
|
||||
}
|
||||
Ok(PeerInfo {
|
||||
node_ids,
|
||||
signed_node_info,
|
||||
})
|
||||
Ok(PeerInfo::new(node_ids, signed_node_info))
|
||||
}
|
||||
|
||||
@@ -67,10 +67,7 @@ pub fn encode_route_hop(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_route_hop(
|
||||
reader: &veilid_capnp::route_hop::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<RouteHop, RPCError> {
|
||||
pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result<RouteHop, RPCError> {
|
||||
let n_reader = reader.reborrow().get_node();
|
||||
let node = match n_reader.which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::route_hop::node::Which::NodeId(ni) => {
|
||||
@@ -80,7 +77,7 @@ pub fn decode_route_hop(
|
||||
veilid_capnp::route_hop::node::Which::PeerInfo(pi) => {
|
||||
let pi_reader = pi.map_err(RPCError::protocol)?;
|
||||
RouteNode::PeerInfo(
|
||||
decode_peer_info(&pi_reader, crypto)
|
||||
decode_peer_info(&pi_reader)
|
||||
.map_err(RPCError::map_protocol("invalid peer info in route hop"))?,
|
||||
)
|
||||
}
|
||||
@@ -128,7 +125,6 @@ pub fn encode_private_route(
|
||||
|
||||
pub fn decode_private_route(
|
||||
reader: &veilid_capnp::private_route::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<PrivateRoute, RPCError> {
|
||||
let public_key = decode_typed_key(&reader.get_public_key().map_err(
|
||||
RPCError::map_protocol("invalid public key in private route"),
|
||||
@@ -138,7 +134,7 @@ pub fn decode_private_route(
|
||||
let hops = match reader.get_hops().which().map_err(RPCError::protocol)? {
|
||||
veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => {
|
||||
let rh_reader = rh_reader.map_err(RPCError::protocol)?;
|
||||
PrivateRouteHops::FirstHop(decode_route_hop(&rh_reader, crypto)?)
|
||||
PrivateRouteHops::FirstHop(decode_route_hop(&rh_reader)?)
|
||||
}
|
||||
veilid_capnp::private_route::hops::Which::Data(rhd_reader) => {
|
||||
let rhd_reader = rhd_reader.map_err(RPCError::protocol)?;
|
||||
@@ -182,7 +178,6 @@ pub fn encode_safety_route(
|
||||
|
||||
pub fn decode_safety_route(
|
||||
reader: &veilid_capnp::safety_route::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<SafetyRoute, RPCError> {
|
||||
let public_key = decode_typed_key(
|
||||
&reader
|
||||
@@ -197,7 +192,7 @@ pub fn decode_safety_route(
|
||||
}
|
||||
veilid_capnp::safety_route::hops::Which::Private(pr_reader) => {
|
||||
let pr_reader = pr_reader.map_err(RPCError::protocol)?;
|
||||
SafetyRouteHops::Private(decode_private_route(&pr_reader, crypto)?)
|
||||
SafetyRouteHops::Private(decode_private_route(&pr_reader)?)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ pub fn encode_signal_info(
|
||||
|
||||
pub fn decode_signal_info(
|
||||
reader: &veilid_capnp::operation_signal::Reader,
|
||||
crypto: Crypto,
|
||||
) -> Result<SignalInfo, RPCError> {
|
||||
Ok(
|
||||
match reader
|
||||
@@ -53,7 +52,7 @@ pub fn decode_signal_info(
|
||||
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
|
||||
"invalid peer info in hole punch signal info",
|
||||
))?;
|
||||
let peer_info = decode_peer_info(&pi_reader, crypto)?;
|
||||
let peer_info = decode_peer_info(&pi_reader)?;
|
||||
|
||||
SignalInfo::HolePunch { receipt, peer_info }
|
||||
}
|
||||
@@ -69,7 +68,7 @@ pub fn decode_signal_info(
|
||||
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
|
||||
"invalid peer info in reverse connect signal info",
|
||||
))?;
|
||||
let peer_info = decode_peer_info(&pi_reader, crypto)?;
|
||||
let peer_info = decode_peer_info(&pi_reader)?;
|
||||
|
||||
SignalInfo::ReverseConnect { receipt, peer_info }
|
||||
}
|
||||
|
||||
@@ -6,20 +6,20 @@ pub fn encode_signed_direct_node_info(
|
||||
) -> Result<(), RPCError> {
|
||||
//
|
||||
let mut ni_builder = builder.reborrow().init_node_info();
|
||||
encode_node_info(&signed_direct_node_info.node_info, &mut ni_builder)?;
|
||||
encode_node_info(signed_direct_node_info.node_info(), &mut ni_builder)?;
|
||||
|
||||
builder
|
||||
.reborrow()
|
||||
.set_timestamp(signed_direct_node_info.timestamp.into());
|
||||
.set_timestamp(signed_direct_node_info.timestamp().into());
|
||||
|
||||
let mut sigs_builder = builder.reborrow().init_signatures(
|
||||
signed_direct_node_info
|
||||
.signatures
|
||||
.signatures()
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_invalid_format("out of bound error"))?,
|
||||
);
|
||||
for (i, typed_signature) in signed_direct_node_info.signatures.iter().enumerate() {
|
||||
for (i, typed_signature) in signed_direct_node_info.signatures().iter().enumerate() {
|
||||
encode_typed_signature(
|
||||
typed_signature,
|
||||
&mut sigs_builder.reborrow().get(
|
||||
@@ -34,8 +34,6 @@ pub fn encode_signed_direct_node_info(
|
||||
|
||||
pub fn decode_signed_direct_node_info(
|
||||
reader: &veilid_capnp::signed_direct_node_info::Reader,
|
||||
crypto: Crypto,
|
||||
node_ids: &mut TypedKeySet,
|
||||
) -> Result<SignedDirectNodeInfo, RPCError> {
|
||||
let ni_reader = reader
|
||||
.reborrow()
|
||||
@@ -61,6 +59,9 @@ pub fn decode_signed_direct_node_info(
|
||||
typed_signatures.push(typed_signature);
|
||||
}
|
||||
|
||||
SignedDirectNodeInfo::new(crypto, node_ids, node_info, timestamp, typed_signatures)
|
||||
.map_err(RPCError::protocol)
|
||||
Ok(SignedDirectNodeInfo::new(
|
||||
node_info,
|
||||
timestamp,
|
||||
typed_signatures,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ pub fn encode_signed_node_info(
|
||||
|
||||
pub fn decode_signed_node_info(
|
||||
reader: &veilid_capnp::signed_node_info::Reader,
|
||||
crypto: Crypto,
|
||||
node_ids: &mut TypedKeySet,
|
||||
) -> Result<SignedNodeInfo, RPCError> {
|
||||
match reader
|
||||
.which()
|
||||
@@ -29,12 +27,12 @@ pub fn decode_signed_node_info(
|
||||
{
|
||||
veilid_capnp::signed_node_info::Direct(d) => {
|
||||
let d_reader = d.map_err(RPCError::protocol)?;
|
||||
let sdni = decode_signed_direct_node_info(&d_reader, crypto, node_ids)?;
|
||||
let sdni = decode_signed_direct_node_info(&d_reader)?;
|
||||
Ok(SignedNodeInfo::Direct(sdni))
|
||||
}
|
||||
veilid_capnp::signed_node_info::Relayed(r) => {
|
||||
let r_reader = r.map_err(RPCError::protocol)?;
|
||||
let srni = decode_signed_relayed_node_info(&r_reader, crypto, node_ids)?;
|
||||
let srni = decode_signed_relayed_node_info(&r_reader)?;
|
||||
Ok(SignedNodeInfo::Relayed(srni))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ pub fn encode_signed_relayed_node_info(
|
||||
) -> Result<(), RPCError> {
|
||||
//
|
||||
let mut ni_builder = builder.reborrow().init_node_info();
|
||||
encode_node_info(&signed_relayed_node_info.node_info, &mut ni_builder)?;
|
||||
encode_node_info(signed_relayed_node_info.node_info(), &mut ni_builder)?;
|
||||
|
||||
let mut rids_builder = builder.reborrow().init_relay_ids(
|
||||
signed_relayed_node_info
|
||||
.relay_ids
|
||||
.relay_ids()
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_invalid_format("out of bound error"))?,
|
||||
);
|
||||
for (i, typed_key) in signed_relayed_node_info.relay_ids.iter().enumerate() {
|
||||
for (i, typed_key) in signed_relayed_node_info.relay_ids().iter().enumerate() {
|
||||
encode_typed_key(
|
||||
typed_key,
|
||||
&mut rids_builder.reborrow().get(
|
||||
@@ -26,20 +26,20 @@ pub fn encode_signed_relayed_node_info(
|
||||
}
|
||||
|
||||
let mut ri_builder = builder.reborrow().init_relay_info();
|
||||
encode_signed_direct_node_info(&signed_relayed_node_info.relay_info, &mut ri_builder)?;
|
||||
encode_signed_direct_node_info(signed_relayed_node_info.relay_info(), &mut ri_builder)?;
|
||||
|
||||
builder
|
||||
.reborrow()
|
||||
.set_timestamp(signed_relayed_node_info.timestamp.into());
|
||||
.set_timestamp(signed_relayed_node_info.timestamp().into());
|
||||
|
||||
let mut sigs_builder = builder.reborrow().init_signatures(
|
||||
signed_relayed_node_info
|
||||
.signatures
|
||||
.signatures()
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(RPCError::map_invalid_format("out of bound error"))?,
|
||||
);
|
||||
for (i, typed_signature) in signed_relayed_node_info.signatures.iter().enumerate() {
|
||||
for (i, typed_signature) in signed_relayed_node_info.signatures().iter().enumerate() {
|
||||
encode_typed_signature(
|
||||
typed_signature,
|
||||
&mut sigs_builder.reborrow().get(
|
||||
@@ -54,8 +54,6 @@ pub fn encode_signed_relayed_node_info(
|
||||
|
||||
pub fn decode_signed_relayed_node_info(
|
||||
reader: &veilid_capnp::signed_relayed_node_info::Reader,
|
||||
crypto: Crypto,
|
||||
node_ids: &mut TypedKeySet,
|
||||
) -> Result<SignedRelayedNodeInfo, RPCError> {
|
||||
let ni_reader = reader
|
||||
.reborrow()
|
||||
@@ -81,20 +79,7 @@ pub fn decode_signed_relayed_node_info(
|
||||
.reborrow()
|
||||
.get_relay_info()
|
||||
.map_err(RPCError::protocol)?;
|
||||
let relay_info = decode_signed_direct_node_info(&ri_reader, crypto.clone(), &mut relay_ids)?;
|
||||
|
||||
// Ensure the relay info for the node has a superset of the crypto kinds of the node it is relaying
|
||||
if common_crypto_kinds(
|
||||
&node_info.crypto_support,
|
||||
&relay_info.node_info.crypto_support,
|
||||
)
|
||||
.len()
|
||||
!= node_info.crypto_support.len()
|
||||
{
|
||||
return Err(RPCError::protocol(
|
||||
"relay should have superset of node crypto kinds",
|
||||
));
|
||||
}
|
||||
let relay_info = decode_signed_direct_node_info(&ri_reader)?;
|
||||
|
||||
let timestamp = reader.reborrow().get_timestamp().into();
|
||||
|
||||
@@ -113,14 +98,11 @@ pub fn decode_signed_relayed_node_info(
|
||||
let typed_signature = decode_typed_signature(&sig_reader)?;
|
||||
typed_signatures.push(typed_signature);
|
||||
}
|
||||
SignedRelayedNodeInfo::new(
|
||||
crypto,
|
||||
node_ids,
|
||||
Ok(SignedRelayedNodeInfo::new(
|
||||
node_info,
|
||||
relay_ids,
|
||||
relay_info,
|
||||
timestamp,
|
||||
typed_signatures,
|
||||
)
|
||||
.map_err(RPCError::protocol)
|
||||
))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::*;
|
||||
|
||||
pub fn encode_signed_value_data(
|
||||
signed_value_data: &SignedValueData,
|
||||
builder: &mut veilid_capnp::signed_value_data::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
builder.set_seq(signed_value_data.value_data().seq());
|
||||
builder.set_data(signed_value_data.value_data().data());
|
||||
let mut wb = builder.reborrow().init_writer();
|
||||
encode_key256(signed_value_data.value_data().writer(), &mut wb);
|
||||
let mut sb = builder.reborrow().init_signature();
|
||||
encode_signature512(signed_value_data.signature(), &mut sb);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_signed_value_data(
|
||||
reader: &veilid_capnp::signed_value_data::Reader,
|
||||
) -> Result<SignedValueData, RPCError> {
|
||||
let seq = reader.get_seq();
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
|
||||
let wr = reader.get_writer().map_err(RPCError::protocol)?;
|
||||
let writer = decode_key256(&wr);
|
||||
let sr = reader.get_signature().map_err(RPCError::protocol)?;
|
||||
let signature = decode_signature512(&sr);
|
||||
|
||||
Ok(SignedValueData::new(
|
||||
ValueData::new_with_seq(seq, data, writer),
|
||||
signature,
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::SignedValueDescriptor;
|
||||
|
||||
pub fn encode_signed_value_descriptor(
|
||||
signed_value_descriptor: &SignedValueDescriptor,
|
||||
builder: &mut veilid_capnp::signed_value_descriptor::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
let mut ob = builder.reborrow().init_owner();
|
||||
encode_key256(signed_value_descriptor.owner(), &mut ob);
|
||||
builder.set_schema_data(signed_value_descriptor.schema_data());
|
||||
let mut sb = builder.reborrow().init_signature();
|
||||
encode_signature512(signed_value_descriptor.signature(), &mut sb);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_signed_value_descriptor(
|
||||
reader: &veilid_capnp::signed_value_descriptor::Reader,
|
||||
) -> Result<SignedValueDescriptor, RPCError> {
|
||||
let or = reader.get_owner().map_err(RPCError::protocol)?;
|
||||
let owner = decode_key256(&or);
|
||||
let schema_data = reader
|
||||
.get_schema_data()
|
||||
.map_err(RPCError::protocol)?
|
||||
.to_vec();
|
||||
let sr = reader.get_signature().map_err(RPCError::protocol)?;
|
||||
let signature = decode_signature512(&sr);
|
||||
Ok(SignedValueDescriptor::new(owner, schema_data, signature))
|
||||
}
|
||||
@@ -1,18 +1,30 @@
|
||||
use super::*;
|
||||
|
||||
pub fn encode_value_data(
|
||||
value_data: &ValueData,
|
||||
builder: &mut veilid_capnp::value_data::Builder,
|
||||
pub fn encode_signed_value_data(
|
||||
signed_value_data: &SignedValueData,
|
||||
builder: &mut veilid_capnp::signed_value_data::Builder,
|
||||
) -> Result<(), RPCError> {
|
||||
builder.set_data(&value_data.data);
|
||||
builder.set_schema(u32::from_be_bytes(value_data.schema.0));
|
||||
builder.set_seq(value_data.seq);
|
||||
builder.set_seq(signed_value_data.value_data().seq());
|
||||
builder.set_data(signed_value_data.value_data().data());
|
||||
let mut wb = builder.reborrow().init_writer();
|
||||
encode_key256(signed_value_data.value_data().writer(), &mut wb);
|
||||
let mut sb = builder.reborrow().init_signature();
|
||||
encode_signature512(signed_value_data.signature(), &mut sb);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_value_data(reader: &veilid_capnp::value_data::Reader) -> Result<ValueData, RPCError> {
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
|
||||
pub fn decode_signed_value_data(
|
||||
reader: &veilid_capnp::signed_value_data::Reader,
|
||||
) -> Result<ValueData, RPCError> {
|
||||
let seq = reader.get_seq();
|
||||
let schema = FourCC::from(reader.get_schema().to_be_bytes());
|
||||
Ok(ValueData { data, schema, seq })
|
||||
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
|
||||
let wr = reader.get_writer().map_err(RPCError::protocol)?;
|
||||
let writer = decode_key256(&wr);
|
||||
let sr = reader.get_signature().map_err(RPCError::protocol)?;
|
||||
let signature = decode_signature512(&sr);
|
||||
|
||||
Ok(SignedValueData {
|
||||
value_data: ValueData { seq, data, writer },
|
||||
signature,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
use super::*;
|
||||
|
||||
struct FanoutContext<R>
|
||||
where
|
||||
R: Unpin,
|
||||
{
|
||||
closest_nodes: Vec<NodeRef>,
|
||||
called_nodes: TypedKeySet,
|
||||
result: Option<Result<R, RPCError>>,
|
||||
}
|
||||
|
||||
pub type FanoutCallReturnType = Result<Option<Vec<PeerInfo>>, RPCError>;
|
||||
|
||||
pub struct FanoutCall<R, F, C, D>
|
||||
where
|
||||
R: Unpin,
|
||||
F: Future<Output = FanoutCallReturnType>,
|
||||
C: Fn(NodeRef) -> F,
|
||||
D: Fn(&[NodeRef]) -> Option<R>,
|
||||
{
|
||||
routing_table: RoutingTable,
|
||||
crypto_kind: CryptoKind,
|
||||
node_id: TypedKey,
|
||||
context: Mutex<FanoutContext<R>>,
|
||||
node_count: usize,
|
||||
fanout: usize,
|
||||
timeout_us: TimestampDuration,
|
||||
call_routine: C,
|
||||
check_done: D,
|
||||
}
|
||||
|
||||
impl<R, F, C, D> FanoutCall<R, F, C, D>
|
||||
where
|
||||
R: Unpin,
|
||||
F: Future<Output = FanoutCallReturnType>,
|
||||
C: Fn(NodeRef) -> F,
|
||||
D: Fn(&[NodeRef]) -> Option<R>,
|
||||
{
|
||||
pub fn new(
|
||||
routing_table: RoutingTable,
|
||||
node_id: TypedKey,
|
||||
node_count: usize,
|
||||
fanout: usize,
|
||||
timeout_us: TimestampDuration,
|
||||
call_routine: C,
|
||||
check_done: D,
|
||||
) -> Arc<Self> {
|
||||
let context = Mutex::new(FanoutContext {
|
||||
closest_nodes: Vec::with_capacity(node_count),
|
||||
called_nodes: TypedKeySet::new(),
|
||||
result: None,
|
||||
});
|
||||
|
||||
Arc::new(Self {
|
||||
routing_table,
|
||||
node_id,
|
||||
crypto_kind: node_id.kind,
|
||||
context,
|
||||
node_count,
|
||||
fanout,
|
||||
timeout_us,
|
||||
call_routine,
|
||||
check_done,
|
||||
})
|
||||
}
|
||||
|
||||
fn add_new_nodes(self: Arc<Self>, new_nodes: Vec<NodeRef>) {
|
||||
let mut ctx = self.context.lock();
|
||||
|
||||
for nn in new_nodes {
|
||||
let mut dup = false;
|
||||
for cn in &ctx.closest_nodes {
|
||||
if cn.same_entry(&nn) {
|
||||
dup = true;
|
||||
}
|
||||
}
|
||||
if !dup {
|
||||
ctx.closest_nodes.push(nn.clone());
|
||||
}
|
||||
}
|
||||
|
||||
self.routing_table
|
||||
.sort_and_clean_closest_noderefs(self.node_id, &mut ctx.closest_nodes);
|
||||
ctx.closest_nodes.truncate(self.node_count);
|
||||
}
|
||||
|
||||
fn remove_node(self: Arc<Self>, dead_node: NodeRef) {
|
||||
let mut ctx = self.context.lock();
|
||||
for n in 0..ctx.closest_nodes.len() {
|
||||
let cn = &ctx.closest_nodes[n];
|
||||
if cn.same_entry(&dead_node) {
|
||||
ctx.closest_nodes.remove(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_next_node(self: Arc<Self>) -> Option<NodeRef> {
|
||||
let mut next_node = None;
|
||||
let mut ctx = self.context.lock();
|
||||
for cn in ctx.closest_nodes.clone() {
|
||||
if let Some(key) = cn.node_ids().get(self.crypto_kind) {
|
||||
if !ctx.called_nodes.contains(&key) {
|
||||
// New fanout call candidate found
|
||||
next_node = Some(cn.clone());
|
||||
ctx.called_nodes.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
next_node
|
||||
}
|
||||
|
||||
fn evaluate_done(self: Arc<Self>) -> bool {
|
||||
let mut ctx = self.context.lock();
|
||||
|
||||
// If we have a result, then we're done
|
||||
if ctx.result.is_some() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for a new done result
|
||||
ctx.result = (self.check_done)(&ctx.closest_nodes).map(|o| Ok(o));
|
||||
ctx.result.is_some()
|
||||
}
|
||||
|
||||
async fn fanout_processor(self: Arc<Self>) {
|
||||
// Check to see if we have a result or are done
|
||||
while !self.clone().evaluate_done() {
|
||||
// Get the closest node we haven't processed yet
|
||||
let next_node = self.clone().get_next_node();
|
||||
|
||||
// If we don't have a node to process, stop fanning out
|
||||
let Some(next_node) = next_node else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Do the call for this node
|
||||
match (self.call_routine)(next_node.clone()).await {
|
||||
Ok(Some(v)) => {
|
||||
// Call succeeded
|
||||
// Register the returned nodes and add them to the closest nodes list in sorted order
|
||||
let new_nodes = self
|
||||
.routing_table
|
||||
.register_find_node_answer(self.crypto_kind, v);
|
||||
self.clone().add_new_nodes(new_nodes);
|
||||
}
|
||||
Ok(None) => {
|
||||
// Call failed, remove the node so it isn't included in the output
|
||||
self.clone().remove_node(next_node);
|
||||
}
|
||||
Err(e) => {
|
||||
// Error happened, abort everything and return the error
|
||||
let mut ctx = self.context.lock();
|
||||
ctx.result = Some(Err(e));
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn init_closest_nodes(self: Arc<Self>) {
|
||||
// Get the 'node_count' closest nodes to the key out of our routing table
|
||||
let closest_nodes = {
|
||||
let routing_table = self.routing_table.clone();
|
||||
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||
// Exclude our own node
|
||||
if opt_entry.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
||||
rti.filter_has_valid_signed_node_info(
|
||||
RoutingDomain::PublicInternet,
|
||||
true,
|
||||
opt_entry,
|
||||
)
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
let filters = VecDeque::from([filter]);
|
||||
|
||||
let transform = |_rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
|
||||
NodeRef::new(routing_table.clone(), v.unwrap().clone(), None)
|
||||
};
|
||||
|
||||
routing_table.find_closest_nodes(self.node_count, self.node_id, filters, transform)
|
||||
};
|
||||
|
||||
let mut ctx = self.context.lock();
|
||||
ctx.closest_nodes = closest_nodes;
|
||||
}
|
||||
|
||||
pub async fn run(self: Arc<Self>) -> TimeoutOr<Result<Option<R>, RPCError>> {
|
||||
// Get timeout in milliseconds
|
||||
let timeout_ms = match us_to_ms(self.timeout_us.as_u64()).map_err(RPCError::internal) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
return TimeoutOr::value(Err(e));
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize closest nodes list
|
||||
self.clone().init_closest_nodes();
|
||||
|
||||
// Do a quick check to see if we're already done
|
||||
if self.clone().evaluate_done() {
|
||||
let mut ctx = self.context.lock();
|
||||
return TimeoutOr::value(ctx.result.take().transpose());
|
||||
}
|
||||
|
||||
// If not, do the fanout
|
||||
let mut unord = FuturesUnordered::new();
|
||||
{
|
||||
// Spin up 'fanout' tasks to process the fanout
|
||||
for _ in 0..self.fanout {
|
||||
let h = self.clone().fanout_processor();
|
||||
unord.push(h);
|
||||
}
|
||||
}
|
||||
// Wait for them to complete
|
||||
timeout(timeout_ms, async {
|
||||
while let Some(_) = unord.next().await {}
|
||||
})
|
||||
.await
|
||||
.into_timeout_or()
|
||||
.map(|_| {
|
||||
// Finished, return whatever value we came up with
|
||||
let mut ctx = self.context.lock();
|
||||
ctx.result.take().transpose()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod coders;
|
||||
mod destination;
|
||||
mod fanout_call;
|
||||
mod operation_waiter;
|
||||
mod rpc_app_call;
|
||||
mod rpc_app_message;
|
||||
@@ -22,18 +23,20 @@ mod rpc_watch_value;
|
||||
|
||||
pub use coders::*;
|
||||
pub use destination::*;
|
||||
pub use fanout_call::*;
|
||||
pub use operation_waiter::*;
|
||||
pub use rpc_error::*;
|
||||
pub use rpc_status::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::crypto::*;
|
||||
use crypto::*;
|
||||
use futures_util::StreamExt;
|
||||
use network_manager::*;
|
||||
use receipt_manager::*;
|
||||
use routing_table::*;
|
||||
use stop_token::future::FutureExt;
|
||||
use storage_manager::*;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -149,7 +152,7 @@ where
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WaitableReply {
|
||||
handle: OperationWaitHandle<RPCMessage>,
|
||||
handle: OperationWaitHandle<RPCMessage, Option<QuestionContext>>,
|
||||
timeout_us: TimestampDuration,
|
||||
node_ref: NodeRef,
|
||||
send_ts: Timestamp,
|
||||
@@ -235,8 +238,8 @@ pub struct RPCProcessorUnlockedInner {
|
||||
max_route_hop_count: usize,
|
||||
validate_dial_info_receipt_time_ms: u32,
|
||||
update_callback: UpdateCallback,
|
||||
waiting_rpc_table: OperationWaiter<RPCMessage>,
|
||||
waiting_app_call_table: OperationWaiter<Vec<u8>>,
|
||||
waiting_rpc_table: OperationWaiter<RPCMessage, Option<QuestionContext>>,
|
||||
waiting_app_call_table: OperationWaiter<Vec<u8>, ()>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -244,6 +247,7 @@ pub struct RPCProcessor {
|
||||
crypto: Crypto,
|
||||
config: VeilidConfig,
|
||||
network_manager: NetworkManager,
|
||||
storage_manager: StorageManager,
|
||||
routing_table: RoutingTable,
|
||||
inner: Arc<Mutex<RPCProcessorInner>>,
|
||||
unlocked_inner: Arc<RPCProcessorUnlockedInner>,
|
||||
@@ -295,6 +299,7 @@ impl RPCProcessor {
|
||||
config: config.clone(),
|
||||
network_manager: network_manager.clone(),
|
||||
routing_table: network_manager.routing_table(),
|
||||
storage_manager: network_manager.storage_manager(),
|
||||
inner: Arc::new(Mutex::new(Self::new_inner())),
|
||||
unlocked_inner: Arc::new(Self::new_unlocked_inner(config, update_callback)),
|
||||
}
|
||||
@@ -308,33 +313,44 @@ impl RPCProcessor {
|
||||
self.routing_table.clone()
|
||||
}
|
||||
|
||||
pub fn storage_manager(&self) -> StorageManager {
|
||||
self.storage_manager.clone()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[instrument(level = "debug", skip_all, err)]
|
||||
pub async fn startup(&self) -> EyreResult<()> {
|
||||
trace!("startup rpc processor");
|
||||
let mut inner = self.inner.lock();
|
||||
debug!("startup rpc processor");
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
|
||||
let channel = flume::bounded(self.unlocked_inner.queue_size as usize);
|
||||
inner.send_channel = Some(channel.0.clone());
|
||||
inner.stop_source = Some(StopSource::new());
|
||||
let channel = flume::bounded(self.unlocked_inner.queue_size as usize);
|
||||
inner.send_channel = Some(channel.0.clone());
|
||||
inner.stop_source = Some(StopSource::new());
|
||||
|
||||
// spin up N workers
|
||||
trace!(
|
||||
"Spinning up {} RPC workers",
|
||||
self.unlocked_inner.concurrency
|
||||
);
|
||||
for _ in 0..self.unlocked_inner.concurrency {
|
||||
let this = self.clone();
|
||||
let receiver = channel.1.clone();
|
||||
let jh = spawn(Self::rpc_worker(
|
||||
this,
|
||||
inner.stop_source.as_ref().unwrap().token(),
|
||||
receiver,
|
||||
));
|
||||
inner.worker_join_handles.push(jh);
|
||||
// spin up N workers
|
||||
trace!(
|
||||
"Spinning up {} RPC workers",
|
||||
self.unlocked_inner.concurrency
|
||||
);
|
||||
for _ in 0..self.unlocked_inner.concurrency {
|
||||
let this = self.clone();
|
||||
let receiver = channel.1.clone();
|
||||
let jh = spawn(Self::rpc_worker(
|
||||
this,
|
||||
inner.stop_source.as_ref().unwrap().token(),
|
||||
receiver,
|
||||
));
|
||||
inner.worker_join_handles.push(jh);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform storage manager we are up
|
||||
self.storage_manager
|
||||
.set_rpc_processor(Some(self.clone()))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -342,6 +358,9 @@ impl RPCProcessor {
|
||||
pub async fn shutdown(&self) {
|
||||
debug!("starting rpc processor shutdown");
|
||||
|
||||
// Stop storage manager from using us
|
||||
self.storage_manager.set_rpc_processor(None).await;
|
||||
|
||||
// Stop the rpc workers
|
||||
let mut unord = FuturesUnordered::new();
|
||||
{
|
||||
@@ -382,44 +401,79 @@ impl RPCProcessor {
|
||||
|
||||
/// Search the DHT for a single node closest to a key and add it to the routing table and return the node reference
|
||||
/// If no node was found in the timeout, this returns None
|
||||
pub async fn search_dht_single_key(
|
||||
async fn search_dht_single_key(
|
||||
&self,
|
||||
_node_id: PublicKey,
|
||||
_count: u32,
|
||||
_fanout: u32,
|
||||
_timeout: Option<u64>,
|
||||
) -> Result<Option<NodeRef>, RPCError> {
|
||||
//let routing_table = self.routing_table();
|
||||
node_id: TypedKey,
|
||||
count: usize,
|
||||
fanout: usize,
|
||||
timeout_us: TimestampDuration,
|
||||
safety_selection: SafetySelection,
|
||||
) -> TimeoutOr<Result<Option<NodeRef>, RPCError>> {
|
||||
let routing_table = self.routing_table();
|
||||
|
||||
// xxx find node but stop if we find the exact node we want
|
||||
// xxx return whatever node is closest after the timeout
|
||||
Err(RPCError::unimplemented("search_dht_single_key")).map_err(logthru_rpc!(error))
|
||||
}
|
||||
// Routine to call to generate fanout
|
||||
let call_routine = |next_node: NodeRef| {
|
||||
let this = self.clone();
|
||||
async move {
|
||||
match this
|
||||
.clone()
|
||||
.rpc_call_find_node(
|
||||
Destination::direct(next_node).with_safety(safety_selection),
|
||||
node_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(v) => {
|
||||
let v = network_result_value_or_log!(v => {
|
||||
// Any other failures, just try the next node
|
||||
return Ok(None);
|
||||
});
|
||||
Ok(Some(v.answer))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Search the DHT for the 'count' closest nodes to a key, adding them all to the routing table if they are not there and returning their node references
|
||||
pub async fn search_dht_multi_key(
|
||||
&self,
|
||||
_node_id: PublicKey,
|
||||
_count: u32,
|
||||
_fanout: u32,
|
||||
_timeout: Option<u64>,
|
||||
) -> Result<Vec<NodeRef>, RPCError> {
|
||||
// xxx return closest nodes after the timeout
|
||||
Err(RPCError::unimplemented("search_dht_multi_key")).map_err(logthru_rpc!(error))
|
||||
// Routine to call to check if we're done at each step
|
||||
let check_done = |closest_nodes: &[NodeRef]| {
|
||||
// If the node we want to locate is one of the closest nodes, return it immediately
|
||||
if let Some(out) = closest_nodes
|
||||
.iter()
|
||||
.find(|x| x.node_ids().contains(&node_id))
|
||||
{
|
||||
return Some(out.clone());
|
||||
}
|
||||
None
|
||||
};
|
||||
|
||||
// Call the fanout
|
||||
let fanout_call = FanoutCall::new(
|
||||
routing_table.clone(),
|
||||
node_id,
|
||||
count,
|
||||
fanout,
|
||||
timeout_us,
|
||||
call_routine,
|
||||
check_done,
|
||||
);
|
||||
|
||||
fanout_call.run().await
|
||||
}
|
||||
|
||||
/// Search the DHT for a specific node corresponding to a key unless we have that node in our routing table already, and return the node reference
|
||||
/// Note: This routine can possible be recursive, hence the SendPinBoxFuture async form
|
||||
pub fn resolve_node(
|
||||
&self,
|
||||
node_id: PublicKey,
|
||||
node_id: TypedKey,
|
||||
safety_selection: SafetySelection,
|
||||
) -> SendPinBoxFuture<Result<Option<NodeRef>, RPCError>> {
|
||||
let this = self.clone();
|
||||
Box::pin(async move {
|
||||
let routing_table = this.routing_table();
|
||||
|
||||
// First see if we have the node in our routing table already
|
||||
if let Some(nr) = routing_table.lookup_any_node_ref(node_id) {
|
||||
if let Some(nr) = routing_table.lookup_node_ref(node_id) {
|
||||
// ensure we have some dial info for the entry already,
|
||||
// if not, we should do the find_node anyway
|
||||
if nr.has_any_dial_info() {
|
||||
@@ -428,21 +482,30 @@ impl RPCProcessor {
|
||||
}
|
||||
|
||||
// If nobody knows where this node is, ask the DHT for it
|
||||
let (count, fanout, timeout) = {
|
||||
let (node_count, _consensus_count, fanout, timeout) = {
|
||||
let c = this.config.get();
|
||||
(
|
||||
c.network.dht.resolve_node_count,
|
||||
c.network.dht.resolve_node_fanout,
|
||||
c.network.dht.resolve_node_timeout_ms.map(ms_to_us),
|
||||
c.network.dht.max_find_node_count as usize,
|
||||
c.network.dht.resolve_node_count as usize,
|
||||
c.network.dht.resolve_node_fanout as usize,
|
||||
TimestampDuration::from(ms_to_us(c.network.dht.resolve_node_timeout_ms)),
|
||||
)
|
||||
};
|
||||
|
||||
let nr = this
|
||||
.search_dht_single_key(node_id, count, fanout, timeout)
|
||||
.await?;
|
||||
// Search in preferred cryptosystem order
|
||||
let nr = match this
|
||||
.search_dht_single_key(node_id, node_count, fanout, timeout, safety_selection)
|
||||
.await
|
||||
{
|
||||
TimeoutOr::Timeout => None,
|
||||
TimeoutOr::Value(Ok(v)) => v,
|
||||
TimeoutOr::Value(Err(e)) => {
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(nr) = &nr {
|
||||
if nr.node_ids().contains_key(&node_id) {
|
||||
if nr.node_ids().contains(&node_id) {
|
||||
// found a close node, but not exact within our configured resolve_node timeout
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -542,10 +605,7 @@ impl RPCProcessor {
|
||||
|
||||
// Prepare route operation
|
||||
let sr_hop_count = compiled_route.safety_route.hop_count;
|
||||
let route_operation = RPCOperationRoute {
|
||||
safety_route: compiled_route.safety_route,
|
||||
operation,
|
||||
};
|
||||
let route_operation = RPCOperationRoute::new(compiled_route.safety_route, operation);
|
||||
let ssni_route =
|
||||
self.get_sender_peer_info(&Destination::direct(compiled_route.first_hop.clone()));
|
||||
let operation = RPCOperation::new_statement(
|
||||
@@ -753,7 +813,7 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get our node info timestamp
|
||||
let our_node_info_ts = own_peer_info.signed_node_info.timestamp();
|
||||
let our_node_info_ts = own_peer_info.signed_node_info().timestamp();
|
||||
|
||||
// If the target has seen our node info already don't send it again
|
||||
if target.has_seen_our_node_info_ts(routing_domain, our_node_info_ts) {
|
||||
@@ -998,11 +1058,13 @@ impl RPCProcessor {
|
||||
}
|
||||
|
||||
/// Issue a question over the network, possibly using an anonymized route
|
||||
/// Optionally keeps a context to be passed to the answer processor when an answer is received
|
||||
#[instrument(level = "debug", skip(self, question), err)]
|
||||
async fn question(
|
||||
&self,
|
||||
dest: Destination,
|
||||
question: RPCQuestion,
|
||||
context: Option<QuestionContext>,
|
||||
) -> Result<NetworkResult<WaitableReply>, RPCError> {
|
||||
// Get sender peer info if we should send that
|
||||
let spi = self.get_sender_peer_info(&dest);
|
||||
@@ -1030,7 +1092,10 @@ impl RPCProcessor {
|
||||
let timeout_us = self.unlocked_inner.timeout_us * (hop_count as u64);
|
||||
|
||||
// Set up op id eventual
|
||||
let handle = self.unlocked_inner.waiting_rpc_table.add_op_waiter(op_id);
|
||||
let handle = self
|
||||
.unlocked_inner
|
||||
.waiting_rpc_table
|
||||
.add_op_waiter(op_id, context);
|
||||
|
||||
// Send question
|
||||
let bytes: ByteCount = (message.len() as u64).into();
|
||||
@@ -1072,7 +1137,7 @@ impl RPCProcessor {
|
||||
}))
|
||||
}
|
||||
|
||||
// Issue a statement over the network, possibly using an anonymized route
|
||||
/// Issue a statement over the network, possibly using an anonymized route
|
||||
#[instrument(level = "debug", skip(self, statement), err)]
|
||||
async fn statement(
|
||||
&self,
|
||||
@@ -1128,9 +1193,8 @@ impl RPCProcessor {
|
||||
|
||||
Ok(NetworkResult::value(()))
|
||||
}
|
||||
|
||||
// Issue a reply over the network, possibly using an anonymized route
|
||||
// The request must want a response, or this routine fails
|
||||
/// Issue a reply over the network, possibly using an anonymized route
|
||||
/// The request must want a response, or this routine fails
|
||||
#[instrument(level = "debug", skip(self, request, answer), err)]
|
||||
async fn answer(
|
||||
&self,
|
||||
@@ -1189,6 +1253,55 @@ impl RPCProcessor {
|
||||
Ok(NetworkResult::value(()))
|
||||
}
|
||||
|
||||
/// Decoding RPC from the wire
|
||||
/// This performs a capnp decode on the data, and if it passes the capnp schema
|
||||
/// it performs the cryptographic validation required to pass the operation up for processing
|
||||
fn decode_rpc_operation(
|
||||
&self,
|
||||
encoded_msg: &RPCMessageEncoded,
|
||||
) -> Result<RPCOperation, RPCError> {
|
||||
let reader = encoded_msg.data.get_reader()?;
|
||||
let op_reader = reader
|
||||
.get_root::<veilid_capnp::operation::Reader>()
|
||||
.map_err(RPCError::protocol)
|
||||
.map_err(logthru_rpc!())?;
|
||||
let mut operation = RPCOperation::decode(&op_reader)?;
|
||||
|
||||
// Validate the RPC message
|
||||
self.validate_rpc_operation(&mut operation)?;
|
||||
|
||||
Ok(operation)
|
||||
}
|
||||
|
||||
/// Cryptographic RPC validation
|
||||
/// We do this as part of the RPC network layer to ensure that any RPC operations that are
|
||||
/// processed have already been validated cryptographically and it is not the job of the
|
||||
/// caller or receiver. This does not mean the operation is 'semantically correct'. For
|
||||
/// complex operations that require stateful validation and a more robust context than
|
||||
/// 'signatures', the caller must still perform whatever validation is necessary
|
||||
fn validate_rpc_operation(&self, operation: &mut RPCOperation) -> Result<(), RPCError> {
|
||||
// If this is an answer, get the question context for this answer
|
||||
// If we received an answer for a question we did not ask, this will return an error
|
||||
let question_context = if let RPCOperationKind::Answer(_) = operation.kind() {
|
||||
let op_id = operation.op_id();
|
||||
self.unlocked_inner
|
||||
.waiting_rpc_table
|
||||
.get_op_context(op_id)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Validate the RPC operation
|
||||
let validate_context = RPCValidateContext {
|
||||
crypto: self.crypto.clone(),
|
||||
rpc_processor: self.clone(),
|
||||
question_context,
|
||||
};
|
||||
operation.validate(&validate_context)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#[instrument(level = "trace", skip(self, encoded_msg), err)]
|
||||
async fn process_rpc_message(
|
||||
@@ -1198,32 +1311,26 @@ impl RPCProcessor {
|
||||
// Decode operation appropriately based on header detail
|
||||
let msg = match &encoded_msg.header.detail {
|
||||
RPCMessageHeaderDetail::Direct(detail) => {
|
||||
// Decode and validate the RPC operation
|
||||
let operation = match self.decode_rpc_operation(&encoded_msg) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return Ok(NetworkResult::invalid_message(e)),
|
||||
};
|
||||
|
||||
// Get the routing domain this message came over
|
||||
let routing_domain = detail.routing_domain;
|
||||
|
||||
// Decode the operation
|
||||
// Get the sender noderef, incorporating sender's peer info
|
||||
let sender_node_id = TypedKey::new(
|
||||
detail.envelope.get_crypto_kind(),
|
||||
detail.envelope.get_sender_id(),
|
||||
);
|
||||
|
||||
// Decode the RPC message
|
||||
let operation = {
|
||||
let reader = encoded_msg.data.get_reader()?;
|
||||
let op_reader = reader
|
||||
.get_root::<veilid_capnp::operation::Reader>()
|
||||
.map_err(RPCError::protocol)
|
||||
.map_err(logthru_rpc!())?;
|
||||
RPCOperation::decode(&op_reader, self.crypto.clone())?
|
||||
};
|
||||
|
||||
// Get the sender noderef, incorporating sender's peer info
|
||||
let mut opt_sender_nr: Option<NodeRef> = None;
|
||||
if let Some(sender_peer_info) = operation.sender_peer_info() {
|
||||
// Ensure the sender peer info is for the actual sender specified in the envelope
|
||||
|
||||
// Sender PeerInfo was specified, update our routing table with it
|
||||
if !self.filter_node_info(routing_domain, &sender_peer_info.signed_node_info) {
|
||||
if !self.filter_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
||||
return Err(RPCError::invalid_format(
|
||||
"sender peerinfo has invalid peer scope",
|
||||
));
|
||||
@@ -1243,7 +1350,8 @@ impl RPCProcessor {
|
||||
// Update the 'seen our node info' timestamp to determine if this node needs a
|
||||
// 'node info update' ping
|
||||
if let Some(sender_nr) = &opt_sender_nr {
|
||||
sender_nr.set_our_node_info_ts(routing_domain, operation.target_node_info_ts());
|
||||
sender_nr
|
||||
.set_seen_our_node_info_ts(routing_domain, operation.target_node_info_ts());
|
||||
}
|
||||
|
||||
// Make the RPC message
|
||||
@@ -1254,15 +1362,8 @@ impl RPCProcessor {
|
||||
}
|
||||
}
|
||||
RPCMessageHeaderDetail::SafetyRouted(_) | RPCMessageHeaderDetail::PrivateRouted(_) => {
|
||||
// Decode the RPC message
|
||||
let operation = {
|
||||
let reader = encoded_msg.data.get_reader()?;
|
||||
let op_reader = reader
|
||||
.get_root::<veilid_capnp::operation::Reader>()
|
||||
.map_err(RPCError::protocol)
|
||||
.map_err(logthru_rpc!())?;
|
||||
RPCOperation::decode(&op_reader, self.crypto.clone())?
|
||||
};
|
||||
// Decode and validate the RPC operation
|
||||
let operation = self.decode_rpc_operation(&encoded_msg)?;
|
||||
|
||||
// Make the RPC message
|
||||
RPCMessage {
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OperationWaitHandle<T>
|
||||
pub struct OperationWaitHandle<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
waiter: OperationWaiter<T>,
|
||||
waiter: OperationWaiter<T, C>,
|
||||
op_id: OperationId,
|
||||
eventual_instance: Option<EventualValueFuture<(Option<Id>, T)>>,
|
||||
}
|
||||
|
||||
impl<T> Drop for OperationWaitHandle<T>
|
||||
impl<T, C> Drop for OperationWaitHandle<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
if self.eventual_instance.is_some() {
|
||||
@@ -22,24 +24,37 @@ where
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OperationWaiterInner<T>
|
||||
pub struct OperationWaitingOp<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
waiting_op_table: HashMap<OperationId, EventualValue<(Option<Id>, T)>>,
|
||||
context: C,
|
||||
eventual: EventualValue<(Option<Id>, T)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OperationWaiter<T>
|
||||
pub struct OperationWaiterInner<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
inner: Arc<Mutex<OperationWaiterInner<T>>>,
|
||||
waiting_op_table: HashMap<OperationId, OperationWaitingOp<T, C>>,
|
||||
}
|
||||
|
||||
impl<T> Clone for OperationWaiter<T>
|
||||
#[derive(Debug)]
|
||||
pub struct OperationWaiter<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
inner: Arc<Mutex<OperationWaiterInner<T, C>>>,
|
||||
}
|
||||
|
||||
impl<T, C> Clone for OperationWaiter<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
@@ -48,9 +63,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OperationWaiter<T>
|
||||
impl<T, C> OperationWaiter<T, C>
|
||||
where
|
||||
T: Unpin,
|
||||
C: Unpin + Clone,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -60,11 +76,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// set up wait for op
|
||||
pub fn add_op_waiter(&self, op_id: OperationId) -> OperationWaitHandle<T> {
|
||||
/// Set up wait for operation to complete
|
||||
pub fn add_op_waiter(&self, op_id: OperationId, context: C) -> OperationWaitHandle<T, C> {
|
||||
let mut inner = self.inner.lock();
|
||||
let e = EventualValue::new();
|
||||
if inner.waiting_op_table.insert(op_id, e.clone()).is_some() {
|
||||
let waiting_op = OperationWaitingOp {
|
||||
context,
|
||||
eventual: e.clone(),
|
||||
};
|
||||
if inner.waiting_op_table.insert(op_id, waiting_op).is_some() {
|
||||
error!(
|
||||
"add_op_waiter collision should not happen for op_id {}",
|
||||
op_id
|
||||
@@ -78,16 +98,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// remove wait for op
|
||||
/// Get operation context
|
||||
pub fn get_op_context(&self, op_id: OperationId) -> Result<C, RPCError> {
|
||||
let inner = self.inner.lock();
|
||||
let Some(waiting_op) = inner.waiting_op_table.get(&op_id) else {
|
||||
return Err(RPCError::internal("Missing operation id getting op context"));
|
||||
};
|
||||
Ok(waiting_op.context.clone())
|
||||
}
|
||||
|
||||
/// Remove wait for op
|
||||
fn cancel_op_waiter(&self, op_id: OperationId) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.waiting_op_table.remove(&op_id);
|
||||
}
|
||||
|
||||
// complete the app call
|
||||
/// Complete the app call
|
||||
#[instrument(level = "trace", skip(self, message), err)]
|
||||
pub async fn complete_op_waiter(&self, op_id: OperationId, message: T) -> Result<(), RPCError> {
|
||||
let eventual = {
|
||||
let waiting_op = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner
|
||||
.waiting_op_table
|
||||
@@ -97,17 +126,20 @@ where
|
||||
op_id
|
||||
)))?
|
||||
};
|
||||
eventual.resolve((Span::current().id(), message)).await;
|
||||
waiting_op
|
||||
.eventual
|
||||
.resolve((Span::current().id(), message))
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wait for opeation to complete
|
||||
pub async fn wait_for_op(
|
||||
&self,
|
||||
mut handle: OperationWaitHandle<T>,
|
||||
mut handle: OperationWaitHandle<T, C>,
|
||||
timeout_us: TimestampDuration,
|
||||
) -> Result<TimeoutOr<(T, TimestampDuration)>, RPCError> {
|
||||
let timeout_ms = u32::try_from(timeout_us.as_u64() / 1000u64)
|
||||
.map_err(|e| RPCError::map_internal("invalid timeout")(e))?;
|
||||
let timeout_ms = us_to_ms(timeout_us.as_u64()).map_err(RPCError::internal)?;
|
||||
|
||||
// Take the instance
|
||||
// After this, we must manually cancel since the cancel on handle drop is disabled
|
||||
|
||||
@@ -9,14 +9,14 @@ impl RPCProcessor {
|
||||
dest: Destination,
|
||||
message: Vec<u8>,
|
||||
) -> Result<NetworkResult<Answer<Vec<u8>>>, RPCError> {
|
||||
let app_call_q = RPCOperationAppCallQ { message };
|
||||
let app_call_q = RPCOperationAppCallQ::new(message)?;
|
||||
let question = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::AppCallQ(app_call_q),
|
||||
);
|
||||
|
||||
// Send the app call question
|
||||
let waitable_reply = network_result_try!(self.question(dest, question).await?);
|
||||
let waitable_reply = network_result_try!(self.question(dest, question, None).await?);
|
||||
|
||||
// Wait for reply
|
||||
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
||||
@@ -25,18 +25,18 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the right answer type
|
||||
let app_call_a = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Answer(a) => match a.into_detail() {
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let app_call_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::AppCallA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not an appcall answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
};
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
app_call_a.message,
|
||||
)))
|
||||
let a_message = app_call_a.destructure();
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(latency, a_message)))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
||||
@@ -45,9 +45,10 @@ impl RPCProcessor {
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// Get the question
|
||||
let app_call_q = match msg.operation.kind() {
|
||||
RPCOperationKind::Question(q) => match q.detail() {
|
||||
RPCQuestionDetail::AppCallQ(q) => q,
|
||||
let (op_id, _, _, kind) = msg.operation.clone().destructure();
|
||||
let app_call_q = match kind {
|
||||
RPCOperationKind::Question(q) => match q.destructure() {
|
||||
(_, RPCQuestionDetail::AppCallQ(q)) => q,
|
||||
_ => panic!("not an appcall question"),
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
@@ -60,19 +61,19 @@ impl RPCProcessor {
|
||||
let sender = msg
|
||||
.opt_sender_nr
|
||||
.as_ref()
|
||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
|
||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap());
|
||||
|
||||
// Register a waiter for this app call
|
||||
let id = msg.operation.op_id();
|
||||
let handle = self.unlocked_inner.waiting_app_call_table.add_op_waiter(id);
|
||||
let handle = self
|
||||
.unlocked_inner
|
||||
.waiting_app_call_table
|
||||
.add_op_waiter(op_id, ());
|
||||
|
||||
// Pass the call up through the update callback
|
||||
let message = app_call_q.message.clone();
|
||||
(self.unlocked_inner.update_callback)(VeilidUpdate::AppCall(VeilidAppCall {
|
||||
sender,
|
||||
message,
|
||||
id,
|
||||
}));
|
||||
let message_q = app_call_q.destructure();
|
||||
(self.unlocked_inner.update_callback)(VeilidUpdate::AppCall(VeilidAppCall::new(
|
||||
sender, message_q, op_id,
|
||||
)));
|
||||
|
||||
// Wait for an app call answer to come back from the app
|
||||
let res = self
|
||||
@@ -80,17 +81,17 @@ impl RPCProcessor {
|
||||
.waiting_app_call_table
|
||||
.wait_for_op(handle, self.unlocked_inner.timeout_us)
|
||||
.await?;
|
||||
let (message, _latency) = match res {
|
||||
let (message_a, _latency) = match res {
|
||||
TimeoutOr::Timeout => {
|
||||
// No message sent on timeout, but this isn't an error
|
||||
log_rpc!(debug "App call timed out for id {}", id);
|
||||
log_rpc!(debug "App call timed out for id {}", op_id);
|
||||
return Ok(NetworkResult::timeout());
|
||||
}
|
||||
TimeoutOr::Value(v) => v,
|
||||
};
|
||||
|
||||
// Return the appcall answer
|
||||
let app_call_a = RPCOperationAppCallA { message };
|
||||
let app_call_a = RPCOperationAppCallA::new(message_a)?;
|
||||
|
||||
// Send status answer
|
||||
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::AppCallA(app_call_a)))
|
||||
|
||||
@@ -9,7 +9,7 @@ impl RPCProcessor {
|
||||
dest: Destination,
|
||||
message: Vec<u8>,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
let app_message = RPCOperationAppMessage { message };
|
||||
let app_message = RPCOperationAppMessage::new(message)?;
|
||||
let statement = RPCStatement::new(RPCStatementDetail::AppMessage(app_message));
|
||||
|
||||
// Send the app message request
|
||||
@@ -22,8 +22,9 @@ impl RPCProcessor {
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// Get the statement
|
||||
let app_message = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Statement(s) => match s.into_detail() {
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let app_message = match kind {
|
||||
RPCOperationKind::Statement(s) => match s.destructure() {
|
||||
RPCStatementDetail::AppMessage(s) => s,
|
||||
_ => panic!("not an app message"),
|
||||
},
|
||||
@@ -37,14 +38,13 @@ impl RPCProcessor {
|
||||
let sender = msg
|
||||
.opt_sender_nr
|
||||
.as_ref()
|
||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
|
||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap());
|
||||
|
||||
// Pass the message up through the update callback
|
||||
let message = app_message.message;
|
||||
(self.unlocked_inner.update_callback)(VeilidUpdate::AppMessage(VeilidAppMessage {
|
||||
sender,
|
||||
message,
|
||||
}));
|
||||
let message = app_message.destructure();
|
||||
(self.unlocked_inner.update_callback)(VeilidUpdate::AppMessage(VeilidAppMessage::new(
|
||||
sender, message,
|
||||
)));
|
||||
|
||||
Ok(NetworkResult::value(()))
|
||||
}
|
||||
|
||||
@@ -26,14 +26,14 @@ impl RPCProcessor {
|
||||
));
|
||||
}
|
||||
|
||||
let find_node_q_detail = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ { node_id });
|
||||
let find_node_q_detail = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ::new(node_id));
|
||||
let find_node_q = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
find_node_q_detail,
|
||||
);
|
||||
|
||||
// Send the find_node request
|
||||
let waitable_reply = network_result_try!(self.question(dest, find_node_q).await?);
|
||||
let waitable_reply = network_result_try!(self.question(dest, find_node_q, None).await?);
|
||||
|
||||
// Wait for reply
|
||||
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
||||
@@ -42,8 +42,9 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the right answer type
|
||||
let find_node_a = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Answer(a) => match a.into_detail() {
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let find_node_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::FindNodeA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a find_node answer")),
|
||||
},
|
||||
@@ -51,18 +52,17 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Verify peers are in the correct peer scope
|
||||
for peer_info in &find_node_a.peers {
|
||||
if !self.filter_node_info(RoutingDomain::PublicInternet, &peer_info.signed_node_info) {
|
||||
let peers = find_node_a.destructure();
|
||||
|
||||
for peer_info in &peers {
|
||||
if !self.filter_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
||||
return Err(RPCError::invalid_format(
|
||||
"find_node response has invalid peer scope",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
find_node_a.peers,
|
||||
)))
|
||||
Ok(NetworkResult::value(Answer::new(latency, peers)))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
||||
@@ -81,55 +81,24 @@ impl RPCProcessor {
|
||||
}
|
||||
|
||||
// Get the question
|
||||
let find_node_q = match msg.operation.kind() {
|
||||
RPCOperationKind::Question(q) => match q.detail() {
|
||||
RPCQuestionDetail::FindNodeQ(q) => q,
|
||||
_ => panic!("not a status question"),
|
||||
let kind = msg.operation.kind().clone();
|
||||
let find_node_q = match kind {
|
||||
RPCOperationKind::Question(q) => match q.destructure() {
|
||||
(_, RPCQuestionDetail::FindNodeQ(q)) => q,
|
||||
_ => panic!("not a findnode question"),
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
};
|
||||
let node_id = find_node_q.destructure();
|
||||
|
||||
// add node information for the requesting node to our routing table
|
||||
// Get a chunk of the routing table near the requested node id
|
||||
let routing_table = self.routing_table();
|
||||
let Some(own_peer_info) = routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
// Our own node info is not yet available, drop this request.
|
||||
return Ok(NetworkResult::service_unavailable());
|
||||
};
|
||||
let closest_nodes = network_result_try!(routing_table.find_all_closest_peers(node_id));
|
||||
|
||||
// find N nodes closest to the target node in our routing table
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||
// Ensure only things that are valid/signed in the PublicInternet domain are returned
|
||||
rti.filter_has_valid_signed_node_info(
|
||||
RoutingDomain::PublicInternet,
|
||||
true,
|
||||
opt_entry,
|
||||
)
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
let filters = VecDeque::from([filter]);
|
||||
// Make FindNode answer
|
||||
let find_node_a = RPCOperationFindNodeA::new(closest_nodes)?;
|
||||
|
||||
let node_count = {
|
||||
let c = self.config.get();
|
||||
c.network.dht.max_find_node_count as usize
|
||||
};
|
||||
|
||||
let closest_nodes = routing_table.find_closest_nodes(
|
||||
node_count,
|
||||
find_node_q.node_id,
|
||||
filters,
|
||||
// transform
|
||||
|rti, entry| {
|
||||
rti.transform_to_peer_info(RoutingDomain::PublicInternet, &own_peer_info, entry)
|
||||
},
|
||||
);
|
||||
|
||||
// Make status answer
|
||||
let find_node_a = RPCOperationFindNodeA {
|
||||
peers: closest_nodes,
|
||||
};
|
||||
|
||||
// Send status answer
|
||||
// Send FindNode answer
|
||||
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::FindNodeA(find_node_a)))
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -1,11 +1,138 @@
|
||||
use super::*;
|
||||
use crate::storage_manager::{SignedValueData, SignedValueDescriptor};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GetValueAnswer {
|
||||
pub value: Option<SignedValueData>,
|
||||
pub peers: Vec<PeerInfo>,
|
||||
pub descriptor: Option<SignedValueDescriptor>,
|
||||
}
|
||||
|
||||
impl RPCProcessor {
|
||||
/// Sends a get value request and wait for response
|
||||
/// Can be sent via all methods including relays
|
||||
/// Safety routes may be used, but never private routes.
|
||||
/// Because this leaks information about the identity of the node itself,
|
||||
/// replying to this request received over a private route will leak
|
||||
/// the identity of the node and defeat the private route.
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn rpc_call_get_value(
|
||||
self,
|
||||
dest: Destination,
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
last_descriptor: Option<SignedValueDescriptor>,
|
||||
) -> Result<NetworkResult<Answer<GetValueAnswer>>, RPCError> {
|
||||
// Ensure destination never has a private route
|
||||
if matches!(
|
||||
dest,
|
||||
Destination::PrivateRoute {
|
||||
private_route: _,
|
||||
safety_selection: _
|
||||
}
|
||||
) {
|
||||
return Err(RPCError::internal(
|
||||
"Never send get value requests over private routes",
|
||||
));
|
||||
}
|
||||
|
||||
let get_value_q = RPCOperationGetValueQ::new(key, subkey, last_descriptor.is_none());
|
||||
let question = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::GetValueQ(get_value_q),
|
||||
);
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
|
||||
// Send the getvalue question
|
||||
let question_context = QuestionContext::GetValue(ValidateGetValueContext {
|
||||
last_descriptor,
|
||||
subkey,
|
||||
vcrypto,
|
||||
});
|
||||
|
||||
let waitable_reply = network_result_try!(
|
||||
self.question(dest, question, Some(question_context))
|
||||
.await?
|
||||
);
|
||||
|
||||
// Wait for reply
|
||||
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
||||
TimeoutOr::Timeout => return Ok(NetworkResult::Timeout),
|
||||
TimeoutOr::Value(v) => v,
|
||||
};
|
||||
|
||||
// Get the right answer type
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let get_value_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::GetValueA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a getvalue answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
};
|
||||
|
||||
let (value, peers, descriptor) = get_value_a.destructure();
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
GetValueAnswer {
|
||||
value,
|
||||
peers,
|
||||
descriptor,
|
||||
},
|
||||
)))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
||||
pub(crate) async fn process_get_value_q(
|
||||
&self,
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
Err(RPCError::unimplemented("process_get_value_q"))
|
||||
// Ensure this never came over a private route, safety route is okay though
|
||||
match &msg.header.detail {
|
||||
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
||||
RPCMessageHeaderDetail::PrivateRouted(_) => {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"not processing get value request over private route",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Get the question
|
||||
let kind = msg.operation.kind().clone();
|
||||
let get_value_q = match kind {
|
||||
RPCOperationKind::Question(q) => match q.destructure() {
|
||||
(_, RPCQuestionDetail::GetValueQ(q)) => q,
|
||||
_ => panic!("not a getvalue question"),
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
};
|
||||
|
||||
// Destructure
|
||||
let (key, subkey, want_descriptor) = get_value_q.destructure();
|
||||
|
||||
// Get the nodes that we know about that are closer to the the key than our own node
|
||||
let routing_table = self.routing_table();
|
||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key));
|
||||
|
||||
// See if we have this record ourselves
|
||||
let storage_manager = self.storage_manager();
|
||||
let subkey_result = network_result_try!(storage_manager
|
||||
.inbound_get_value(key, subkey, want_descriptor)
|
||||
.await
|
||||
.map_err(RPCError::internal)?);
|
||||
|
||||
// Make GetValue answer
|
||||
let get_value_a = RPCOperationGetValueA::new(
|
||||
subkey_result.value,
|
||||
closer_to_key_peers,
|
||||
subkey_result.descriptor,
|
||||
)?;
|
||||
|
||||
// Send GetValue answer
|
||||
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::GetValueA(get_value_a)))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ impl RPCProcessor {
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
let receipt = receipt.as_ref().to_vec();
|
||||
|
||||
let return_receipt = RPCOperationReturnReceipt { receipt };
|
||||
let return_receipt = RPCOperationReturnReceipt::new(receipt)?;
|
||||
let statement = RPCStatement::new(RPCStatementDetail::ReturnReceipt(return_receipt));
|
||||
|
||||
// Send the return_receipt request
|
||||
@@ -26,9 +26,10 @@ impl RPCProcessor {
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// Get the statement
|
||||
let RPCOperationReturnReceipt { receipt } = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Statement(s) => match s.into_detail() {
|
||||
RPCStatementDetail::ReturnReceipt(s) => s,
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let receipt = match kind {
|
||||
RPCOperationKind::Statement(s) => match s.destructure() {
|
||||
RPCStatementDetail::ReturnReceipt(s) => s.destructure(),
|
||||
_ => panic!("not a return receipt"),
|
||||
},
|
||||
_ => panic!("not a statement"),
|
||||
|
||||
@@ -34,17 +34,17 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Apply sequencing preference
|
||||
next_hop_nr.set_sequencing(routed_operation.sequencing);
|
||||
next_hop_nr.set_sequencing(routed_operation.sequencing());
|
||||
|
||||
// Pass along the route
|
||||
let next_hop_route = RPCOperationRoute {
|
||||
safety_route: SafetyRoute {
|
||||
let next_hop_route = RPCOperationRoute::new(
|
||||
SafetyRoute {
|
||||
public_key: safety_route.public_key,
|
||||
hop_count: safety_route.hop_count - 1,
|
||||
hops: SafetyRouteHops::Data(route_hop.next_hop.unwrap()),
|
||||
},
|
||||
operation: routed_operation,
|
||||
};
|
||||
routed_operation,
|
||||
);
|
||||
let next_hop_route_stmt = RPCStatement::new(RPCStatementDetail::Route(next_hop_route));
|
||||
|
||||
// Send the next route statement
|
||||
@@ -76,17 +76,17 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Apply sequencing preference
|
||||
next_hop_nr.set_sequencing(routed_operation.sequencing);
|
||||
next_hop_nr.set_sequencing(routed_operation.sequencing());
|
||||
|
||||
// Pass along the route
|
||||
let next_hop_route = RPCOperationRoute {
|
||||
safety_route: SafetyRoute {
|
||||
let next_hop_route = RPCOperationRoute::new(
|
||||
SafetyRoute {
|
||||
public_key: safety_route_public_key,
|
||||
hop_count: 0,
|
||||
hops: SafetyRouteHops::Private(next_private_route),
|
||||
},
|
||||
operation: routed_operation,
|
||||
};
|
||||
routed_operation,
|
||||
);
|
||||
let next_hop_route_stmt = RPCStatement::new(RPCStatementDetail::Route(next_hop_route));
|
||||
|
||||
// Send the next route statement
|
||||
@@ -114,8 +114,8 @@ impl RPCProcessor {
|
||||
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
||||
.map_err(RPCError::protocol)?;
|
||||
let body = match vcrypto.decrypt_aead(
|
||||
&routed_operation.data,
|
||||
&routed_operation.nonce,
|
||||
routed_operation.data(),
|
||||
routed_operation.nonce(),
|
||||
&dh_secret,
|
||||
None,
|
||||
) {
|
||||
@@ -132,7 +132,7 @@ impl RPCProcessor {
|
||||
self.enqueue_safety_routed_message(
|
||||
detail,
|
||||
remote_sr_pubkey.value,
|
||||
routed_operation.sequencing,
|
||||
routed_operation.sequencing(),
|
||||
body,
|
||||
)
|
||||
.map_err(RPCError::internal)?;
|
||||
@@ -162,8 +162,8 @@ impl RPCProcessor {
|
||||
let Some((secret_key, safety_spec)) = rss
|
||||
.with_signature_validated_route(
|
||||
&pr_pubkey,
|
||||
&routed_operation.signatures,
|
||||
&routed_operation.data,
|
||||
routed_operation.signatures(),
|
||||
routed_operation.data(),
|
||||
sender_id.value,
|
||||
|rssd, rsd| {
|
||||
(
|
||||
@@ -172,7 +172,7 @@ impl RPCProcessor {
|
||||
preferred_route,
|
||||
hop_count: rssd.hop_count(),
|
||||
stability: rssd.get_stability(),
|
||||
sequencing: routed_operation.sequencing,
|
||||
sequencing: routed_operation.sequencing(),
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -188,8 +188,8 @@ impl RPCProcessor {
|
||||
.map_err(RPCError::protocol)?;
|
||||
let body = vcrypto
|
||||
.decrypt_aead(
|
||||
&routed_operation.data,
|
||||
&routed_operation.nonce,
|
||||
routed_operation.data(),
|
||||
routed_operation.nonce(),
|
||||
&dh_secret,
|
||||
None,
|
||||
)
|
||||
@@ -341,8 +341,11 @@ impl RPCProcessor {
|
||||
let rh_reader = dec_blob_reader
|
||||
.get_root::<veilid_capnp::route_hop::Reader>()
|
||||
.map_err(RPCError::protocol)?;
|
||||
decode_route_hop(&rh_reader, self.crypto.clone())?
|
||||
decode_route_hop(&rh_reader)?
|
||||
};
|
||||
|
||||
// Validate the RouteHop
|
||||
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
||||
|
||||
// Sign the operation if this is not our last hop
|
||||
// as the last hop is already signed by the envelope
|
||||
@@ -350,9 +353,9 @@ impl RPCProcessor {
|
||||
let node_id = self.routing_table.node_id(crypto_kind);
|
||||
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||
let sig = vcrypto
|
||||
.sign(&node_id.value, &node_id_secret, &route_operation.data)
|
||||
.sign(&node_id.value, &node_id_secret, route_operation.data())
|
||||
.map_err(RPCError::internal)?;
|
||||
route_operation.signatures.push(sig);
|
||||
route_operation.add_signature(sig);
|
||||
}
|
||||
|
||||
Ok(NetworkResult::value(route_hop))
|
||||
@@ -374,8 +377,9 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the statement
|
||||
let mut route = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Statement(s) => match s.into_detail() {
|
||||
let (_,_,_,kind) = msg.operation.destructure();
|
||||
let route = match kind {
|
||||
RPCOperationKind::Statement(s) => match s.destructure() {
|
||||
RPCStatementDetail::Route(s) => s,
|
||||
_ => panic!("not a route statement"),
|
||||
},
|
||||
@@ -383,7 +387,7 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get crypto kind
|
||||
let crypto_kind = route.safety_route.crypto_kind();
|
||||
let crypto_kind = route.safety_route().crypto_kind();
|
||||
let Some(vcrypto) = self.crypto.get(crypto_kind) else {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"routed operation crypto is not supported",
|
||||
@@ -391,13 +395,14 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// See what kind of safety route we have going on here
|
||||
match route.safety_route.hops {
|
||||
let (safety_route, mut routed_operation) = route.destructure();
|
||||
match safety_route.hops {
|
||||
// There is a safety route hop
|
||||
SafetyRouteHops::Data(ref route_hop_data) => {
|
||||
// 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_key(crypto_kind);
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&route.safety_route.public_key.value, &node_id_secret)
|
||||
.cached_dh(&safety_route.public_key.value, &node_id_secret)
|
||||
.map_err(RPCError::protocol)?;
|
||||
let mut dec_blob_data = vcrypto
|
||||
.decrypt_aead(
|
||||
@@ -422,14 +427,17 @@ impl RPCProcessor {
|
||||
let pr_reader = dec_blob_reader
|
||||
.get_root::<veilid_capnp::private_route::Reader>()
|
||||
.map_err(RPCError::protocol)?;
|
||||
decode_private_route(&pr_reader, self.crypto.clone())?
|
||||
decode_private_route(&pr_reader)?
|
||||
};
|
||||
|
||||
// Validate the private route
|
||||
private_route.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
||||
|
||||
// Switching from full safety route to private route first hop
|
||||
network_result_try!(
|
||||
self.process_private_route_first_hop(
|
||||
route.operation,
|
||||
route.safety_route.public_key,
|
||||
routed_operation,
|
||||
safety_route.public_key,
|
||||
private_route,
|
||||
)
|
||||
.await?
|
||||
@@ -440,15 +448,18 @@ impl RPCProcessor {
|
||||
let rh_reader = dec_blob_reader
|
||||
.get_root::<veilid_capnp::route_hop::Reader>()
|
||||
.map_err(RPCError::protocol)?;
|
||||
decode_route_hop(&rh_reader, self.crypto.clone())?
|
||||
decode_route_hop(&rh_reader)?
|
||||
};
|
||||
|
||||
// Validate the route hop
|
||||
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
||||
|
||||
// Continue the full safety route with another hop
|
||||
network_result_try!(
|
||||
self.process_route_safety_route_hop(
|
||||
route.operation,
|
||||
routed_operation,
|
||||
route_hop,
|
||||
route.safety_route
|
||||
safety_route
|
||||
)
|
||||
.await?
|
||||
);
|
||||
@@ -464,8 +475,8 @@ impl RPCProcessor {
|
||||
// Safety route was a stub, start with the beginning of the private route
|
||||
network_result_try!(
|
||||
self.process_private_route_first_hop(
|
||||
route.operation,
|
||||
route.safety_route.public_key,
|
||||
routed_operation,
|
||||
safety_route.public_key,
|
||||
private_route,
|
||||
)
|
||||
.await?
|
||||
@@ -476,7 +487,7 @@ impl RPCProcessor {
|
||||
let route_hop = network_result_try!(self.decrypt_private_route_hop_data(
|
||||
&route_hop_data,
|
||||
&private_route.public_key,
|
||||
&mut route.operation
|
||||
&mut routed_operation
|
||||
)?);
|
||||
|
||||
// Ensure hop count > 0
|
||||
@@ -489,9 +500,9 @@ impl RPCProcessor {
|
||||
// Make next PrivateRoute and pass it on
|
||||
network_result_try!(
|
||||
self.process_route_private_route_hop(
|
||||
route.operation,
|
||||
routed_operation,
|
||||
route_hop.node,
|
||||
route.safety_route.public_key,
|
||||
safety_route.public_key,
|
||||
PrivateRoute {
|
||||
public_key: private_route.public_key,
|
||||
hop_count: private_route.hop_count - 1,
|
||||
@@ -511,7 +522,7 @@ impl RPCProcessor {
|
||||
"route should be at the end",
|
||||
));
|
||||
}
|
||||
if route.safety_route.hop_count != 0 {
|
||||
if safety_route.hop_count != 0 {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"Safety hop count should be zero if switched to private route",
|
||||
));
|
||||
@@ -521,8 +532,8 @@ impl RPCProcessor {
|
||||
network_result_try!(self.process_routed_operation(
|
||||
detail,
|
||||
vcrypto,
|
||||
route.operation,
|
||||
route.safety_route.public_key,
|
||||
routed_operation,
|
||||
safety_route.public_key,
|
||||
private_route.public_key,
|
||||
)?);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,154 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SetValueAnswer {
|
||||
pub set: bool,
|
||||
pub value: Option<SignedValueData>,
|
||||
pub peers: Vec<PeerInfo>,
|
||||
}
|
||||
|
||||
impl RPCProcessor {
|
||||
/// Sends a set value request and wait for response
|
||||
/// Can be sent via all methods including relays
|
||||
/// Safety routes may be used, but never private routes.
|
||||
/// Because this leaks information about the identity of the node itself,
|
||||
/// replying to this request received over a private route will leak
|
||||
/// the identity of the node and defeat the private route.
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn rpc_call_set_value(
|
||||
self,
|
||||
dest: Destination,
|
||||
key: TypedKey,
|
||||
subkey: ValueSubkey,
|
||||
value: SignedValueData,
|
||||
descriptor: SignedValueDescriptor,
|
||||
send_descriptor: bool,
|
||||
) -> Result<NetworkResult<Answer<SetValueAnswer>>, RPCError> {
|
||||
// Ensure destination never has a private route
|
||||
if matches!(
|
||||
dest,
|
||||
Destination::PrivateRoute {
|
||||
private_route: _,
|
||||
safety_selection: _
|
||||
}
|
||||
) {
|
||||
return Err(RPCError::internal(
|
||||
"Never send set value requests over private routes",
|
||||
));
|
||||
}
|
||||
|
||||
let set_value_q = RPCOperationSetValueQ::new(
|
||||
key,
|
||||
subkey,
|
||||
value,
|
||||
if send_descriptor {
|
||||
Some(descriptor.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
);
|
||||
let question = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::SetValueQ(set_value_q),
|
||||
);
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
|
||||
// Send the setvalue question
|
||||
let question_context = QuestionContext::SetValue(ValidateSetValueContext {
|
||||
descriptor,
|
||||
subkey,
|
||||
vcrypto,
|
||||
});
|
||||
|
||||
let waitable_reply = network_result_try!(
|
||||
self.question(dest, question, Some(question_context))
|
||||
.await?
|
||||
);
|
||||
|
||||
// Wait for reply
|
||||
let (msg, latency) = match self.wait_for_reply(waitable_reply).await? {
|
||||
TimeoutOr::Timeout => return Ok(NetworkResult::Timeout),
|
||||
TimeoutOr::Value(v) => v,
|
||||
};
|
||||
|
||||
// Get the right answer type
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let set_value_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::SetValueA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a setvalue answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
};
|
||||
|
||||
let (set, value, peers) = set_value_a.destructure();
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
SetValueAnswer { set, value, peers },
|
||||
)))
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), ret, err)]
|
||||
pub(crate) async fn process_set_value_q(
|
||||
&self,
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// tracing::Span::current().record("res", &tracing::field::display(res));
|
||||
Err(RPCError::unimplemented("process_set_value_q"))
|
||||
// Ensure this never came over a private route, safety route is okay though
|
||||
match &msg.header.detail {
|
||||
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
|
||||
RPCMessageHeaderDetail::PrivateRouted(_) => {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"not processing set value request over private route",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Get the question
|
||||
let kind = msg.operation.kind().clone();
|
||||
let set_value_q = match kind {
|
||||
RPCOperationKind::Question(q) => match q.destructure() {
|
||||
(_, RPCQuestionDetail::SetValueQ(q)) => q,
|
||||
_ => panic!("not a setvalue question"),
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
};
|
||||
|
||||
// Destructure
|
||||
let (key, subkey, value, descriptor) = set_value_q.destructure();
|
||||
|
||||
// Get the nodes that we know about that are closer to the the key than our own node
|
||||
let routing_table = self.routing_table();
|
||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key));
|
||||
|
||||
// If there are less than 'set_value_count' peers that are closer, then store here too
|
||||
let set_value_count = {
|
||||
let c = self.config.get();
|
||||
c.network.dht.set_value_fanout as usize
|
||||
};
|
||||
let (set, new_value) = if closer_to_key_peers.len() >= set_value_count {
|
||||
// Not close enough
|
||||
(false, None)
|
||||
} else {
|
||||
// Close enough, lets set it
|
||||
|
||||
// Save the subkey, creating a new record if necessary
|
||||
let storage_manager = self.storage_manager();
|
||||
let new_value = network_result_try!(storage_manager
|
||||
.inbound_set_value(key, subkey, value, descriptor)
|
||||
.await
|
||||
.map_err(RPCError::internal)?);
|
||||
|
||||
(true, new_value)
|
||||
};
|
||||
|
||||
// Make SetValue answer
|
||||
let set_value_a = RPCOperationSetValueA::new(set, new_value, closer_to_key_peers)?;
|
||||
|
||||
// Send SetValue answer
|
||||
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::SetValueA(set_value_a)))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ impl RPCProcessor {
|
||||
));
|
||||
}
|
||||
|
||||
let signal = RPCOperationSignal { signal_info };
|
||||
let signal = RPCOperationSignal::new(signal_info);
|
||||
let statement = RPCStatement::new(RPCStatementDetail::Signal(signal));
|
||||
|
||||
// Send the signal request
|
||||
@@ -44,8 +44,9 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the statement
|
||||
let signal = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Statement(s) => match s.into_detail() {
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let signal = match kind {
|
||||
RPCOperationKind::Statement(s) => match s.destructure() {
|
||||
RPCStatementDetail::Signal(s) => s,
|
||||
_ => panic!("not a signal"),
|
||||
},
|
||||
@@ -54,8 +55,9 @@ impl RPCProcessor {
|
||||
|
||||
// Handle it
|
||||
let network_manager = self.network_manager();
|
||||
let signal_info = signal.destructure();
|
||||
network_manager
|
||||
.handle_signal(signal.signal_info)
|
||||
.handle_signal(signal_info)
|
||||
.await
|
||||
.map_err(RPCError::network)
|
||||
}
|
||||
|
||||
@@ -68,14 +68,15 @@ impl RPCProcessor {
|
||||
}
|
||||
};
|
||||
|
||||
let status_q = RPCOperationStatusQ { node_status };
|
||||
let status_q = RPCOperationStatusQ::new(node_status);
|
||||
let question = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::StatusQ(status_q),
|
||||
);
|
||||
|
||||
// Send the info request
|
||||
let waitable_reply = network_result_try!(self.question(dest.clone(), question).await?);
|
||||
let waitable_reply =
|
||||
network_result_try!(self.question(dest.clone(), question, None).await?);
|
||||
|
||||
// Note what kind of ping this was and to what peer scope
|
||||
let send_data_kind = waitable_reply.send_data_kind;
|
||||
@@ -87,27 +88,29 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the right answer type
|
||||
let status_a = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Answer(a) => match a.into_detail() {
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let status_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::StatusA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a status answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
};
|
||||
let (a_node_status, sender_info) = status_a.destructure();
|
||||
|
||||
// Ensure the returned node status is the kind for the routing domain we asked for
|
||||
if let Some(target_nr) = opt_target_nr {
|
||||
if let Some(node_status) = status_a.node_status {
|
||||
if let Some(a_node_status) = a_node_status {
|
||||
match routing_domain {
|
||||
RoutingDomain::PublicInternet => {
|
||||
if !matches!(node_status, NodeStatus::PublicInternet(_)) {
|
||||
if !matches!(a_node_status, NodeStatus::PublicInternet(_)) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"node status doesn't match PublicInternet routing domain",
|
||||
));
|
||||
}
|
||||
}
|
||||
RoutingDomain::LocalNetwork => {
|
||||
if !matches!(node_status, NodeStatus::LocalNetwork(_)) {
|
||||
if !matches!(a_node_status, NodeStatus::LocalNetwork(_)) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"node status doesn't match LocalNetwork routing domain",
|
||||
));
|
||||
@@ -116,7 +119,7 @@ impl RPCProcessor {
|
||||
}
|
||||
|
||||
// Update latest node status in routing table
|
||||
target_nr.update_node_status(node_status);
|
||||
target_nr.update_node_status(a_node_status.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +133,7 @@ impl RPCProcessor {
|
||||
safety_selection,
|
||||
} => {
|
||||
if matches!(safety_selection, SafetySelection::Unsafe(_)) {
|
||||
if let Some(sender_info) = status_a.sender_info {
|
||||
if let Some(sender_info) = sender_info {
|
||||
match send_data_kind {
|
||||
SendDataKind::Direct(connection_descriptor) => {
|
||||
// Directly requested status that actually gets sent directly and not over a relay will tell us what our IP address appears as
|
||||
@@ -184,13 +187,15 @@ impl RPCProcessor {
|
||||
msg: RPCMessage,
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// Get the question
|
||||
let status_q = match msg.operation.kind() {
|
||||
RPCOperationKind::Question(q) => match q.detail() {
|
||||
RPCQuestionDetail::StatusQ(q) => q,
|
||||
let kind = msg.operation.kind().clone();
|
||||
let status_q = match kind {
|
||||
RPCOperationKind::Question(q) => match q.destructure() {
|
||||
(_, RPCQuestionDetail::StatusQ(q)) => q,
|
||||
_ => panic!("not a status question"),
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
};
|
||||
let q_node_status = status_q.destructure();
|
||||
|
||||
let (node_status, sender_info) = match &msg.header.detail {
|
||||
RPCMessageHeaderDetail::Direct(detail) => {
|
||||
@@ -198,17 +203,17 @@ impl RPCProcessor {
|
||||
let routing_domain = detail.routing_domain;
|
||||
|
||||
// Ensure the node status from the question is the kind for the routing domain we received the request in
|
||||
if let Some(node_status) = &status_q.node_status {
|
||||
if let Some(q_node_status) = q_node_status {
|
||||
match routing_domain {
|
||||
RoutingDomain::PublicInternet => {
|
||||
if !matches!(node_status, NodeStatus::PublicInternet(_)) {
|
||||
if !matches!(q_node_status, NodeStatus::PublicInternet(_)) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"node status doesn't match PublicInternet routing domain",
|
||||
));
|
||||
}
|
||||
}
|
||||
RoutingDomain::LocalNetwork => {
|
||||
if !matches!(node_status, NodeStatus::LocalNetwork(_)) {
|
||||
if !matches!(q_node_status, NodeStatus::LocalNetwork(_)) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"node status doesn't match LocalNetwork routing domain",
|
||||
));
|
||||
@@ -219,7 +224,7 @@ impl RPCProcessor {
|
||||
// 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
|
||||
sender_nr.update_node_status(node_status.clone());
|
||||
sender_nr.update_node_status(q_node_status.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,10 +248,7 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Make status answer
|
||||
let status_a = RPCOperationStatusA {
|
||||
node_status,
|
||||
sender_info,
|
||||
};
|
||||
let status_a = RPCOperationStatusA::new(node_status, sender_info);
|
||||
|
||||
// Send status answer
|
||||
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::StatusA(status_a)))
|
||||
|
||||
@@ -17,11 +17,7 @@ impl RPCProcessor {
|
||||
.generate_single_shot_receipt(receipt_time, [])
|
||||
.map_err(RPCError::internal)?;
|
||||
|
||||
let validate_dial_info = RPCOperationValidateDialInfo {
|
||||
dial_info,
|
||||
receipt,
|
||||
redirect,
|
||||
};
|
||||
let validate_dial_info = RPCOperationValidateDialInfo::new(dial_info, receipt, redirect)?;
|
||||
let statement = RPCStatement::new(RPCStatementDetail::ValidateDialInfo(validate_dial_info));
|
||||
|
||||
// Send the validate_dial_info request
|
||||
@@ -69,13 +65,10 @@ impl RPCProcessor {
|
||||
};
|
||||
|
||||
// Get the statement
|
||||
let RPCOperationValidateDialInfo {
|
||||
dial_info,
|
||||
receipt,
|
||||
redirect,
|
||||
} = match msg.operation.into_kind() {
|
||||
RPCOperationKind::Statement(s) => match s.into_detail() {
|
||||
RPCStatementDetail::ValidateDialInfo(s) => s,
|
||||
let (_, _, _, kind) = msg.operation.destructure();
|
||||
let (dial_info, receipt, redirect) = match kind {
|
||||
RPCOperationKind::Statement(s) => match s.destructure() {
|
||||
RPCStatementDetail::ValidateDialInfo(s) => s.destructure(),
|
||||
_ => panic!("not a validate dial info"),
|
||||
},
|
||||
_ => panic!("not a statement"),
|
||||
@@ -137,11 +130,8 @@ impl RPCProcessor {
|
||||
}
|
||||
|
||||
// Make a copy of the request, without the redirect flag
|
||||
let validate_dial_info = RPCOperationValidateDialInfo {
|
||||
dial_info: dial_info.clone(),
|
||||
receipt: receipt.clone(),
|
||||
redirect: false,
|
||||
};
|
||||
let validate_dial_info =
|
||||
RPCOperationValidateDialInfo::new(dial_info.clone(), receipt.clone(), false)?;
|
||||
let statement =
|
||||
RPCStatement::new(RPCStatementDetail::ValidateDialInfo(validate_dial_info));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user