use std::time::Duration;
use peashape::{ID_SIZE, Node, ShapeConfig, ShapingStrategy};
const MAGIC: &[u8; 4] = b"PESH";
fn frame_payload(data: &[u8]) -> Vec<u8> {
assert!(data.len() <= 255, "payload too long for 1-byte length");
let mut out = Vec::with_capacity(MAGIC.len() + 1 + data.len());
out.extend_from_slice(MAGIC);
out.push(data.len() as u8);
out.extend_from_slice(data);
out
}
fn extract_payload(frame: &[u8]) -> Option<&[u8]> {
let payload = frame.get(ID_SIZE..)?;
let rest = payload.strip_prefix(MAGIC)?;
let len = *rest.first()? as usize;
rest.get(1..1 + len)
}
#[tokio::main(flavor = "multi_thread", worker_threads = 2)]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mk_node = |name: &str| {
Ok::<_, Box<dyn std::error::Error>>(Node::new(ShapeConfig {
name: Some(name.into()),
listener_addr: Some("127.0.0.1:0".parse()?),
strategy: ShapingStrategy::Constant {
interval: Duration::from_millis(100),
},
..Default::default()
}))
};
let alice = mk_node("alice")?;
let bob = mk_node("bob")?;
alice.spawn().await?;
bob.spawn().await?;
alice.connect(bob.local_addr().await?).await?;
let bob_addr = bob.local_addr().await?;
for _ in 0..50 {
if alice.connected_peers().contains(&bob_addr) {
break;
}
tokio::time::sleep(Duration::from_millis(10)).await;
}
let mut bob_rx = bob.subscribe();
let real_payload = frame_payload(b"hello, peashape!");
let pub_id = alice.broadcast_shaped(&real_payload)?;
println!("Alice broadcast message with id {pub_id:?}");
let deadline = tokio::time::Instant::now() + Duration::from_secs(2);
let mut got = None;
while tokio::time::Instant::now() < deadline {
match tokio::time::timeout(Duration::from_millis(200), bob_rx.recv()).await {
Ok(Ok(frame)) => {
if let Some(payload) = extract_payload(&frame) {
got = Some(payload.to_vec());
break;
}
}
_ => continue,
}
}
match got {
Some(payload) => {
println!(
"Bob received the real message: {:?}",
String::from_utf8_lossy(&payload)
);
}
None => {
println!("Bob did not receive the real message within the deadline.");
}
}
alice.shutdown().await;
bob.shutdown().await;
Ok(())
}