use libconfig::Config;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
fn build_message(seq: u32) -> String {
format!(
r#"seq = {};
timestamp = {};
sensor = "sensor-{}";
readings = {{
temperature = {:.1};
humidity = {:.1};
pressure = {:.2};
}};
tags = ["environment", "building-{}"];
active = {};"#,
seq,
1700000000 + seq,
seq % 4,
20.0 + seq as f64 * 0.5,
45.0 + seq as f64 * 1.2,
1013.25 + seq as f64 * 0.1,
seq % 3,
if seq % 2 == 0 { "true" } else { "false" },
)
}
async fn sender(addr: std::net::SocketAddr) {
let mut stream = TcpStream::connect(addr).await.expect("Failed to connect");
for seq in 0..10 {
let msg = build_message(seq);
let len = msg.len() as u32;
stream
.write_all(&len.to_be_bytes())
.await
.expect("Failed to write length");
stream
.write_all(msg.as_bytes())
.await
.expect("Failed to write payload");
}
stream.shutdown().await.expect("Failed to shutdown");
}
async fn receiver(mut stream: TcpStream) {
let mut len_buf = [0u8; 4];
loop {
match stream.read_exact(&mut len_buf).await {
Ok(_) => {}
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break,
Err(e) => panic!("Failed to read length: {}", e),
}
let len = u32::from_be_bytes(len_buf) as usize;
let mut payload = vec![0u8; len];
stream
.read_exact(&mut payload)
.await
.expect("Failed to read payload");
let text = String::from_utf8(payload).expect("Invalid UTF-8");
let cfg = Config::from_str(&text).expect("Failed to parse libconfig");
println!(
" packet seq={}, sensor={}, temp={}, active={}, tags={:?}",
cfg["seq"],
cfg["sensor"],
cfg["readings.temperature"],
cfg["active"],
cfg["tags"]
.as_array()
.unwrap()
.iter()
.map(|t| t.as_str().unwrap())
.collect::<Vec<_>>(),
);
}
}
#[tokio::main]
async fn main() {
println!("=== Streaming Libconfig over TCP ===\n");
let listener = TcpListener::bind("127.0.0.1:0")
.await
.expect("Failed to bind");
let addr = listener.local_addr().unwrap();
println!("Listening on {}\n", addr);
let sender_handle = tokio::spawn(sender(addr));
let (stream, peer) = listener.accept().await.expect("Failed to accept");
println!("Accepted connection from {}\n", peer);
receiver(stream).await;
sender_handle.await.expect("Sender task failed");
println!("\nReceived all 10 packets successfully.");
}