use std::str::FromStr;
use crate::{Error, ffi, moq_client_config};
#[derive(Clone, Default)]
pub struct Config {
pub connect: moq_tokio::connect::Config,
pub quic: moq_tokio::quic::Config,
}
pub unsafe fn parse_client(config: Option<&moq_client_config>) -> Result<Config, Error> {
let mut out = Config::default();
let Some(config) = config else {
return Ok(out);
};
let versions = unsafe { ffi::parse_strings(config.versions, config.versions_len)? };
if !versions.is_empty() {
out.connect.version = versions
.iter()
.map(|version| moq_net::Version::from_str(version).map_err(Error::InvalidConfig))
.collect::<Result<_, _>>()?;
}
if let Some(bind) = unsafe { ffi::parse_str_optional(config.bind, config.bind_len)? } {
let addr: std::net::SocketAddr = bind
.parse()
.map_err(|_| Error::InvalidConfig(format!("invalid bind address: {bind}")))?;
out.connect.bind = Some(addr);
}
if config.has_connect_timeout {
out.connect.timeout = std::time::Duration::from_micros(config.connect_timeout_us);
}
if config.has_failover_delay {
out.connect.race = std::time::Duration::from_micros(config.failover_delay_us);
}
if config.has_resolution_delay {
out.connect.resolution_delay = std::time::Duration::from_micros(config.resolution_delay_us);
}
if config.has_websocket_enabled {
out.connect.websocket.enabled = Some(config.websocket_enabled);
}
if config.has_websocket_delay {
out.connect.websocket.delay = std::time::Duration::from_micros(config.websocket_delay_us);
}
if config.tls_disable_verify {
out.connect.tls.insecure = Some(true);
}
if config.has_tls_system_roots {
out.connect.tls.system_roots = Some(config.tls_system_roots);
}
let roots = unsafe { ffi::parse_strings(config.tls_roots, config.tls_roots_len)? };
if !roots.is_empty() {
out.connect.tls.root = roots.into_iter().map(Into::into).collect();
}
let fingerprints = unsafe { ffi::parse_strings(config.tls_fingerprints, config.tls_fingerprints_len)? };
if !fingerprints.is_empty() {
out.connect.tls.fingerprint = fingerprints;
}
out.connect.tls.host_name =
unsafe { ffi::parse_str_optional(config.tls_host_name, config.tls_host_name_len)? }.map(str::to_string);
out.connect.tls.cert = unsafe { ffi::parse_str_optional(config.tls_cert, config.tls_cert_len)? }.map(Into::into);
out.connect.tls.key = unsafe { ffi::parse_str_optional(config.tls_key, config.tls_key_len)? }.map(Into::into);
if config.has_backoff_initial {
out.connect.backoff.initial = std::time::Duration::from_micros(config.backoff_initial_us);
}
if config.has_backoff_multiplier {
out.connect.backoff.multiplier = config.backoff_multiplier;
}
if config.has_backoff_max {
out.connect.backoff.max = std::time::Duration::from_micros(config.backoff_max_us);
}
if config.has_backoff_timeout {
out.connect.backoff.timeout = std::time::Duration::from_micros(config.backoff_timeout_us);
}
if config.has_quic_max_streams {
out.quic.max_streams = Some(config.quic_max_streams);
}
if config.has_quic_idle_timeout {
out.quic.idle_timeout = std::time::Duration::from_micros(config.quic_idle_timeout_us);
}
if config.has_quic_keep_alive {
out.quic.keep_alive = std::time::Duration::from_micros(config.quic_keep_alive_us);
}
if config.has_quic_gso {
out.quic.gso = Some(config.quic_gso);
}
if config.has_quic_mtu_discovery {
out.quic.mtu_discovery = Some(config.quic_mtu_discovery);
}
if let Some(family) =
unsafe { ffi::parse_str_optional(config.quic_congestion_control, config.quic_congestion_control_len)? }
{
out.quic.congestion_control =
Some(moq_tokio::quic::CongestionControl::from_str(family).map_err(Error::InvalidConfig)?);
}
out.quic.qlog = unsafe { ffi::parse_str_optional(config.quic_qlog, config.quic_qlog_len)? }.map(Into::into);
Ok(out)
}