@feng3d/cts 0.0.10 → 0.0.11
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.
- package/README.md +12 -3
- package/dist/data-channel.d.ts +93 -0
- package/dist/data-channel.d.ts.map +1 -0
- package/dist/data-channel.js +211 -0
- package/dist/data-channel.js.map +1 -0
- package/dist/handlers/control-handler.d.ts +10 -122
- package/dist/handlers/control-handler.d.ts.map +1 -1
- package/dist/handlers/control-handler.js +14 -164
- package/dist/handlers/control-handler.js.map +1 -1
- package/dist/handlers/unified-proxy.d.ts +40 -157
- package/dist/handlers/unified-proxy.d.ts.map +1 -1
- package/dist/handlers/unified-proxy.js +221 -355
- package/dist/handlers/unified-proxy.js.map +1 -1
- package/dist/server.d.ts +24 -68
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +144 -251
- package/dist/server.js.map +1 -1
- package/dist/session-manager.d.ts +2 -2
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +1 -1
- package/dist/session-manager.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
9
|
-
- WebSocket 控制通道
|
|
9
|
+
- 三通道架构:WebSocket 控制通道 + TCP 二进制数据通道 + UDP 数据通道
|
|
10
|
+
- **每个代理端口同时支持 HTTP/WebSocket/TCP/UDP 四种协议**,自动识别协议类型
|
|
11
|
+
- 控制端口复用:同一端口处理 WebSocket 控制连接、TCP 数据通道和 UDP 数据通道
|
|
10
12
|
- 动态端口分配
|
|
11
13
|
- 自动心跳检测
|
|
12
14
|
- 多客户端支持
|
|
@@ -140,10 +142,17 @@ npx @feng3d/cts start -t "client1-token,client2-token,client3-token"
|
|
|
140
142
|
## 架构
|
|
141
143
|
|
|
142
144
|
```
|
|
143
|
-
|
|
145
|
+
控制端口(复用):
|
|
146
|
+
├─ WebSocket 控制通道 ── JSON 消息(认证/注册/心跳/连接通知)
|
|
147
|
+
├─ TCP 数据通道 ─────── 二进制帧(HTTP/WS/TCP 数据转发)
|
|
148
|
+
└─ UDP 数据通道 ─────── UDP 数据帧(UDP 数据转发)
|
|
149
|
+
|
|
150
|
+
代理端口(每端口同时监听 TCP + UDP):
|
|
151
|
+
├─ TCP 服务器 → 自动识别 HTTP/WebSocket/TCP 协议
|
|
152
|
+
└─ UDP 服务器 → 转发 UDP 数据
|
|
144
153
|
```
|
|
145
154
|
|
|
146
|
-
**每个代理端口同时支持 HTTP
|
|
155
|
+
**每个代理端口同时支持 HTTP/WebSocket/TCP/UDP 四种协议**,客户端无需指定协议类型。
|
|
147
156
|
|
|
148
157
|
## 许可证
|
|
149
158
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module data-channel
|
|
3
|
+
*
|
|
4
|
+
* 服务端数据通道管理器。
|
|
5
|
+
*
|
|
6
|
+
* 管理穿透客户端的 TCP 数据通道和 UDP 数据通道连接。
|
|
7
|
+
* TCP 数据通道用于高效传输 HTTP/WS/TCP 的原始二进制数据,
|
|
8
|
+
* UDP 数据通道用于保留 UDP 语义的数据转发。
|
|
9
|
+
*/
|
|
10
|
+
import { Socket } from 'net';
|
|
11
|
+
import { Socket as UdpSocket, RemoteInfo } from 'dgram';
|
|
12
|
+
import { EventEmitter } from 'events';
|
|
13
|
+
import { SessionManager } from './session-manager.js';
|
|
14
|
+
/**
|
|
15
|
+
* 服务端数据通道管理器
|
|
16
|
+
*
|
|
17
|
+
* 管理所有客户端的 TCP 二进制数据通道和 UDP 数据通道。
|
|
18
|
+
*
|
|
19
|
+
* 事件:
|
|
20
|
+
* - `'data'(clientId, connectionId, data)` — 收到客户端 TCP 数据帧
|
|
21
|
+
* - `'udpData'(clientId, connectionId, data)` — 收到客户端 UDP 数据帧
|
|
22
|
+
*/
|
|
23
|
+
export declare class DataChannelManager extends EventEmitter {
|
|
24
|
+
/** 客户端 TCP 数据通道:clientId → Socket */
|
|
25
|
+
private tcpChannels;
|
|
26
|
+
/** 客户端 TCP 帧解析器:clientId → FrameParser */
|
|
27
|
+
private frameParsers;
|
|
28
|
+
/** 客户端 UDP 地址:clientId → RemoteInfo */
|
|
29
|
+
private udpClients;
|
|
30
|
+
/** 服务端 UDP socket 引用 */
|
|
31
|
+
private udpSocket;
|
|
32
|
+
/** 会话管理器 */
|
|
33
|
+
private sessionManager;
|
|
34
|
+
constructor(sessionManager: SessionManager);
|
|
35
|
+
/**
|
|
36
|
+
* 设置 UDP socket 引用
|
|
37
|
+
*/
|
|
38
|
+
setUdpSocket(socket: UdpSocket): void;
|
|
39
|
+
/**
|
|
40
|
+
* 处理新的 TCP 数据通道连接
|
|
41
|
+
*
|
|
42
|
+
* 解析认证帧,验证 clientId,建立关联。
|
|
43
|
+
*
|
|
44
|
+
* @param socket - 新的 TCP 连接
|
|
45
|
+
* @param initialData - 包含认证帧的初始数据
|
|
46
|
+
*/
|
|
47
|
+
handleNewTcpConnection(socket: Socket, initialData: Buffer): void;
|
|
48
|
+
/**
|
|
49
|
+
* 处理 UDP 消息
|
|
50
|
+
*
|
|
51
|
+
* 区分控制帧(注册/保活)和数据帧。
|
|
52
|
+
*
|
|
53
|
+
* @param msg - 收到的 UDP 数据包
|
|
54
|
+
* @param rinfo - 发送方地址信息
|
|
55
|
+
*/
|
|
56
|
+
handleUdpMessage(msg: Buffer, rinfo: RemoteInfo): void;
|
|
57
|
+
private handleUdpRegister;
|
|
58
|
+
/**
|
|
59
|
+
* 通过 TCP 数据通道发送数据帧给客户端
|
|
60
|
+
*
|
|
61
|
+
* @param clientId - 目标客户端 ID
|
|
62
|
+
* @param connectionId - 连接 ID
|
|
63
|
+
* @param data - 要发送的原始数据
|
|
64
|
+
* @returns 是否发送成功
|
|
65
|
+
*/
|
|
66
|
+
sendToClient(clientId: string, connectionId: string, data: Buffer): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* 通过 UDP 通道发送数据帧给客户端
|
|
69
|
+
*
|
|
70
|
+
* @param clientId - 目标客户端 ID
|
|
71
|
+
* @param connectionId - 连接 ID
|
|
72
|
+
* @param data - 要发送的原始数据
|
|
73
|
+
* @returns 是否发送成功
|
|
74
|
+
*/
|
|
75
|
+
sendUdpToClient(clientId: string, connectionId: string, data: Buffer): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* 检查客户端是否已建立 TCP 数据通道
|
|
78
|
+
*/
|
|
79
|
+
hasDataChannel(clientId: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* 检查客户端是否已注册 UDP 通道
|
|
82
|
+
*/
|
|
83
|
+
hasUdpChannel(clientId: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* 移除客户端的所有数据通道
|
|
86
|
+
*/
|
|
87
|
+
removeClient(clientId: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* 清理所有数据通道
|
|
90
|
+
*/
|
|
91
|
+
clear(): void;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=data-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-channel.d.ts","sourceRoot":"","sources":["../src/data-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAWtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,qCAAqC;IACrC,OAAO,CAAC,WAAW,CAAkC;IACrD,0CAA0C;IAC1C,OAAO,CAAC,YAAY,CAAuC;IAC3D,uCAAuC;IACvC,OAAO,CAAC,UAAU,CAAsC;IACxD,wBAAwB;IACxB,OAAO,CAAC,SAAS,CAA0B;IAC3C,YAAY;IACZ,OAAO,CAAC,cAAc,CAAiB;gBAE3B,cAAc,EAAE,cAAc;IAK1C;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIrC;;;;;;;OAOG;IACH,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAwDjE;;;;;;;OAOG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IA6BtD,OAAO,CAAC,iBAAiB;IAiBzB;;;;;;;OAOG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAS3E;;;;;;;OAOG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAU9E;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKzC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIxC;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUpC;;OAEG;IACH,KAAK,IAAI,IAAI;CAQd"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module data-channel
|
|
3
|
+
*
|
|
4
|
+
* 服务端数据通道管理器。
|
|
5
|
+
*
|
|
6
|
+
* 管理穿透客户端的 TCP 数据通道和 UDP 数据通道连接。
|
|
7
|
+
* TCP 数据通道用于高效传输 HTTP/WS/TCP 的原始二进制数据,
|
|
8
|
+
* UDP 数据通道用于保留 UDP 语义的数据转发。
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import { parseTcpAuthFrame, parseUdpControlFrame, parseUdpDataFrame, writeDataFrame, writeUdpDataFrame, FrameParser, AUTH_RESPONSE, logger, } from '@feng3d/chuantou-shared';
|
|
12
|
+
/**
|
|
13
|
+
* 服务端数据通道管理器
|
|
14
|
+
*
|
|
15
|
+
* 管理所有客户端的 TCP 二进制数据通道和 UDP 数据通道。
|
|
16
|
+
*
|
|
17
|
+
* 事件:
|
|
18
|
+
* - `'data'(clientId, connectionId, data)` — 收到客户端 TCP 数据帧
|
|
19
|
+
* - `'udpData'(clientId, connectionId, data)` — 收到客户端 UDP 数据帧
|
|
20
|
+
*/
|
|
21
|
+
export class DataChannelManager extends EventEmitter {
|
|
22
|
+
constructor(sessionManager) {
|
|
23
|
+
super();
|
|
24
|
+
/** 客户端 TCP 数据通道:clientId → Socket */
|
|
25
|
+
this.tcpChannels = new Map();
|
|
26
|
+
/** 客户端 TCP 帧解析器:clientId → FrameParser */
|
|
27
|
+
this.frameParsers = new Map();
|
|
28
|
+
/** 客户端 UDP 地址:clientId → RemoteInfo */
|
|
29
|
+
this.udpClients = new Map();
|
|
30
|
+
/** 服务端 UDP socket 引用 */
|
|
31
|
+
this.udpSocket = null;
|
|
32
|
+
this.sessionManager = sessionManager;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 设置 UDP socket 引用
|
|
36
|
+
*/
|
|
37
|
+
setUdpSocket(socket) {
|
|
38
|
+
this.udpSocket = socket;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 处理新的 TCP 数据通道连接
|
|
42
|
+
*
|
|
43
|
+
* 解析认证帧,验证 clientId,建立关联。
|
|
44
|
+
*
|
|
45
|
+
* @param socket - 新的 TCP 连接
|
|
46
|
+
* @param initialData - 包含认证帧的初始数据
|
|
47
|
+
*/
|
|
48
|
+
handleNewTcpConnection(socket, initialData) {
|
|
49
|
+
const clientId = parseTcpAuthFrame(initialData);
|
|
50
|
+
if (!clientId) {
|
|
51
|
+
logger.error('数据通道认证帧解析失败');
|
|
52
|
+
socket.write(AUTH_RESPONSE.FAILURE);
|
|
53
|
+
socket.destroy();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// 验证 clientId 是否为已认证的客户端
|
|
57
|
+
const clientInfo = this.sessionManager.getClientInfo(clientId);
|
|
58
|
+
if (!clientInfo || !clientInfo.authenticated) {
|
|
59
|
+
logger.error(`数据通道认证失败: 客户端 ${clientId} 未认证`);
|
|
60
|
+
socket.write(AUTH_RESPONSE.FAILURE);
|
|
61
|
+
socket.destroy();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// 关闭旧的数据通道(如果存在)
|
|
65
|
+
const oldSocket = this.tcpChannels.get(clientId);
|
|
66
|
+
if (oldSocket) {
|
|
67
|
+
oldSocket.destroy();
|
|
68
|
+
this.frameParsers.get(clientId)?.reset();
|
|
69
|
+
}
|
|
70
|
+
// 建立新的数据通道
|
|
71
|
+
socket.write(AUTH_RESPONSE.SUCCESS);
|
|
72
|
+
this.tcpChannels.set(clientId, socket);
|
|
73
|
+
const parser = new FrameParser();
|
|
74
|
+
this.frameParsers.set(clientId, parser);
|
|
75
|
+
parser.on('frame', (connectionId, data) => {
|
|
76
|
+
this.emit('data', clientId, connectionId, data);
|
|
77
|
+
});
|
|
78
|
+
socket.on('data', (chunk) => {
|
|
79
|
+
parser.push(chunk);
|
|
80
|
+
});
|
|
81
|
+
socket.on('close', () => {
|
|
82
|
+
logger.log(`客户端 ${clientId} 数据通道已关闭`);
|
|
83
|
+
this.tcpChannels.delete(clientId);
|
|
84
|
+
this.frameParsers.delete(clientId);
|
|
85
|
+
});
|
|
86
|
+
socket.on('error', (error) => {
|
|
87
|
+
logger.error(`客户端 ${clientId} 数据通道错误:`, error.message);
|
|
88
|
+
this.tcpChannels.delete(clientId);
|
|
89
|
+
this.frameParsers.delete(clientId);
|
|
90
|
+
});
|
|
91
|
+
logger.log(`客户端 ${clientId} 数据通道已建立`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 处理 UDP 消息
|
|
95
|
+
*
|
|
96
|
+
* 区分控制帧(注册/保活)和数据帧。
|
|
97
|
+
*
|
|
98
|
+
* @param msg - 收到的 UDP 数据包
|
|
99
|
+
* @param rinfo - 发送方地址信息
|
|
100
|
+
*/
|
|
101
|
+
handleUdpMessage(msg, rinfo) {
|
|
102
|
+
// 尝试解析为控制帧
|
|
103
|
+
const control = parseUdpControlFrame(msg);
|
|
104
|
+
if (control) {
|
|
105
|
+
if (control.type === 'register') {
|
|
106
|
+
this.handleUdpRegister(control.clientId, rinfo);
|
|
107
|
+
}
|
|
108
|
+
// keepalive 只需更新地址
|
|
109
|
+
if (control.type === 'keepalive') {
|
|
110
|
+
this.udpClients.set(control.clientId, rinfo);
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// 尝试解析为数据帧
|
|
115
|
+
const frame = parseUdpDataFrame(msg);
|
|
116
|
+
if (frame) {
|
|
117
|
+
// 查找此连接所属的客户端
|
|
118
|
+
// 通过遍历已注册的 UDP 客户端,匹配发送方地址
|
|
119
|
+
for (const [clientId, clientRinfo] of this.udpClients) {
|
|
120
|
+
if (clientRinfo.address === rinfo.address && clientRinfo.port === rinfo.port) {
|
|
121
|
+
this.emit('udpData', clientId, frame.connectionId, frame.data);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
logger.warn(`收到未知来源的 UDP 数据帧: ${rinfo.address}:${rinfo.port}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
handleUdpRegister(clientId, rinfo) {
|
|
129
|
+
const clientInfo = this.sessionManager.getClientInfo(clientId);
|
|
130
|
+
if (!clientInfo || !clientInfo.authenticated) {
|
|
131
|
+
logger.error(`UDP 注册失败: 客户端 ${clientId} 未认证`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.udpClients.set(clientId, rinfo);
|
|
135
|
+
// 发送确认
|
|
136
|
+
if (this.udpSocket) {
|
|
137
|
+
this.udpSocket.send(AUTH_RESPONSE.SUCCESS, rinfo.port, rinfo.address);
|
|
138
|
+
}
|
|
139
|
+
logger.log(`客户端 ${clientId} UDP 通道已注册 (${rinfo.address}:${rinfo.port})`);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 通过 TCP 数据通道发送数据帧给客户端
|
|
143
|
+
*
|
|
144
|
+
* @param clientId - 目标客户端 ID
|
|
145
|
+
* @param connectionId - 连接 ID
|
|
146
|
+
* @param data - 要发送的原始数据
|
|
147
|
+
* @returns 是否发送成功
|
|
148
|
+
*/
|
|
149
|
+
sendToClient(clientId, connectionId, data) {
|
|
150
|
+
const socket = this.tcpChannels.get(clientId);
|
|
151
|
+
if (socket && !socket.destroyed) {
|
|
152
|
+
socket.write(writeDataFrame(connectionId, data));
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 通过 UDP 通道发送数据帧给客户端
|
|
159
|
+
*
|
|
160
|
+
* @param clientId - 目标客户端 ID
|
|
161
|
+
* @param connectionId - 连接 ID
|
|
162
|
+
* @param data - 要发送的原始数据
|
|
163
|
+
* @returns 是否发送成功
|
|
164
|
+
*/
|
|
165
|
+
sendUdpToClient(clientId, connectionId, data) {
|
|
166
|
+
const clientRinfo = this.udpClients.get(clientId);
|
|
167
|
+
if (clientRinfo && this.udpSocket) {
|
|
168
|
+
const frame = writeUdpDataFrame(connectionId, data);
|
|
169
|
+
this.udpSocket.send(frame, clientRinfo.port, clientRinfo.address);
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 检查客户端是否已建立 TCP 数据通道
|
|
176
|
+
*/
|
|
177
|
+
hasDataChannel(clientId) {
|
|
178
|
+
const socket = this.tcpChannels.get(clientId);
|
|
179
|
+
return !!socket && !socket.destroyed;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 检查客户端是否已注册 UDP 通道
|
|
183
|
+
*/
|
|
184
|
+
hasUdpChannel(clientId) {
|
|
185
|
+
return this.udpClients.has(clientId);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 移除客户端的所有数据通道
|
|
189
|
+
*/
|
|
190
|
+
removeClient(clientId) {
|
|
191
|
+
const socket = this.tcpChannels.get(clientId);
|
|
192
|
+
if (socket) {
|
|
193
|
+
socket.destroy();
|
|
194
|
+
this.tcpChannels.delete(clientId);
|
|
195
|
+
}
|
|
196
|
+
this.frameParsers.delete(clientId);
|
|
197
|
+
this.udpClients.delete(clientId);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* 清理所有数据通道
|
|
201
|
+
*/
|
|
202
|
+
clear() {
|
|
203
|
+
for (const socket of this.tcpChannels.values()) {
|
|
204
|
+
socket.destroy();
|
|
205
|
+
}
|
|
206
|
+
this.tcpChannels.clear();
|
|
207
|
+
this.frameParsers.clear();
|
|
208
|
+
this.udpClients.clear();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=data-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-channel.js","sourceRoot":"","sources":["../src/data-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module control-handler
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* 控制通道处理器模块。
|
|
5
|
+
*
|
|
6
|
+
* 负责处理客户端通过 WebSocket 控制通道发送的控制消息,
|
|
7
|
+
* 包括认证、端口注册/注销、心跳以及连接关闭等。
|
|
8
|
+
* 实际数据传输已移至独立的二进制数据通道。
|
|
5
9
|
*/
|
|
6
10
|
import { WebSocket } from 'ws';
|
|
7
11
|
import { ServerConfig } from '@feng3d/chuantou-shared';
|
|
@@ -10,149 +14,33 @@ import { UnifiedProxyHandler } from './unified-proxy.js';
|
|
|
10
14
|
/**
|
|
11
15
|
* 控制通道处理器
|
|
12
16
|
*
|
|
13
|
-
* 处理客户端通过 WebSocket
|
|
17
|
+
* 处理客户端通过 WebSocket 控制通道发送的控制消息:
|
|
14
18
|
* - 客户端认证(AUTH)
|
|
15
19
|
* - 端口注册(REGISTER)与注销(UNREGISTER)
|
|
16
20
|
* - 心跳保活(HEARTBEAT)
|
|
17
|
-
* -
|
|
21
|
+
* - 连接关闭(CONNECTION_CLOSE)
|
|
18
22
|
*/
|
|
19
23
|
export declare class ControlHandler {
|
|
20
|
-
/** 会话管理器实例 */
|
|
21
24
|
private sessionManager;
|
|
22
|
-
/** 服务器配置 */
|
|
23
25
|
private config;
|
|
24
|
-
/** 统一代理处理器(同时支持 HTTP 和 WebSocket) */
|
|
25
26
|
private proxyHandler;
|
|
26
|
-
/**
|
|
27
|
-
* 创建控制通道处理器实例
|
|
28
|
-
*
|
|
29
|
-
* @param sessionManager - 会话管理器,用于管理客户端会话
|
|
30
|
-
* @param config - 服务器配置,包含认证令牌等信息
|
|
31
|
-
* @param proxyHandler - 统一代理处理器,用于启停代理服务器
|
|
32
|
-
*/
|
|
33
27
|
constructor(sessionManager: SessionManager, config: ServerConfig, proxyHandler: UnifiedProxyHandler);
|
|
34
28
|
/**
|
|
35
29
|
* 处理新的 WebSocket 控制通道连接
|
|
36
|
-
*
|
|
37
|
-
* 为新连接创建会话,设置消息处理、关闭处理和错误处理回调,
|
|
38
|
-
* 并启动 30 秒认证超时计时器。
|
|
39
|
-
*
|
|
40
|
-
* @param socket - 新建立的 WebSocket 连接
|
|
41
30
|
*/
|
|
42
31
|
handleConnection(socket: WebSocket): void;
|
|
43
32
|
/**
|
|
44
|
-
*
|
|
33
|
+
* 处理控制消息
|
|
45
34
|
*
|
|
46
|
-
*
|
|
47
|
-
* 支持的消息类型包括:AUTH、REGISTER、UNREGISTER、HEARTBEAT。
|
|
48
|
-
*
|
|
49
|
-
* @param clientId - 发送消息的客户端 ID
|
|
50
|
-
* @param socket - 客户端的 WebSocket 连接
|
|
51
|
-
* @param data - 收到的原始消息数据
|
|
35
|
+
* 仅处理控制消息,数据传输由独立的二进制数据通道处理。
|
|
52
36
|
*/
|
|
53
37
|
private handleMessage;
|
|
54
|
-
/**
|
|
55
|
-
* 处理认证消息
|
|
56
|
-
*
|
|
57
|
-
* 验证客户端提供的令牌是否在配置的有效令牌列表中。
|
|
58
|
-
* 认证成功后清除认证超时计时器;认证失败则关闭连接。
|
|
59
|
-
*
|
|
60
|
-
* @param clientId - 客户端唯一标识 ID
|
|
61
|
-
* @param socket - 客户端的 WebSocket 连接
|
|
62
|
-
* @param message - 收到的认证消息
|
|
63
|
-
*/
|
|
64
38
|
private handleAuth;
|
|
65
|
-
/**
|
|
66
|
-
* 处理端口注册消息
|
|
67
|
-
*
|
|
68
|
-
* 验证客户端认证状态和端口范围(1024-65535),检查端口是否已被占用,
|
|
69
|
-
* 然后注册端口并启动代理服务器(同时支持 HTTP 和 WebSocket)。
|
|
70
|
-
* 若启动失败则自动回滚端口注册。
|
|
71
|
-
*
|
|
72
|
-
* @param clientId - 客户端唯一标识 ID
|
|
73
|
-
* @param socket - 客户端的 WebSocket 连接
|
|
74
|
-
* @param message - 收到的端口注册消息
|
|
75
|
-
*/
|
|
76
39
|
private handleRegister;
|
|
77
|
-
/**
|
|
78
|
-
* 处理端口注销消息
|
|
79
|
-
*
|
|
80
|
-
* 验证客户端认证状态和端口归属,停止代理服务器并注销端口。
|
|
81
|
-
*
|
|
82
|
-
* @param clientId - 客户端唯一标识 ID
|
|
83
|
-
* @param socket - 客户端的 WebSocket 连接
|
|
84
|
-
* @param message - 收到的端口注销消息
|
|
85
|
-
*/
|
|
86
40
|
private handleUnregister;
|
|
87
|
-
/**
|
|
88
|
-
* 处理心跳消息
|
|
89
|
-
*
|
|
90
|
-
* 更新客户端的最后心跳时间并回复心跳响应。
|
|
91
|
-
*
|
|
92
|
-
* @param clientId - 客户端唯一标识 ID
|
|
93
|
-
* @param socket - 客户端的 WebSocket 连接
|
|
94
|
-
* @param message - 收到的心跳消息
|
|
95
|
-
*/
|
|
96
41
|
private handleHeartbeat;
|
|
97
|
-
/**
|
|
98
|
-
* 处理客户端断开连接
|
|
99
|
-
*
|
|
100
|
-
* 停止该客户端注册的所有代理服务器,并移除其会话。
|
|
101
|
-
*
|
|
102
|
-
* @param clientId - 断开连接的客户端唯一标识 ID
|
|
103
|
-
*/
|
|
104
42
|
private handleDisconnect;
|
|
105
|
-
/**
|
|
106
|
-
* 通过 WebSocket 发送消息
|
|
107
|
-
*
|
|
108
|
-
* 将消息对象序列化为 JSON 字符串后发送,仅在连接处于 OPEN 状态时发送。
|
|
109
|
-
*
|
|
110
|
-
* @param socket - 目标 WebSocket 连接
|
|
111
|
-
* @param message - 需要发送的消息对象
|
|
112
|
-
*/
|
|
113
43
|
private sendMessage;
|
|
114
|
-
/**
|
|
115
|
-
* 发送错误消息
|
|
116
|
-
*
|
|
117
|
-
* 构造并发送一条 CONNECTION_ERROR 类型的错误消息给客户端。
|
|
118
|
-
*
|
|
119
|
-
* @param socket - 目标 WebSocket 连接
|
|
120
|
-
* @param error - 错误描述信息
|
|
121
|
-
*/
|
|
122
44
|
private sendError;
|
|
123
|
-
/**
|
|
124
|
-
* 处理客户端返回的 HTTP 响应数据
|
|
125
|
-
*
|
|
126
|
-
* @param connectionId - 连接唯一标识 ID
|
|
127
|
-
* @param data - 客户端返回的 HTTP 响应数据
|
|
128
|
-
*/
|
|
129
|
-
handleClientResponse(connectionId: string, data: any): void;
|
|
130
|
-
/**
|
|
131
|
-
* 处理来自客户端的 WebSocket 数据
|
|
132
|
-
*
|
|
133
|
-
* @param connectionId - 连接唯一标识 ID
|
|
134
|
-
* @param data - 客户端发送的数据
|
|
135
|
-
*/
|
|
136
|
-
handleClientData(connectionId: string, data: Buffer): void;
|
|
137
|
-
/**
|
|
138
|
-
* 处理来自客户端的连接关闭请求
|
|
139
|
-
*
|
|
140
|
-
* @param connectionId - 需要关闭的连接唯一标识 ID
|
|
141
|
-
* @param code - 可选的关闭状态码
|
|
142
|
-
*/
|
|
143
|
-
handleClientClose(connectionId: string, code?: number): void;
|
|
144
|
-
/**
|
|
145
|
-
* 处理来自客户端的流式响应数据
|
|
146
|
-
*
|
|
147
|
-
* @param connectionId - 连接唯一标识 ID
|
|
148
|
-
* @param data - 客户端发送的流式数据
|
|
149
|
-
*/
|
|
150
|
-
handleClientStreamData(connectionId: string, data: Buffer): void;
|
|
151
|
-
/**
|
|
152
|
-
* 处理来自客户端的流式响应结束通知
|
|
153
|
-
*
|
|
154
|
-
* @param connectionId - 连接唯一标识 ID
|
|
155
|
-
*/
|
|
156
|
-
handleClientStreamEnd(connectionId: string): void;
|
|
157
45
|
}
|
|
158
46
|
//# sourceMappingURL=control-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/control-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"control-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/control-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAOL,YAAY,EAEb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,YAAY,CAAsB;gBAGxC,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,mBAAmB;IAOnC;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAiCzC;;;;OAIG;YACW,aAAa;YAsCb,UAAU;YA2CV,cAAc;YA0Dd,gBAAgB;YAuBhB,eAAe;IAO7B,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;CAMlB"}
|