1use std::{fs, path::Path};
4
5use clap::Parser;
6use serde::{Deserialize, Serialize};
7use trojan_core::defaults;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Config {
11 pub server: ServerConfig,
12 pub tls: TlsConfig,
13 pub auth: AuthConfig,
14 #[serde(default)]
15 pub websocket: WebSocketConfig,
16 #[serde(default)]
17 pub metrics: MetricsConfig,
18 #[serde(default)]
19 pub logging: LoggingConfig,
20 #[serde(default)]
21 pub analytics: AnalyticsConfig,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ServerConfig {
26 pub listen: String,
27 pub fallback: String,
28 #[serde(default = "default_tcp_timeout_secs")]
29 pub tcp_idle_timeout_secs: u64,
30 #[serde(default = "default_udp_timeout_secs")]
31 pub udp_timeout_secs: u64,
32 #[serde(default = "default_max_udp_payload")]
33 pub max_udp_payload: usize,
34 #[serde(default = "default_max_udp_buffer_bytes")]
35 pub max_udp_buffer_bytes: usize,
36 #[serde(default = "default_max_header_bytes")]
37 pub max_header_bytes: usize,
38 #[serde(default)]
40 pub max_connections: Option<usize>,
41 #[serde(default)]
43 pub rate_limit: Option<RateLimitConfig>,
44 #[serde(default)]
46 pub fallback_pool: Option<FallbackPoolConfig>,
47 #[serde(default)]
49 pub resource_limits: Option<ResourceLimitsConfig>,
50 #[serde(default)]
52 pub tcp: TcpConfig,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct TcpConfig {
58 #[serde(default = "default_tcp_no_delay")]
60 pub no_delay: bool,
61 #[serde(default = "default_tcp_keepalive_secs")]
63 pub keepalive_secs: u64,
64 #[serde(default = "default_tcp_reuse_port")]
66 pub reuse_port: bool,
67 #[serde(default = "default_tcp_fast_open")]
69 pub fast_open: bool,
70 #[serde(default = "default_tcp_fast_open_qlen")]
72 pub fast_open_qlen: u32,
73}
74
75impl Default for TcpConfig {
76 fn default() -> Self {
77 Self {
78 no_delay: default_tcp_no_delay(),
79 keepalive_secs: default_tcp_keepalive_secs(),
80 reuse_port: default_tcp_reuse_port(),
81 fast_open: default_tcp_fast_open(),
82 fast_open_qlen: default_tcp_fast_open_qlen(),
83 }
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct FallbackPoolConfig {
95 #[serde(default = "default_pool_max_idle")]
97 pub max_idle: usize,
98 #[serde(default = "default_pool_max_age_secs")]
100 pub max_age_secs: u64,
101 #[serde(default = "default_pool_fill_batch")]
103 pub fill_batch: usize,
104 #[serde(default = "default_pool_fill_delay_ms")]
106 pub fill_delay_ms: u64,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct ResourceLimitsConfig {
112 #[serde(default = "default_relay_buffer_size")]
114 pub relay_buffer_size: usize,
115 #[serde(default)]
117 pub tcp_send_buffer: usize,
118 #[serde(default)]
120 pub tcp_recv_buffer: usize,
121 #[serde(default = "default_connection_backlog")]
123 pub connection_backlog: u32,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct RateLimitConfig {
129 #[serde(default = "default_rate_limit_max_connections")]
131 pub max_connections_per_ip: u32,
132 #[serde(default = "default_rate_limit_window_secs")]
134 pub window_secs: u64,
135 #[serde(default = "default_rate_limit_cleanup_secs")]
137 pub cleanup_interval_secs: u64,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct TlsConfig {
142 pub cert: String,
144 pub key: String,
146 #[serde(default)]
148 pub alpn: Vec<String>,
149 #[serde(default = "default_min_tls_version")]
151 pub min_version: String,
152 #[serde(default = "default_max_tls_version")]
154 pub max_version: String,
155 #[serde(default)]
158 pub client_ca: Option<String>,
159 #[serde(default)]
162 pub cipher_suites: Vec<String>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize, Default)]
166pub struct WebSocketConfig {
167 #[serde(default = "default_ws_enabled")]
168 pub enabled: bool,
169 #[serde(default = "default_ws_mode")]
170 pub mode: String,
171 #[serde(default = "default_ws_path")]
172 pub path: String,
173 #[serde(default)]
174 pub host: Option<String>,
175 #[serde(default)]
176 pub listen: Option<String>,
177 #[serde(default = "default_ws_max_frame_bytes")]
178 pub max_frame_bytes: usize,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct AuthConfig {
183 pub passwords: Vec<String>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize, Default)]
187pub struct MetricsConfig {
188 pub listen: Option<String>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize, Default)]
192pub struct LoggingConfig {
193 pub level: Option<String>,
195 pub format: Option<String>,
197 pub output: Option<String>,
199 #[serde(default)]
201 pub filters: std::collections::HashMap<String, String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, Default)]
210pub struct AnalyticsConfig {
211 #[serde(default)]
213 pub enabled: bool,
214
215 #[serde(default)]
217 pub clickhouse: Option<ClickHouseConfig>,
218
219 #[serde(default)]
221 pub buffer: AnalyticsBufferConfig,
222
223 #[serde(default)]
225 pub sampling: AnalyticsSamplingConfig,
226
227 #[serde(default)]
229 pub privacy: AnalyticsPrivacyConfig,
230
231 #[serde(default)]
233 pub server_id: Option<String>,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct ClickHouseConfig {
239 pub url: String,
241
242 #[serde(default = "default_analytics_database")]
244 pub database: String,
245
246 #[serde(default = "default_analytics_table")]
248 pub table: String,
249
250 #[serde(default)]
252 pub username: Option<String>,
253
254 #[serde(default)]
256 pub password: Option<String>,
257
258 #[serde(default = "default_analytics_connect_timeout")]
260 pub connect_timeout_secs: u64,
261
262 #[serde(default = "default_analytics_write_timeout")]
264 pub write_timeout_secs: u64,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
269pub struct AnalyticsBufferConfig {
270 #[serde(default = "default_analytics_buffer_size")]
272 pub size: usize,
273
274 #[serde(default = "default_analytics_flush_interval")]
276 pub flush_interval_secs: u64,
277
278 #[serde(default = "default_analytics_batch_size")]
280 pub batch_size: usize,
281
282 #[serde(default)]
284 pub fallback_path: Option<String>,
285}
286
287impl Default for AnalyticsBufferConfig {
288 fn default() -> Self {
289 Self {
290 size: default_analytics_buffer_size(),
291 flush_interval_secs: default_analytics_flush_interval(),
292 batch_size: default_analytics_batch_size(),
293 fallback_path: None,
294 }
295 }
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct AnalyticsSamplingConfig {
301 #[serde(default = "default_analytics_sample_rate")]
303 pub rate: f64,
304
305 #[serde(default)]
307 pub always_record_users: Vec<String>,
308}
309
310impl Default for AnalyticsSamplingConfig {
311 fn default() -> Self {
312 Self {
313 rate: default_analytics_sample_rate(),
314 always_record_users: Vec::new(),
315 }
316 }
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct AnalyticsPrivacyConfig {
322 #[serde(default = "default_true")]
324 pub record_peer_ip: bool,
325
326 #[serde(default)]
328 pub full_user_id: bool,
329
330 #[serde(default = "default_analytics_user_id_prefix_len")]
332 pub user_id_prefix_len: usize,
333
334 #[serde(default = "default_true")]
336 pub record_sni: bool,
337}
338
339impl Default for AnalyticsPrivacyConfig {
340 fn default() -> Self {
341 Self {
342 record_peer_ip: true,
343 full_user_id: false,
344 user_id_prefix_len: default_analytics_user_id_prefix_len(),
345 record_sni: true,
346 }
347 }
348}
349
350fn default_analytics_database() -> String {
352 "trojan".to_string()
353}
354
355fn default_analytics_table() -> String {
356 "connections".to_string()
357}
358
359fn default_analytics_buffer_size() -> usize {
360 10000
361}
362
363fn default_analytics_flush_interval() -> u64 {
364 5
365}
366
367fn default_analytics_batch_size() -> usize {
368 1000
369}
370
371fn default_analytics_sample_rate() -> f64 {
372 1.0
373}
374
375fn default_analytics_user_id_prefix_len() -> usize {
376 8
377}
378
379fn default_analytics_connect_timeout() -> u64 {
380 10
381}
382
383fn default_analytics_write_timeout() -> u64 {
384 30
385}
386
387fn default_true() -> bool {
388 true
389}
390
391#[derive(Debug, Clone, Parser, Default)]
392pub struct CliOverrides {
393 #[arg(long)]
395 pub listen: Option<String>,
396 #[arg(long)]
398 pub fallback: Option<String>,
399 #[arg(long)]
401 pub tls_cert: Option<String>,
402 #[arg(long)]
404 pub tls_key: Option<String>,
405 #[arg(long, num_args = 1.., value_delimiter = ',')]
407 pub alpn: Option<Vec<String>>,
408 #[arg(long, num_args = 1.., value_delimiter = ',')]
410 pub password: Option<Vec<String>>,
411 #[arg(long)]
413 pub tcp_idle_timeout_secs: Option<u64>,
414 #[arg(long)]
416 pub udp_timeout_secs: Option<u64>,
417 #[arg(long)]
419 pub max_header_bytes: Option<usize>,
420 #[arg(long)]
422 pub max_udp_payload: Option<usize>,
423 #[arg(long)]
425 pub max_udp_buffer_bytes: Option<usize>,
426 #[arg(long)]
428 pub max_connections: Option<usize>,
429 #[arg(long)]
431 pub metrics_listen: Option<String>,
432 #[arg(long)]
434 pub log_level: Option<String>,
435 #[arg(long)]
437 pub rate_limit_max_per_ip: Option<u32>,
438 #[arg(long)]
440 pub rate_limit_window_secs: Option<u64>,
441 #[arg(long)]
443 pub tls_min_version: Option<String>,
444 #[arg(long)]
446 pub tls_max_version: Option<String>,
447 #[arg(long)]
449 pub tls_client_ca: Option<String>,
450 #[arg(long)]
452 pub relay_buffer_size: Option<usize>,
453 #[arg(long)]
455 pub tcp_send_buffer: Option<usize>,
456 #[arg(long)]
458 pub tcp_recv_buffer: Option<usize>,
459 #[arg(long)]
461 pub connection_backlog: Option<u32>,
462 #[arg(long)]
464 pub ws_enabled: Option<bool>,
465 #[arg(long)]
467 pub ws_mode: Option<String>,
468 #[arg(long)]
470 pub ws_path: Option<String>,
471 #[arg(long)]
473 pub ws_host: Option<String>,
474 #[arg(long)]
476 pub ws_listen: Option<String>,
477 #[arg(long)]
479 pub ws_max_frame_bytes: Option<usize>,
480 #[arg(long)]
482 pub tcp_no_delay: Option<bool>,
483 #[arg(long)]
485 pub tcp_keepalive_secs: Option<u64>,
486 #[arg(long)]
488 pub tcp_reuse_port: Option<bool>,
489 #[arg(long)]
491 pub tcp_fast_open: Option<bool>,
492 #[arg(long)]
494 pub tcp_fast_open_qlen: Option<u32>,
495}
496
497#[derive(Debug, thiserror::Error)]
498pub enum ConfigError {
499 #[error("io: {0}")]
500 Io(#[from] std::io::Error),
501 #[error("json: {0}")]
502 Json(#[from] serde_json::Error),
503 #[error("yaml: {0}")]
504 Yaml(#[from] serde_yaml::Error),
505 #[error("toml: {0}")]
506 Toml(#[from] toml::de::Error),
507 #[error("unsupported config format")]
508 UnsupportedFormat,
509 #[error("validation: {0}")]
510 Validation(String),
511}
512
513pub fn load_config(path: impl AsRef<Path>) -> Result<Config, ConfigError> {
514 let path = path.as_ref();
515 let data = fs::read_to_string(path)?;
516 match path.extension().and_then(|s| s.to_str()).unwrap_or("") {
517 "json" => Ok(serde_json::from_str(&data)?),
518 "yaml" | "yml" => Ok(serde_yaml::from_str(&data)?),
519 "toml" => Ok(toml::from_str(&data)?),
520 _ => Err(ConfigError::UnsupportedFormat),
521 }
522}
523
524pub fn apply_overrides(config: &mut Config, overrides: &CliOverrides) {
525 if let Some(v) = &overrides.listen {
526 config.server.listen = v.clone();
527 }
528 if let Some(v) = &overrides.fallback {
529 config.server.fallback = v.clone();
530 }
531 if let Some(v) = overrides.tcp_idle_timeout_secs {
532 config.server.tcp_idle_timeout_secs = v;
533 }
534 if let Some(v) = overrides.udp_timeout_secs {
535 config.server.udp_timeout_secs = v;
536 }
537 if let Some(v) = overrides.max_header_bytes {
538 config.server.max_header_bytes = v;
539 }
540 if let Some(v) = overrides.max_udp_payload {
541 config.server.max_udp_payload = v;
542 }
543 if let Some(v) = overrides.max_udp_buffer_bytes {
544 config.server.max_udp_buffer_bytes = v;
545 }
546 if let Some(v) = overrides.max_connections {
547 config.server.max_connections = if v == 0 { None } else { Some(v) };
548 }
549 if let Some(v) = &overrides.tls_cert {
550 config.tls.cert = v.clone();
551 }
552 if let Some(v) = &overrides.tls_key {
553 config.tls.key = v.clone();
554 }
555 if let Some(v) = &overrides.alpn {
556 config.tls.alpn = v.clone();
557 }
558 if let Some(v) = &overrides.password {
559 config.auth.passwords = v.clone();
560 }
561 if let Some(v) = &overrides.metrics_listen {
562 config.metrics.listen = Some(v.clone());
563 }
564 if let Some(v) = &overrides.log_level {
565 config.logging.level = Some(v.clone());
566 }
567 if let Some(max) = overrides.rate_limit_max_per_ip {
569 if max == 0 {
570 config.server.rate_limit = None;
571 } else {
572 let rl = config
573 .server
574 .rate_limit
575 .get_or_insert_with(|| RateLimitConfig {
576 max_connections_per_ip: default_rate_limit_max_connections(),
577 window_secs: default_rate_limit_window_secs(),
578 cleanup_interval_secs: default_rate_limit_cleanup_secs(),
579 });
580 rl.max_connections_per_ip = max;
581 }
582 }
583 if let Some(window) = overrides.rate_limit_window_secs
584 && let Some(ref mut rl) = config.server.rate_limit
585 {
586 rl.window_secs = window;
587 }
588 if let Some(v) = &overrides.tls_min_version {
590 config.tls.min_version = v.clone();
591 }
592 if let Some(v) = &overrides.tls_max_version {
593 config.tls.max_version = v.clone();
594 }
595 if let Some(v) = &overrides.tls_client_ca {
596 config.tls.client_ca = Some(v.clone());
597 }
598 if overrides.relay_buffer_size.is_some()
600 || overrides.tcp_send_buffer.is_some()
601 || overrides.tcp_recv_buffer.is_some()
602 || overrides.connection_backlog.is_some()
603 {
604 let rl = config
605 .server
606 .resource_limits
607 .get_or_insert_with(|| ResourceLimitsConfig {
608 relay_buffer_size: default_relay_buffer_size(),
609 tcp_send_buffer: 0,
610 tcp_recv_buffer: 0,
611 connection_backlog: default_connection_backlog(),
612 });
613 if let Some(v) = overrides.relay_buffer_size {
614 rl.relay_buffer_size = v;
615 }
616 if let Some(v) = overrides.tcp_send_buffer {
617 rl.tcp_send_buffer = v;
618 }
619 if let Some(v) = overrides.tcp_recv_buffer {
620 rl.tcp_recv_buffer = v;
621 }
622 if let Some(v) = overrides.connection_backlog {
623 rl.connection_backlog = v;
624 }
625 }
626 if let Some(v) = overrides.ws_enabled {
627 config.websocket.enabled = v;
628 }
629 if let Some(v) = &overrides.ws_mode {
630 config.websocket.mode = v.clone();
631 }
632 if let Some(v) = &overrides.ws_path {
633 config.websocket.path = v.clone();
634 }
635 if let Some(v) = &overrides.ws_host {
636 config.websocket.host = Some(v.clone());
637 }
638 if let Some(v) = &overrides.ws_listen {
639 config.websocket.listen = Some(v.clone());
640 }
641 if let Some(v) = overrides.ws_max_frame_bytes {
642 config.websocket.max_frame_bytes = v;
643 }
644 if let Some(v) = overrides.tcp_no_delay {
646 config.server.tcp.no_delay = v;
647 }
648 if let Some(v) = overrides.tcp_keepalive_secs {
649 config.server.tcp.keepalive_secs = v;
650 }
651 if let Some(v) = overrides.tcp_reuse_port {
652 config.server.tcp.reuse_port = v;
653 }
654 if let Some(v) = overrides.tcp_fast_open {
655 config.server.tcp.fast_open = v;
656 }
657 if let Some(v) = overrides.tcp_fast_open_qlen {
658 config.server.tcp.fast_open_qlen = v;
659 }
660}
661
662pub fn validate_config(config: &Config) -> Result<(), ConfigError> {
663 if config.server.listen.trim().is_empty() {
664 return Err(ConfigError::Validation("server.listen is empty".into()));
665 }
666 if config.server.fallback.trim().is_empty() {
667 return Err(ConfigError::Validation("server.fallback is empty".into()));
668 }
669 if config.tls.cert.trim().is_empty() {
670 return Err(ConfigError::Validation("tls.cert is empty".into()));
671 }
672 if config.tls.key.trim().is_empty() {
673 return Err(ConfigError::Validation("tls.key is empty".into()));
674 }
675 if config.auth.passwords.is_empty() {
676 return Err(ConfigError::Validation("auth.passwords is empty".into()));
677 }
678 if config.server.tcp_idle_timeout_secs == 0 {
679 return Err(ConfigError::Validation(
680 "server.tcp_idle_timeout_secs must be > 0".into(),
681 ));
682 }
683 if config.server.udp_timeout_secs == 0 {
684 return Err(ConfigError::Validation(
685 "server.udp_timeout_secs must be > 0".into(),
686 ));
687 }
688 if config.server.max_header_bytes < min_header_bytes() {
689 return Err(ConfigError::Validation(format!(
690 "server.max_header_bytes too small (min {})",
691 min_header_bytes()
692 )));
693 }
694 if config.server.max_udp_payload == 0 || config.server.max_udp_payload > u16::MAX as usize {
695 return Err(ConfigError::Validation(
696 "server.max_udp_payload must be 1..=65535".into(),
697 ));
698 }
699 if config.server.max_udp_buffer_bytes == 0 {
700 return Err(ConfigError::Validation(
701 "server.max_udp_buffer_bytes must be > 0".into(),
702 ));
703 }
704 if config.server.max_udp_buffer_bytes < config.server.max_udp_payload + 8 {
705 return Err(ConfigError::Validation(
706 "server.max_udp_buffer_bytes must be >= max_udp_payload + 8".into(),
707 ));
708 }
709 let valid_versions = ["tls12", "tls13"];
711 if !valid_versions.contains(&config.tls.min_version.as_str()) {
712 return Err(ConfigError::Validation(format!(
713 "tls.min_version must be one of: {:?}",
714 valid_versions
715 )));
716 }
717 if !valid_versions.contains(&config.tls.max_version.as_str()) {
718 return Err(ConfigError::Validation(format!(
719 "tls.max_version must be one of: {:?}",
720 valid_versions
721 )));
722 }
723 let min_ord = if config.tls.min_version == "tls13" {
725 1
726 } else {
727 0
728 };
729 let max_ord = if config.tls.max_version == "tls13" {
730 1
731 } else {
732 0
733 };
734 if min_ord > max_ord {
735 return Err(ConfigError::Validation(
736 "tls.min_version cannot be greater than tls.max_version".into(),
737 ));
738 }
739 if let Some(ref rl) = config.server.resource_limits {
741 if rl.relay_buffer_size < 1024 {
742 return Err(ConfigError::Validation(
743 "resource_limits.relay_buffer_size must be >= 1024".into(),
744 ));
745 }
746 if rl.relay_buffer_size > 1024 * 1024 {
747 return Err(ConfigError::Validation(
748 "resource_limits.relay_buffer_size must be <= 1MB".into(),
749 ));
750 }
751 if rl.connection_backlog == 0 {
752 return Err(ConfigError::Validation(
753 "resource_limits.connection_backlog must be > 0".into(),
754 ));
755 }
756 }
757 if let Some(ref pool) = config.server.fallback_pool {
758 if pool.max_idle == 0 {
759 return Err(ConfigError::Validation(
760 "fallback_pool.max_idle must be > 0".into(),
761 ));
762 }
763 if pool.max_age_secs == 0 {
764 return Err(ConfigError::Validation(
765 "fallback_pool.max_age_secs must be > 0".into(),
766 ));
767 }
768 if pool.fill_batch == 0 || pool.fill_batch > pool.max_idle {
769 return Err(ConfigError::Validation(
770 "fallback_pool.fill_batch must be 1..=max_idle".into(),
771 ));
772 }
773 }
774 if config.websocket.mode != "mixed" && config.websocket.mode != "split" {
775 return Err(ConfigError::Validation(
776 "websocket.mode must be 'mixed' or 'split'".into(),
777 ));
778 }
779 if config.websocket.path.is_empty() {
780 return Err(ConfigError::Validation("websocket.path is empty".into()));
781 }
782 if config.websocket.enabled
783 && config.websocket.mode == "split"
784 && config.websocket.listen.as_deref().unwrap_or("").is_empty()
785 {
786 return Err(ConfigError::Validation(
787 "websocket.listen is required in split mode".into(),
788 ));
789 }
790 Ok(())
791}
792
793macro_rules! default_fns {
799 ($($fn_name:ident => $const_name:ident : $ty:ty),* $(,)?) => {
801 $(
802 fn $fn_name() -> $ty {
803 defaults::$const_name
804 }
805 )*
806 };
807}
808
809macro_rules! default_string_fns {
811 ($($fn_name:ident => $const_name:ident),* $(,)?) => {
812 $(
813 fn $fn_name() -> String {
814 defaults::$const_name.to_string()
815 }
816 )*
817 };
818}
819
820default_fns! {
821 default_udp_timeout_secs => DEFAULT_UDP_TIMEOUT_SECS: u64,
822 default_tcp_timeout_secs => DEFAULT_TCP_TIMEOUT_SECS: u64,
823 default_max_udp_payload => DEFAULT_MAX_UDP_PAYLOAD: usize,
824 default_max_udp_buffer_bytes => DEFAULT_MAX_UDP_BUFFER_BYTES: usize,
825 default_max_header_bytes => DEFAULT_MAX_HEADER_BYTES: usize,
826 min_header_bytes => MIN_HEADER_BYTES: usize,
827 default_rate_limit_max_connections => DEFAULT_RATE_LIMIT_MAX_CONNECTIONS: u32,
828 default_rate_limit_window_secs => DEFAULT_RATE_LIMIT_WINDOW_SECS: u64,
829 default_rate_limit_cleanup_secs => DEFAULT_RATE_LIMIT_CLEANUP_SECS: u64,
830 default_pool_max_idle => DEFAULT_POOL_MAX_IDLE: usize,
831 default_pool_max_age_secs => DEFAULT_POOL_MAX_AGE_SECS: u64,
832 default_pool_fill_batch => DEFAULT_POOL_FILL_BATCH: usize,
833 default_pool_fill_delay_ms => DEFAULT_POOL_FILL_DELAY_MS: u64,
834 default_relay_buffer_size => DEFAULT_RELAY_BUFFER_SIZE: usize,
835 default_connection_backlog => DEFAULT_CONNECTION_BACKLOG: u32,
836 default_ws_enabled => DEFAULT_WS_ENABLED: bool,
837 default_ws_max_frame_bytes => DEFAULT_WS_MAX_FRAME_BYTES: usize,
838 default_tcp_no_delay => DEFAULT_TCP_NO_DELAY: bool,
840 default_tcp_keepalive_secs => DEFAULT_TCP_KEEPALIVE_SECS: u64,
841 default_tcp_reuse_port => DEFAULT_TCP_REUSE_PORT: bool,
842 default_tcp_fast_open => DEFAULT_TCP_FAST_OPEN: bool,
843 default_tcp_fast_open_qlen => DEFAULT_TCP_FAST_OPEN_QLEN: u32,
844}
845
846default_string_fns! {
847 default_min_tls_version => DEFAULT_TLS_MIN_VERSION,
848 default_max_tls_version => DEFAULT_TLS_MAX_VERSION,
849 default_ws_mode => DEFAULT_WS_MODE,
850 default_ws_path => DEFAULT_WS_PATH,
851}