use std::net::{SocketAddr, TcpListener};
use std::time::Duration;
use super::AcceptorSettings;
use crate::ServerError;
use crate::config::types::WebSocketConfig;
#[cfg(test)]
#[path = "bound_tests.rs"]
pub(in crate::server) mod tests;
#[derive(Debug)]
pub struct BoundWebSocket {
pub(super) listener: TcpListener,
pub(super) local_addr: SocketAddr,
pub(super) settings: AcceptorSettings,
}
impl BoundWebSocket {
pub fn bind(config: &WebSocketConfig) -> Result<Self, ServerError> {
let settings = AcceptorSettings {
path: config.path.clone(),
allowed_origins: config.allowed_origins.clone(),
allowed_origin_ports: config.allowed_origin_ports.clone(),
ping_interval: config.ping_interval_ms.map(Duration::from_millis),
message_bound: super::liminal_ws_message_bound()?,
};
let listener = TcpListener::bind(config.listen_address).map_err(|source| {
ServerError::ListenerBind {
address: config.listen_address,
source,
}
})?;
let local_addr = listener
.local_addr()
.map_err(|error| ServerError::ListenerAccept {
message: format!("failed to inspect websocket listener address: {error}"),
})?;
tracing::info!(
websocket_listen_address = %local_addr,
upgrade_path = %settings.path,
allowed_origins = settings.allowed_origins.len(),
allowed_origin_ports = settings.allowed_origin_ports.len(),
keepalive = ?settings.ping_interval,
"liminal websocket listener bound"
);
Ok(Self {
listener,
local_addr,
settings,
})
}
#[must_use]
pub const fn local_addr(&self) -> SocketAddr {
self.local_addr
}
}