use std::sync::Arc;
use tokio::net::TcpListener;
use super::connection::ServerConnection;
use super::registry::MountPointRegistry;
use super::state::RtspServerConfig;
use crate::error::NetError;
pub struct RtspServer {
config: Arc<RtspServerConfig>,
registry: MountPointRegistry,
}
impl RtspServer {
#[must_use]
pub fn new(config: RtspServerConfig) -> Self {
Self {
config: Arc::new(config),
registry: MountPointRegistry::new(),
}
}
#[must_use]
pub fn with_default_config() -> Self {
Self::new(RtspServerConfig::default())
}
#[must_use]
pub fn registry(&self) -> &MountPointRegistry {
&self.registry
}
pub async fn run(self) -> Result<(), NetError> {
let listener = TcpListener::bind(&self.config.bind_address)
.await
.map_err(|e| NetError::Connection(format!("bind failed: {e}")))?;
self.run_with_listener(listener).await
}
pub async fn run_with_listener(self, listener: TcpListener) -> Result<(), NetError> {
let mut connection_count: usize = 0;
loop {
match listener.accept().await {
Ok((stream, _addr)) => {
if connection_count >= self.config.max_connections {
drop(stream);
continue;
}
connection_count += 1;
let config = Arc::clone(&self.config);
let registry = self.registry.clone();
tokio::spawn(async move {
ServerConnection::new(stream, config, registry).run().await;
});
}
Err(e) => {
return Err(NetError::Connection(format!("accept failed: {e}")));
}
}
}
}
}