use std::net::SocketAddr;
use std::time::Duration;
use anyhow::Context;
use axum::http::Method;
use hang::moq_net;
use hang::moq_net::AsPath;
use crate::moq::notify_ready;
#[derive(clap::Args, Clone)]
pub struct ImportArgs {
pub playlist: String,
}
#[derive(clap::Args, Clone)]
pub struct ExportArgs {
#[arg(long, default_value = "[::]:8089")]
pub listen: SocketAddr,
#[command(flatten)]
pub tls: moq_native::tls::Server,
#[arg(long, default_value = "16s", value_parser = humantime::parse_duration)]
pub window: Duration,
#[command(flatten)]
pub cors: crate::web::Cors,
}
pub async fn import(origin: &moq_net::origin::Producer, name: String, playlist: String) -> anyhow::Result<()> {
let mut producer = origin
.create_broadcast(&name, moq_net::broadcast::Route::new().with_announce(true))
.context("failed to create broadcast")?;
let catalog = moq_mux::catalog::Producer::new(&mut producer)?;
let mut importer = moq_hls::import::Import::new(producer, catalog, moq_hls::import::Config::new(playlist))?;
tracing::info!(%name, "importing HLS");
importer.init().await?;
notify_ready();
Ok(importer.run().await?)
}
pub async fn export(origin: moq_net::origin::Consumer, args: ExportArgs, name: String) -> anyhow::Result<()> {
let scoped = origin
.scope(&[name.as_path()])
.with_context(|| format!("failed to scope origin to broadcast `{name}`"))?;
let mut config = moq_hls::export::Config::default();
config.window = args.window;
let server = moq_hls::Server::new(scoped, config);
let app = server.router().layer(args.cors.layer([Method::GET])?);
let tls = if args.tls.cert.is_empty() && args.tls.generate.is_empty() {
None
} else {
let alpn = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
Some(args.tls.server_config(alpn)?)
};
let listener = moq_native::bind::tcp(args.listen)?;
tracing::info!(listen = %args.listen, "serving HLS");
notify_ready();
crate::web::serve(listener, app, tls).await
}