aerosocket_client/
config.rs1use aerosocket_core::error::ConfigError;
6use aerosocket_core::Error;
7use std::time::Duration;
8
9#[derive(Debug, Clone)]
11pub struct ClientConfig {
12 pub max_frame_size: usize,
14 pub max_message_size: usize,
16 pub handshake_timeout: Duration,
18 pub idle_timeout: Duration,
20 pub compression: CompressionConfig,
22 pub tls: Option<TlsConfig>,
24 pub user_agent: String,
26 pub origin: Option<String>,
28 pub protocols: Vec<String>,
30 pub headers: Vec<(String, String)>,
32}
33
34impl Default for ClientConfig {
35 fn default() -> Self {
36 Self {
37 max_frame_size: aerosocket_core::protocol::constants::DEFAULT_MAX_FRAME_SIZE,
38 max_message_size: aerosocket_core::protocol::constants::DEFAULT_MAX_MESSAGE_SIZE,
39 handshake_timeout: aerosocket_core::protocol::constants::DEFAULT_HANDSHAKE_TIMEOUT,
40 idle_timeout: aerosocket_core::protocol::constants::DEFAULT_IDLE_TIMEOUT,
41 compression: CompressionConfig::default(),
42 tls: None,
43 user_agent: format!("aerosocket-client/{}", env!("CARGO_PKG_VERSION")),
44 origin: None,
45 protocols: Vec::new(),
46 headers: Vec::new(),
47 }
48 }
49}
50
51impl ClientConfig {
52 pub fn validate(&self) -> aerosocket_core::Result<()> {
54 if self.max_frame_size == 0 {
55 return Err(Error::Config(ConfigError::Validation(
56 "max_frame_size must be greater than 0".to_string(),
57 )));
58 }
59
60 if self.max_message_size == 0 {
61 return Err(Error::Config(ConfigError::Validation(
62 "max_message_size must be greater than 0".to_string(),
63 )));
64 }
65
66 if self.max_message_size < self.max_frame_size {
67 return Err(Error::Config(ConfigError::Validation(
68 "max_message_size must be greater than or equal to max_frame_size".to_string(),
69 )));
70 }
71
72 if self.handshake_timeout.is_zero() {
73 return Err(Error::Config(ConfigError::Validation(
74 "handshake_timeout must be greater than 0".to_string(),
75 )));
76 }
77
78 Ok(())
79 }
80
81 pub fn max_frame_size(mut self, size: usize) -> Self {
83 self.max_frame_size = size;
84 self
85 }
86
87 pub fn max_message_size(mut self, size: usize) -> Self {
89 self.max_message_size = size;
90 self
91 }
92
93 pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
95 self.handshake_timeout = timeout;
96 self
97 }
98
99 pub fn idle_timeout(mut self, timeout: Duration) -> Self {
101 self.idle_timeout = timeout;
102 self
103 }
104
105 pub fn user_agent(mut self, agent: String) -> Self {
107 self.user_agent = agent;
108 self
109 }
110
111 pub fn origin(mut self, origin: String) -> Self {
113 self.origin = Some(origin);
114 self
115 }
116
117 pub fn add_protocol(mut self, protocol: String) -> Self {
119 self.protocols.push(protocol);
120 self
121 }
122
123 pub fn add_header(mut self, name: String, value: String) -> Self {
125 self.headers.push((name, value));
126 self
127 }
128
129 pub fn tls(mut self, config: TlsConfig) -> Self {
131 self.tls = Some(config);
132 self
133 }
134}
135
136#[derive(Debug, Clone)]
138pub struct CompressionConfig {
139 pub enabled: bool,
141 pub level: u8,
143 pub server_context_takeover: bool,
145 pub client_context_takeover: bool,
147 pub server_max_window_bits: Option<u8>,
149 pub client_max_window_bits: Option<u8>,
151}
152
153impl Default for CompressionConfig {
154 fn default() -> Self {
155 Self {
156 enabled: false,
157 level: 6,
158 server_context_takeover: true,
159 client_context_takeover: true,
160 server_max_window_bits: None,
161 client_max_window_bits: None,
162 }
163 }
164}
165
166#[derive(Debug, Clone)]
168pub struct TlsConfig {
169 pub verify: bool,
171 pub ca_file: Option<String>,
173 pub cert_file: Option<String>,
175 pub key_file: Option<String>,
177 pub server_name: Option<String>,
179 pub min_version: Option<TlsVersion>,
181 pub max_version: Option<TlsVersion>,
183}
184
185#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187pub enum TlsVersion {
188 V1_0,
190 V1_1,
192 V1_2,
194 V1_3,
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_client_config_default() {
204 let config = ClientConfig::default();
205 assert!(config.validate().is_ok());
206 assert_eq!(config.max_frame_size, 16 * 1024 * 1024); assert_eq!(config.max_message_size, 64 * 1024 * 1024); }
209
210 #[test]
211 fn test_client_config_validation() {
212 let config = ClientConfig {
213 max_frame_size: 0,
214 ..Default::default()
215 };
216 assert!(config.validate().is_err());
217
218 let config = ClientConfig {
219 max_frame_size: 1024,
220 max_message_size: 512,
221 ..Default::default()
222 };
223 assert!(config.validate().is_err());
224 }
225
226 #[test]
227 fn test_client_config_builder() {
228 let config = ClientConfig::default()
229 .max_frame_size(2048)
230 .user_agent("test-agent".to_string())
231 .add_protocol("chat".to_string())
232 .add_header("X-Custom".to_string(), "value".to_string());
233
234 assert_eq!(config.max_frame_size, 2048);
235 assert_eq!(config.user_agent, "test-agent");
236 assert_eq!(config.protocols.len(), 1);
237 assert_eq!(config.protocols[0], "chat");
238 assert_eq!(config.headers.len(), 1);
239 assert_eq!(
240 config.headers[0],
241 ("X-Custom".to_string(), "value".to_string())
242 );
243 }
244}