mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Reduce protocol packet-flow allocations
Replace vector-backed endpoint outcomes with single-action results, skip payload deserialization on forwarded data and faults, and route local call and data emissions without encode/decode roundtrips.
This commit is contained in:
@@ -11,10 +11,95 @@ use crate::protocol::{
|
||||
encode_packet, validate_call, validate_header, validate_procedure_id,
|
||||
};
|
||||
|
||||
use super::core::{ChildRoute, EndpointError, ProtocolEndpoint};
|
||||
use super::super::RouteDecision;
|
||||
use super::core::{ChildRoute, EndpointError, EndpointOutcome, ProtocolEndpoint};
|
||||
use crate::protocol::tree::LeafSpec;
|
||||
|
||||
impl ProtocolEndpoint {
|
||||
fn prepare_call(
|
||||
&self,
|
||||
dst_path: Vec<String>,
|
||||
dst_leaf: Option<String>,
|
||||
procedure_id: impl Into<String>,
|
||||
response_hook_id: Option<u64>,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(PacketHeader, CallMessage), EndpointError> {
|
||||
let procedure_id = procedure_id.into();
|
||||
validate_procedure_id(&procedure_id)?;
|
||||
|
||||
let response_hook = response_hook_id.map(|hook_id| HookTarget {
|
||||
hook_id,
|
||||
return_path: self.path.clone(),
|
||||
});
|
||||
let header = PacketHeader {
|
||||
packet_type: PacketType::Call,
|
||||
src_path: self.path.clone(),
|
||||
dst_path,
|
||||
dst_leaf,
|
||||
hook_id: None,
|
||||
};
|
||||
let call = CallMessage {
|
||||
procedure_id,
|
||||
data,
|
||||
response_hook,
|
||||
};
|
||||
|
||||
validate_header(&header)?;
|
||||
validate_call(&header, &call)?;
|
||||
Ok((header, call))
|
||||
}
|
||||
|
||||
fn register_outbound_call_hook(
|
||||
&mut self,
|
||||
header: &PacketHeader,
|
||||
call: &CallMessage,
|
||||
) -> Result<(), EndpointError> {
|
||||
if let Some(hook) = &call.response_hook
|
||||
&& self
|
||||
.hooks
|
||||
.insert_active(ActiveHook {
|
||||
return_path: hook.return_path.clone(),
|
||||
hook_id: hook.hook_id,
|
||||
peer_path: header.dst_path.clone(),
|
||||
procedure_id: call.procedure_id.clone(),
|
||||
dst_leaf: header.dst_leaf.clone(),
|
||||
peer_finished: false,
|
||||
})
|
||||
.is_err()
|
||||
{
|
||||
return Err(EndpointError::Validation(ValidationError::InvalidHookId));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_data(
|
||||
&self,
|
||||
dst_path: Vec<String>,
|
||||
hook_id: u64,
|
||||
procedure_id: impl Into<String>,
|
||||
data: Vec<u8>,
|
||||
end_hook: bool,
|
||||
) -> Result<(PacketHeader, DataMessage), EndpointError> {
|
||||
let procedure_id = procedure_id.into();
|
||||
validate_procedure_id(&procedure_id)?;
|
||||
|
||||
let header = PacketHeader {
|
||||
packet_type: PacketType::Data,
|
||||
src_path: self.path.clone(),
|
||||
dst_path,
|
||||
dst_leaf: None,
|
||||
hook_id: Some(hook_id),
|
||||
};
|
||||
let message = DataMessage {
|
||||
procedure_id,
|
||||
data,
|
||||
end_hook,
|
||||
};
|
||||
|
||||
validate_header(&header)?;
|
||||
Ok((header, message))
|
||||
}
|
||||
|
||||
/// Creates a runtime endpoint with static tree topology and leaf metadata.
|
||||
///
|
||||
/// ```
|
||||
@@ -69,48 +154,31 @@ impl ProtocolEndpoint {
|
||||
response_hook_id: Option<u64>,
|
||||
data: Vec<u8>,
|
||||
) -> Result<FrameBytes, EndpointError> {
|
||||
let procedure_id = procedure_id.into();
|
||||
validate_procedure_id(&procedure_id)?;
|
||||
|
||||
let response_hook = response_hook_id.map(|hook_id| HookTarget {
|
||||
hook_id,
|
||||
return_path: self.path.clone(),
|
||||
});
|
||||
let header = PacketHeader {
|
||||
packet_type: PacketType::Call,
|
||||
src_path: self.path.clone(),
|
||||
dst_path: dst_path.clone(),
|
||||
dst_leaf: dst_leaf.clone(),
|
||||
hook_id: None,
|
||||
};
|
||||
let call = CallMessage {
|
||||
procedure_id: procedure_id.clone(),
|
||||
data,
|
||||
response_hook,
|
||||
};
|
||||
|
||||
validate_header(&header)?;
|
||||
validate_call(&header, &call)?;
|
||||
|
||||
if let Some(hook) = &call.response_hook
|
||||
&& self
|
||||
.hooks
|
||||
.insert_active(ActiveHook {
|
||||
return_path: hook.return_path.clone(),
|
||||
hook_id: hook.hook_id,
|
||||
peer_path: dst_path,
|
||||
procedure_id,
|
||||
dst_leaf,
|
||||
peer_finished: false,
|
||||
})
|
||||
.is_err()
|
||||
{
|
||||
return Err(EndpointError::Validation(ValidationError::InvalidHookId));
|
||||
}
|
||||
|
||||
let (header, call) =
|
||||
self.prepare_call(dst_path, dst_leaf, procedure_id, response_hook_id, data)?;
|
||||
self.register_outbound_call_hook(&header, &call)?;
|
||||
Ok(encode_packet(&header, &call)?)
|
||||
}
|
||||
|
||||
/// Routes one locally originated `Call` without an encode/decode roundtrip.
|
||||
pub fn send_call(
|
||||
&mut self,
|
||||
dst_path: Vec<String>,
|
||||
dst_leaf: Option<String>,
|
||||
procedure_id: impl Into<String>,
|
||||
response_hook_id: Option<u64>,
|
||||
data: Vec<u8>,
|
||||
) -> Result<EndpointOutcome, EndpointError> {
|
||||
let (header, call) =
|
||||
self.prepare_call(dst_path, dst_leaf, procedure_id, response_hook_id, data)?;
|
||||
self.register_outbound_call_hook(&header, &call)?;
|
||||
|
||||
match self.decide_route(&header.dst_path) {
|
||||
RouteDecision::Local => self.handle_local_call(header, call),
|
||||
route => Ok(EndpointOutcome::forward(route, encode_packet(&header, &call)?)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds an outbound `Data` packet for an existing hook.
|
||||
pub fn make_data(
|
||||
&self,
|
||||
@@ -120,23 +188,24 @@ impl ProtocolEndpoint {
|
||||
data: Vec<u8>,
|
||||
end_hook: bool,
|
||||
) -> Result<FrameBytes, EndpointError> {
|
||||
let procedure_id = procedure_id.into();
|
||||
validate_procedure_id(&procedure_id)?;
|
||||
|
||||
let header = PacketHeader {
|
||||
packet_type: PacketType::Data,
|
||||
src_path: self.path.clone(),
|
||||
dst_path,
|
||||
dst_leaf: None,
|
||||
hook_id: Some(hook_id),
|
||||
};
|
||||
let message = DataMessage {
|
||||
procedure_id,
|
||||
data,
|
||||
end_hook,
|
||||
};
|
||||
|
||||
validate_header(&header)?;
|
||||
let (header, message) = self.prepare_data(dst_path, hook_id, procedure_id, data, end_hook)?;
|
||||
Ok(encode_packet(&header, &message)?)
|
||||
}
|
||||
|
||||
/// Routes one locally originated `Data` packet without an encode/decode roundtrip.
|
||||
pub fn send_data(
|
||||
&mut self,
|
||||
dst_path: Vec<String>,
|
||||
hook_id: u64,
|
||||
procedure_id: impl Into<String>,
|
||||
data: Vec<u8>,
|
||||
end_hook: bool,
|
||||
) -> Result<EndpointOutcome, EndpointError> {
|
||||
let (header, message) = self.prepare_data(dst_path, hook_id, procedure_id, data, end_hook)?;
|
||||
|
||||
match self.decide_route(&header.dst_path) {
|
||||
RouteDecision::Local => self.handle_local_data(header, message),
|
||||
route => Ok(EndpointOutcome::forward(route, encode_packet(&header, &message)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user