Skip to main content

platform/config/
signaling.rs

1//! Signaling 服务配置
2
3use crate::config::signer::SignerClientConfig;
4use serde::{Deserialize, Serialize};
5
6/// Signaling 服务配置
7///
8/// Service enable/disable is controlled by the bitmask in ActrixConfig.enable.
9/// The ENABLE_SIGNALING bit (bit 0) must be set to enable this service.
10#[derive(Debug, Serialize, Deserialize, Clone, Default)]
11pub struct SignalingConfig {
12    /// Signaling 服务器配置
13    #[serde(default)]
14    pub server: SignalingServerConfig,
15
16    /// Signaling 的依赖服务配置
17    #[serde(default)]
18    pub dependencies: SignalingDependencies,
19}
20
21/// Signaling 服务器配置
22#[derive(Debug, Serialize, Deserialize, Clone)]
23pub struct SignalingServerConfig {
24    /// WebSocket 路径
25    pub ws_path: String,
26
27    /// 速率限制配置
28    #[serde(default)]
29    pub rate_limit: RateLimitConfig,
30}
31
32/// 速率限制配置
33#[derive(Debug, Serialize, Deserialize, Clone, Default)]
34pub struct RateLimitConfig {
35    /// 连接速率限制配置
36    #[serde(default)]
37    pub connection: ConnectionRateLimit,
38
39    /// 消息速率限制配置
40    #[serde(default)]
41    pub message: MessageRateLimit,
42}
43
44/// 连接速率限制配置
45#[derive(Debug, Serialize, Deserialize, Clone)]
46pub struct ConnectionRateLimit {
47    /// 是否启用连接速率限制
48    #[serde(default = "default_true")]
49    pub enabled: bool,
50
51    /// 每分钟允许的新连接数
52    #[serde(default = "default_connections_per_minute")]
53    pub per_minute: u32,
54
55    /// 突发允许的连接数
56    #[serde(default = "default_connection_burst")]
57    pub burst_size: u32,
58
59    /// 每个 IP 的最大并发连接数
60    #[serde(default = "default_max_concurrent_connections")]
61    pub max_concurrent_per_ip: u32,
62}
63
64/// 消息速率限制配置
65#[derive(Debug, Serialize, Deserialize, Clone)]
66pub struct MessageRateLimit {
67    /// 是否启用消息速率限制
68    #[serde(default = "default_true")]
69    pub enabled: bool,
70
71    /// 每秒允许的消息数
72    #[serde(default = "default_messages_per_second")]
73    pub per_second: u32,
74
75    /// 突发允许的消息数
76    #[serde(default = "default_message_burst")]
77    pub burst_size: u32,
78}
79
80// 默认值函数
81fn default_true() -> bool {
82    true
83}
84
85fn default_connections_per_minute() -> u32 {
86    5
87}
88
89fn default_connection_burst() -> u32 {
90    10
91}
92
93fn default_max_concurrent_connections() -> u32 {
94    100
95}
96
97fn default_messages_per_second() -> u32 {
98    10
99}
100
101fn default_message_burst() -> u32 {
102    50
103}
104
105/// Signaling 依赖的外部服务
106#[derive(Debug, Serialize, Deserialize, Clone, Default)]
107pub struct SignalingDependencies {
108    /// Signer 客户端配置(可选,如果需要加密)
109    ///
110    /// 如果未配置但需要 Signer,会自动查找本地 Signer 服务:
111    /// - 如果 Signer 服务已启用(ENABLE_SIGNER 位已设置),使用 localhost:SIGNER_PORT
112    /// - 否则返回 None(Signaling 可以不依赖 Signer)
113    #[serde(default)]
114    pub signer: Option<SignerClientConfig>,
115
116    /// AIS 客户端配置(可选,用于 Credential 刷新)
117    ///
118    /// 如果未配置但需要 AIS,会自动查找本地 AIS 服务:
119    /// - 如果 AIS 服务已启用(ENABLE_AIS 位已设置),使用 localhost:AIS_PORT
120    /// - 否则返回 None
121    #[serde(default)]
122    pub ais: Option<AisClientConfig>,
123}
124
125/// AIS 客户端配置
126#[derive(Debug, Serialize, Deserialize, Clone)]
127pub struct AisClientConfig {
128    /// AIS 服务端点 URL
129    pub endpoint: String,
130    /// 请求超时时间(秒)
131    #[serde(default = "default_timeout")]
132    pub timeout_seconds: u64,
133}
134
135fn default_timeout() -> u64 {
136    30
137}
138
139impl Default for SignalingServerConfig {
140    fn default() -> Self {
141        Self {
142            ws_path: "/signaling".to_string(),
143            rate_limit: RateLimitConfig::default(),
144        }
145    }
146}
147
148impl Default for ConnectionRateLimit {
149    fn default() -> Self {
150        Self {
151            enabled: default_true(),
152            per_minute: default_connections_per_minute(),
153            burst_size: default_connection_burst(),
154            max_concurrent_per_ip: default_max_concurrent_connections(),
155        }
156    }
157}
158
159impl Default for MessageRateLimit {
160    fn default() -> Self {
161        Self {
162            enabled: default_true(),
163            per_second: default_messages_per_second(),
164            burst_size: default_message_burst(),
165        }
166    }
167}
168
169impl SignalingConfig {
170    /// 获取 Signer 客户端配置
171    ///
172    /// 支持智能默认:
173    /// 1. 如果显式配置了 dependencies.signer,直接返回
174    /// 2. 如果本地启用了 Signer 服务,返回指向本地 Signer 的配置
175    /// 3. 否则返回 None(Signaling 可以不依赖 Signer)
176    pub fn get_signer_client_config(
177        &self,
178        global_config: &super::ActrixConfig,
179    ) -> Option<SignerClientConfig> {
180        // 优先使用显式配置
181        if let Some(ref signer_config) = self.dependencies.signer {
182            return Some(signer_config.clone());
183        }
184
185        // 回退:检查是否启用了本地 Signer 服务
186        if global_config.is_signer_enabled() && global_config.services.signer.is_some() {
187            // 自动生成指向本地 Signer 的客户端配置
188            // Signer gRPC 复用实例主 HTTP/HTTPS 端口
189            let http_cfg = global_config.bind.http.as_ref();
190            let port = http_cfg.map(|h| h.port).unwrap_or(8080);
191            let use_tls = http_cfg.is_some_and(|h| h.is_tls());
192            let protocol = if use_tls { "https" } else { "http" };
193            let tls_domain = if use_tls {
194                http_cfg.map(|h| h.domain_name.clone())
195            } else {
196                None
197            };
198
199            return Some(SignerClientConfig {
200                endpoint: format!("{protocol}://127.0.0.1:{port}"),
201                timeout_seconds: 30,
202                enable_tls: use_tls,
203                tls_domain,
204                ca_cert: None,
205                client_cert: None,
206                client_key: None,
207            });
208        }
209
210        None
211    }
212
213    /// 获取 AIS 客户端配置
214    ///
215    /// 支持智能默认:
216    /// 1. 如果显式配置了 dependencies.ais,直接返回
217    /// 2. 如果本地启用了 AIS 服务,返回指向本地 AIS 的配置
218    /// 3. 否则返回 None
219    pub fn get_ais_client_config(
220        &self,
221        global_config: &super::ActrixConfig,
222    ) -> Option<AisClientConfig> {
223        // 优先使用显式配置
224        if let Some(ref ais_config) = self.dependencies.ais {
225            return Some(ais_config.clone());
226        }
227
228        // 回退:检查是否启用了本地 AIS 服务
229        if global_config.is_ais_enabled() && global_config.services.ais.is_some() {
230            // 自动生成指向本地 AIS 的客户端配置
231            // AIS 作为 HTTP router service 共享同一个 HTTP/HTTPS 端口
232            let http_cfg = global_config.bind.http.as_ref();
233            let port = http_cfg.map(|h| h.port).unwrap_or(8080);
234            let protocol = if http_cfg.is_some_and(|h| h.is_tls()) {
235                "https"
236            } else {
237                "http"
238            };
239
240            return Some(AisClientConfig {
241                endpoint: format!("{protocol}://127.0.0.1:{port}"),
242                timeout_seconds: 30,
243            });
244        }
245
246        None
247    }
248}