Files
omnivox-rs/examples/omnivox-client.rs
T
michael fea8ea3ab1 0.15.0: simple builder API, v2.1 framing, stream lane, benches
- omnivox::server::<T>()/client::<T>() builders; plain closures, enum in,
  match in the callback — the original C++ UX with the ceremony removed
- serde + bincode replace the hand-rolled Cereal codec (vectors.rs still
  governs the crypto leaves via the C++ golden oracles)
- v2.1 frames: u32 len | type | ct | tag; nonce derived from the sequence
  counter (no wire nonce), type byte authenticated as AAD; any frame-level
  failure is fatal, authenticated-but-undecodable payloads are skipped
- stream lane: send_stream/on_stream, 1 MiB frames, shared sequence with
  messages (exact sender interleaving preserved); see dump-agent/viewer
- per-connection bounded queues + writer tasks; reply/reply_stream are
  non-blocking try_send lanes for callbacks
- benches: seal/open criterion group + transport harness (spray msg/s,
  stream GiB/s, raw loopback baseline)
- profile.dev.package scrypt/pbkdf2 opt-level 3: golden-vector scrypt at
  N=2^17 was unusable in debug builds
- PROTOCOL-V2.md and README rewritten for v2.1
2026-09-30 08:07:38 -04:00

49 lines
1.6 KiB
Rust

//! The minimal OmniVox client: connect, talk, done.
//!
//! Companion to `omnivox-server`. Sends `Hello`, prints the echo, then
//! exchanges two more notes and stops.
use omnivox::ConnectionStatus;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Serialize, Deserialize, Debug)]
enum ChatMsg {
Hello,
Note(String),
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_target(false)
.without_time()
.init();
let client = omnivox::client::<ChatMsg>()
// Same password + salt as the server — they derive the same PSK.
.password("SecurePassword123", b"static-demo-salt")
.on_data(|msg, _ctx| match msg {
ChatMsg::Hello => tracing::info!("server greeted us unprompted?"),
ChatMsg::Note(text) => tracing::info!("server note: {text}"),
})
// Fires on Connected, ConnectionFailed, and later NotConnected.
.on_state(|ctx| {
tracing::info!("state: {:?}", ctx.status());
if ctx.status() == ConnectionStatus::ConnectionFailed {
tracing::error!("is the server running? (cargo run --example omnivox-server)");
}
})
.connect("127.0.0.1", 8080)
.await?;
client.send(&ChatMsg::Hello).await;
tokio::time::sleep(Duration::from_millis(300)).await;
client.send(&ChatMsg::Note("first note".into())).await;
client.send(&ChatMsg::Note("second note".into())).await;
tokio::time::sleep(Duration::from_millis(300)).await;
client.stop().await;
Ok(())
}