This commit is contained in:
2026-04-09 16:00:07 -03:00
parent e69fec5aea
commit 5921cd6562
13 changed files with 1104 additions and 0 deletions

11
media/server/Cargo.toml Normal file
View File

@@ -0,0 +1,11 @@
[package]
name = "cht-server"
version = "0.1.0"
edition = "2021"
[dependencies]
cht-common = { path = "../common" }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
anyhow = { workspace = true }

74
media/server/src/main.rs Normal file
View File

@@ -0,0 +1,74 @@
use anyhow::Result;
use cht_common::protocol::{self, ControlMessage, PacketType};
use tokio::io::BufReader;
use tokio::net::TcpListener;
use tracing::{error, info};
const LISTEN_ADDR: &str = "0.0.0.0:4444";
#[tokio::main]
async fn main() -> Result<()> {
cht_common::logging::init("server");
let listener = TcpListener::bind(LISTEN_ADDR).await?;
info!("Server listening on {LISTEN_ADDR}");
loop {
let (stream, addr) = listener.accept().await?;
info!("Client connected from {addr}");
tokio::spawn(async move {
if let Err(e) = handle_client(stream).await {
error!("Client {addr} error: {e:#}");
}
info!("Client {addr} disconnected");
});
}
}
async fn handle_client(stream: tokio::net::TcpStream) -> Result<()> {
let mut reader = BufReader::new(stream);
let mut video_packets = 0u64;
let mut audio_packets = 0u64;
loop {
let packet = match protocol::read_packet(&mut reader).await {
Ok(p) => p,
Err(e) => {
// Any read error at the header boundary is a clean disconnect
// (includes EOF from flush + shutdown)
let msg = format!("{e:#}");
if msg.contains("eof") || msg.contains("Eof")
|| msg.contains("connection reset")
|| msg.contains("broken pipe")
{
break;
}
return Err(e);
}
};
match packet.header.packet_type {
PacketType::Video => {
video_packets += 1;
if video_packets % 300 == 1 {
info!(
"video: {video_packets} packets, ts={}ms, keyframe={}",
packet.header.timestamp_ns / 1_000_000,
packet.header.is_keyframe(),
);
}
}
PacketType::Audio => {
audio_packets += 1;
}
PacketType::Control => {
let ctrl = ControlMessage::from_payload(&packet.payload)?;
info!("control: {ctrl:?}");
}
}
}
info!("Session totals: {video_packets} video, {audio_packets} audio packets");
Ok(())
}