Skip to main content

futu_backend/
proto_handler.rs

1// 内部协议处理框架
2//
3// 管理内部协议命令 ID 到处理函数的映射。
4// 用于处理后端推送和请求转发。
5
6use std::collections::HashMap;
7use std::sync::Arc;
8
9use async_trait::async_trait;
10use bytes::Bytes;
11use parking_lot::RwLock;
12
13/// 内部协议命令 ID 常量(对应 C++ NNBase_Define_ProtoCmd.h)
14pub mod nn_cmd {
15    // 登录/连接
16    pub const MAIN_LOGIN: u16 = 1001;
17    pub const SUB_LOGIN: u16 = 6001;
18    pub const MAIN_HEARTBEAT: u16 = 1003;
19    pub const SUB_HEARTBEAT: u16 = 6003;
20    pub const SESSION_KEY: u16 = 1004;
21    pub const SVR_NOTIFY: u16 = 1005;
22    pub const ERROR_CODE: u16 = 1306;
23    pub const PING: u16 = 1316;
24    pub const CONN_POINT: u16 = 1321;
25
26    // 行情
27    pub const QOT_PUSH: u16 = 6212;
28    pub const QOT_RIGHT: u16 = 6006;
29    pub const QOT_SUB: u16 = 6211;
30    pub const QOT_PULL_TICKER: u16 = 6128;
31    pub const QOT_PULL_TIMESHARE: u16 = 6160;
32    pub const QOT_PULL_KLINE: u16 = 6161;
33    pub const QOT_PULL_SEC_LIST: u16 = 6515;
34    pub const QOT_PULL_CAPITAL_DIST: u16 = 6514;
35    pub const QOT_PULL_CAPITAL_FLOW: u16 = 6516;
36    pub const QOT_MARKET_STATUS: u16 = 6823;
37
38    // 交易
39    pub const QUERY_ACC_LIST: u16 = 2008;
40    pub const TRD_HK_ORDER_PLACE: u16 = 2211;
41    pub const TRD_HK_ORDER_CHANGE: u16 = 2212;
42    pub const TRD_HK_ORDER_LIST: u16 = 2201;
43    pub const TRD_HK_DEAL_LIST: u16 = 2101;
44    pub const TRD_HK_ACC_INFO: u16 = 2023;
45}
46
47/// 推送处理器 trait
48#[async_trait]
49pub trait NNPushHandler: Send + Sync + 'static {
50    /// 处理后端推送
51    async fn on_push(&self, cmd_id: u16, body: Bytes);
52}
53
54/// 内部协议处理器注册表
55pub struct NNProtoRegistry {
56    push_handlers: RwLock<HashMap<u16, Arc<dyn NNPushHandler>>>,
57}
58
59impl NNProtoRegistry {
60    pub fn new() -> Self {
61        Self {
62            push_handlers: RwLock::new(HashMap::new()),
63        }
64    }
65
66    /// 注册推送处理器
67    pub fn register_push_handler(&self, cmd_id: u16, handler: Arc<dyn NNPushHandler>) {
68        self.push_handlers.write().insert(cmd_id, handler);
69    }
70
71    /// 分发推送
72    pub async fn dispatch_push(&self, cmd_id: u16, body: Bytes) {
73        let handler = {
74            let handlers = self.push_handlers.read();
75            handlers.get(&cmd_id).cloned()
76        };
77
78        if let Some(h) = handler {
79            h.on_push(cmd_id, body).await;
80        } else {
81            tracing::debug!(cmd_id = cmd_id, "unhandled backend push");
82        }
83    }
84}
85
86impl Default for NNProtoRegistry {
87    fn default() -> Self {
88        Self::new()
89    }
90}