diff --git a/Cargo.toml b/Cargo.toml index 53d3a36..5b40365 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,10 @@ path = "examples/protocol/remote_shell_endpoint.rs" name = "remote_shell_receive" path = "examples/protocol/remote_shell_receive.rs" +[[example]] +name = "remote_shell_single_endpoint" +path = "examples/protocol/remote_shell_single_endpoint.rs" + [[example]] name = "bench" path = "examples/protocol/bench/bench.rs" @@ -109,3 +113,4 @@ unsafe_op_in_unsafe_fn = "warn" unused_import_braces = "warn" unused_lifetimes = "warn" trivial_casts = "allow" +missing_docs = "warn" diff --git a/examples/protocol/bench/bench.rs b/examples/protocol/bench/bench.rs index b99071d..a3d58f7 100644 --- a/examples/protocol/bench/bench.rs +++ b/examples/protocol/bench/bench.rs @@ -1,3 +1,8 @@ +//! Protocol benchmark driver. +//! +//! Running the example normally prints the in-process benchmark table. Running it with `tools` +//! builds the standalone operation binaries and feeds them to external profiling tools. + use std::hint::black_box; use std::path::{Path, PathBuf}; use std::process::Command; diff --git a/examples/protocol/bench/op_decode_call.rs b/examples/protocol/bench/op_decode_call.rs index 3eed735..da2d8d4 100644 --- a/examples/protocol/bench/op_decode_call.rs +++ b/examples/protocol/bench/op_decode_call.rs @@ -1,3 +1,5 @@ +//! Standalone benchmark binary for `decode_call`. + #[path = "support/bench_common.rs"] mod common; diff --git a/examples/protocol/bench/op_encode_call.rs b/examples/protocol/bench/op_encode_call.rs index 3706e35..60969bc 100644 --- a/examples/protocol/bench/op_encode_call.rs +++ b/examples/protocol/bench/op_encode_call.rs @@ -1,3 +1,5 @@ +//! Standalone benchmark binary for `encode_call`. + #[path = "support/bench_common.rs"] mod common; diff --git a/examples/protocol/bench/op_forward_call_receive.rs b/examples/protocol/bench/op_forward_call_receive.rs index 4882774..b20e878 100644 --- a/examples/protocol/bench/op_forward_call_receive.rs +++ b/examples/protocol/bench/op_forward_call_receive.rs @@ -1,3 +1,5 @@ +//! Standalone benchmark binary for `forward_call_receive`. + #[path = "support/bench_common.rs"] mod common; diff --git a/examples/protocol/bench/op_hook_data_receive.rs b/examples/protocol/bench/op_hook_data_receive.rs index b298a97..3e553b7 100644 --- a/examples/protocol/bench/op_hook_data_receive.rs +++ b/examples/protocol/bench/op_hook_data_receive.rs @@ -1,3 +1,5 @@ +//! Standalone benchmark binary for `hook_data_receive`. + #[path = "support/bench_common.rs"] mod common; diff --git a/examples/protocol/bench/op_local_call_receive.rs b/examples/protocol/bench/op_local_call_receive.rs index 06de76a..22d58f1 100644 --- a/examples/protocol/bench/op_local_call_receive.rs +++ b/examples/protocol/bench/op_local_call_receive.rs @@ -1,3 +1,5 @@ +//! Standalone benchmark binary for `local_call_receive`. + #[path = "support/bench_common.rs"] mod common; diff --git a/examples/protocol/bench/support/bench_common.rs b/examples/protocol/bench/support/bench_common.rs index e2a7393..e145232 100644 --- a/examples/protocol/bench/support/bench_common.rs +++ b/examples/protocol/bench/support/bench_common.rs @@ -1,3 +1,8 @@ +//! Shared helpers for the standalone benchmark operation binaries. +//! +//! These helpers keep each operation binary tiny while still exposing the same setup and checksum +//! logic to strace, perf, and heaptrack. + #![allow(dead_code)] use std::hint::black_box; diff --git a/examples/protocol/leaf_derive.rs b/examples/protocol/leaf_derive.rs index 4c48e45..57dbaf1 100644 --- a/examples/protocol/leaf_derive.rs +++ b/examples/protocol/leaf_derive.rs @@ -1,3 +1,8 @@ +//! Small end-to-end example for the `Leaf` and `procedures` derive macros. +//! +//! This stays entirely local. A controller endpoint opens one call against a single in-process +//! leaf runtime, and the example decodes the returned reply payload. + use std::error::Error; use std::{convert::Infallible, string::String}; diff --git a/examples/protocol/remote_shell_endpoint.rs b/examples/protocol/remote_shell_endpoint.rs index 974980b..9102401 100644 --- a/examples/protocol/remote_shell_endpoint.rs +++ b/examples/protocol/remote_shell_endpoint.rs @@ -1,3 +1,9 @@ +//! Remote shell endpoint example. +//! +//! This binary acts as the single remote-shell endpoint process. It connects to the controller +//! example over TCP, feeds inbound frames into the `ProcedureRuntime`, and flushes any resulting +//! protocol frames back to the controller. + #[path = "../../src/leaf/remote_shell/mod.rs"] mod remote_shell; diff --git a/examples/protocol/remote_shell_receive.rs b/examples/protocol/remote_shell_receive.rs index 003899d..b1dcc31 100644 --- a/examples/protocol/remote_shell_receive.rs +++ b/examples/protocol/remote_shell_receive.rs @@ -1,3 +1,8 @@ +//! Remote shell controller example. +//! +//! This binary listens for the endpoint example, opens one remote shell session, sends a few +//! commands, and prints returned hook data until the shell closes. + #[path = "../../src/leaf/remote_shell/mod.rs"] mod remote_shell; diff --git a/examples/protocol/remote_shell_single_endpoint.rs b/examples/protocol/remote_shell_single_endpoint.rs new file mode 100644 index 0000000..92ac761 --- /dev/null +++ b/examples/protocol/remote_shell_single_endpoint.rs @@ -0,0 +1,46 @@ +//! Smallest in-process `RemoteShellLeaf` endpoint example. +//! +//! This example hosts exactly one protocol endpoint with exactly one leaf, `RemoteShellLeaf`, and +//! performs a local introspection request against that leaf. It does not open any sockets or spawn +//! a shell process, so it is the easiest place to see how the endpoint and leaf metadata fit +//! together. + +#[path = "../../src/leaf/remote_shell/mod.rs"] +mod remote_shell; + +use std::error::Error; + +use unshell::protocol::tree::{EndpointOutcome, LocalEvent, ProtocolEndpoint}; +use unshell::protocol::{LeafIntrospection, INTROSPECTION_PROCEDURE_ID}; + +fn main() -> Result<(), Box> { + let mut endpoint = ProtocolEndpoint::new( + remote_shell::agent_path(), + Some(Vec::new()), + Vec::new(), + vec![unshell::protocol::tree::LeafSpec { + name: remote_shell::shell_leaf_name(), + procedures: vec![remote_shell::shell_open_procedure()], + }], + ); + + let hook_id = endpoint.allocate_hook_id(); + let outcome = endpoint.send_call( + remote_shell::agent_path(), + Some(remote_shell::shell_leaf_name()), + INTROSPECTION_PROCEDURE_ID, + Some(hook_id), + Vec::new(), + )?; + + let EndpointOutcome::Local(LocalEvent::Data { message, .. }) = outcome else { + return Err("expected one local introspection response".into()); + }; + + let payload = unshell::protocol::tree::decode_call_input::(&message.data)?; + println!("remote-shell examples normally listen on {}", remote_shell::LISTEN_ADDR); + println!("endpoint path: {:?}", remote_shell::agent_path()); + println!("leaf: {}", payload.leaf_name); + println!("procedures: {:?}", payload.procedures); + Ok(()) +} diff --git a/src/protocol/tree/endpoint/core.rs b/src/protocol/tree/endpoint/core.rs index 1b540b6..9db059e 100644 --- a/src/protocol/tree/endpoint/core.rs +++ b/src/protocol/tree/endpoint/core.rs @@ -166,7 +166,9 @@ pub enum LocalEvent { pub enum EndpointOutcome { /// Frame to forward, together with the next routing decision. Forward { + /// The next routing decision chosen for the forwarded frame. route: RouteDecision, + /// The encoded frame bytes to send along that route. frame: FrameBytes, }, /// Locally-delivered protocol event.