@feng3d/ctc 0.0.20 → 0.2.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 (56) hide show
  1. package/README.md +82 -106
  2. package/dist/cli.d.ts +13 -12
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +190 -966
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config.d.ts +18 -51
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +42 -180
  9. package/dist/config.js.map +1 -1
  10. package/dist/controller.d.ts +47 -5
  11. package/dist/controller.d.ts.map +1 -1
  12. package/dist/controller.js +10 -23
  13. package/dist/controller.js.map +1 -1
  14. package/dist/handlers/unified-handler.d.ts.map +1 -1
  15. package/dist/handlers/unified-handler.js +3 -1
  16. package/dist/handlers/unified-handler.js.map +1 -1
  17. package/dist/index.d.ts +7 -5
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +5 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/proxy-manager.d.ts +32 -32
  22. package/dist/proxy-manager.d.ts.map +1 -1
  23. package/dist/proxy-manager.js +81 -111
  24. package/dist/proxy-manager.js.map +1 -1
  25. package/package.json +5 -10
  26. package/admin-ui/dist/app.js +0 -29
  27. package/admin-ui/dist/index.html +0 -222
  28. package/admin-ui/dist/style.css +0 -1
  29. package/dist/admin-server.d.ts +0 -149
  30. package/dist/admin-server.d.ts.map +0 -1
  31. package/dist/admin-server.js +0 -426
  32. package/dist/admin-server.js.map +0 -1
  33. package/dist/app.d.ts +0 -17
  34. package/dist/app.d.ts.map +0 -1
  35. package/dist/app.js +0 -97
  36. package/dist/app.js.map +0 -1
  37. package/dist/daemon-entry.d.ts +0 -8
  38. package/dist/daemon-entry.d.ts.map +0 -1
  39. package/dist/daemon-entry.js +0 -15
  40. package/dist/daemon-entry.js.map +0 -1
  41. package/dist/daemon.d.ts +0 -32
  42. package/dist/daemon.d.ts.map +0 -1
  43. package/dist/daemon.js +0 -370
  44. package/dist/daemon.js.map +0 -1
  45. package/dist/forward-proxy.d.ts +0 -100
  46. package/dist/forward-proxy.d.ts.map +0 -1
  47. package/dist/forward-proxy.js +0 -407
  48. package/dist/forward-proxy.js.map +0 -1
  49. package/dist/ipc-handler.d.ts +0 -124
  50. package/dist/ipc-handler.d.ts.map +0 -1
  51. package/dist/ipc-handler.js +0 -305
  52. package/dist/ipc-handler.js.map +0 -1
  53. package/dist/process-utils.d.ts +0 -31
  54. package/dist/process-utils.d.ts.map +0 -1
  55. package/dist/process-utils.js +0 -87
  56. package/dist/process-utils.js.map +0 -1
package/dist/daemon.js DELETED
@@ -1,370 +0,0 @@
1
- /**
2
- * @module daemon
3
- *
4
- * 守护进程运行逻辑。
5
- * 从 index.ts 分离而来,使 index.ts 成为纯库导出模块。
6
- *
7
- * 该模块提供客户端的独立运行功能,包括:
8
- * - PID 文件管理
9
- * - 单实例检查
10
- * - 代理配置管理
11
- * - 核心组件编排(Controller、ProxyManager、ForwardProxy)
12
- * - IPC 通信
13
- * - 信号处理与优雅关闭
14
- */
15
- import { Config } from './config.js';
16
- import { Controller } from './controller.js';
17
- import { ProxyManager } from './proxy-manager.js';
18
- import { IpcHandler } from './ipc-handler.js';
19
- import { AdminServer } from './admin-server.js';
20
- import { logger } from '@feng3d/chuantou-shared';
21
- import { join } from 'path';
22
- import { homedir } from 'os';
23
- import { ForwardProxy } from './forward-proxy.js';
24
- import { writeFile, writeFileSync, mkdirSync, unlinkSync, readFileSync } from 'fs';
25
- import { isProcessAlive, killProcess } from './process-utils.js';
26
- /** 客户端目录 */
27
- const CLIENT_DIR = join(homedir(), '.chuantou', 'client');
28
- /** PID 文件 */
29
- const PID_FILE = join(CLIENT_DIR, 'client.pid');
30
- /**
31
- * 读取 PID 文件
32
- */
33
- function readPidFile() {
34
- try {
35
- return JSON.parse(readFileSync(PID_FILE, 'utf-8'));
36
- }
37
- catch {
38
- return null;
39
- }
40
- }
41
- /**
42
- * 写入 PID 文件
43
- */
44
- function writePidFile(info) {
45
- mkdirSync(CLIENT_DIR, { recursive: true });
46
- writeFileSync(PID_FILE, JSON.stringify(info, null, 2));
47
- }
48
- /**
49
- * 单实例检查
50
- * @returns true 表示应该继续启动,false 表示已有实例在运行,应该退出
51
- */
52
- async function checkSingleInstance(serverUrl) {
53
- const info = readPidFile();
54
- if (!info) {
55
- // PID 文件不存在,创建新的
56
- writePidFile({
57
- pid: process.pid,
58
- serverUrl,
59
- adminPort: 0, // 不再使用 adminPort
60
- startedAt: Date.now(),
61
- });
62
- return true;
63
- }
64
- // 检查记录的进程是否存活
65
- if (isProcessAlive(info.pid)) {
66
- // 进程存活,检查是否是同一个配置
67
- if (info.serverUrl === serverUrl) {
68
- logger.log('客户端已在运行中,退出当前启动');
69
- logger.log(` 现有实例 PID: ${info.pid}`);
70
- logger.log(` 服务器: ${info.serverUrl}`);
71
- return false;
72
- }
73
- // 配置不同,先关闭旧进程再启动新进程
74
- logger.warn(`检测到不同配置的实例 (PID: ${info.pid}),正在关闭旧进程...`);
75
- const result = await killProcess(info.pid);
76
- if (result.success) {
77
- logger.log(`旧进程已关闭 (方式: ${result.method})`);
78
- }
79
- else {
80
- logger.warn(`无法关闭旧进程: ${result.error},继续启动新进程`);
81
- }
82
- }
83
- // 旧进程不存在或已关闭,更新 PID 文件
84
- writePidFile({
85
- pid: process.pid,
86
- serverUrl,
87
- adminPort: 0,
88
- startedAt: Date.now(),
89
- });
90
- return true;
91
- }
92
- /**
93
- * 启动守护进程。
94
- *
95
- * 执行以下步骤:
96
- * 1. 从配置文件或命令行参数加载配置
97
- * 2. 验证配置合法性
98
- * 3. 单实例检查
99
- * 4. 创建控制器并连接服务器
100
- * 5. 认证成功后注册所有代理隧道
101
- * 6. 启动 IPC 通信处理
102
- * 7. 监听进程信号实现优雅关闭
103
- *
104
- * @param config - 客户端配置,如未提供则从默认路径加载
105
- * @returns 无返回值的 Promise
106
- */
107
- export async function startDaemon(config) {
108
- logger.log('正在启动穿透客户端...');
109
- // 加载配置(从用户目录 .chuantou/client.json 或命令行参数)
110
- const cfg = config ?? await Config.load();
111
- // 单实例检查:防止多个客户端实例同时运行
112
- if (!await checkSingleInstance(cfg.serverUrl)) {
113
- process.exit(0);
114
- }
115
- // 验证配置
116
- cfg.validate();
117
- logger.log('配置已加载:');
118
- logger.log(` 服务器地址: ${cfg.serverUrl}`);
119
- logger.log(` 代理数量: 已配置 ${cfg.proxies.length} 个`);
120
- for (const proxy of cfg.proxies) {
121
- logger.log(` - :${proxy.remotePort} -> ${proxy.localHost || 'localhost'}:${proxy.localPort}`);
122
- }
123
- // 记录启动时间
124
- const startTime = Date.now();
125
- // 创建控制器
126
- const controller = new Controller(cfg);
127
- // 创建代理管理器
128
- const proxyManager = new ProxyManager(controller);
129
- // 创建正向穿透代理
130
- const forwardProxy = new ForwardProxy(controller);
131
- // 已注册的代理配置列表
132
- const registeredProxies = [];
133
- for (const p of cfg.proxies) {
134
- registeredProxies.push({ remotePort: p.remotePort, localPort: p.localPort, localHost: p.localHost });
135
- }
136
- // 获取状态回调
137
- const getStatusCallback = () => {
138
- // 获取实际在 ProxyManager 中注册的端口
139
- const actualRegisteredPorts = proxyManager.getRegisteredPorts();
140
- // 返回所有配置的代理(去重),并标记注册状态
141
- const actualRegisteredProxies = registeredProxies
142
- .filter((p, index, self) => {
143
- // 去重:只保留第一次出现的端口
144
- return index === self.findIndex(other => other.remotePort === p.remotePort);
145
- })
146
- .map((p, i) => ({ ...p, registered: actualRegisteredPorts.includes(p.remotePort), index: i + 1 }));
147
- const status = {
148
- running: true,
149
- serverUrl: cfg.serverUrl,
150
- connected: controller.isConnected(),
151
- authenticated: controller.isAuthenticated(),
152
- uptime: Date.now() - startTime,
153
- proxies: actualRegisteredProxies,
154
- reconnectAttempts: controller.getReconnectAttempts(),
155
- };
156
- // 添加正向穿透相关信息
157
- try {
158
- const forwardProxies = forwardProxy.getProxies();
159
- status.forwardProxies = forwardProxies;
160
- status.isRegistered = true; // 假设已注册(实际应从 Controller 获取)
161
- status.clientId = controller.getClientId();
162
- }
163
- catch (e) {
164
- // 如果获取失败,返回基础状态
165
- }
166
- return status;
167
- };
168
- // 更新配置文件中的代理列表
169
- const updateConfigProxies = async (proxies) => {
170
- const config = await Config.load();
171
- config.proxies = proxies;
172
- const configPath = join(homedir(), '.chuantou', 'client', 'config.json');
173
- writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8', (err) => {
174
- if (err) {
175
- logger.error('更新配置文件失败:', err);
176
- }
177
- else {
178
- logger.log('配置文件已更新');
179
- }
180
- });
181
- };
182
- // 设置 IPC 请求监听(用于处理 CLI 添加代理的请求)
183
- const ipcHandler = new IpcHandler({
184
- requestDir: join(homedir(), '.chuantou', 'proxy-requests'),
185
- controller,
186
- proxyManager,
187
- registeredProxies,
188
- forwardProxy,
189
- getStatus: getStatusCallback,
190
- updateConfigProxies,
191
- });
192
- ipcHandler.start();
193
- // 创建并启动 Admin Server(管理页面)
194
- const adminPort = 9001; // 客户端管理页面固定端口
195
- const adminServer = new AdminServer({
196
- port: adminPort,
197
- host: '127.0.0.1',
198
- }, getStatusCallback, async (proxy) => {
199
- await proxyManager.registerProxy(proxy);
200
- registeredProxies.push(proxy);
201
- await updateConfigProxies(registeredProxies);
202
- }, async (remotePort) => {
203
- await proxyManager.unregisterProxy(remotePort);
204
- const index = registeredProxies.findIndex(p => p.remotePort === remotePort);
205
- if (index !== -1) {
206
- registeredProxies.splice(index, 1);
207
- }
208
- await updateConfigProxies(registeredProxies);
209
- }, async (entry) => {
210
- await forwardProxy.addProxy(entry);
211
- }, async (localPort) => {
212
- await forwardProxy.removeProxy(localPort);
213
- }, async (description) => {
214
- await forwardProxy.registerAsClient(description);
215
- }, async () => {
216
- return await forwardProxy.getClientList();
217
- }, async (message) => {
218
- return await controller.sendRequest(message, 5000);
219
- }, async () => {
220
- controller.disconnect();
221
- await controller.connect();
222
- });
223
- // 设置 shutdown 回调
224
- adminServer.setShutdownCallback(async () => {
225
- shutdown();
226
- });
227
- // 启动 Admin Server
228
- try {
229
- await adminServer.start();
230
- // 更新 PID 文件中的 adminPort
231
- const pidInfo = readPidFile();
232
- if (pidInfo) {
233
- pidInfo.adminPort = adminPort;
234
- writePidFile(pidInfo);
235
- }
236
- }
237
- catch (err) {
238
- logger.error('管理页面启动失败:', err);
239
- }
240
- // 监听控制器事件
241
- controller.on('connected', () => {
242
- logger.log('已连接到服务器');
243
- });
244
- controller.on('disconnected', () => {
245
- logger.log('已断开与服务器的连接');
246
- });
247
- controller.on('authenticated', async () => {
248
- logger.log('已认证,正在注册代理...');
249
- // 获取实际在 ProxyManager 中注册的端口
250
- const actualRegisteredPorts = proxyManager.getRegisteredPorts();
251
- // 注册所有代理(只注册尚未实际注册的)
252
- for (const proxyConfig of cfg.proxies) {
253
- if (actualRegisteredPorts.includes(proxyConfig.remotePort)) {
254
- logger.log(`代理 :${proxyConfig.remotePort} 已注册,跳过`);
255
- continue;
256
- }
257
- try {
258
- await proxyManager.registerProxy(proxyConfig);
259
- }
260
- catch (error) {
261
- const errorMessage = error instanceof Error ? error.message : String(error);
262
- logger.error(`注册代理失败: ${errorMessage}`);
263
- }
264
- }
265
- });
266
- // 监听远程管理命令
267
- controller.on('remoteCommand', async (message) => {
268
- const { type, id, payload } = message;
269
- try {
270
- switch (type) {
271
- case 'remote_add_proxy': {
272
- const { remotePort, localPort, localHost = 'localhost' } = payload;
273
- await proxyManager.registerProxy({ remotePort, localPort, localHost });
274
- registeredProxies.push({ remotePort, localPort, localHost });
275
- // 同步更新配置文件
276
- await updateConfigProxies(registeredProxies);
277
- // 发送成功响应
278
- controller.sendMessage({
279
- type: 'remote_command_resp',
280
- id,
281
- payload: { commandId: id, success: true },
282
- });
283
- logger.log(`远程命令: 已添加代理 :${remotePort} -> ${localHost}:${localPort}`);
284
- break;
285
- }
286
- case 'remote_remove_proxy': {
287
- const { remotePort } = payload;
288
- await proxyManager.unregisterProxy(remotePort);
289
- const index = registeredProxies.findIndex(p => p.remotePort === remotePort);
290
- if (index !== -1) {
291
- registeredProxies.splice(index, 1);
292
- }
293
- // 同步更新配置文件
294
- await updateConfigProxies(registeredProxies);
295
- // 发送成功响应
296
- controller.sendMessage({
297
- type: 'remote_command_resp',
298
- id,
299
- payload: { commandId: id, success: true },
300
- });
301
- logger.log(`远程命令: 已删除代理 :${remotePort}`);
302
- break;
303
- }
304
- case 'remote_get_status': {
305
- const status = getStatusCallback();
306
- // 发送状态响应
307
- controller.sendMessage({
308
- type: 'remote_status_resp',
309
- id,
310
- payload: { requestId: id, success: true, status },
311
- });
312
- break;
313
- }
314
- default:
315
- logger.warn(`未知的远程命令: ${type}`);
316
- // 发送错误响应
317
- controller.sendMessage({
318
- type: 'remote_command_resp',
319
- id,
320
- payload: { commandId: id, success: false, error: `未知命令: ${type}` },
321
- });
322
- }
323
- }
324
- catch (error) {
325
- const errorMessage = error instanceof Error ? error.message : String(error);
326
- logger.error(`处理远程命令失败 (${type}):`, errorMessage);
327
- // 发送错误响应
328
- controller.sendMessage({
329
- type: 'remote_command_resp',
330
- id,
331
- payload: { commandId: id, success: false, error: errorMessage },
332
- });
333
- }
334
- });
335
- // 优雅关闭
336
- const shutdown = async () => {
337
- ipcHandler.stop();
338
- logger.log('\n正在关闭...');
339
- await forwardProxy.destroy();
340
- await proxyManager.destroy();
341
- controller.disconnect();
342
- // 清理 PID 文件(只有当前进程是 PID 文件中的进程时才清理)
343
- const pidInfo = readPidFile();
344
- if (pidInfo && pidInfo.pid === process.pid) {
345
- try {
346
- unlinkSync(PID_FILE);
347
- }
348
- catch {
349
- // ignore
350
- }
351
- }
352
- process.exit(0);
353
- };
354
- process.on('SIGINT', shutdown);
355
- process.on('SIGTERM', shutdown);
356
- // 未捕获异常处理 - 崩溃时记录退出码
357
- process.on('uncaughtException', (error) => {
358
- logger.error('未捕获异常:', error);
359
- // 写入非零退出码,让父进程知道是异常退出
360
- process.exit(1);
361
- });
362
- process.on('unhandledRejection', (reason, promise) => {
363
- logger.error('未处理的 Promise 拒绝:', reason);
364
- // 写入非零退出码
365
- process.exit(1);
366
- });
367
- // 连接到服务器(不会抛出连接失败的异常,会自动重连)
368
- await controller.connect();
369
- }
370
- //# sourceMappingURL=daemon.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -1,100 +0,0 @@
1
- /**
2
- * @module forward-proxy
3
- *
4
- * 正向穿透代理模块。
5
- *
6
- * 实现从本地端口到远程客户端端口的穿透功能。
7
- * 用户连接本地端口 → 通过中继服务器数据通道 → 连接到目标客户端的指定端口。
8
- */
9
- import { EventEmitter } from 'events';
10
- import { ClientListMessage, ForwardProxyEntry } from '@feng3d/chuantou-shared';
11
- import { Controller } from './controller.js';
12
- export type { ForwardProxyEntry };
13
- /**
14
- * 正向穿透代理类
15
- *
16
- * 管理从本地端口到远程客户端的穿透映射。
17
- * 支持两种角色:
18
- * - 发起方: 用户连接本地端口,数据转发到目标客户端
19
- * - 目标方: 接受来自其他客户端的连接,转发到本地服务
20
- */
21
- export declare class ForwardProxy extends EventEmitter {
22
- private controller;
23
- private proxies;
24
- private servers;
25
- private sessions;
26
- constructor(controller: Controller);
27
- /**
28
- * 设置消息处理器
29
- */
30
- private setupMessageHandlers;
31
- /**
32
- * 设置数据通道处理器
33
- */
34
- private setupDataChannelHandlers;
35
- /**
36
- * 处理数据通道数据
37
- */
38
- private handleDataChannelData;
39
- /**
40
- * 注册客户端(正向穿透模式)
41
- */
42
- registerAsClient(description?: string): Promise<void>;
43
- /**
44
- * 获取在线客户端列表
45
- */
46
- getClientList(): Promise<ClientListMessage['payload']>;
47
- /**
48
- * 添加正向穿透代理
49
- */
50
- addProxy(entry: ForwardProxyEntry): Promise<void>;
51
- /**
52
- * 移除正向穿透代理
53
- */
54
- removeProxy(localPort: number): Promise<void>;
55
- /**
56
- * 移除指定目标的所有代理
57
- */
58
- removeByTarget(targetClientId: string): Promise<number>;
59
- /**
60
- * 获取所有代理
61
- */
62
- getProxies(): ForwardProxyEntry[];
63
- /**
64
- * 检查端口是否可用
65
- */
66
- private isPortAvailable;
67
- /**
68
- * 处理本地连接(发起方)
69
- */
70
- private handleLocalConnection;
71
- /**
72
- * 处理入站连接请求(目标方)
73
- */
74
- private handleIncomingConnection;
75
- /**
76
- * 处理连接已建立消息(发起方)
77
- */
78
- private handleConnectionEstablished;
79
- /**
80
- * 处理代理目标端口请求(目标方)
81
- */
82
- private handleProxyTargetPort;
83
- /**
84
- * 处理连接错误
85
- */
86
- private handleConnectionError;
87
- /**
88
- * 清理会话
89
- */
90
- private cleanupSession;
91
- /**
92
- * 生成会话 ID
93
- */
94
- private generateSessionId;
95
- /**
96
- * 销毁所有代理
97
- */
98
- destroy(): Promise<void>;
99
- }
100
- //# sourceMappingURL=forward-proxy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"forward-proxy.d.ts","sourceRoot":"","sources":["../src/forward-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAML,iBAAiB,EAQjB,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAgBlC;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,OAAO,CAAgC;IAG/C,OAAO,CAAC,QAAQ,CAAqC;gBAEzC,UAAU,EAAE,UAAU;IAWlC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAShC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0B7B;;OAEG;IACG,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB3D;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAU5D;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCvD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnD;;OAEG;IACG,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe7D;;OAEG;IACH,UAAU,IAAI,iBAAiB,EAAE;IAIjC;;OAEG;YACW,eAAe;IAY7B;;OAEG;YACW,qBAAqB;IA4DnC;;OAEG;YACW,wBAAwB;IAkBtC;;OAEG;YACW,2BAA2B;IA8BzC;;OAEG;YACW,qBAAqB;IA8DnC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAQ7B;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAiB/B"}