Skip to main content

futu_backend/auth/commconfig/
types.rs

1//! auth/commconfig/types — type aliases / consts / structs
2//! (v1.4.110 CC Batch M: 拆自 commconfig.rs L78-181)
3
4use std::collections::HashMap;
5
6use crate::auth::UserAttribution;
7
8/// TOTP 密钥(base32)——C++ `NNBiz_CommonConfig.cpp:10`
9///
10/// 这个 key 不是每个用户独立的——整个 FutuOpenD 客户端都用这一个固定值。
11/// 服务端拿 `uid + svr_time/30 → HMAC-SHA1 → TOTP` 反向校验。
12pub(super) const AUTH_TOKEN_KEY_B32: &str = "PEHMABDNLXIOG65U";
13
14/// 解析后的 Platform 部分 `guaranteed_ip_for_conn` —— attribution → IP 列表。
15pub type GuaranteedIpMap = HashMap<UserAttribution, Vec<(String, u16)>>;
16
17/// 解析后的 Broker 部分 `guaranteed_ip_for_conn` —— broker_id → IP 列表。
18/// key 是 `FTConnCmn.proto` `ConnIdentity` 里的 `CONN_BROKER_FUTU_*` 值
19/// (1001=HK / 1007=US / 1008=SG / 1009=AU / 1012=JP / 1017=MY / 1019=CA)。
20pub type GuaranteedBrokerIpMap = HashMap<u32, Vec<(String, u16)>>;
21
22/// 解析后的 WebTCP-short 部分 `guaranteed_ip_for_conn` —— web conn_identity → IP 列表。
23/// key 是 `FTConnCmn.proto` `CONN_WEB_*` 的 10100..10107。
24pub type GuaranteedWebIpMap = HashMap<u32, Vec<(String, u16)>>;
25
26/// 解析后的 `auth_guaranteed_domain_list` —— 原始鉴权域名 → 兜底域名。
27///
28/// 对齐 C++ `FTAuthImpl::GetRetryDomain()`:先查 CommConfig
29/// `auth_guaranteed_domain_list`,没有动态配置时才使用本地 HK fallback。
30pub type AuthGuaranteedDomainMap = HashMap<String, String>;
31
32pub const CONN_WEB_CN: u32 = 10100;
33pub const CONN_WEB_HK: u32 = 10101;
34pub const CONN_WEB_US: u32 = 10102;
35pub const CONN_WEB_SG: u32 = 10103;
36pub const CONN_WEB_AU: u32 = 10104;
37pub const CONN_WEB_JP: u32 = 10105;
38pub const CONN_WEB_MY: u32 = 10106;
39pub const CONN_WEB_CA: u32 = 10107;
40
41/// 解析后的 `forced_ip_for_conn` —— identity → (ip, port, expire_ts)。
42///
43/// 对齐 C++ `address.cpp:398-400` 的 `forced_ip_map_` —— 每个 identity 只
44/// 有**一个**强制 IP(不是数组),带 `expire` 时间戳。过期后忽略,走
45/// guaranteed_ip / 通道专属 fallback 链。
46pub type ForcedIpMap = HashMap<UserAttribution, ForcedIpEntry>;
47
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct ForcedIpEntry {
50    pub ip: String,
51    pub port: u16,
52    /// Unix 时间戳(秒),0 表示无过期(保守处理为立即过期)。
53    pub expire_ts: i64,
54}
55
56impl ForcedIpEntry {
57    /// 当前是否仍然有效(now < expire_ts)。
58    pub fn is_valid(&self, now_ts: i64) -> bool {
59        self.expire_ts > 0 && now_ts < self.expire_ts
60    }
61}
62
63/// CommConfig 协议返回的完整快照(含过期时间)。
64#[derive(Debug, Clone)]
65pub struct CommonConfigSnapshot {
66    /// 按 attribution 分组的 Platform guaranteed IP 池(identity 1-6)。
67    pub guaranteed_ip: GuaranteedIpMap,
68    /// 按 broker_id 分组的 **Broker 通道** guaranteed IP 池(identity
69    /// 1001/1007/1008/1009/1012/1017/1019)。v1.4.26 起对齐 C++
70    /// `ChannelAddressManager::guaranteed_ip_map_` 完整收集 —— broker
71    /// CMD 1001 登录必须连对 IP,不然服务端按 customer_id 返**错 broker 的
72    /// 账户列表**(2026-04-17 实测:broker 1001 连到 Platform US IP 时
73    /// 返回的是 broker 1007 的账户)。
74    pub guaranteed_ip_broker: GuaranteedBrokerIpMap,
75    /// 按 web conn_identity 分组的 **WebTCP-short** guaranteed IP 池
76    /// (identity 10100..10107)。broker_auth 在 C++ 中先走 WebTCP-short,
77    /// 这里保留服务端下发 IP,避免走系统 DNS。
78    pub guaranteed_ip_web: GuaranteedWebIpMap,
79    /// C++ `WebRequestManager` 使用的全局 WebTCP-short identity。
80    ///
81    /// Ref:
82    /// - `FTLogin/Src/ftlogin/channel/impl/web_request_mgr.cpp:251-275`
83    /// - `FTLogin/Src/ftlogin/channel/impl/web_request_mgr.cpp:635-656`
84    ///
85    /// 这是整个客户端的 Web 通道 identity,不是按 broker_id 选择。broker auth
86    /// 虽然请求的是 `authority.us.moomoo.com` / `authority.sg.moomoo.com`
87    /// 等 broker 域名,WebTCP-short 连接目标仍由这个全局 identity 决定。
88    pub web_conn_identity: Option<u32>,
89    /// C++ `FTAuthImpl::GetRetryDomain()` 使用的动态鉴权兜底域名表。
90    ///
91    /// key 是原始鉴权域名(如 `authority.us.moomoo.com`),value 是
92    /// WebTCP/HTTP 失败后的 retry-domain 阶段使用的域名。没有服务端下发
93    /// 时,broker_auth 只使用 C++ 本地 HK fallback。
94    pub auth_guaranteed_domains: AuthGuaranteedDomainMap,
95    /// `auth_guaranteed_domain_list` 是否以有效 JSON object 形式下发过。
96    ///
97    /// C++ 在配置可解析但缺少当前域名 key 时返回空 retry-domain,不再使用
98    /// 本地 HK fallback;只有配置缺失或解析失败时才走本地 fallback。
99    pub auth_guaranteed_domains_configured: bool,
100    /// 按 attribution 分组的 forced IP(优先级最高,**未过期时绕过所有
101    /// fallback 直接用这个 IP**,对齐 C++ `GetStrategyAddressInfo` 的
102    /// "if (forced_ip && !expired) return forced_ip;")。
103    pub forced_ip: ForcedIpMap,
104    /// 下次整体刷新的 Unix 时间戳(秒)。`limit_time` 累加当前时间。
105    pub next_refresh_ts: i64,
106}