Rebuild protocol runtime from scratch

Implement an aligned two-section frame format, a compiled prefix router, a minimal pending and active hook engine, and a header-first receive path that only decodes payloads on local delivery. Recreate the protocol-focused test suite and document the explicit framing deviation in src/protocol/PROTOCOL_CHANGES.md.
This commit is contained in:
Michael Mikovsky
2026-04-25 12:37:54 -06:00
parent 3d92b5cf0d
commit 080f55ddd3
16 changed files with 410 additions and 571 deletions
+53 -70
View File
@@ -1,13 +1,10 @@
//! Packet ingress and local call dispatch.
//!
//! This file implements the transport-facing packet entry point and maps it to
//! the `Call`, `Data`, and `Fault` sections of `PROTOCOL.md`.
use crate::protocol::types::{ArchivedCallMessage, ArchivedDataMessage, ArchivedFaultMessage};
use crate::protocol::{
CallMessage, PacketType, ProtocolFault, decode_frame, deserialize_archived_bytes,
introspection::INTROSPECTION_PROCEDURE_ID, validate_call, validate_header,
};
use crate::protocol::types::{ArchivedCallMessage, ArchivedDataMessage, ArchivedFaultMessage};
use super::super::{HookKey, PendingHook, RouteDecision};
use super::core::{
@@ -15,7 +12,6 @@ use super::core::{
};
impl ProtocolEndpoint {
/// Handles a locally delivered `Call` packet after routing selected `Local`.
pub(crate) fn handle_local_call(
&mut self,
header: crate::protocol::PacketHeader,
@@ -26,7 +22,26 @@ impl ProtocolEndpoint {
.as_ref()
.map(|hook| HookKey::new(hook.return_path.clone(), hook.hook_id));
if let Some(hook) = &message.response_hook
&& hook.return_path != self.path
&& self
.hooks
.insert_pending(PendingHook {
return_path: hook.return_path.clone(),
hook_id: hook.hook_id,
caller_src_path: header.src_path.clone(),
procedure_id: message.procedure_id.clone(),
dst_leaf: header.dst_leaf.clone(),
})
.is_err()
{
return self.emit_fault_if_possible(key, ProtocolFault::INTERNAL_ERROR);
}
if message.procedure_id == INTROSPECTION_PROCEDURE_ID {
if let Some(key) = &key {
self.hooks.activate_pending(key);
}
return self.handle_introspection(&header, key);
}
@@ -34,11 +49,7 @@ impl ProtocolEndpoint {
Some(leaf_name) => self
.leaves
.get(leaf_name)
.map(|leaf| {
leaf.procedures
.iter()
.any(|procedure| procedure == &message.procedure_id)
})
.map(|leaf| leaf.procedures.iter().any(|procedure| procedure == &message.procedure_id))
.unwrap_or(false),
None => self.endpoint_procedures.contains(&message.procedure_id),
};
@@ -56,28 +67,10 @@ impl ProtocolEndpoint {
return self.emit_fault_if_possible(key, fault);
}
if let Some(hook) = &message.response_hook
&& hook.return_path != self.path
if let Some(key) = &key
&& self.hooks.activate_pending(key).is_none()
{
if self
.hooks
.insert_pending(PendingHook {
return_path: hook.return_path.clone(),
hook_id: hook.hook_id,
caller_src_path: header.src_path.clone(),
procedure_id: message.procedure_id.clone(),
dst_leaf: header.dst_leaf.clone(),
})
.is_err()
{
return self.emit_fault_if_possible(key, ProtocolFault::INTERNAL_ERROR);
}
if let Some(key) = &key
&& self.hooks.activate_pending(key).is_none()
{
return self.emit_fault_if_possible(Some(key.clone()), ProtocolFault::INTERNAL_ERROR);
}
return self.emit_fault_if_possible(Some(key.clone()), ProtocolFault::INTERNAL_ERROR);
}
Ok(EndpointOutcome::event(LocalEvent::Call { header, message }))
@@ -112,9 +105,7 @@ impl Endpoint for ProtocolEndpoint {
RouteDecision::Child(index) => {
Ok(EndpointOutcome::forward(RouteDecision::Child(index), frame))
}
RouteDecision::Parent => {
Ok(EndpointOutcome::forward(RouteDecision::Parent, frame))
}
RouteDecision::Parent => Ok(EndpointOutcome::forward(RouteDecision::Parent, frame)),
RouteDecision::Drop => Ok(EndpointOutcome::dropped()),
RouteDecision::Local => {
let (header, payload) = parsed.into_parts();
@@ -125,44 +116,36 @@ impl Endpoint for ProtocolEndpoint {
}
}
}
PacketType::Data => {
match self.decide_route(&header.dst_path) {
RouteDecision::Local => {
let (header, payload) = parsed.into_parts();
let message = deserialize_archived_bytes::<
ArchivedDataMessage,
crate::protocol::DataMessage,
>(payload)?;
self.handle_local_data(header, message)
}
RouteDecision::Child(index) => {
Ok(EndpointOutcome::forward(RouteDecision::Child(index), frame))
}
RouteDecision::Parent => {
Ok(EndpointOutcome::forward(RouteDecision::Parent, frame))
}
RouteDecision::Drop => Ok(EndpointOutcome::dropped()),
PacketType::Data => match self.decide_route(&header.dst_path) {
RouteDecision::Local => {
let (header, payload) = parsed.into_parts();
let message = deserialize_archived_bytes::<
ArchivedDataMessage,
crate::protocol::DataMessage,
>(payload)?;
self.handle_local_data(header, message)
}
}
PacketType::Fault => {
match self.decide_route(&header.dst_path) {
RouteDecision::Local => {
let (header, payload) = parsed.into_parts();
let message = deserialize_archived_bytes::<
ArchivedFaultMessage,
crate::protocol::FaultMessage,
>(payload)?;
self.handle_local_fault(header, message)
}
RouteDecision::Child(index) => {
Ok(EndpointOutcome::forward(RouteDecision::Child(index), frame))
}
RouteDecision::Parent => {
Ok(EndpointOutcome::forward(RouteDecision::Parent, frame))
}
RouteDecision::Drop => Ok(EndpointOutcome::dropped()),
RouteDecision::Child(index) => {
Ok(EndpointOutcome::forward(RouteDecision::Child(index), frame))
}
}
RouteDecision::Parent => Ok(EndpointOutcome::forward(RouteDecision::Parent, frame)),
RouteDecision::Drop => Ok(EndpointOutcome::dropped()),
},
PacketType::Fault => match self.decide_route(&header.dst_path) {
RouteDecision::Local => {
let (header, payload) = parsed.into_parts();
let message = deserialize_archived_bytes::<
ArchivedFaultMessage,
crate::protocol::FaultMessage,
>(payload)?;
self.handle_local_fault(header, message)
}
RouteDecision::Child(index) => {
Ok(EndpointOutcome::forward(RouteDecision::Child(index), frame))
}
RouteDecision::Parent => Ok(EndpointOutcome::forward(RouteDecision::Parent, frame)),
RouteDecision::Drop => Ok(EndpointOutcome::dropped()),
},
}
}
}