@feng3d/ctc 0.0.6

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.
@@ -0,0 +1,340 @@
1
+ /**
2
+ * @module controller
3
+ *
4
+ * 客户端控制器模块。
5
+ *
6
+ * 管理客户端与穿透服务器之间的 WebSocket 控制连接,
7
+ * 负责身份认证、心跳保活、消息收发、断线重连等核心通信逻辑。
8
+ */
9
+ import { WebSocket } from 'ws';
10
+ import { EventEmitter } from 'events';
11
+ import { MessageType, createMessage, logger, } from '@feng3d/chuantou-shared';
12
+ /**
13
+ * 客户端控制器类,管理与穿透服务器的 WebSocket 控制连接。
14
+ *
15
+ * 继承自 {@link EventEmitter},提供以下事件:
16
+ * - `connected` - 成功连接到服务器时触发
17
+ * - `disconnected` - 与服务器断开连接时触发
18
+ * - `authenticated` - 身份认证成功时触发
19
+ * - `maxReconnectAttemptsReached` - 达到最大重连次数时触发
20
+ * - `newConnection` - 收到新的代理连接请求时触发
21
+ * - `connectionClose` - 收到连接关闭通知时触发
22
+ * - `connectionError` - 收到连接错误通知时触发
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const controller = new Controller(config);
27
+ * controller.on('authenticated', () => logger.log('已认证'));
28
+ * await controller.connect();
29
+ * ```
30
+ */
31
+ export class Controller extends EventEmitter {
32
+ /**
33
+ * 创建控制器实例。
34
+ *
35
+ * @param config - 客户端配置对象
36
+ */
37
+ constructor(config) {
38
+ super();
39
+ /** 与服务器的 WebSocket 连接实例 */
40
+ this.ws = null;
41
+ /** 是否已连接到服务器 */
42
+ this.connected = false;
43
+ /** 是否已通过身份认证 */
44
+ this.authenticated = false;
45
+ /** 重连定时器 */
46
+ this.reconnectTimer = null;
47
+ /** 心跳定时器 */
48
+ this.heartbeatTimer = null;
49
+ /** 当前重连尝试次数 */
50
+ this.reconnectAttempts = 0;
51
+ /** 待响应的请求映射表,键为消息 ID */
52
+ this.pendingRequests = new Map();
53
+ this.config = config;
54
+ }
55
+ /**
56
+ * 连接到穿透服务器。
57
+ *
58
+ * 建立 WebSocket 连接后会自动进行身份认证和启动心跳。
59
+ * 连接断开时会自动安排重连。
60
+ *
61
+ * @returns 连接并认证成功后解析的 Promise
62
+ * @throws {Error} 连接失败或认证失败时抛出错误
63
+ */
64
+ async connect() {
65
+ return new Promise((resolve, reject) => {
66
+ logger.log(`正在连接 ${this.config.serverUrl}...`);
67
+ this.ws = new WebSocket(this.config.serverUrl);
68
+ this.ws.on('open', async () => {
69
+ logger.log('已连接到服务器');
70
+ this.connected = true;
71
+ this.reconnectAttempts = 0;
72
+ this.emit('connected');
73
+ // 认证
74
+ try {
75
+ await this.authenticate();
76
+ this.startHeartbeat();
77
+ resolve();
78
+ }
79
+ catch (error) {
80
+ reject(error);
81
+ }
82
+ });
83
+ this.ws.on('message', (data) => {
84
+ this.handleMessage(data);
85
+ });
86
+ this.ws.on('close', () => {
87
+ logger.log('连接已关闭');
88
+ this.connected = false;
89
+ this.authenticated = false;
90
+ this.stopHeartbeat();
91
+ this.emit('disconnected');
92
+ this.scheduleReconnect();
93
+ });
94
+ this.ws.on('error', (error) => {
95
+ logger.error('WebSocket 错误:', error.message);
96
+ if (!this.connected) {
97
+ reject(error);
98
+ }
99
+ });
100
+ });
101
+ }
102
+ /**
103
+ * 向服务器发送身份认证请求。
104
+ *
105
+ * 使用配置中的 token 进行认证,认证成功后触发 `authenticated` 事件。
106
+ *
107
+ * @throws {Error} 认证失败时抛出错误,包含服务器返回的错误信息
108
+ */
109
+ async authenticate() {
110
+ logger.log('正在认证...');
111
+ const authMsg = createMessage(MessageType.AUTH, {
112
+ token: this.config.token,
113
+ });
114
+ const response = await this.sendRequest(authMsg);
115
+ if (!response.payload.success) {
116
+ throw new Error(`认证失败: ${response.payload.error}`);
117
+ }
118
+ this.authenticated = true;
119
+ logger.log('认证成功');
120
+ this.emit('authenticated');
121
+ }
122
+ /**
123
+ * 启动心跳定时器。
124
+ *
125
+ * 每 30 秒向服务器发送一次心跳消息,仅在已连接且已认证状态下发送。
126
+ */
127
+ startHeartbeat() {
128
+ this.heartbeatTimer = setInterval(() => {
129
+ if (this.connected && this.authenticated) {
130
+ const heartbeatMsg = createMessage(MessageType.HEARTBEAT, {
131
+ timestamp: Date.now(),
132
+ });
133
+ this.sendMessage(heartbeatMsg);
134
+ }
135
+ }, 30000); // 30秒
136
+ }
137
+ /**
138
+ * 停止心跳定时器。
139
+ *
140
+ * 清除心跳定时器并将其设置为 null。
141
+ */
142
+ stopHeartbeat() {
143
+ if (this.heartbeatTimer) {
144
+ clearInterval(this.heartbeatTimer);
145
+ this.heartbeatTimer = null;
146
+ }
147
+ }
148
+ /**
149
+ * 安排断线重连。
150
+ *
151
+ * 使用指数退避策略计算重连延迟时间。如果已达到最大重连次数,
152
+ * 则触发 `maxReconnectAttemptsReached` 事件并停止重连。
153
+ */
154
+ scheduleReconnect() {
155
+ if (this.reconnectTimer) {
156
+ return; // 已经安排了重连
157
+ }
158
+ if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
159
+ logger.error('已达到最大重连次数');
160
+ this.emit('maxReconnectAttemptsReached');
161
+ return;
162
+ }
163
+ const delay = this.calculateReconnectDelay();
164
+ logger.log(`将在 ${delay}ms 后重连... (第 ${this.reconnectAttempts + 1}/${this.config.maxReconnectAttempts} 次尝试)`);
165
+ this.reconnectTimer = setTimeout(() => {
166
+ this.reconnectTimer = null;
167
+ this.reconnectAttempts++;
168
+ this.connect().catch((error) => {
169
+ const errorMessage = error instanceof Error ? error.message : String(error);
170
+ logger.error('重连失败:', errorMessage);
171
+ this.scheduleReconnect();
172
+ });
173
+ }, delay);
174
+ }
175
+ /**
176
+ * 计算重连延迟时间(指数退避算法)。
177
+ *
178
+ * 基于重连间隔和当前重连次数计算延迟,最大不超过 60 秒,
179
+ * 并添加 0~1 秒的随机抖动以避免多客户端同时重连造成服务器压力。
180
+ *
181
+ * @returns 重连延迟时间(毫秒)
182
+ */
183
+ calculateReconnectDelay() {
184
+ const baseDelay = this.config.reconnectInterval;
185
+ const maxDelay = 60000; // 最大60秒
186
+ const delay = Math.min(baseDelay * Math.pow(2, this.reconnectAttempts), maxDelay);
187
+ // 添加随机抖动
188
+ return delay + Math.random() * 1000;
189
+ }
190
+ /**
191
+ * 处理从服务器接收到的消息。
192
+ *
193
+ * 根据消息类型进行分发:
194
+ * - 响应类消息(AUTH_RESP、REGISTER_RESP、HEARTBEAT_RESP)交由 {@link handleResponse} 处理
195
+ * - 新连接、连接关闭、连接错误等消息通过事件触发通知上层
196
+ *
197
+ * @param data - 接收到的原始消息数据
198
+ */
199
+ handleMessage(data) {
200
+ try {
201
+ const message = JSON.parse(data.toString());
202
+ const msgType = message.type;
203
+ switch (msgType) {
204
+ case MessageType.AUTH_RESP:
205
+ case MessageType.REGISTER_RESP:
206
+ case MessageType.HEARTBEAT_RESP:
207
+ // 响应消息,由pendingRequests处理
208
+ this.handleResponse(message);
209
+ break;
210
+ case MessageType.NEW_CONNECTION:
211
+ this.emit('newConnection', message);
212
+ break;
213
+ case MessageType.CONNECTION_CLOSE:
214
+ this.emit('connectionClose', message);
215
+ break;
216
+ case MessageType.CONNECTION_ERROR:
217
+ this.emit('connectionError', message);
218
+ break;
219
+ default:
220
+ logger.warn(`未知消息类型: ${msgType}`);
221
+ }
222
+ }
223
+ catch (error) {
224
+ const errorMessage = error instanceof Error ? error.message : String(error);
225
+ logger.error('处理消息时出错:', errorMessage);
226
+ }
227
+ }
228
+ /**
229
+ * 处理响应类消息。
230
+ *
231
+ * 根据消息 ID 查找对应的待处理请求,清除超时定时器并解析 Promise。
232
+ *
233
+ * @param message - 服务器返回的响应消息对象
234
+ */
235
+ handleResponse(message) {
236
+ const pending = this.pendingRequests.get(message.id);
237
+ if (pending) {
238
+ clearTimeout(pending.timeout);
239
+ this.pendingRequests.delete(message.id);
240
+ pending.resolve(message);
241
+ }
242
+ }
243
+ /**
244
+ * 发送请求消息并等待服务器响应。
245
+ *
246
+ * 将消息发送到服务器,并在指定超时时间内等待对应的响应消息。
247
+ * 如果超时未收到响应,Promise 将被拒绝。
248
+ *
249
+ * @typeParam T - 期望的响应消息类型
250
+ * @param message - 要发送的请求消息对象,必须包含 `id` 字段
251
+ * @param timeout - 请求超时时间(毫秒),默认为 30000
252
+ * @returns 服务器响应消息的 Promise
253
+ * @throws {Error} 请求超时时抛出 "Request timeout" 错误
254
+ */
255
+ sendRequest(message, timeout = 30000) {
256
+ return new Promise((resolve, reject) => {
257
+ const timer = setTimeout(() => {
258
+ this.pendingRequests.delete(message.id);
259
+ reject(new Error('请求超时'));
260
+ }, timeout);
261
+ this.pendingRequests.set(message.id, { resolve, reject, timeout: timer });
262
+ this.sendMessage(message);
263
+ });
264
+ }
265
+ /**
266
+ * 向服务器发送消息。
267
+ *
268
+ * 将消息对象序列化为 JSON 并通过 WebSocket 发送。
269
+ * 仅在 WebSocket 连接处于 OPEN 状态时才能发送。
270
+ *
271
+ * @param message - 要发送的消息对象
272
+ * @returns 发送成功返回 `true`,未连接时返回 `false`
273
+ */
274
+ sendMessage(message) {
275
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
276
+ this.ws.send(JSON.stringify(message));
277
+ return true;
278
+ }
279
+ logger.error('无法发送消息: 未连接');
280
+ return false;
281
+ }
282
+ /**
283
+ * 检查是否已连接到服务器。
284
+ *
285
+ * @returns 已连接返回 `true`,否则返回 `false`
286
+ */
287
+ isConnected() {
288
+ return this.connected;
289
+ }
290
+ /**
291
+ * 检查是否已通过身份认证。
292
+ *
293
+ * @returns 已认证返回 `true`,否则返回 `false`
294
+ */
295
+ isAuthenticated() {
296
+ return this.authenticated;
297
+ }
298
+ /**
299
+ * 获取当前重连尝试次数。
300
+ *
301
+ * @returns 当前重连次数
302
+ */
303
+ getReconnectAttempts() {
304
+ return this.reconnectAttempts;
305
+ }
306
+ /**
307
+ * 断开与服务器的连接。
308
+ *
309
+ * 清除重连定时器、停止心跳、关闭 WebSocket 连接,
310
+ * 并重置连接和认证状态。
311
+ */
312
+ disconnect() {
313
+ if (this.reconnectTimer) {
314
+ clearTimeout(this.reconnectTimer);
315
+ this.reconnectTimer = null;
316
+ }
317
+ this.stopHeartbeat();
318
+ if (this.ws) {
319
+ this.ws.close();
320
+ this.ws = null;
321
+ }
322
+ this.connected = false;
323
+ this.authenticated = false;
324
+ }
325
+ /**
326
+ * 销毁控制器实例,释放所有资源。
327
+ *
328
+ * 断开连接、清除所有待处理请求的超时定时器、
329
+ * 清空待处理请求映射表并移除所有事件监听器。
330
+ */
331
+ destroy() {
332
+ this.disconnect();
333
+ for (const { timeout } of this.pendingRequests.values()) {
334
+ clearTimeout(timeout);
335
+ }
336
+ this.pendingRequests.clear();
337
+ this.removeAllListeners();
338
+ }
339
+ }
340
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @module handlers/unified-handler
3
+ *
4
+ * 统一代理连接处理器模块。
5
+ *
6
+ * 负责处理通过穿透隧道传输的 HTTP 和 WebSocket 连接。
7
+ * 同时支持 HTTP 请求转发和 WebSocket 连接桥接,无需区分协议类型。
8
+ */
9
+ import { EventEmitter } from 'events';
10
+ import { Controller } from '../controller.js';
11
+ import { ProxyConfig } from '@feng3d/chuantou-shared';
12
+ /**
13
+ * 统一代理连接处理器类。
14
+ *
15
+ * 继承自 {@link EventEmitter},负责在远程客户端和本地服务之间建立双向数据转发通道。
16
+ * 同时支持 HTTP 请求转发和 WebSocket 连接桥接。
17
+ *
18
+ * 工作流程:
19
+ * 1. 监听控制器的 `newConnection` 事件,接收新的连接请求
20
+ * 2. 根据协议类型(http/websocket)建立相应的本地连接
21
+ * 3. 将本地服务发送的数据转发给服务器
22
+ * 4. 将服务器转发的远程客户端数据转发到本地服务
23
+ * 5. 处理连接关闭和错误情况
24
+ *
25
+ * 触发的事件:
26
+ * - `error` - 处理连接时发生错误
27
+ */
28
+ export declare class UnifiedHandler extends EventEmitter {
29
+ /** 控制器实例,用于与服务器通信 */
30
+ private controller;
31
+ /** 代理配置,包含本地服务地址和端口信息 */
32
+ private config;
33
+ /** 正在处理的 HTTP 连接映射表 */
34
+ private pendingConnections;
35
+ /** 本地 WebSocket 连接映射表 */
36
+ private localWsConnections;
37
+ /** 流式 HTTP 响应映射表(如 SSE) */
38
+ private streamingResponses;
39
+ /**
40
+ * 创建统一处理器实例。
41
+ *
42
+ * 自动监听控制器的 `newConnection` 和 `connectionClose` 事件,
43
+ * 并设置数据转发监听器。
44
+ *
45
+ * @param controller - 控制器实例,用于与服务器通信
46
+ * @param config - 代理配置对象,包含本地服务地址和端口
47
+ */
48
+ constructor(controller: Controller, config: ProxyConfig);
49
+ /**
50
+ * 设置从服务器接收数据的监听器。
51
+ */
52
+ private setupDataListener;
53
+ /**
54
+ * 处理来自服务器的新 HTTP 连接请求。
55
+ */
56
+ private handleHttpConnection;
57
+ /**
58
+ * 处理来自服务器的新 WebSocket 连接请求。
59
+ */
60
+ private handleWebSocketConnection;
61
+ /**
62
+ * 将本地数据转发到服务器。
63
+ */
64
+ private forwardToServer;
65
+ /**
66
+ * 处理从服务器接收到的远程客户端数据。
67
+ */
68
+ private handleClientData;
69
+ /**
70
+ * 将 HTTP 响应数据发送回服务器。
71
+ */
72
+ private sendResponse;
73
+ /**
74
+ * 发送流式响应头(用于 SSE)。
75
+ */
76
+ private sendResponseHeaders;
77
+ /**
78
+ * 发送流式响应数据块(用于 SSE)。
79
+ */
80
+ private forwardStreamData;
81
+ /**
82
+ * 通知服务器流式响应结束(用于 SSE)。
83
+ */
84
+ private notifyStreamEnd;
85
+ /**
86
+ * 向服务器发送错误响应。
87
+ */
88
+ private sendError;
89
+ /**
90
+ * 通知服务器某个 WebSocket 连接已关闭。
91
+ */
92
+ private notifyServerClose;
93
+ /**
94
+ * 处理来自服务器的连接关闭通知。
95
+ */
96
+ private handleConnectionClose;
97
+ /**
98
+ * 清理 WebSocket 连接资源。
99
+ */
100
+ private cleanupWsConnection;
101
+ /**
102
+ * 过滤请求头,移除逐跳头部字段。
103
+ */
104
+ private filterHeaders;
105
+ /**
106
+ * 销毁处理器,释放所有资源。
107
+ */
108
+ destroy(): void;
109
+ }
110
+ //# sourceMappingURL=unified-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/unified-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAuB,MAAM,yBAAyB,CAAC;AAS3E;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,qBAAqB;IACrB,OAAO,CAAC,UAAU,CAAa;IAE/B,yBAAyB;IACzB,OAAO,CAAC,MAAM,CAAc;IAE5B,uBAAuB;IACvB,OAAO,CAAC,kBAAkB,CAGX;IAEf,yBAAyB;IACzB,OAAO,CAAC,kBAAkB,CAAqC;IAE/D,2BAA2B;IAC3B,OAAO,CAAC,kBAAkB,CAA+B;IAEzD;;;;;;;;OAQG;gBACS,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW;IAuBvD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;OAEG;YACW,oBAAoB;IA4FlC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAoCjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAyB7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,OAAO,CAAC,aAAa;IA0BrB;;OAEG;IACH,OAAO,IAAI,IAAI;CAqBhB"}