//! The original OmniVox use case: a dump **agent** streams physical //! memory to a viewer while spraying small control messages over the same //! encrypted session. //! //! This example fabricates a toy 16 MiB "memory" image (no root needed :), //! streams it in 1 MiB encrypted chunks through the stream lane, and //! interleaves `Progress` messages through the message lane. Run //! `dump-viewer` first, then this. use serde::{Deserialize, Serialize}; use std::time::Duration; /// Control-plane messages. Bulk bytes deliberately do NOT travel as /// messages — the stream lane skips serde entirely. #[derive(Serialize, Deserialize, Debug)] enum AgentMsg { /// "About to stream page {page} of {pages}" Progress { page: u32, pages: u32 }, /// "Entire image streamed; {bytes} bytes sent." Done { bytes: u64 }, } const PAGE: usize = 1024 * 1024; // 1 MiB stream frames const PAGES: u32 = 16; #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt() .with_target(false) .without_time() .init(); let agent = omnivox::client::() .password("SecurePassword123", b"static-demo-salt") .connect("127.0.0.1", 8080) .await?; let mut image = Vec::with_capacity(PAGE * PAGES as usize); for page in 0..(PAGE * PAGES as usize) { // A deterministic fake "memory image": anything recognizable works. image.push((page % 251) as u8); } for (n, page) in image.chunks(PAGE).enumerate() { // Control plane: announce the page (tiny, latency-sensitive). agent .send(&AgentMsg::Progress { page: n as u32, pages: PAGES, }) .await; // Data plane: stream the page. `send_stream` splits anything larger // than Config::max_stream_frame and awaits each chunk, so even a // 4 GiB dump here would flow with proper backpressure — a slow // viewer throttles the agent instead of exploding memory. if !agent.send_stream(page).await { tracing::error!("viewer vanished mid-dump"); break; } // Pace the toy dump so the interleaving is visible in the logs. tokio::time::sleep(Duration::from_millis(50)).await; } agent .send(&AgentMsg::Done { bytes: image.len() as u64, }) .await; tokio::time::sleep(Duration::from_millis(200)).await; agent.stop().await; Ok(()) }