protocol level capabilities
This commit is contained in:
@@ -5,11 +5,15 @@ const MAX_FIND_NODE_A_PEERS_LEN: usize = 20;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCOperationFindNodeQ {
|
||||
node_id: TypedKey,
|
||||
capabilities: Vec<Capability>,
|
||||
}
|
||||
|
||||
impl RPCOperationFindNodeQ {
|
||||
pub fn new(node_id: TypedKey) -> Self {
|
||||
Self { node_id }
|
||||
pub fn new(node_id: TypedKey, capabilities: Vec<Capability>) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
capabilities,
|
||||
}
|
||||
}
|
||||
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
|
||||
Ok(())
|
||||
@@ -18,15 +22,33 @@ impl RPCOperationFindNodeQ {
|
||||
// pub fn node_id(&self) -> &TypedKey {
|
||||
// &self.node_id
|
||||
// }
|
||||
// pub fn capabilities(&self) -> &[Capability] {
|
||||
// &self.capabilities
|
||||
// }
|
||||
|
||||
pub fn destructure(self) -> TypedKey {
|
||||
self.node_id
|
||||
pub fn destructure(self) -> (TypedKey, Vec<Capability>) {
|
||||
(self.node_id, self.capabilities)
|
||||
}
|
||||
|
||||
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(Self { node_id })
|
||||
let cap_reader = reader
|
||||
.reborrow()
|
||||
.get_capabilities()
|
||||
.map_err(RPCError::protocol)?;
|
||||
if cap_reader.len() as usize > MAX_CAPABILITIES {
|
||||
return Err(RPCError::protocol("too many capabilities"));
|
||||
}
|
||||
let capabilities = cap_reader
|
||||
.as_slice()
|
||||
.map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Self {
|
||||
node_id,
|
||||
capabilities,
|
||||
})
|
||||
}
|
||||
pub fn encode(
|
||||
&self,
|
||||
@@ -34,6 +56,19 @@ impl RPCOperationFindNodeQ {
|
||||
) -> Result<(), RPCError> {
|
||||
let mut ni_builder = builder.reborrow().init_node_id();
|
||||
encode_typed_key(&self.node_id, &mut ni_builder);
|
||||
|
||||
let mut cap_builder = builder
|
||||
.reborrow()
|
||||
.init_capabilities(self.capabilities.len() as u32);
|
||||
if let Some(s) = cap_builder.as_slice() {
|
||||
let capvec: Vec<u32> = self
|
||||
.capabilities
|
||||
.iter()
|
||||
.map(|x| u32::from_be_bytes(x.0))
|
||||
.collect();
|
||||
|
||||
s.clone_from_slice(&capvec);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,9 +442,11 @@ impl RPCProcessor {
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
signed_node_info: &SignedNodeInfo,
|
||||
capabilities: &[Capability],
|
||||
) -> bool {
|
||||
let routing_table = self.routing_table();
|
||||
routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
|
||||
&& signed_node_info.node_info().has_capabilities(capabilities)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -470,6 +472,7 @@ impl RPCProcessor {
|
||||
.rpc_call_find_node(
|
||||
Destination::direct(next_node).with_safety(safety_selection),
|
||||
node_id,
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -1474,7 +1477,11 @@ impl RPCProcessor {
|
||||
// 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.verify_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
||||
if !self.verify_node_info(
|
||||
routing_domain,
|
||||
sender_peer_info.signed_node_info(),
|
||||
&[],
|
||||
) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"sender peerinfo has invalid peer scope",
|
||||
));
|
||||
|
||||
@@ -57,7 +57,11 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_appmessage() {
|
||||
if !opi
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capability(CAP_APPMESSAGE)
|
||||
{
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"app call is not available",
|
||||
));
|
||||
|
||||
@@ -28,7 +28,11 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_appmessage() {
|
||||
if !opi
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capability(CAP_APPMESSAGE)
|
||||
{
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"app message is not available",
|
||||
));
|
||||
|
||||
@@ -12,7 +12,11 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_tunnel() {
|
||||
if !opi
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capability(CAP_TUNNEL)
|
||||
{
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"tunnel is not available",
|
||||
));
|
||||
|
||||
@@ -12,7 +12,11 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_tunnel() {
|
||||
if !opi
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capability(CAP_TUNNEL)
|
||||
{
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"tunnel is not available",
|
||||
));
|
||||
|
||||
@@ -15,6 +15,7 @@ impl RPCProcessor {
|
||||
self,
|
||||
dest: Destination,
|
||||
node_id: TypedKey,
|
||||
capabilities: Vec<Capability>,
|
||||
) -> Result<NetworkResult<Answer<Vec<PeerInfo>>>, RPCError> {
|
||||
// Ensure destination never has a private route
|
||||
if matches!(
|
||||
@@ -29,7 +30,8 @@ impl RPCProcessor {
|
||||
));
|
||||
}
|
||||
|
||||
let find_node_q_detail = RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ::new(node_id));
|
||||
let find_node_q_detail =
|
||||
RPCQuestionDetail::FindNodeQ(RPCOperationFindNodeQ::new(node_id, capabilities.clone()));
|
||||
let find_node_q = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
find_node_q_detail,
|
||||
@@ -60,9 +62,13 @@ impl RPCProcessor {
|
||||
let peers = find_node_a.destructure();
|
||||
|
||||
for peer_info in &peers {
|
||||
if !self.verify_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
||||
if !self.verify_node_info(
|
||||
RoutingDomain::PublicInternet,
|
||||
peer_info.signed_node_info(),
|
||||
&capabilities,
|
||||
) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"find_node response has invalid peer scope",
|
||||
"find_node response does not meet peer criteria",
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -94,11 +100,12 @@ impl RPCProcessor {
|
||||
},
|
||||
_ => panic!("not a question"),
|
||||
};
|
||||
let node_id = find_node_q.destructure();
|
||||
let (node_id, capabilities) = find_node_q.destructure();
|
||||
|
||||
// Get a chunk of the routing table near the requested node id
|
||||
let routing_table = self.routing_table();
|
||||
let closest_nodes = network_result_try!(routing_table.find_all_closest_peers(node_id));
|
||||
let closest_nodes =
|
||||
network_result_try!(routing_table.find_all_closest_peers(node_id, &capabilities));
|
||||
|
||||
// Make FindNode answer
|
||||
let find_node_a = RPCOperationFindNodeA::new(closest_nodes)?;
|
||||
|
||||
@@ -177,7 +177,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_dht() {
|
||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"dht is not available",
|
||||
));
|
||||
@@ -199,7 +199,7 @@ impl RPCProcessor {
|
||||
|
||||
// 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));
|
||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key, vec![CAP_DHT]));
|
||||
|
||||
let debug_string = format!(
|
||||
"IN <=== GetValueQ({} #{}{}) <== {}",
|
||||
|
||||
@@ -369,7 +369,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_route() {
|
||||
if !opi.signed_node_info().node_info().has_capability(CAP_ROUTE) {
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"route is not available",
|
||||
));
|
||||
|
||||
@@ -179,7 +179,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_dht() {
|
||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"dht is not available",
|
||||
));
|
||||
@@ -211,7 +211,7 @@ impl RPCProcessor {
|
||||
|
||||
// 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));
|
||||
let closer_to_key_peers = network_result_try!(routing_table.find_peers_closer_to_key(key, vec![CAP_DHT]));
|
||||
|
||||
let debug_string = format!(
|
||||
"IN <=== SetValueQ({} #{} len={} seq={} writer={}{}) <== {}",
|
||||
|
||||
@@ -41,7 +41,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_signal() {
|
||||
if !opi.signed_node_info().node_info().is_signal_capable() {
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"signal is not available",
|
||||
));
|
||||
|
||||
@@ -12,7 +12,11 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_tunnel() {
|
||||
if !opi
|
||||
.signed_node_info()
|
||||
.node_info()
|
||||
.has_capability(CAP_TUNNEL)
|
||||
{
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"tunnel is not available",
|
||||
));
|
||||
|
||||
@@ -71,7 +71,8 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(detail.routing_domain) {
|
||||
if !opi.signed_node_info().node_info().can_validate_dial_info() {
|
||||
let ni = opi.signed_node_info().node_info();
|
||||
if !ni.has_capability(CAP_VALIDATE_DIAL_INFO) || !ni.is_signal_capable() {
|
||||
return Ok(NetworkResult::service_unavailable(
|
||||
"validate dial info is not available",
|
||||
));
|
||||
@@ -116,7 +117,9 @@ impl RPCProcessor {
|
||||
let entry = v.unwrap();
|
||||
entry.with(rti, move |_rti, e| {
|
||||
e.node_info(routing_domain)
|
||||
.map(|ni| ni.can_validate_dial_info())
|
||||
.map(|ni| {
|
||||
ni.has_capability(CAP_VALIDATE_DIAL_INFO) && ni.is_signal_capable()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_dht() {
|
||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ impl RPCProcessor {
|
||||
let routing_table = self.routing_table();
|
||||
{
|
||||
if let Some(opi) = routing_table.get_own_peer_info(msg.header.routing_domain()) {
|
||||
if !opi.signed_node_info().node_info().can_dht() {
|
||||
if !opi.signed_node_info().node_info().has_capability(CAP_DHT) {
|
||||
return Ok(NetworkResult::service_unavailable("dht is not available"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user