0.3.4-alpha.4

This commit is contained in:
2026-09-21 18:00:32 +02:00
parent bbecae5e0d
commit fa17ea0ca5
12 changed files with 792 additions and 47 deletions

View File

@@ -0,0 +1,167 @@
// file: crates/common/game-realtime-websocket-lib/src/config.rs
// version: 1
const DEFAULT_CLOSE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(2);
const DEFAULT_CONNECT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
const DEFAULT_MAX_FRAME_SIZE: usize = 1024 * 1024;
const DEFAULT_MAX_MESSAGE_SIZE: usize = 1024 * 1024;
const DEFAULT_MAX_WRITE_BUFFER_SIZE: usize = 2 * 1024 * 1024;
const DEFAULT_SEND_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
const DEFAULT_WRITE_BUFFER_SIZE: usize = 64 * 1024;
/// Product-facing limits and operation deadlines for one WebSocket connection.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WebSocketConfig {
max_message_size: usize,
max_frame_size: usize,
write_buffer_size: usize,
max_write_buffer_size: usize,
connect_timeout: std::time::Duration,
send_timeout: std::time::Duration,
close_timeout: std::time::Duration,
}
impl Default for WebSocketConfig {
fn default() -> Self {
return Self {
max_message_size: DEFAULT_MAX_MESSAGE_SIZE,
max_frame_size: DEFAULT_MAX_FRAME_SIZE,
write_buffer_size: DEFAULT_WRITE_BUFFER_SIZE,
max_write_buffer_size: DEFAULT_MAX_WRITE_BUFFER_SIZE,
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
send_timeout: DEFAULT_SEND_TIMEOUT,
close_timeout: DEFAULT_CLOSE_TIMEOUT,
};
}
}
impl WebSocketConfig {
/// Returns a copy with a different maximum binary message size.
#[must_use]
pub fn with_max_message_size(mut self, value: usize) -> Self {
self.max_message_size = value;
return self;
}
/// Returns a copy with a different maximum WebSocket frame payload size.
#[must_use]
pub fn with_max_frame_size(mut self, value: usize) -> Self {
self.max_frame_size = value;
return self;
}
/// Returns a copy with a different Tungstenite write-buffer target.
#[must_use]
pub fn with_write_buffer_size(mut self, value: usize) -> Self {
self.write_buffer_size = value;
return self;
}
/// Returns a copy with a different hard maximum for the Tungstenite write buffer.
#[must_use]
pub fn with_max_write_buffer_size(mut self, value: usize) -> Self {
self.max_write_buffer_size = value;
return self;
}
/// Returns a copy with a different connection or handshake deadline.
#[must_use]
pub fn with_connect_timeout(mut self, value: std::time::Duration) -> Self {
self.connect_timeout = value;
return self;
}
/// Returns a copy with a different deadline for one send operation.
#[must_use]
pub fn with_send_timeout(mut self, value: std::time::Duration) -> Self {
self.send_timeout = value;
return self;
}
/// Returns a copy with a different deadline for a clean local close operation.
#[must_use]
pub fn with_close_timeout(mut self, value: std::time::Duration) -> Self {
self.close_timeout = value;
return self;
}
/// Returns the configured maximum binary message size.
#[must_use]
pub fn max_message_size(&self) -> usize {
return self.max_message_size;
}
/// Returns the configured maximum WebSocket frame payload size.
#[must_use]
pub fn max_frame_size(&self) -> usize {
return self.max_frame_size;
}
/// Returns the configured Tungstenite write-buffer target.
#[must_use]
pub fn write_buffer_size(&self) -> usize {
return self.write_buffer_size;
}
/// Returns the configured hard maximum for the Tungstenite write buffer.
#[must_use]
pub fn max_write_buffer_size(&self) -> usize {
return self.max_write_buffer_size;
}
/// Returns the configured connection or handshake deadline.
#[must_use]
pub fn connect_timeout(&self) -> std::time::Duration {
return self.connect_timeout;
}
/// Returns the configured deadline for one send operation.
#[must_use]
pub fn send_timeout(&self) -> std::time::Duration {
return self.send_timeout;
}
/// Returns the configured deadline for a clean local close operation.
#[must_use]
pub fn close_timeout(&self) -> std::time::Duration {
return self.close_timeout;
}
/// Validates all invariants required before creating a WebSocket endpoint or connection.
pub fn validate(&self) -> Result<(), game_realtime_transport_lib::TransportError> {
if self.max_message_size == 0 {
return Err(invalid_configuration("max_message_size must be greater than zero"));
}
if self.max_frame_size == 0 {
return Err(invalid_configuration("max_frame_size must be greater than zero"));
}
if self.max_frame_size > self.max_message_size {
return Err(invalid_configuration("max_frame_size must not exceed max_message_size"));
}
let minimum_max_write_buffer_size = match self.write_buffer_size.checked_add(self.max_message_size) {
Some(value) => value,
None => return Err(invalid_configuration("write_buffer_size + max_message_size overflows usize")),
};
if self.max_write_buffer_size < minimum_max_write_buffer_size {
return Err(invalid_configuration("max_write_buffer_size must fit write_buffer_size plus one maximum-sized message"));
}
if self.connect_timeout.is_zero() {
return Err(invalid_configuration("connect_timeout must be greater than zero"));
}
if self.send_timeout.is_zero() {
return Err(invalid_configuration("send_timeout must be greater than zero"));
}
if self.close_timeout.is_zero() {
return Err(invalid_configuration("close_timeout must be greater than zero"));
}
return Ok(());
}
}
fn invalid_configuration(detail: &str) -> game_realtime_transport_lib::TransportError {
return game_realtime_transport_lib::TransportError::new(game_realtime_transport_lib::TransportErrorKind::InvalidConfiguration, detail);
}
#[cfg(test)]
#[path = "../unit_tests/config.rs"]
mod tests;