network-infra-utility 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/GUIDE.md +212 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +70 -0
  6. data/Rakefile +1 -1
  7. data/bin/dns-query +836 -0
  8. data/bin/geo-doc +135 -0
  9. data/bin/geo-get +1 -1
  10. data/bin/geo-update +429 -0
  11. data/document/ASNum/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +242 -0
  12. data/document/DNSQuery/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +248 -0
  13. data/document/Geo/345/221/275/344/273/244/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +441 -0
  14. data/document/IP/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +297 -0
  15. data/document/MAC/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +296 -0
  16. data/document/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/344/275/277/347/224/250/346/226/271/346/263/225.md +764 -0
  17. data/network-infra-utility.gemspec +4 -2
  18. data/network.rb +3 -1
  19. data/service/geodb/geodb.rb +278 -1
  20. data/service/ssh/README.md +955 -0
  21. data/service/ssh/bin/ssh-client +198 -0
  22. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/345/212/237/350/203/275/351/234/200/346/261/202/346/226/207/346/241/243.md +292 -0
  23. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/257/246/347/273/206/350/256/276/350/256/241/346/226/207/346/241/243.md +1521 -0
  24. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/275/257/344/273/266/350/256/276/350/256/241/346/226/207/346/241/243.md +2493 -0
  25. data/service/ssh/ext/ssh_core/bin/ssh_core.cmd +28 -0
  26. data/service/ssh/ext/ssh_core/config/sys.config +0 -0
  27. data/service/ssh/ext/ssh_core/config/vm.args +0 -0
  28. data/service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM +1 -0
  29. data/service/ssh/ext/ssh_core/local_deps/jsx/LICENSE +21 -0
  30. data/service/ssh/ext/ssh_core/local_deps/jsx/README.md +696 -0
  31. data/service/ssh/ext/ssh_core/local_deps/jsx/VERSION +1 -0
  32. data/service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz +0 -0
  33. data/service/ssh/ext/ssh_core/local_deps/jsx/metadata.config +15 -0
  34. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.config +17 -0
  35. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock +1 -0
  36. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src +10 -0
  37. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl +506 -0
  38. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl +393 -0
  39. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl +18 -0
  40. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl +81 -0
  41. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl +1909 -0
  42. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl +116 -0
  43. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl +1214 -0
  44. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl +408 -0
  45. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl +389 -0
  46. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl +121 -0
  47. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl +506 -0
  48. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl +393 -0
  49. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl +18 -0
  50. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl +81 -0
  51. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl +1909 -0
  52. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl +116 -0
  53. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl +1214 -0
  54. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl +408 -0
  55. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl +389 -0
  56. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl +121 -0
  57. data/service/ssh/ext/ssh_core/rebar.config +24 -0
  58. data/service/ssh/ext/ssh_core/rebar.lock +1 -0
  59. data/service/ssh/ext/ssh_core/src/ssh_auth_engine.erl +156 -0
  60. data/service/ssh/ext/ssh_core/src/ssh_channel_stm.erl +232 -0
  61. data/service/ssh/ext/ssh_core/src/ssh_codec.erl +83 -0
  62. data/service/ssh/ext/ssh_core/src/ssh_conn_sup.erl +48 -0
  63. data/service/ssh/ext/ssh_core/src/ssh_conn_worker.erl +535 -0
  64. data/service/ssh/ext/ssh_core/src/ssh_core.app.src +36 -0
  65. data/service/ssh/ext/ssh_core/src/ssh_core_app.erl +11 -0
  66. data/service/ssh/ext/ssh_core/src/ssh_core_sup.erl +46 -0
  67. data/service/ssh/ext/ssh_core/src/ssh_infra_sup.erl +117 -0
  68. data/service/ssh/ext/ssh_core/src/ssh_ipc.hrl +80 -0
  69. data/service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl +94 -0
  70. data/service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl +467 -0
  71. data/service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl +95 -0
  72. data/service/ssh/ext/ssh_core/src/ssh_jump_chain.erl +101 -0
  73. data/service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl +222 -0
  74. data/service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl +67 -0
  75. data/service/ssh/ext/ssh_core/src/ssh_port_fwd.erl +225 -0
  76. data/service/ssh/ext/ssh_core/src/ssh_sftp_session.erl +250 -0
  77. data/service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl +62 -0
  78. data/service/ssh/ext/ssh_core_rs/Cargo.lock +2345 -0
  79. data/service/ssh/ext/ssh_core_rs/Cargo.toml +30 -0
  80. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs +34 -0
  81. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd +40 -0
  82. data/service/ssh/ext/ssh_core_rs/src/channel.rs +296 -0
  83. data/service/ssh/ext/ssh_core_rs/src/coalesce.rs +143 -0
  84. data/service/ssh/ext/ssh_core_rs/src/codec.rs +71 -0
  85. data/service/ssh/ext/ssh_core_rs/src/conn.rs +628 -0
  86. data/service/ssh/ext/ssh_core_rs/src/gateway.rs +389 -0
  87. data/service/ssh/ext/ssh_core_rs/src/handler.rs +293 -0
  88. data/service/ssh/ext/ssh_core_rs/src/keepalive.rs +194 -0
  89. data/service/ssh/ext/ssh_core_rs/src/main.rs +351 -0
  90. data/service/ssh/ext/ssh_core_rs/src/portfwd.rs +378 -0
  91. data/service/ssh/ext/ssh_core_rs/src/proto.rs +198 -0
  92. data/service/ssh/ext/ssh_core_rs/src/sftp.rs +294 -0
  93. data/service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb +213 -0
  94. data/service/ssh/lib/network_infra_utility/ssh/client.rb +257 -0
  95. data/service/ssh/lib/network_infra_utility/ssh/config/schema.rb +90 -0
  96. data/service/ssh/lib/network_infra_utility/ssh/config/settings.rb +103 -0
  97. data/service/ssh/lib/network_infra_utility/ssh/config/store.rb +90 -0
  98. data/service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb +83 -0
  99. data/service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb +36 -0
  100. data/service/ssh/lib/network_infra_utility/ssh/ipc/router.rb +212 -0
  101. data/service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb +81 -0
  102. data/service/ssh/lib/network_infra_utility/ssh/security/host_key.rb +211 -0
  103. data/service/ssh/lib/network_infra_utility/ssh/security/vault.rb +211 -0
  104. data/service/ssh/lib/network_infra_utility/ssh/session/history.rb +56 -0
  105. data/service/ssh/lib/network_infra_utility/ssh/session/manager.rb +92 -0
  106. data/service/ssh/lib/network_infra_utility/ssh/session/session.rb +109 -0
  107. data/service/ssh/lib/network_infra_utility/ssh/session/tree.rb +95 -0
  108. data/service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb +435 -0
  109. data/service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb +78 -0
  110. data/service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb +159 -0
  111. data/service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb +195 -0
  112. data/service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb +212 -0
  113. data/service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb +127 -0
  114. data/service/ssh/lib/network_infra_utility/ssh/version.rb +7 -0
  115. data/service/ssh/lib/network_infra_utility/ssh.rb +44 -0
  116. data/support/basic/as_num.rb +221 -0
  117. data/support/basic/mac_address.rb +281 -0
  118. data/version.rb +1 -1
  119. metadata +142 -1
@@ -0,0 +1,194 @@
1
+ //! 保活管理器 — 周期性检查所有活动连接,发送 keepalive 心跳。
2
+ //! 对应 Erlang 端的 ssh_keepalive_mgr.erl。
3
+ //!
4
+ //! 核心设计(与 Erlang 端完全对齐):
5
+ //! - 定时扫描所有 Ready 状态的连接,发送 keepalive 全局请求
6
+ //! - 连续 KEEPALIVE_MAX_FAIL(3)次失败 → 推送 conn.closed
7
+ //! - 重连决策由 Ruby 决定(通过 conn.reconnect RPC),核心不自主重连
8
+ //! - 活动感知:有数据流时跳过心跳(简化版:由 channel.rs 通知活动)
9
+ //!
10
+ //! RPC 方法:
11
+ //! - keepalive.set_interval:设置心跳间隔
12
+ //! - keepalive.get_interval:获取当前间隔
13
+ //! - keepalive.get_status:获取所有连接的保活状态
14
+
15
+ use std::collections::HashMap;
16
+ use std::sync::Arc;
17
+ use std::time::Duration;
18
+
19
+ use serde_json::{json, Value};
20
+ use tokio::sync::{Mutex, RwLock};
21
+ use tracing::{debug, warn};
22
+
23
+ use crate::codec;
24
+ use crate::conn::ConnManager;
25
+ use crate::gateway::Gateway;
26
+ use crate::proto;
27
+
28
+ /// 默认保活间隔(毫秒)
29
+ const KEEPALIVE_DEFAULT_INTERVAL_MS: u64 = 30_000;
30
+
31
+ /// 最大连续失败次数
32
+ const KEEPALIVE_MAX_FAIL: u32 = 3;
33
+
34
+ /// 保活管理器
35
+ pub struct KeepaliveMgr {
36
+ /// 心跳间隔(毫秒)
37
+ interval_ms: RwLock<u64>,
38
+ /// 失败计数:conn_id → count
39
+ fail_counts: Mutex<HashMap<String, u32>>,
40
+ /// 最近活动时间戳:conn_id → unix_ms
41
+ last_activity: Mutex<HashMap<String, u64>>,
42
+ /// 上次检查时间戳:conn_id → unix_ms
43
+ last_check: Mutex<HashMap<String, u64>>,
44
+ /// 连接管理器引用
45
+ conn_mgr: Arc<ConnManager>,
46
+ /// 网关引用
47
+ gateway: Arc<Gateway>,
48
+ }
49
+
50
+ impl KeepaliveMgr {
51
+ pub fn new(conn_mgr: Arc<ConnManager>, gateway: Arc<Gateway>) -> Arc<Self> {
52
+ Arc::new(Self {
53
+ interval_ms: RwLock::new(KEEPALIVE_DEFAULT_INTERVAL_MS),
54
+ fail_counts: Mutex::new(HashMap::new()),
55
+ last_activity: Mutex::new(HashMap::new()),
56
+ last_check: Mutex::new(HashMap::new()),
57
+ conn_mgr,
58
+ gateway,
59
+ })
60
+ }
61
+
62
+ /// 启动保活循环
63
+ pub fn start(self: &Arc<Self>) {
64
+ let this = Arc::clone(self);
65
+ tokio::spawn(async move {
66
+ this.run_loop().await;
67
+ });
68
+ }
69
+
70
+ /// 保活主循环
71
+ async fn run_loop(&self) {
72
+ loop {
73
+ let ms = *self.interval_ms.read().await;
74
+ tokio::time::sleep(Duration::from_millis(ms)).await;
75
+ self.tick().await;
76
+ }
77
+ }
78
+
79
+ /// 单次保活检查
80
+ async fn tick(&self) {
81
+ let now = codec::unix_ms();
82
+ let conn_ids = self.conn_mgr.ready_conn_ids().await;
83
+
84
+ // 记录检查时间
85
+ {
86
+ let mut checks = self.last_check.lock().await;
87
+ for id in &conn_ids {
88
+ checks.insert(id.clone(), now);
89
+ }
90
+ }
91
+
92
+ for conn_id in &conn_ids {
93
+ self.check_keepalive(conn_id).await;
94
+ }
95
+
96
+ // 清理已断开的连接
97
+ let active_ids: std::collections::HashSet<String> = conn_ids.into_iter().collect();
98
+ {
99
+ let mut fails = self.fail_counts.lock().await;
100
+ fails.retain(|k, _| active_ids.contains(k));
101
+ }
102
+ {
103
+ let mut acts = self.last_activity.lock().await;
104
+ acts.retain(|k, _| active_ids.contains(k));
105
+ }
106
+ }
107
+
108
+ /// 检查单个连接的保活
109
+ async fn check_keepalive(&self, conn_id: &str) {
110
+ // 发送 keepalive 全局请求
111
+ let handle = self.conn_mgr.get_handle(conn_id).await;
112
+ if handle.is_none() {
113
+ // 连接已断开
114
+ return;
115
+ }
116
+ let handle = handle.unwrap();
117
+
118
+ let result = handle
119
+ .send_keepalive(true)
120
+ .await;
121
+
122
+ match result {
123
+ Ok(_) => {
124
+ // 成功——重置失败计数
125
+ self.fail_counts.lock().await.remove(conn_id);
126
+ debug!("keepalive ok for conn {}", conn_id);
127
+ }
128
+ Err(e) => {
129
+ let mut fails = self.fail_counts.lock().await;
130
+ let count = fails.entry(conn_id.to_string()).or_insert(0);
131
+ *count += 1;
132
+
133
+ if *count >= KEEPALIVE_MAX_FAIL {
134
+ warn!(
135
+ "conn {} keepalive failed {}/{}: {}, marking closed",
136
+ conn_id, *count, KEEPALIVE_MAX_FAIL, e
137
+ );
138
+ drop(fails);
139
+ self.conn_mgr
140
+ .mark_conn_closed(conn_id, "keepalive_failed")
141
+ .await;
142
+ } else {
143
+ warn!(
144
+ "conn {} keepalive failed {}/{}: {}",
145
+ conn_id, *count, KEEPALIVE_MAX_FAIL, e
146
+ );
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ /// 通知活动(由 channel.rs 在数据收发时调用)
153
+ pub async fn notify_activity(&self, conn_id: &str) {
154
+ let now = codec::unix_ms();
155
+ self.last_activity.lock().await.insert(conn_id.to_string(), now);
156
+ self.fail_counts.lock().await.remove(conn_id);
157
+ }
158
+
159
+ /// RPC: keepalive.set_interval
160
+ pub async fn rpc_set_interval(&self, params: Value) -> Result<Value, String> {
161
+ let interval_ms = proto::get_num(&params, "interval_ms")
162
+ .ok_or("missing interval_ms")? as u64;
163
+ *self.interval_ms.write().await = interval_ms;
164
+ Ok(json!({"ok": true}))
165
+ }
166
+
167
+ /// RPC: keepalive.get_interval
168
+ pub async fn rpc_get_interval(&self, _params: Value) -> Result<Value, String> {
169
+ let ms = *self.interval_ms.read().await;
170
+ Ok(json!({"interval_ms": ms}))
171
+ }
172
+
173
+ /// RPC: keepalive.get_status
174
+ pub async fn rpc_get_status(&self, _params: Value) -> Result<Value, String> {
175
+ let fails = self.fail_counts.lock().await;
176
+ let acts = self.last_activity.lock().await;
177
+ let checks = self.last_check.lock().await;
178
+
179
+ let conn_ids = self.conn_mgr.all_conn_ids().await;
180
+ let status: Vec<Value> = conn_ids
181
+ .iter()
182
+ .map(|id| {
183
+ json!({
184
+ "conn_id": id,
185
+ "fail_count": fails.get(id).copied().unwrap_or(0),
186
+ "last_activity": acts.get(id).copied().unwrap_or(0),
187
+ "last_check": checks.get(id).copied().unwrap_or(0),
188
+ })
189
+ })
190
+ .collect();
191
+
192
+ Ok(json!({"connections": status}))
193
+ }
194
+ }
@@ -0,0 +1,351 @@
1
+ //! SSH Core RS — 主入口
2
+ //! 对应 Erlang 端的 ssh_core_app.erl + ssh_infra_sup.erl + ssh_ipc_gateway.erl:start_link/1。
3
+ //!
4
+ //! 启动流程:
5
+ //! 1. 生成 auth_token
6
+ //! 2. 删除旧的端点文件
7
+ //! 3. 创建 Gateway(TCP 监听 127.0.0.1:0,分配端口)
8
+ //! 4. 写入端点文件(tcp://127.0.0.1:port\n auth_token)
9
+ //! 5. 创建 ConnManager、Coalescer、ChannelManager、KeepaliveMgr
10
+ //! 6. 注册所有 RPC 路由
11
+ //! 7. 启动 coalesce tick 循环和 keepalive 循环
12
+ //! 8. 进入 gateway accept 循环(阻塞)
13
+
14
+ mod codec;
15
+ mod coalesce;
16
+ mod channel;
17
+ mod conn;
18
+ mod gateway;
19
+ mod handler;
20
+ mod keepalive;
21
+ mod portfwd;
22
+ mod proto;
23
+ mod sftp;
24
+
25
+ use std::path::PathBuf;
26
+ use std::sync::Arc;
27
+
28
+ use serde_json::{json, Value};
29
+ use tracing::{error, info};
30
+
31
+ use channel::ChannelManager;
32
+ use conn::ConnManager;
33
+ use gateway::Gateway;
34
+ use keepalive::KeepaliveMgr;
35
+ use coalesce::Coalescer;
36
+ use portfwd::PortFwdManager;
37
+ use sftp::SftpManager;
38
+ use std::time::Instant;
39
+
40
+ /// 端点文件路径:与 Erlang 端完全一致
41
+ /// Windows: %TEMP%\ssh_core_<USERNAME>.endpoint
42
+ /// Unix: /tmp/ssh_core_<uid>.endpoint
43
+ fn endpoint_file_path() -> PathBuf {
44
+ let tmp = std::env::temp_dir();
45
+ let uid = if cfg!(windows) {
46
+ std::env::var("USERNAME").unwrap_or_else(|_| "default".to_string())
47
+ } else {
48
+ std::env::var("UID").unwrap_or_else(|_| {
49
+ // 尝试通过 id -u 获取 uid
50
+ std::process::Command::new("id")
51
+ .arg("-u")
52
+ .output()
53
+ .ok()
54
+ .and_then(|o| String::from_utf8(o.stdout).ok())
55
+ .map(|s| s.trim().to_string())
56
+ .unwrap_or_else(|| "0".to_string())
57
+ })
58
+ };
59
+ tmp.join(format!("ssh_core_{}.endpoint", uid))
60
+ }
61
+
62
+ #[tokio::main]
63
+ async fn main() {
64
+ // 初始化日志
65
+ tracing_subscriber::fmt()
66
+ .with_env_filter(
67
+ tracing_subscriber::EnvFilter::try_from_default_env()
68
+ .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
69
+ )
70
+ .init();
71
+
72
+ info!("ssh_core_rs starting up...");
73
+
74
+ // 0. 记录启动时间(用于 engine.stats 的 uptime_ms)
75
+ let start_time = Instant::now();
76
+
77
+ // 1. 生成 auth_token
78
+ let auth_token = codec::gen_auth_token();
79
+
80
+ // 2. 删除旧端点文件
81
+ let endpoint_file = endpoint_file_path();
82
+ if endpoint_file.exists() {
83
+ let _ = std::fs::remove_file(&endpoint_file);
84
+ }
85
+ info!("endpoint file: {}", endpoint_file.display());
86
+
87
+ // 3. 创建 Gateway
88
+ let gateway = Gateway::new(auth_token);
89
+
90
+ // 4. 创建各管理器
91
+ let conn_mgr = ConnManager::new(Arc::clone(&gateway));
92
+ let coalesce = Coalescer::new(Arc::clone(&gateway));
93
+ let channel_mgr = ChannelManager::new(Arc::clone(&conn_mgr), Arc::clone(&coalesce));
94
+ let keepalive_mgr = KeepaliveMgr::new(Arc::clone(&conn_mgr), Arc::clone(&gateway));
95
+ let sftp_mgr = SftpManager::new(Arc::clone(&conn_mgr));
96
+ let portfwd_mgr = PortFwdManager::new(Arc::clone(&conn_mgr));
97
+
98
+ // 5. 注册所有 RPC 路由
99
+ register_routes(
100
+ &gateway,
101
+ &conn_mgr,
102
+ &channel_mgr,
103
+ &keepalive_mgr,
104
+ &sftp_mgr,
105
+ &portfwd_mgr,
106
+ start_time,
107
+ )
108
+ .await;
109
+
110
+ // 6. 启动 coalesce tick 循环
111
+ coalesce.start();
112
+
113
+ // 7. 启动 keepalive 循环
114
+ keepalive_mgr.start();
115
+
116
+ // 8. 启动 Gateway(写入端点文件 + accept 循环)
117
+ info!("starting IPC gateway...");
118
+ if let Err(e) = gateway.start(endpoint_file).await {
119
+ error!("gateway failed: {}", e);
120
+ std::process::exit(1);
121
+ }
122
+ }
123
+
124
+ /// 注册所有 JSON-RPC 路由
125
+ async fn register_routes(
126
+ gateway: &Arc<Gateway>,
127
+ conn_mgr: &Arc<ConnManager>,
128
+ channel_mgr: &Arc<ChannelManager>,
129
+ keepalive_mgr: &Arc<KeepaliveMgr>,
130
+ sftp_mgr: &Arc<SftpManager>,
131
+ portfwd_mgr: &Arc<PortFwdManager>,
132
+ start_time: Instant,
133
+ ) {
134
+ // --- 连接管理 ---
135
+ let cm = Arc::clone(conn_mgr);
136
+ gateway
137
+ .register_route("conn.connect", move |params| {
138
+ let cm = Arc::clone(&cm);
139
+ async move { cm.rpc_connect(params).await }
140
+ })
141
+ .await;
142
+
143
+ let cm = Arc::clone(conn_mgr);
144
+ gateway
145
+ .register_route("conn.disconnect", move |params| {
146
+ let cm = Arc::clone(&cm);
147
+ async move { cm.rpc_disconnect(params).await }
148
+ })
149
+ .await;
150
+
151
+ let cm = Arc::clone(conn_mgr);
152
+ gateway
153
+ .register_route("conn.list", move |params| {
154
+ let cm = Arc::clone(&cm);
155
+ async move { cm.rpc_list(params).await }
156
+ })
157
+ .await;
158
+
159
+ let cm = Arc::clone(conn_mgr);
160
+ gateway
161
+ .register_route("conn.reconnect", move |params| {
162
+ let cm = Arc::clone(&cm);
163
+ async move { cm.rpc_reconnect(params).await }
164
+ })
165
+ .await;
166
+
167
+ // --- 通道管理 ---
168
+ let chm = Arc::clone(channel_mgr);
169
+ gateway
170
+ .register_route("channel.open", move |params| {
171
+ let chm = Arc::clone(&chm);
172
+ async move { chm.rpc_open(params).await }
173
+ })
174
+ .await;
175
+
176
+ let chm = Arc::clone(channel_mgr);
177
+ gateway
178
+ .register_route("channel.send", move |params| {
179
+ let chm = Arc::clone(&chm);
180
+ async move { chm.rpc_send(params).await }
181
+ })
182
+ .await;
183
+
184
+ let chm = Arc::clone(channel_mgr);
185
+ gateway
186
+ .register_route("channel.close", move |params| {
187
+ let chm = Arc::clone(&chm);
188
+ async move { chm.rpc_close(params).await }
189
+ })
190
+ .await;
191
+
192
+ let chm = Arc::clone(channel_mgr);
193
+ gateway
194
+ .register_route("channel.window_change", move |params| {
195
+ let chm = Arc::clone(&chm);
196
+ async move { chm.rpc_window_change(params).await }
197
+ })
198
+ .await;
199
+
200
+ // --- 保活管理 ---
201
+ let km = Arc::clone(keepalive_mgr);
202
+ gateway
203
+ .register_route("keepalive.set_interval", move |params| {
204
+ let km = Arc::clone(&km);
205
+ async move { km.rpc_set_interval(params).await }
206
+ })
207
+ .await;
208
+
209
+ let km = Arc::clone(keepalive_mgr);
210
+ gateway
211
+ .register_route("keepalive.get_interval", move |params| {
212
+ let km = Arc::clone(&km);
213
+ async move { km.rpc_get_interval(params).await }
214
+ })
215
+ .await;
216
+
217
+ let km = Arc::clone(keepalive_mgr);
218
+ gateway
219
+ .register_route("keepalive.get_status", move |params| {
220
+ let km = Arc::clone(&km);
221
+ async move { km.rpc_get_status(params).await }
222
+ })
223
+ .await;
224
+
225
+ // --- 引擎管理 ---
226
+ gateway
227
+ .register_route("engine.ping", move |_params| {
228
+ async move { Ok(json!({"ok": true, "timestamp": codec::unix_ms()})) }
229
+ })
230
+ .await;
231
+
232
+ let cm2 = Arc::clone(conn_mgr);
233
+ gateway
234
+ .register_route("engine.stats", move |_params| {
235
+ let cm2 = Arc::clone(&cm2);
236
+ let st = start_time;
237
+ async move {
238
+ let conn_count = cm2.all_conn_ids().await.len();
239
+ let uptime_ms = st.elapsed().as_millis() as u64;
240
+ Ok(json!({
241
+ "connections": conn_count,
242
+ "uptime_ms": uptime_ms
243
+ }))
244
+ }
245
+ })
246
+ .await;
247
+
248
+ gateway
249
+ .register_route("engine.shutdown", move |_params| {
250
+ async move {
251
+ info!("engine.shutdown received, exiting...");
252
+ tokio::spawn(async {
253
+ tokio::time::sleep(std::time::Duration::from_millis(100)).await;
254
+ std::process::exit(0);
255
+ });
256
+ Ok(json!({"ok": true}))
257
+ }
258
+ })
259
+ .await;
260
+
261
+ // --- bye ---
262
+ gateway
263
+ .register_route("bye", move |_params| {
264
+ async move { Ok(json!({"ok": true})) }
265
+ })
266
+ .await;
267
+
268
+ // --- SFTP ---
269
+ let sm = Arc::clone(sftp_mgr);
270
+ gateway
271
+ .register_route("sftp.open", move |params| {
272
+ let sm = Arc::clone(&sm);
273
+ async move { sm.rpc_open(params).await }
274
+ })
275
+ .await;
276
+
277
+ let sm = Arc::clone(sftp_mgr);
278
+ gateway
279
+ .register_route("sftp.list_dir", move |params| {
280
+ let sm = Arc::clone(&sm);
281
+ async move { sm.rpc_list_dir(params).await }
282
+ })
283
+ .await;
284
+
285
+ let sm = Arc::clone(sftp_mgr);
286
+ gateway
287
+ .register_route("sftp.download", move |params| {
288
+ let sm = Arc::clone(&sm);
289
+ async move { sm.rpc_download(params).await }
290
+ })
291
+ .await;
292
+
293
+ let sm = Arc::clone(sftp_mgr);
294
+ gateway
295
+ .register_route("sftp.upload", move |params| {
296
+ let sm = Arc::clone(&sm);
297
+ async move { sm.rpc_upload(params).await }
298
+ })
299
+ .await;
300
+
301
+ let sm = Arc::clone(sftp_mgr);
302
+ gateway
303
+ .register_route("sftp.mkdir", move |params| {
304
+ let sm = Arc::clone(&sm);
305
+ async move { sm.rpc_mkdir(params).await }
306
+ })
307
+ .await;
308
+
309
+ let sm = Arc::clone(sftp_mgr);
310
+ gateway
311
+ .register_route("sftp.remove", move |params| {
312
+ let sm = Arc::clone(&sm);
313
+ async move { sm.rpc_remove(params).await }
314
+ })
315
+ .await;
316
+
317
+ let sm = Arc::clone(sftp_mgr);
318
+ gateway
319
+ .register_route("sftp.stat", move |params| {
320
+ let sm = Arc::clone(&sm);
321
+ async move { sm.rpc_stat(params).await }
322
+ })
323
+ .await;
324
+
325
+ // --- 端口转发 ---
326
+ let pm = Arc::clone(portfwd_mgr);
327
+ gateway
328
+ .register_route("portfwd.add", move |params| {
329
+ let pm = Arc::clone(&pm);
330
+ async move { pm.rpc_add(params).await }
331
+ })
332
+ .await;
333
+
334
+ let pm = Arc::clone(portfwd_mgr);
335
+ gateway
336
+ .register_route("portfwd.remove", move |params| {
337
+ let pm = Arc::clone(&pm);
338
+ async move { pm.rpc_remove(params).await }
339
+ })
340
+ .await;
341
+
342
+ let pm = Arc::clone(portfwd_mgr);
343
+ gateway
344
+ .register_route("portfwd.list", move |params| {
345
+ let pm = Arc::clone(&pm);
346
+ async move { pm.rpc_list(params).await }
347
+ })
348
+ .await;
349
+
350
+ info!("all RPC routes registered");
351
+ }