@feng3d/cts 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.
- package/README.md +150 -0
- package/dist/boot.d.ts +41 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +204 -0
- package/dist/boot.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +377 -0
- package/dist/cli.js.map +1 -0
- package/dist/handlers/control-handler.d.ts +158 -0
- package/dist/handlers/control-handler.d.ts.map +1 -0
- package/dist/handlers/control-handler.js +378 -0
- package/dist/handlers/control-handler.js.map +1 -0
- package/dist/handlers/unified-proxy.d.ts +207 -0
- package/dist/handlers/unified-proxy.d.ts.map +1 -0
- package/dist/handlers/unified-proxy.js +475 -0
- package/dist/handlers/unified-proxy.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +115 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +433 -0
- package/dist/server.js.map +1 -0
- package/dist/session-manager.d.ts +218 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +372 -0
- package/dist/session-manager.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module session-manager
|
|
3
|
+
* @description 会话管理模块,负责管理所有连接的客户端会话。
|
|
4
|
+
* 提供客户端的创建、认证、端口注册、连接跟踪、心跳检测和会话清理等功能。
|
|
5
|
+
*/
|
|
6
|
+
import { WebSocket } from 'ws';
|
|
7
|
+
import { ClientInfo } from '@feng3d/chuantou-shared';
|
|
8
|
+
/**
|
|
9
|
+
* 会话管理器
|
|
10
|
+
*
|
|
11
|
+
* 管理所有连接的客户端会话,包括:
|
|
12
|
+
* - 创建和销毁客户端会话
|
|
13
|
+
* - 客户端认证和端口注册
|
|
14
|
+
* - 连接的添加和移除跟踪
|
|
15
|
+
* - 定时心跳检测,自动清除超时会话
|
|
16
|
+
* - 统计信息汇总
|
|
17
|
+
*/
|
|
18
|
+
export declare class SessionManager {
|
|
19
|
+
/** 客户端信息映射表,键为客户端 ID */
|
|
20
|
+
private clients;
|
|
21
|
+
/** WebSocket 到客户端 ID 的映射表 */
|
|
22
|
+
private socketToClientId;
|
|
23
|
+
/** 心跳检测间隔时间(毫秒) */
|
|
24
|
+
private heartbeatInterval;
|
|
25
|
+
/** 会话超时时间(毫秒) */
|
|
26
|
+
private sessionTimeout;
|
|
27
|
+
/** 心跳检测定时器 */
|
|
28
|
+
private heartbeatTimer?;
|
|
29
|
+
/**
|
|
30
|
+
* 创建会话管理器实例
|
|
31
|
+
*
|
|
32
|
+
* @param heartbeatInterval - 心跳检测间隔时间(毫秒),默认使用 {@link DEFAULT_CONFIG.HEARTBEAT_INTERVAL}
|
|
33
|
+
* @param sessionTimeout - 会话超时时间(毫秒),默认使用 {@link DEFAULT_CONFIG.SESSION_TIMEOUT}
|
|
34
|
+
*/
|
|
35
|
+
constructor(heartbeatInterval?: number, sessionTimeout?: number);
|
|
36
|
+
/**
|
|
37
|
+
* 创建新会话
|
|
38
|
+
*
|
|
39
|
+
* 为新连接的 WebSocket 创建一个客户端会话,分配唯一 ID 并初始化客户端信息。
|
|
40
|
+
*
|
|
41
|
+
* @param socket - 客户端的 WebSocket 连接
|
|
42
|
+
* @returns 新创建的客户端唯一标识 ID
|
|
43
|
+
*/
|
|
44
|
+
createSession(socket: WebSocket): string;
|
|
45
|
+
/**
|
|
46
|
+
* 获取客户端 ID
|
|
47
|
+
*
|
|
48
|
+
* 根据 WebSocket 连接查找对应的客户端 ID。
|
|
49
|
+
*
|
|
50
|
+
* @param socket - 客户端的 WebSocket 连接
|
|
51
|
+
* @returns 对应的客户端 ID;若未找到则返回 `undefined`
|
|
52
|
+
*/
|
|
53
|
+
getClientId(socket: WebSocket): string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* 获取客户端 WebSocket 连接
|
|
56
|
+
*
|
|
57
|
+
* 根据客户端 ID 查找对应的 WebSocket 连接。
|
|
58
|
+
*
|
|
59
|
+
* @param clientId - 客户端唯一标识 ID
|
|
60
|
+
* @returns 对应的 WebSocket 连接;若未找到则返回 `undefined`
|
|
61
|
+
*/
|
|
62
|
+
getClientSocket(clientId: string): WebSocket | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* 获取客户端信息
|
|
65
|
+
*
|
|
66
|
+
* 根据客户端 ID 查找并返回完整的客户端信息。
|
|
67
|
+
*
|
|
68
|
+
* @param clientId - 客户端唯一标识 ID
|
|
69
|
+
* @returns 对应的 {@link ClientInfo} 客户端信息;若未找到则返回 `undefined`
|
|
70
|
+
*/
|
|
71
|
+
getClientInfo(clientId: string): ClientInfo | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* 认证客户端
|
|
74
|
+
*
|
|
75
|
+
* 将指定客户端标记为已认证状态,并记录认证时间。
|
|
76
|
+
*
|
|
77
|
+
* @param clientId - 客户端唯一标识 ID
|
|
78
|
+
* @returns 认证是否成功;若客户端不存在则返回 `false`
|
|
79
|
+
*/
|
|
80
|
+
authenticateClient(clientId: string): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 注册端口
|
|
83
|
+
*
|
|
84
|
+
* 为已认证的客户端注册一个远程端口。注册前会检查端口是否已被其他客户端占用。
|
|
85
|
+
*
|
|
86
|
+
* @param clientId - 客户端唯一标识 ID
|
|
87
|
+
* @param port - 需要注册的远程端口号
|
|
88
|
+
* @returns 注册是否成功;客户端未认证或端口已被占用时返回 `false`
|
|
89
|
+
*/
|
|
90
|
+
registerPort(clientId: string, port: number): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* 注销端口
|
|
93
|
+
*
|
|
94
|
+
* 从指定客户端的已注册端口列表中移除一个端口。
|
|
95
|
+
*
|
|
96
|
+
* @param clientId - 客户端唯一标识 ID
|
|
97
|
+
* @param port - 需要注销的远程端口号
|
|
98
|
+
* @returns 注销是否成功;客户端不存在或端口未注册时返回 `false`
|
|
99
|
+
*/
|
|
100
|
+
unregisterPort(clientId: string, port: number): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* 获取注册指定端口的客户端 ID
|
|
103
|
+
*
|
|
104
|
+
* 遍历所有客户端,查找注册了指定端口的客户端。
|
|
105
|
+
*
|
|
106
|
+
* @param port - 需要查询的端口号
|
|
107
|
+
* @returns 注册该端口的客户端 ID;若无客户端注册该端口则返回 `undefined`
|
|
108
|
+
*/
|
|
109
|
+
getClientByPort(port: number): string | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* 添加连接记录
|
|
112
|
+
*
|
|
113
|
+
* 为指定客户端记录一个新的活跃连接。
|
|
114
|
+
*
|
|
115
|
+
* @param clientId - 客户端唯一标识 ID
|
|
116
|
+
* @param connectionId - 连接唯一标识 ID
|
|
117
|
+
* @param remoteAddress - 远程连接的 IP 地址
|
|
118
|
+
* @param protocol - 连接协议类型,`'http'` 或 `'websocket'`
|
|
119
|
+
*/
|
|
120
|
+
addConnection(clientId: string, connectionId: string, remoteAddress: string, protocol: 'http' | 'websocket'): void;
|
|
121
|
+
/**
|
|
122
|
+
* 移除连接记录
|
|
123
|
+
*
|
|
124
|
+
* 从所有客户端中移除指定的连接记录。
|
|
125
|
+
*
|
|
126
|
+
* @param connectionId - 需要移除的连接唯一标识 ID
|
|
127
|
+
*/
|
|
128
|
+
removeConnection(connectionId: string): void;
|
|
129
|
+
/**
|
|
130
|
+
* 移除会话
|
|
131
|
+
*
|
|
132
|
+
* 根据客户端 ID 移除对应的会话,清理其所有连接记录、注册端口和 WebSocket 映射。
|
|
133
|
+
*
|
|
134
|
+
* @param clientId - 需要移除的客户端唯一标识 ID
|
|
135
|
+
*/
|
|
136
|
+
removeSession(clientId: string): void;
|
|
137
|
+
/**
|
|
138
|
+
* 根据 WebSocket 连接移除会话
|
|
139
|
+
*
|
|
140
|
+
* 通过 WebSocket 连接查找对应的客户端 ID,并移除其会话。
|
|
141
|
+
*
|
|
142
|
+
* @param socket - 需要移除会话的 WebSocket 连接
|
|
143
|
+
*/
|
|
144
|
+
removeSessionBySocket(socket: WebSocket): void;
|
|
145
|
+
/**
|
|
146
|
+
* 更新心跳时间
|
|
147
|
+
*
|
|
148
|
+
* 更新指定客户端的最后心跳时间为当前时间,用于保持会话活跃。
|
|
149
|
+
*
|
|
150
|
+
* @param clientId - 客户端唯一标识 ID
|
|
151
|
+
*/
|
|
152
|
+
updateHeartbeat(clientId: string): void;
|
|
153
|
+
/**
|
|
154
|
+
* 获取所有已认证客户端的 ID 列表
|
|
155
|
+
*
|
|
156
|
+
* 遍历所有客户端,筛选出已通过认证的客户端。
|
|
157
|
+
*
|
|
158
|
+
* @returns 已认证客户端的 ID 数组
|
|
159
|
+
*/
|
|
160
|
+
getAuthenticatedClients(): string[];
|
|
161
|
+
/**
|
|
162
|
+
* 获取所有已注册端口的映射
|
|
163
|
+
*
|
|
164
|
+
* 遍历所有客户端,收集所有已注册的端口及其对应的客户端 ID。
|
|
165
|
+
*
|
|
166
|
+
* @returns 端口号到客户端 ID 的 Map 映射
|
|
167
|
+
*/
|
|
168
|
+
getAllRegisteredPorts(): Map<number, string>;
|
|
169
|
+
/**
|
|
170
|
+
* 启动心跳检查定时器
|
|
171
|
+
*
|
|
172
|
+
* 定期检查所有已认证客户端的最后心跳时间,
|
|
173
|
+
* 若超过会话超时时间则自动关闭连接并移除会话。
|
|
174
|
+
*/
|
|
175
|
+
private startHeartbeatCheck;
|
|
176
|
+
/**
|
|
177
|
+
* 停止心跳检查定时器
|
|
178
|
+
*
|
|
179
|
+
* 清除心跳检测定时器,停止定期的超时检查。
|
|
180
|
+
*/
|
|
181
|
+
stopHeartbeatCheck(): void;
|
|
182
|
+
/**
|
|
183
|
+
* 获取统计信息
|
|
184
|
+
*
|
|
185
|
+
* 汇总当前所有客户端的统计数据,包括总客户端数、已认证数、连接数和端口数。
|
|
186
|
+
*
|
|
187
|
+
* @returns 包含以下字段的统计对象:
|
|
188
|
+
* - `totalClients` - 总客户端数
|
|
189
|
+
* - `authenticatedClients` - 已认证客户端数
|
|
190
|
+
* - `totalConnections` - 活跃连接总数
|
|
191
|
+
* - `totalPorts` - 已注册端口总数
|
|
192
|
+
*/
|
|
193
|
+
getStats(): {
|
|
194
|
+
totalClients: number;
|
|
195
|
+
authenticatedClients: number;
|
|
196
|
+
totalConnections: number;
|
|
197
|
+
totalPorts: number;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* 清理所有会话
|
|
201
|
+
*
|
|
202
|
+
* 停止心跳检查定时器,并清除所有客户端会话和 WebSocket 映射数据。
|
|
203
|
+
*/
|
|
204
|
+
clear(): void;
|
|
205
|
+
/**
|
|
206
|
+
* 获取已认证客户端的会话列表
|
|
207
|
+
*
|
|
208
|
+
* 返回所有已认证客户端的简要信息,用于状态展示。
|
|
209
|
+
*
|
|
210
|
+
* @returns 会话列表数组
|
|
211
|
+
*/
|
|
212
|
+
getSessions(): Array<{
|
|
213
|
+
clientId: string;
|
|
214
|
+
connectedAt: number;
|
|
215
|
+
registeredPorts: number[];
|
|
216
|
+
}>;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAkC,MAAM,yBAAyB,CAAC;AAErF;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,wBAAwB;IACxB,OAAO,CAAC,OAAO,CAA0B;IACzC,6BAA6B;IAC7B,OAAO,CAAC,gBAAgB,CAAyB;IACjD,mBAAmB;IACnB,OAAO,CAAC,iBAAiB,CAAS;IAClC,iBAAiB;IACjB,OAAO,CAAC,cAAc,CAAS;IAC/B,cAAc;IACd,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC;;;;;OAKG;gBACS,iBAAiB,GAAE,MAA0C,EAAE,cAAc,GAAE,MAAuC;IAQlI;;;;;;;OAOG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAaxC;;;;;;;OAOG;IACH,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS;IAIlD;;;;;;;OAOG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IASxD;;;;;;;OAOG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIvD;;;;;;;OAOG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAU7C;;;;;;;;OAQG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAerD;;;;;;;;OAQG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAQvD;;;;;;;OAOG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASjD;;;;;;;;;OASG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAalH;;;;;;OAMG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAM5C;;;;;;OAMG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAiBrC;;;;;;OAMG;IACH,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAO9C;;;;;;OAMG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOvC;;;;;;OAMG;IACH,uBAAuB,IAAI,MAAM,EAAE;IAUnC;;;;;;OAMG;IACH,qBAAqB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAU5C;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IAO1B;;;;;;;;;;OAUG;IACH,QAAQ,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAqBhH;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAMb;;;;;;OAMG;IACH,WAAW,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAa3F"}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module session-manager
|
|
3
|
+
* @description 会话管理模块,负责管理所有连接的客户端会话。
|
|
4
|
+
* 提供客户端的创建、认证、端口注册、连接跟踪、心跳检测和会话清理等功能。
|
|
5
|
+
*/
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
7
|
+
import { DEFAULT_CONFIG } from '@feng3d/chuantou-shared';
|
|
8
|
+
/**
|
|
9
|
+
* 会话管理器
|
|
10
|
+
*
|
|
11
|
+
* 管理所有连接的客户端会话,包括:
|
|
12
|
+
* - 创建和销毁客户端会话
|
|
13
|
+
* - 客户端认证和端口注册
|
|
14
|
+
* - 连接的添加和移除跟踪
|
|
15
|
+
* - 定时心跳检测,自动清除超时会话
|
|
16
|
+
* - 统计信息汇总
|
|
17
|
+
*/
|
|
18
|
+
export class SessionManager {
|
|
19
|
+
/**
|
|
20
|
+
* 创建会话管理器实例
|
|
21
|
+
*
|
|
22
|
+
* @param heartbeatInterval - 心跳检测间隔时间(毫秒),默认使用 {@link DEFAULT_CONFIG.HEARTBEAT_INTERVAL}
|
|
23
|
+
* @param sessionTimeout - 会话超时时间(毫秒),默认使用 {@link DEFAULT_CONFIG.SESSION_TIMEOUT}
|
|
24
|
+
*/
|
|
25
|
+
constructor(heartbeatInterval = DEFAULT_CONFIG.HEARTBEAT_INTERVAL, sessionTimeout = DEFAULT_CONFIG.SESSION_TIMEOUT) {
|
|
26
|
+
this.clients = new Map();
|
|
27
|
+
this.socketToClientId = new Map();
|
|
28
|
+
this.heartbeatInterval = heartbeatInterval;
|
|
29
|
+
this.sessionTimeout = sessionTimeout;
|
|
30
|
+
this.startHeartbeatCheck();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 创建新会话
|
|
34
|
+
*
|
|
35
|
+
* 为新连接的 WebSocket 创建一个客户端会话,分配唯一 ID 并初始化客户端信息。
|
|
36
|
+
*
|
|
37
|
+
* @param socket - 客户端的 WebSocket 连接
|
|
38
|
+
* @returns 新创建的客户端唯一标识 ID
|
|
39
|
+
*/
|
|
40
|
+
createSession(socket) {
|
|
41
|
+
const clientId = uuidv4();
|
|
42
|
+
const clientInfo = {
|
|
43
|
+
id: clientId,
|
|
44
|
+
authenticated: false,
|
|
45
|
+
registeredPorts: new Set(),
|
|
46
|
+
connections: new Map(),
|
|
47
|
+
};
|
|
48
|
+
this.clients.set(clientId, clientInfo);
|
|
49
|
+
this.socketToClientId.set(socket, clientId);
|
|
50
|
+
return clientId;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 获取客户端 ID
|
|
54
|
+
*
|
|
55
|
+
* 根据 WebSocket 连接查找对应的客户端 ID。
|
|
56
|
+
*
|
|
57
|
+
* @param socket - 客户端的 WebSocket 连接
|
|
58
|
+
* @returns 对应的客户端 ID;若未找到则返回 `undefined`
|
|
59
|
+
*/
|
|
60
|
+
getClientId(socket) {
|
|
61
|
+
return this.socketToClientId.get(socket);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 获取客户端 WebSocket 连接
|
|
65
|
+
*
|
|
66
|
+
* 根据客户端 ID 查找对应的 WebSocket 连接。
|
|
67
|
+
*
|
|
68
|
+
* @param clientId - 客户端唯一标识 ID
|
|
69
|
+
* @returns 对应的 WebSocket 连接;若未找到则返回 `undefined`
|
|
70
|
+
*/
|
|
71
|
+
getClientSocket(clientId) {
|
|
72
|
+
for (const [socket, id] of this.socketToClientId.entries()) {
|
|
73
|
+
if (id === clientId) {
|
|
74
|
+
return socket;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 获取客户端信息
|
|
81
|
+
*
|
|
82
|
+
* 根据客户端 ID 查找并返回完整的客户端信息。
|
|
83
|
+
*
|
|
84
|
+
* @param clientId - 客户端唯一标识 ID
|
|
85
|
+
* @returns 对应的 {@link ClientInfo} 客户端信息;若未找到则返回 `undefined`
|
|
86
|
+
*/
|
|
87
|
+
getClientInfo(clientId) {
|
|
88
|
+
return this.clients.get(clientId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 认证客户端
|
|
92
|
+
*
|
|
93
|
+
* 将指定客户端标记为已认证状态,并记录认证时间。
|
|
94
|
+
*
|
|
95
|
+
* @param clientId - 客户端唯一标识 ID
|
|
96
|
+
* @returns 认证是否成功;若客户端不存在则返回 `false`
|
|
97
|
+
*/
|
|
98
|
+
authenticateClient(clientId) {
|
|
99
|
+
const client = this.clients.get(clientId);
|
|
100
|
+
if (client) {
|
|
101
|
+
client.authenticated = true;
|
|
102
|
+
client.authenticatedAt = Date.now();
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 注册端口
|
|
109
|
+
*
|
|
110
|
+
* 为已认证的客户端注册一个远程端口。注册前会检查端口是否已被其他客户端占用。
|
|
111
|
+
*
|
|
112
|
+
* @param clientId - 客户端唯一标识 ID
|
|
113
|
+
* @param port - 需要注册的远程端口号
|
|
114
|
+
* @returns 注册是否成功;客户端未认证或端口已被占用时返回 `false`
|
|
115
|
+
*/
|
|
116
|
+
registerPort(clientId, port) {
|
|
117
|
+
const client = this.clients.get(clientId);
|
|
118
|
+
if (!client || !client.authenticated) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
// 检查端口是否已被其他客户端注册
|
|
122
|
+
for (const [id, info] of this.clients.entries()) {
|
|
123
|
+
if (id !== clientId && info.registeredPorts.has(port)) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
client.registeredPorts.add(port);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 注销端口
|
|
132
|
+
*
|
|
133
|
+
* 从指定客户端的已注册端口列表中移除一个端口。
|
|
134
|
+
*
|
|
135
|
+
* @param clientId - 客户端唯一标识 ID
|
|
136
|
+
* @param port - 需要注销的远程端口号
|
|
137
|
+
* @returns 注销是否成功;客户端不存在或端口未注册时返回 `false`
|
|
138
|
+
*/
|
|
139
|
+
unregisterPort(clientId, port) {
|
|
140
|
+
const client = this.clients.get(clientId);
|
|
141
|
+
if (client) {
|
|
142
|
+
return client.registeredPorts.delete(port);
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 获取注册指定端口的客户端 ID
|
|
148
|
+
*
|
|
149
|
+
* 遍历所有客户端,查找注册了指定端口的客户端。
|
|
150
|
+
*
|
|
151
|
+
* @param port - 需要查询的端口号
|
|
152
|
+
* @returns 注册该端口的客户端 ID;若无客户端注册该端口则返回 `undefined`
|
|
153
|
+
*/
|
|
154
|
+
getClientByPort(port) {
|
|
155
|
+
for (const [id, info] of this.clients.entries()) {
|
|
156
|
+
if (info.registeredPorts.has(port)) {
|
|
157
|
+
return id;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 添加连接记录
|
|
164
|
+
*
|
|
165
|
+
* 为指定客户端记录一个新的活跃连接。
|
|
166
|
+
*
|
|
167
|
+
* @param clientId - 客户端唯一标识 ID
|
|
168
|
+
* @param connectionId - 连接唯一标识 ID
|
|
169
|
+
* @param remoteAddress - 远程连接的 IP 地址
|
|
170
|
+
* @param protocol - 连接协议类型,`'http'` 或 `'websocket'`
|
|
171
|
+
*/
|
|
172
|
+
addConnection(clientId, connectionId, remoteAddress, protocol) {
|
|
173
|
+
const client = this.clients.get(clientId);
|
|
174
|
+
if (client) {
|
|
175
|
+
const connectionInfo = {
|
|
176
|
+
id: connectionId,
|
|
177
|
+
remoteAddress,
|
|
178
|
+
protocol,
|
|
179
|
+
createdAt: Date.now(),
|
|
180
|
+
};
|
|
181
|
+
client.connections.set(connectionId, connectionInfo);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 移除连接记录
|
|
186
|
+
*
|
|
187
|
+
* 从所有客户端中移除指定的连接记录。
|
|
188
|
+
*
|
|
189
|
+
* @param connectionId - 需要移除的连接唯一标识 ID
|
|
190
|
+
*/
|
|
191
|
+
removeConnection(connectionId) {
|
|
192
|
+
for (const client of this.clients.values()) {
|
|
193
|
+
client.connections.delete(connectionId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 移除会话
|
|
198
|
+
*
|
|
199
|
+
* 根据客户端 ID 移除对应的会话,清理其所有连接记录、注册端口和 WebSocket 映射。
|
|
200
|
+
*
|
|
201
|
+
* @param clientId - 需要移除的客户端唯一标识 ID
|
|
202
|
+
*/
|
|
203
|
+
removeSession(clientId) {
|
|
204
|
+
const client = this.clients.get(clientId);
|
|
205
|
+
if (client) {
|
|
206
|
+
// 清理所有连接
|
|
207
|
+
client.connections.clear();
|
|
208
|
+
client.registeredPorts.clear();
|
|
209
|
+
}
|
|
210
|
+
this.clients.delete(clientId);
|
|
211
|
+
// 删除socket映射
|
|
212
|
+
for (const [socket, id] of this.socketToClientId.entries()) {
|
|
213
|
+
if (id === clientId) {
|
|
214
|
+
this.socketToClientId.delete(socket);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* 根据 WebSocket 连接移除会话
|
|
221
|
+
*
|
|
222
|
+
* 通过 WebSocket 连接查找对应的客户端 ID,并移除其会话。
|
|
223
|
+
*
|
|
224
|
+
* @param socket - 需要移除会话的 WebSocket 连接
|
|
225
|
+
*/
|
|
226
|
+
removeSessionBySocket(socket) {
|
|
227
|
+
const clientId = this.socketToClientId.get(socket);
|
|
228
|
+
if (clientId) {
|
|
229
|
+
this.removeSession(clientId);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* 更新心跳时间
|
|
234
|
+
*
|
|
235
|
+
* 更新指定客户端的最后心跳时间为当前时间,用于保持会话活跃。
|
|
236
|
+
*
|
|
237
|
+
* @param clientId - 客户端唯一标识 ID
|
|
238
|
+
*/
|
|
239
|
+
updateHeartbeat(clientId) {
|
|
240
|
+
const client = this.clients.get(clientId);
|
|
241
|
+
if (client) {
|
|
242
|
+
client.lastHeartbeat = Date.now();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* 获取所有已认证客户端的 ID 列表
|
|
247
|
+
*
|
|
248
|
+
* 遍历所有客户端,筛选出已通过认证的客户端。
|
|
249
|
+
*
|
|
250
|
+
* @returns 已认证客户端的 ID 数组
|
|
251
|
+
*/
|
|
252
|
+
getAuthenticatedClients() {
|
|
253
|
+
const result = [];
|
|
254
|
+
for (const [id, info] of this.clients.entries()) {
|
|
255
|
+
if (info.authenticated) {
|
|
256
|
+
result.push(id);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* 获取所有已注册端口的映射
|
|
263
|
+
*
|
|
264
|
+
* 遍历所有客户端,收集所有已注册的端口及其对应的客户端 ID。
|
|
265
|
+
*
|
|
266
|
+
* @returns 端口号到客户端 ID 的 Map 映射
|
|
267
|
+
*/
|
|
268
|
+
getAllRegisteredPorts() {
|
|
269
|
+
const result = new Map();
|
|
270
|
+
for (const [id, info] of this.clients.entries()) {
|
|
271
|
+
for (const port of info.registeredPorts) {
|
|
272
|
+
result.set(port, id);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return result;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* 启动心跳检查定时器
|
|
279
|
+
*
|
|
280
|
+
* 定期检查所有已认证客户端的最后心跳时间,
|
|
281
|
+
* 若超过会话超时时间则自动关闭连接并移除会话。
|
|
282
|
+
*/
|
|
283
|
+
startHeartbeatCheck() {
|
|
284
|
+
this.heartbeatTimer = setInterval(() => {
|
|
285
|
+
const now = Date.now();
|
|
286
|
+
for (const [id, info] of this.clients.entries()) {
|
|
287
|
+
if (info.authenticated && info.lastHeartbeat) {
|
|
288
|
+
const elapsed = now - info.lastHeartbeat;
|
|
289
|
+
if (elapsed > this.sessionTimeout) {
|
|
290
|
+
console.log(`会话 ${id} 超时,正在移除...`);
|
|
291
|
+
const socket = this.getClientSocket(id);
|
|
292
|
+
if (socket) {
|
|
293
|
+
socket.close();
|
|
294
|
+
}
|
|
295
|
+
this.removeSession(id);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}, this.heartbeatInterval);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* 停止心跳检查定时器
|
|
303
|
+
*
|
|
304
|
+
* 清除心跳检测定时器,停止定期的超时检查。
|
|
305
|
+
*/
|
|
306
|
+
stopHeartbeatCheck() {
|
|
307
|
+
if (this.heartbeatTimer) {
|
|
308
|
+
clearInterval(this.heartbeatTimer);
|
|
309
|
+
this.heartbeatTimer = undefined;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* 获取统计信息
|
|
314
|
+
*
|
|
315
|
+
* 汇总当前所有客户端的统计数据,包括总客户端数、已认证数、连接数和端口数。
|
|
316
|
+
*
|
|
317
|
+
* @returns 包含以下字段的统计对象:
|
|
318
|
+
* - `totalClients` - 总客户端数
|
|
319
|
+
* - `authenticatedClients` - 已认证客户端数
|
|
320
|
+
* - `totalConnections` - 活跃连接总数
|
|
321
|
+
* - `totalPorts` - 已注册端口总数
|
|
322
|
+
*/
|
|
323
|
+
getStats() {
|
|
324
|
+
let authenticatedClients = 0;
|
|
325
|
+
let totalConnections = 0;
|
|
326
|
+
let totalPorts = 0;
|
|
327
|
+
for (const info of this.clients.values()) {
|
|
328
|
+
if (info.authenticated) {
|
|
329
|
+
authenticatedClients++;
|
|
330
|
+
}
|
|
331
|
+
totalConnections += info.connections.size;
|
|
332
|
+
totalPorts += info.registeredPorts.size;
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
totalClients: this.clients.size,
|
|
336
|
+
authenticatedClients,
|
|
337
|
+
totalConnections,
|
|
338
|
+
totalPorts,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* 清理所有会话
|
|
343
|
+
*
|
|
344
|
+
* 停止心跳检查定时器,并清除所有客户端会话和 WebSocket 映射数据。
|
|
345
|
+
*/
|
|
346
|
+
clear() {
|
|
347
|
+
this.stopHeartbeatCheck();
|
|
348
|
+
this.clients.clear();
|
|
349
|
+
this.socketToClientId.clear();
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* 获取已认证客户端的会话列表
|
|
353
|
+
*
|
|
354
|
+
* 返回所有已认证客户端的简要信息,用于状态展示。
|
|
355
|
+
*
|
|
356
|
+
* @returns 会话列表数组
|
|
357
|
+
*/
|
|
358
|
+
getSessions() {
|
|
359
|
+
const result = [];
|
|
360
|
+
for (const [id, info] of this.clients.entries()) {
|
|
361
|
+
if (info.authenticated) {
|
|
362
|
+
result.push({
|
|
363
|
+
clientId: id,
|
|
364
|
+
connectedAt: info.authenticatedAt ?? 0,
|
|
365
|
+
registeredPorts: Array.from(info.registeredPorts),
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return result;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@feng3d/cts",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"feng3d-cts": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"watch": "tsc --watch",
|
|
22
|
+
"start": "node dist/cli.js",
|
|
23
|
+
"test": "vitest run"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@feng3d/chuantou-shared": "^0.0.6",
|
|
27
|
+
"chalk": "^5.6.2",
|
|
28
|
+
"commander": "^14.0.3",
|
|
29
|
+
"uuid": "^9.0.1",
|
|
30
|
+
"ws": "^8.16.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.10.0",
|
|
34
|
+
"@types/uuid": "^9.0.7",
|
|
35
|
+
"@types/ws": "^8.5.10",
|
|
36
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
37
|
+
"@vitest/ui": "^2.1.8",
|
|
38
|
+
"typescript": "^5.3.3",
|
|
39
|
+
"vitest": "^2.1.8"
|
|
40
|
+
}
|
|
41
|
+
}
|