egos-transfer 0.2.4 → 0.2.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/.claude/settings.local.json +7 -0
- package/dist/index.d.ts +19 -58
- package/dist/index.js +285 -577
- package/package.json +1 -1
- package/src/connection-manager.ts +223 -0
- package/src/file-transfer.ts +0 -1
- package/src/index.ts +2 -924
- package/src/interfaces.ts +7 -0
- package/src/peer-transfer.ts +671 -0
- package/src/server.ts +0 -5
package/dist/index.js
CHANGED
|
@@ -33,117 +33,45 @@ const entity_1 = require("./entity");
|
|
|
33
33
|
const router_1 = require("./router");
|
|
34
34
|
const axios_1 = __importDefault(require("axios"));
|
|
35
35
|
const delay_1 = __importDefault(require("delay"));
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const BASE_RECONNECT_BACKOFF = 1000; // 基础退避 1s
|
|
36
|
+
const MAX_RECONNECT_BACKOFF = 30000;
|
|
37
|
+
const BASE_RECONNECT_BACKOFF = 1000;
|
|
39
38
|
class PeerTransfer {
|
|
40
|
-
constructor(deviceId, config
|
|
41
|
-
this.checkerId = null;
|
|
42
|
-
/** 重连尝试次数,成功连接后归零 */
|
|
43
|
-
this.reconnectAttempt = 0;
|
|
44
|
-
/** 标记实例已销毁,防止异步操作继续 */
|
|
45
|
-
this.destroyed = false;
|
|
46
|
-
/** 按 requestId 追踪进行中的请求 */
|
|
47
|
-
this.inRequest = new Map();
|
|
39
|
+
constructor(deviceId, config) {
|
|
48
40
|
this.connectPool = new Map();
|
|
49
|
-
this.peerConfig = Object.assign(Object.assign({}, config), { key: String(Date.now()) });
|
|
50
41
|
this.requests = new Map();
|
|
51
|
-
this.requestTimers = new Map();
|
|
52
|
-
this.timeout = entity_1.REQUEST_TIMEOUT;
|
|
53
42
|
this.router = new router_1.PeerRouter();
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
43
|
+
this.reconnectAttempt = 0;
|
|
44
|
+
this.destroyed = false;
|
|
45
|
+
/** connectionId → Set<requestId> — settle in-flight requests on connection drop */
|
|
46
|
+
this.connRequests = new Map();
|
|
47
|
+
this._reconnecting = false;
|
|
48
|
+
this.peerConfig = Object.assign(Object.assign({}, config), { key: String(Date.now()) });
|
|
49
|
+
this.peerId = deviceId;
|
|
56
50
|
this.deviceId = deviceId;
|
|
57
51
|
}
|
|
52
|
+
// ── Peer lifecycle ──────────────────────────────────────────────
|
|
58
53
|
createPeer() {
|
|
59
|
-
return __awaiter(this,
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
55
|
var _a;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
if (this.booted) {
|
|
66
|
-
return this.booted;
|
|
67
|
-
}
|
|
68
|
-
if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && !force) {
|
|
56
|
+
if (this.destroyed)
|
|
57
|
+
throw new Error('destroyed');
|
|
58
|
+
if ((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)
|
|
69
59
|
return this.peer;
|
|
70
|
-
|
|
71
|
-
this.destroy();
|
|
72
|
-
yield (0, delay_1.default)(1500);
|
|
60
|
+
this.destroyPeer();
|
|
73
61
|
yield this.reloadConfig();
|
|
74
62
|
const peer = new peerjs_1.Peer(this.peerId, Object.assign(Object.assign({}, this.peerConfig), { pingInterval: 9000 }));
|
|
75
63
|
this.peer = peer;
|
|
76
|
-
yield this.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
if (this.booted) {
|
|
89
|
-
return this.booted;
|
|
90
|
-
}
|
|
91
|
-
this.booted = new Promise((resolve) => {
|
|
92
|
-
const timer = setTimeout(() => {
|
|
93
|
-
resolve(null);
|
|
94
|
-
}, constant_1.PEER_OPEN_TIMEOUT);
|
|
95
|
-
const done = (p) => {
|
|
96
|
-
clearTimeout(timer);
|
|
97
|
-
resolve(p);
|
|
98
|
-
};
|
|
99
|
-
peer.on('open', (id) => {
|
|
100
|
-
console.log('peer@open');
|
|
101
|
-
this.reconnectAttempt = 0; // 连接成功,重置退避计数
|
|
102
|
-
done(peer);
|
|
103
|
-
});
|
|
104
|
-
// peer.on('disconnected', () => {
|
|
105
|
-
// if (!this.isPaused) {
|
|
106
|
-
// this.reconnect();
|
|
107
|
-
// }
|
|
108
|
-
// });
|
|
109
|
-
peer.on('close', () => {
|
|
110
|
-
setTimeout(() => {
|
|
111
|
-
if (!this.isPaused && !this.destroyed) {
|
|
112
|
-
this.reconnect();
|
|
113
|
-
}
|
|
114
|
-
}, constant_1.CONNECTION_TIMEOUT);
|
|
115
|
-
});
|
|
116
|
-
peer.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
|
|
117
|
-
if (err.message === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
118
|
-
this.stop();
|
|
119
|
-
done(null);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
if (err.message === constant_1.CONNECTION_LIMIT_EXCEED) {
|
|
123
|
-
this.onConnectLimit();
|
|
124
|
-
return done(null);
|
|
125
|
-
}
|
|
126
|
-
if (err.message === constant_1.UNAUTHORIZED) {
|
|
127
|
-
done(null);
|
|
128
|
-
return this.requireAuth();
|
|
129
|
-
}
|
|
130
|
-
if (err.message === constant_1.CONNECTION_DUPLICATED) {
|
|
131
|
-
// 连接级重复错误,不应销毁重建 peer
|
|
132
|
-
// createConnection 重试循环会处理
|
|
133
|
-
console.warn('peer@error: connection duplicated, will retry');
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (err.type === 'network') {
|
|
137
|
-
done(null);
|
|
138
|
-
return this.reconnect();
|
|
139
|
-
}
|
|
140
|
-
if (err.type === 'server-error') {
|
|
141
|
-
done(null);
|
|
142
|
-
return this.reconnect();
|
|
143
|
-
}
|
|
144
|
-
done(null);
|
|
145
|
-
return this.createPeer(true);
|
|
146
|
-
}));
|
|
64
|
+
yield this.waitForOpen(peer);
|
|
65
|
+
peer.on('close', () => {
|
|
66
|
+
if (!this.destroyed)
|
|
67
|
+
this.reconnect();
|
|
68
|
+
});
|
|
69
|
+
peer.on('error', (err) => {
|
|
70
|
+
if (this.destroyed)
|
|
71
|
+
return;
|
|
72
|
+
if (err.type === 'network' || err.type === 'server-error') {
|
|
73
|
+
this.reconnect();
|
|
74
|
+
}
|
|
147
75
|
});
|
|
148
76
|
peer.on('connection', (conn) => {
|
|
149
77
|
conn.label = 'incoming';
|
|
@@ -153,382 +81,202 @@ class PeerTransfer {
|
|
|
153
81
|
socket === null || socket === void 0 ? void 0 : socket.on('message', (message) => {
|
|
154
82
|
this.handleSocketMessage(message);
|
|
155
83
|
});
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
yield this.booted;
|
|
159
|
-
}
|
|
160
|
-
catch (_a) {
|
|
161
|
-
// booted rejected via timer timeout
|
|
162
|
-
}
|
|
163
|
-
finally {
|
|
164
|
-
this.booted = undefined;
|
|
165
|
-
}
|
|
84
|
+
return peer;
|
|
166
85
|
});
|
|
167
86
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.onError(message);
|
|
176
|
-
this.onHeartbeat(message);
|
|
177
|
-
}
|
|
178
|
-
onHeartbeat(message) {
|
|
179
|
-
if (message.type !== 'HEARTBEAT' || this.isPaused) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
onError(message) {
|
|
184
|
-
var _a;
|
|
185
|
-
if (message.type !== 'ERROR') {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
if (((_a = message.payload) === null || _a === void 0 ? void 0 : _a.msg) === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
189
|
-
this.stop();
|
|
190
|
-
this.getStore().dispatch({
|
|
191
|
-
type: 'global/updateNetworkState',
|
|
192
|
-
payload: {
|
|
193
|
-
error: true,
|
|
194
|
-
code: 'PEER_CONNECTION_CONFLICT',
|
|
195
|
-
message: 'peer conflict',
|
|
196
|
-
},
|
|
87
|
+
waitForOpen(peer) {
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
const timer = setTimeout(() => resolve(), constant_1.PEER_OPEN_TIMEOUT);
|
|
90
|
+
peer.once('open', () => {
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
this.reconnectAttempt = 0;
|
|
93
|
+
resolve();
|
|
197
94
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
onDeviceOnline(message) {
|
|
206
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
-
if (message.type !== 'ONLINE') {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
this.online(message.payload.deviceId);
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
onDeviceOffline(message) {
|
|
214
|
-
if (message.type !== 'OFFLINE') {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
this.ping(message.payload.deviceId);
|
|
218
|
-
}
|
|
219
|
-
removeConnection(peerId, connectionId) {
|
|
220
|
-
var _a, _b, _c;
|
|
221
|
-
const conn = this.connectPool.get(peerId);
|
|
222
|
-
if (conn) {
|
|
223
|
-
if (connectionId && conn.connectionId !== connectionId) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
this.connectPool.delete(peerId);
|
|
227
|
-
this.handleConnectionClose(peerId, conn);
|
|
228
|
-
conn.removeAllListeners();
|
|
229
|
-
conn.close();
|
|
230
|
-
(_a = this.peer) === null || _a === void 0 ? void 0 : _a._removeConnection(conn);
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
const connections = ((_b = this.peer) === null || _b === void 0 ? void 0 : _b.connections) || {};
|
|
234
|
-
const conns = connections[peerId] || [];
|
|
235
|
-
if (conns.length > 0) {
|
|
236
|
-
for (const c of conns) {
|
|
237
|
-
c.removeAllListeners();
|
|
238
|
-
c.close();
|
|
239
|
-
(_c = this.peer) === null || _c === void 0 ? void 0 : _c._removeConnection(c);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* 连接关闭时尝试快速重连(5s 超时):
|
|
246
|
-
* - 重连成功 → 保留 inRequest 条目,更新 conn 引用
|
|
247
|
-
* - 重连失败 → 触发 feedback 并清理 inRequest
|
|
248
|
-
*/
|
|
249
|
-
handleConnectionClose(peerId, conn) {
|
|
250
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
251
|
-
const matchedEntries = [];
|
|
252
|
-
for (const [reqId, entry] of this.inRequest) {
|
|
253
|
-
if (entry.conn.connectionId === conn.connectionId) {
|
|
254
|
-
matchedEntries.push([reqId, entry]);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
if (matchedEntries.length === 0) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
// 快速重连,超时 5s
|
|
261
|
-
const newConn = yield Promise.race([
|
|
262
|
-
this.connectToPeer(peerId),
|
|
263
|
-
(0, delay_1.default)(5000).then(() => undefined),
|
|
264
|
-
]);
|
|
265
|
-
if (!this.isValidConnection(newConn)) {
|
|
266
|
-
// 重连失败,触发 feedback 让请求走重试逻辑
|
|
267
|
-
for (const [reqId, entry] of matchedEntries) {
|
|
268
|
-
entry.feedback();
|
|
269
|
-
this.inRequest.delete(reqId);
|
|
270
|
-
}
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
// 重连成功,更新 inRequest 中的 conn 引用
|
|
274
|
-
for (const [reqId, entry] of matchedEntries) {
|
|
275
|
-
if (this.inRequest.has(reqId)) {
|
|
276
|
-
this.inRequest.set(reqId, Object.assign(Object.assign({}, entry), { conn: newConn }));
|
|
95
|
+
peer.once('error', (err) => {
|
|
96
|
+
if (err.message === constant_1.CONNECTION_DUPLICATED)
|
|
97
|
+
return; // wait for open
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
if (err.message === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
100
|
+
resolve();
|
|
101
|
+
return;
|
|
277
102
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
addConnection(conn) {
|
|
282
|
-
this.connectPool.set(conn.peer, conn);
|
|
283
|
-
const connecting = PeerTransfer.connecting.get(conn.peer);
|
|
284
|
-
if (connecting) {
|
|
285
|
-
connecting.resolve(conn);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
checkConnection() {
|
|
289
|
-
if (this.checkerId) {
|
|
290
|
-
clearInterval(this.checkerId);
|
|
291
|
-
}
|
|
292
|
-
this.checkerId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
293
|
-
var _a;
|
|
294
|
-
if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
|
|
295
|
-
yield this.reconnect();
|
|
296
|
-
}
|
|
297
|
-
// turn credential expires
|
|
298
|
-
if (this.peerConfig.turnExpiredAt && this.peerConfig.turnExpiredAt - 30000 < Date.now()) {
|
|
299
|
-
yield this.reloadConfig();
|
|
300
|
-
yield this.createPeer(true);
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
const deviceIds = Array.from(this.connectPool.keys());
|
|
304
|
-
const pingTasks = deviceIds.map((deviceId) => __awaiter(this, void 0, void 0, function* () {
|
|
305
|
-
const conn = this.connectPool.get(deviceId);
|
|
306
|
-
if (!this.isValidConnection(conn)) {
|
|
307
|
-
this.removeConnection(conn.peer, conn.connectionId);
|
|
103
|
+
if (err.message === constant_1.CONNECTION_LIMIT_EXCEED) {
|
|
104
|
+
this.onConnectLimit();
|
|
105
|
+
resolve();
|
|
308
106
|
return;
|
|
309
107
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
108
|
+
if (err.message === constant_1.UNAUTHORIZED) {
|
|
109
|
+
this.requireAuth();
|
|
110
|
+
resolve();
|
|
111
|
+
return;
|
|
313
112
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}), constant_1.HEARTBEAT_INTERVAL);
|
|
318
|
-
}
|
|
319
|
-
getApiHost() {
|
|
320
|
-
var _a, _b, _c;
|
|
321
|
-
const protocol = ((_a = this.peerConfig) === null || _a === void 0 ? void 0 : _a.secure) ? 'https' : 'http';
|
|
322
|
-
const host = ((_b = this.peerConfig) === null || _b === void 0 ? void 0 : _b.host) || 'localhost';
|
|
323
|
-
const port = ((_c = this.peerConfig) === null || _c === void 0 ? void 0 : _c.port) || 9000;
|
|
324
|
-
return `${protocol}://${host}:${port}`;
|
|
113
|
+
resolve();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
325
116
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
117
|
+
handleSocketMessage(message) {
|
|
118
|
+
var _a;
|
|
119
|
+
switch (message.type) {
|
|
120
|
+
case 'ONLINE':
|
|
121
|
+
this.online(message.payload.deviceId);
|
|
122
|
+
break;
|
|
123
|
+
case 'OFFLINE':
|
|
124
|
+
this.ping(message.payload.deviceId);
|
|
125
|
+
break;
|
|
126
|
+
case 'ERROR':
|
|
127
|
+
if (((_a = message.payload) === null || _a === void 0 ? void 0 : _a.msg) === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
128
|
+
this.getStore().dispatch({
|
|
129
|
+
type: 'global/updateNetworkState',
|
|
130
|
+
payload: { error: true, code: 'PEER_CONNECTION_CONFLICT', message: 'peer conflict' },
|
|
131
|
+
});
|
|
333
132
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
console.log('getDeviceStatus@error', err);
|
|
337
|
-
}
|
|
338
|
-
});
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
339
135
|
}
|
|
136
|
+
// ── Connection management ───────────────────────────────────────
|
|
340
137
|
connectToPeer(peerId) {
|
|
341
138
|
return __awaiter(this, void 0, void 0, function* () {
|
|
342
|
-
if (peerId === this.deviceId)
|
|
139
|
+
if (peerId === this.deviceId)
|
|
343
140
|
return;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
return existingConn;
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
this.removeConnection(existingConn.peer, existingConn.connectionId);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
if (PeerTransfer.connecting.has(peerId)) {
|
|
356
|
-
const entry = PeerTransfer.connecting.get(peerId);
|
|
357
|
-
const conn = yield (entry === null || entry === void 0 ? void 0 : entry.promise);
|
|
358
|
-
if (conn) {
|
|
359
|
-
return conn;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
141
|
+
const existing = this.connectPool.get(peerId);
|
|
142
|
+
if (this.isValidConnection(existing))
|
|
143
|
+
return existing;
|
|
144
|
+
if (existing)
|
|
145
|
+
this.removeConnection(peerId, existing.connectionId);
|
|
362
146
|
return this.createConnection(peerId);
|
|
363
147
|
});
|
|
364
148
|
}
|
|
365
149
|
createConnection(peerId) {
|
|
366
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
let reject;
|
|
373
|
-
const connectionPromise = new Promise((res, rej) => {
|
|
374
|
-
resolve = res;
|
|
375
|
-
reject = rej;
|
|
376
|
-
});
|
|
377
|
-
PeerTransfer.connecting.set(peerId, { promise: connectionPromise, resolve, reject });
|
|
378
|
-
// 兜底超时,防止 connecting 条目永远不清理
|
|
379
|
-
const guardTimer = setTimeout(() => {
|
|
380
|
-
PeerTransfer.connecting.delete(peerId);
|
|
381
|
-
resolve(undefined);
|
|
382
|
-
}, constant_1.CONNECTION_TIMEOUT * 3);
|
|
383
|
-
const doConnect = () => __awaiter(this, void 0, void 0, function* () {
|
|
384
|
-
var _a, _b;
|
|
385
|
-
try {
|
|
386
|
-
for (let retry = 0; retry < 3; retry++) {
|
|
387
|
-
if (!this.peer) {
|
|
388
|
-
yield this.createPeer();
|
|
389
|
-
}
|
|
390
|
-
if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
|
|
391
|
-
yield this.reconnect();
|
|
392
|
-
}
|
|
393
|
-
const cur = this.connectPool.get(peerId);
|
|
394
|
-
if (this.isValidConnection(cur)) {
|
|
395
|
-
clearTimeout(guardTimer);
|
|
396
|
-
return resolve(cur);
|
|
397
|
-
}
|
|
398
|
-
const conn = (_b = this.peer) === null || _b === void 0 ? void 0 : _b.connect(peerId, {
|
|
399
|
-
label: 'outgoing',
|
|
400
|
-
metadata: { time: Date.now() },
|
|
401
|
-
});
|
|
402
|
-
if (!conn) {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
const connection = yield this.onConnect(conn).catch(() => { });
|
|
406
|
-
if (connection) {
|
|
407
|
-
clearTimeout(guardTimer);
|
|
408
|
-
return resolve(connection);
|
|
409
|
-
}
|
|
151
|
+
var _a, _b;
|
|
152
|
+
for (let retry = 0; retry < 3; retry++) {
|
|
153
|
+
if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
|
|
154
|
+
try {
|
|
155
|
+
yield this.createPeer();
|
|
410
156
|
}
|
|
411
|
-
|
|
412
|
-
resolve(undefined);
|
|
413
|
-
return undefined;
|
|
414
|
-
}
|
|
415
|
-
catch (err) {
|
|
416
|
-
reject(err);
|
|
157
|
+
catch ( /* fall through */_c) { /* fall through */ }
|
|
417
158
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* 心跳检测 - 直接 send,不走 request 管线,避免重试放大
|
|
429
|
-
*/
|
|
430
|
-
ping(peerId) {
|
|
431
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
432
|
-
if (this.deviceId === peerId) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
const conn = this.connectPool.get(peerId);
|
|
436
|
-
if (!this.isValidConnection(conn)) {
|
|
437
|
-
this.removeConnection(peerId, conn === null || conn === void 0 ? void 0 : conn.connectionId);
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
try {
|
|
441
|
-
const requestId = yield this.genRequestId();
|
|
442
|
-
return new Promise((resolve) => {
|
|
443
|
-
const timer = setTimeout(() => {
|
|
444
|
-
this.requests.delete(requestId);
|
|
445
|
-
resolve(false);
|
|
446
|
-
}, constant_1.PING_TIMEOUT);
|
|
447
|
-
this.requests.set(requestId, () => {
|
|
448
|
-
clearTimeout(timer);
|
|
449
|
-
resolve(true);
|
|
450
|
-
});
|
|
451
|
-
conn.send({
|
|
452
|
-
route: entity_1.PeerRoutes.HEARTBEAT,
|
|
453
|
-
method: 'get',
|
|
454
|
-
body: {},
|
|
455
|
-
requestId,
|
|
456
|
-
scope: entity_1.PeerScope.REQUEST,
|
|
457
|
-
action: entity_1.PeerAction.SEND,
|
|
458
|
-
src: this.peerId,
|
|
459
|
-
dest: peerId,
|
|
460
|
-
headers: {},
|
|
461
|
-
createdAt: Date.now(),
|
|
462
|
-
});
|
|
159
|
+
if (!((_b = this.peer) === null || _b === void 0 ? void 0 : _b.open))
|
|
160
|
+
continue;
|
|
161
|
+
const pooled = this.connectPool.get(peerId);
|
|
162
|
+
if (this.isValidConnection(pooled))
|
|
163
|
+
return pooled;
|
|
164
|
+
const conn = this.peer.connect(peerId, {
|
|
165
|
+
label: 'outgoing',
|
|
166
|
+
metadata: { time: Date.now() },
|
|
463
167
|
});
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
168
|
+
if (!conn)
|
|
169
|
+
continue;
|
|
170
|
+
const result = yield this.onConnect(conn).catch(() => undefined);
|
|
171
|
+
if (result)
|
|
172
|
+
return result;
|
|
173
|
+
const pooled2 = this.connectPool.get(peerId);
|
|
174
|
+
if (this.isValidConnection(pooled2))
|
|
175
|
+
return pooled2;
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
468
178
|
});
|
|
469
179
|
}
|
|
470
180
|
onConnect(conn) {
|
|
471
181
|
return __awaiter(this, void 0, void 0, function* () {
|
|
472
|
-
if (!conn)
|
|
182
|
+
if (!conn)
|
|
473
183
|
return;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
// 双方同时建连时,保留 peerId 字典序大的那条(确定性,不依赖时间戳)
|
|
478
|
-
if (exists.connectionId > conn.connectionId) {
|
|
184
|
+
const existing = this.connectPool.get(conn.peer);
|
|
185
|
+
if (existing) {
|
|
186
|
+
if (existing.connectionId > conn.connectionId) {
|
|
479
187
|
this.removeConnection(conn.peer, conn.connectionId);
|
|
480
|
-
if (this.isValidConnection(
|
|
481
|
-
return
|
|
482
|
-
}
|
|
188
|
+
if (this.isValidConnection(existing))
|
|
189
|
+
return existing;
|
|
483
190
|
}
|
|
484
191
|
else {
|
|
485
|
-
this.removeConnection(
|
|
192
|
+
this.removeConnection(existing.peer, existing.connectionId);
|
|
486
193
|
}
|
|
487
194
|
}
|
|
488
195
|
if (conn.open) {
|
|
489
|
-
this.
|
|
490
|
-
this.bindConnectionData(conn);
|
|
196
|
+
this.setupConnection(conn);
|
|
491
197
|
return conn;
|
|
492
198
|
}
|
|
493
199
|
return new Promise((resolve) => {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
if (connection) {
|
|
501
|
-
this.addConnection(connection);
|
|
502
|
-
}
|
|
503
|
-
resolve(connection);
|
|
504
|
-
};
|
|
505
|
-
timer = setTimeout(() => {
|
|
506
|
-
if (this.isValidConnection(conn)) {
|
|
507
|
-
this.addConnection(conn);
|
|
508
|
-
done(conn);
|
|
509
|
-
}
|
|
510
|
-
else {
|
|
511
|
-
this.removeConnection(conn.peer, conn.connectionId);
|
|
512
|
-
done(undefined);
|
|
513
|
-
}
|
|
200
|
+
const timer = setTimeout(() => {
|
|
201
|
+
conn.off('open', onOpen);
|
|
202
|
+
conn.off('error', onError);
|
|
203
|
+
conn.off('close', onClose);
|
|
204
|
+
resolve(this.isValidConnection(conn) ? this.setupConnection(conn) : undefined);
|
|
514
205
|
}, constant_1.CONNECTION_TIMEOUT);
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
206
|
+
const onOpen = () => {
|
|
207
|
+
clearTimeout(timer);
|
|
208
|
+
conn.off('error', onError);
|
|
209
|
+
conn.off('close', onClose);
|
|
210
|
+
resolve(this.setupConnection(conn));
|
|
211
|
+
};
|
|
212
|
+
const onError = () => {
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
conn.off('open', onOpen);
|
|
215
|
+
conn.off('close', onClose);
|
|
216
|
+
const pooled = this.connectPool.get(conn.peer);
|
|
217
|
+
resolve(this.isValidConnection(pooled) ? pooled : undefined);
|
|
218
|
+
};
|
|
219
|
+
const onClose = () => {
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
conn.off('open', onOpen);
|
|
222
|
+
conn.off('error', onError);
|
|
223
|
+
resolve(undefined);
|
|
224
|
+
};
|
|
225
|
+
conn.once('open', onOpen);
|
|
226
|
+
conn.once('error', onError);
|
|
227
|
+
conn.once('close', onClose);
|
|
528
228
|
});
|
|
529
229
|
});
|
|
530
230
|
}
|
|
531
|
-
|
|
231
|
+
setupConnection(conn) {
|
|
232
|
+
this.connectPool.set(conn.peer, conn);
|
|
233
|
+
this.bindConnectionData(conn);
|
|
234
|
+
conn.on('close', () => this.onConnClosed(conn));
|
|
235
|
+
conn.on('error', () => this.onConnClosed(conn));
|
|
236
|
+
return conn;
|
|
237
|
+
}
|
|
238
|
+
onConnClosed(conn) {
|
|
239
|
+
this.connectPool.delete(conn.peer);
|
|
240
|
+
const reqIds = this.connRequests.get(conn.connectionId);
|
|
241
|
+
if (reqIds) {
|
|
242
|
+
for (const reqId of reqIds) {
|
|
243
|
+
const cb = this.requests.get(reqId);
|
|
244
|
+
if (cb) {
|
|
245
|
+
cb({ error: { message: 'connection closed', code: 'CONN_CLOSED' } });
|
|
246
|
+
this.requests.delete(reqId);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
this.connRequests.delete(conn.connectionId);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
removeConnection(peerId, connectionId) {
|
|
253
|
+
var _a, _b, _c;
|
|
254
|
+
const conn = this.connectPool.get(peerId);
|
|
255
|
+
if (conn) {
|
|
256
|
+
if (connectionId && conn.connectionId !== connectionId)
|
|
257
|
+
return;
|
|
258
|
+
this.connectPool.delete(peerId);
|
|
259
|
+
this.connRequests.delete(conn.connectionId);
|
|
260
|
+
conn.removeAllListeners();
|
|
261
|
+
conn.close();
|
|
262
|
+
(_a = this.peer) === null || _a === void 0 ? void 0 : _a._removeConnection(conn);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
const connections = ((_b = this.peer) === null || _b === void 0 ? void 0 : _b.connections) || {};
|
|
266
|
+
for (const c of connections[peerId] || []) {
|
|
267
|
+
c.removeAllListeners();
|
|
268
|
+
c.close();
|
|
269
|
+
(_c = this.peer) === null || _c === void 0 ? void 0 : _c._removeConnection(c);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
isValidConnection(conn) {
|
|
274
|
+
if (!(conn === null || conn === void 0 ? void 0 : conn.open))
|
|
275
|
+
return false;
|
|
276
|
+
if (!(conn === null || conn === void 0 ? void 0 : conn.peerConnection))
|
|
277
|
+
return false;
|
|
278
|
+
return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
|
|
279
|
+
}
|
|
532
280
|
bindConnectionData(conn) {
|
|
533
281
|
conn.on('data', (message) => {
|
|
534
282
|
switch (message.scope) {
|
|
@@ -541,39 +289,29 @@ class PeerTransfer {
|
|
|
541
289
|
}
|
|
542
290
|
});
|
|
543
291
|
}
|
|
292
|
+
// ── Request / Reply ─────────────────────────────────────────────
|
|
544
293
|
request(peerId, payload) {
|
|
545
294
|
return __awaiter(this, void 0, void 0, function* () {
|
|
546
295
|
var _a;
|
|
547
296
|
const requestId = payload.requestId || (yield this.genRequestId());
|
|
548
|
-
const maxRetry = 2;
|
|
549
297
|
let res;
|
|
550
|
-
for (let attempt = 0; attempt <=
|
|
298
|
+
for (let attempt = 0; attempt <= 2; attempt++) {
|
|
551
299
|
res = yield this.doRequestOnce(peerId, payload, requestId);
|
|
552
|
-
console.log('request once', res);
|
|
553
300
|
const code = (_a = res.error) === null || _a === void 0 ? void 0 : _a.code;
|
|
554
|
-
if (!res.error || (code !== 'CONN_CLOSED' && code !== 'CONN_FAILED'))
|
|
301
|
+
if (!res.error || (code !== 'CONN_CLOSED' && code !== 'CONN_FAILED'))
|
|
555
302
|
return res;
|
|
556
|
-
}
|
|
557
303
|
}
|
|
558
304
|
return res;
|
|
559
305
|
});
|
|
560
306
|
}
|
|
561
|
-
/**
|
|
562
|
-
* 执行一次请求,返回带错误码的结果供外层判断是否重试
|
|
563
|
-
* @param peerId - 目标 peerId
|
|
564
|
-
* @param payload - 请求负载
|
|
565
|
-
* @param requestId - 请求ID(重试时复用)
|
|
566
|
-
* @returns error.code: CONN_CLOSED/CONN_FAILED(可重试)、TIMEOUT(不重试)
|
|
567
|
-
*/
|
|
568
307
|
doRequestOnce(peerId, payload, requestId) {
|
|
569
308
|
return __awaiter(this, void 0, void 0, function* () {
|
|
570
|
-
console.log('doRequestOnce@@', peerId, this.destroyed, payload.route);
|
|
571
309
|
if (this.destroyed) {
|
|
572
310
|
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'destroyed', code: 'CONN_CLOSED' } });
|
|
573
311
|
}
|
|
574
312
|
const conn = yield this.connectToPeer(peerId);
|
|
575
313
|
if (!this.isValidConnection(conn)) {
|
|
576
|
-
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: '
|
|
314
|
+
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'connection failed', code: 'CONN_FAILED' } });
|
|
577
315
|
}
|
|
578
316
|
return new Promise((resolve) => {
|
|
579
317
|
let timeout = null;
|
|
@@ -582,39 +320,30 @@ class PeerTransfer {
|
|
|
582
320
|
clearTimeout(timeout);
|
|
583
321
|
timeout = null;
|
|
584
322
|
}
|
|
585
|
-
this.inRequest.delete(requestId);
|
|
586
323
|
this.requests.delete(requestId);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
324
|
+
const reqs = this.connRequests.get(conn.connectionId);
|
|
325
|
+
if (reqs) {
|
|
326
|
+
reqs.delete(requestId);
|
|
327
|
+
if (reqs.size === 0)
|
|
328
|
+
this.connRequests.delete(conn.connectionId);
|
|
592
329
|
}
|
|
593
330
|
};
|
|
594
331
|
timeout = setTimeout(() => {
|
|
595
|
-
// 先清理,避免 removeConnection 触发 feedback 二次 resolve
|
|
596
332
|
cleanup();
|
|
597
333
|
this.removeConnection(conn.peer, conn.connectionId);
|
|
598
|
-
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: '
|
|
334
|
+
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'timeout', code: 'TIMEOUT' } }));
|
|
599
335
|
}, payload.timeout || entity_1.REQUEST_TIMEOUT);
|
|
600
|
-
this.
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
},
|
|
607
|
-
});
|
|
608
|
-
// 直接 set,避免 addRequest 内部 setTimeout 在重试时误删新回调
|
|
336
|
+
let reqs = this.connRequests.get(conn.connectionId);
|
|
337
|
+
if (!reqs) {
|
|
338
|
+
reqs = new Set();
|
|
339
|
+
this.connRequests.set(conn.connectionId, reqs);
|
|
340
|
+
}
|
|
341
|
+
reqs.add(requestId);
|
|
609
342
|
this.requests.set(requestId, (message) => {
|
|
610
343
|
cleanup();
|
|
611
|
-
const now = Date.now();
|
|
612
|
-
if (now - message.createdAt > 3000) {
|
|
613
|
-
console.warn('[egos] slow peer request:', message.route, now - message.createdAt);
|
|
614
|
-
}
|
|
615
344
|
resolve(message);
|
|
616
345
|
});
|
|
617
|
-
this.send(conn, Object.assign(Object.assign({}, payload), { requestId
|
|
346
|
+
this.send(conn, Object.assign(Object.assign({}, payload), { requestId })).catch(() => {
|
|
618
347
|
cleanup();
|
|
619
348
|
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'send failed', code: 'CONN_CLOSED' } }));
|
|
620
349
|
});
|
|
@@ -625,8 +354,8 @@ class PeerTransfer {
|
|
|
625
354
|
return __awaiter(this, void 0, void 0, function* () {
|
|
626
355
|
const data = Object.assign(Object.assign(Object.assign({}, this.inheritMessage(oldMessage)), message), { dest: conn.peer, scope: entity_1.PeerScope.RESPONSE, updatedAt: Date.now() });
|
|
627
356
|
if (!this.isValidConnection(conn)) {
|
|
628
|
-
const
|
|
629
|
-
return
|
|
357
|
+
const c = yield this.connectToPeer(conn.peer);
|
|
358
|
+
return c === null || c === void 0 ? void 0 : c.send(data);
|
|
630
359
|
}
|
|
631
360
|
return conn.send(data);
|
|
632
361
|
});
|
|
@@ -636,114 +365,96 @@ class PeerTransfer {
|
|
|
636
365
|
const internalApi = yield this.getApi(conn.peer);
|
|
637
366
|
let connection = conn;
|
|
638
367
|
if (!this.isValidConnection(conn)) {
|
|
639
|
-
const
|
|
640
|
-
if (!
|
|
368
|
+
const c = yield this.connectToPeer(conn.peer);
|
|
369
|
+
if (!c)
|
|
641
370
|
return this.responseFail(conn, message, 'send with invalid connection');
|
|
642
|
-
|
|
643
|
-
connection = con;
|
|
371
|
+
connection = c;
|
|
644
372
|
}
|
|
645
373
|
const requestId = message.requestId || (yield this.genRequestId());
|
|
646
374
|
return connection.send(Object.assign(Object.assign({}, message), { requestId, headers: Object.assign(Object.assign({}, message.headers), { ['x-device-token']: internalApi === null || internalApi === void 0 ? void 0 : internalApi.token }), scope: entity_1.PeerScope.REQUEST, action: entity_1.PeerAction.SEND, src: this.peerId, dest: conn.peer, createdAt: Date.now() }), false);
|
|
647
375
|
});
|
|
648
376
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
src: this.peerId,
|
|
652
|
-
id: receiveMsg.id,
|
|
653
|
-
requestId: receiveMsg.requestId,
|
|
654
|
-
route: receiveMsg.route,
|
|
655
|
-
createdAt: receiveMsg.createdAt,
|
|
656
|
-
action: entity_1.PeerAction.RECEIVE,
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
reconnect() {
|
|
377
|
+
// ── Ping ────────────────────────────────────────────────────────
|
|
378
|
+
ping(peerId) {
|
|
660
379
|
return __awaiter(this, void 0, void 0, function* () {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
380
|
+
if (this.deviceId === peerId)
|
|
381
|
+
return false;
|
|
382
|
+
const conn = this.connectPool.get(peerId);
|
|
383
|
+
if (!this.isValidConnection(conn)) {
|
|
384
|
+
this.removeConnection(peerId, conn === null || conn === void 0 ? void 0 : conn.connectionId);
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
const requestId = yield this.genRequestId();
|
|
389
|
+
return new Promise((resolve) => {
|
|
390
|
+
const timer = setTimeout(() => { this.requests.delete(requestId); resolve(false); }, constant_1.PING_TIMEOUT);
|
|
391
|
+
this.requests.set(requestId, () => { clearTimeout(timer); resolve(true); });
|
|
392
|
+
conn.send({
|
|
393
|
+
route: entity_1.PeerRoutes.HEARTBEAT, method: 'get', body: {}, requestId,
|
|
394
|
+
scope: entity_1.PeerScope.REQUEST, action: entity_1.PeerAction.SEND,
|
|
395
|
+
src: this.peerId, dest: peerId, headers: {}, createdAt: Date.now(),
|
|
396
|
+
});
|
|
397
|
+
});
|
|
664
398
|
}
|
|
665
|
-
|
|
666
|
-
return
|
|
399
|
+
catch (_a) {
|
|
400
|
+
return false;
|
|
667
401
|
}
|
|
668
|
-
this.reconnectingPromise = this.doReconnect();
|
|
669
|
-
return yield this.reconnectingPromise.finally(() => {
|
|
670
|
-
this.reconnectingPromise = undefined;
|
|
671
|
-
});
|
|
672
402
|
});
|
|
673
403
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
}
|
|
681
|
-
return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
|
|
404
|
+
// ── Server helpers ──────────────────────────────────────────────
|
|
405
|
+
getApiHost() {
|
|
406
|
+
var _a, _b, _c;
|
|
407
|
+
const protocol = ((_a = this.peerConfig) === null || _a === void 0 ? void 0 : _a.secure) ? 'https' : 'http';
|
|
408
|
+
const host = ((_b = this.peerConfig) === null || _b === void 0 ? void 0 : _b.host) || 'localhost';
|
|
409
|
+
const port = ((_c = this.peerConfig) === null || _c === void 0 ? void 0 : _c.port) || 9000;
|
|
410
|
+
return `${protocol}://${host}:${port}`;
|
|
682
411
|
}
|
|
683
|
-
|
|
412
|
+
getDeviceStatus(peerId) {
|
|
684
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
685
|
-
var _a, _b, _c, _d;
|
|
686
414
|
try {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
415
|
+
const res = yield axios_1.default.get(`${this.getApiHost()}/api/v1/devices/${peerId}/status`);
|
|
416
|
+
if (res.status < 400)
|
|
417
|
+
return res.data.data;
|
|
418
|
+
}
|
|
419
|
+
catch ( /* ignore */_a) { /* ignore */ }
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
// ── Reconnection ────────────────────────────────────────────────
|
|
423
|
+
reconnect() {
|
|
424
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
425
|
+
if (this.destroyed || this._reconnecting)
|
|
426
|
+
return;
|
|
427
|
+
this._reconnecting = true;
|
|
428
|
+
try {
|
|
695
429
|
this.reconnectAttempt++;
|
|
696
430
|
const backoff = Math.min(BASE_RECONNECT_BACKOFF * Math.pow(2, this.reconnectAttempt - 1), MAX_RECONNECT_BACKOFF);
|
|
697
431
|
yield (0, delay_1.default)(backoff);
|
|
698
432
|
yield this.reloadConfig();
|
|
699
|
-
|
|
700
|
-
if (((_c = this.peer) === null || _c === void 0 ? void 0 : _c.disconnected) && ((_d = this.peer) === null || _d === void 0 ? void 0 : _d.options.token) === this.peerConfig.token) {
|
|
701
|
-
this.peer.reconnect();
|
|
702
|
-
return this.peer;
|
|
703
|
-
}
|
|
704
|
-
return this.createPeer();
|
|
433
|
+
return yield this.createPeer();
|
|
705
434
|
}
|
|
706
|
-
catch (
|
|
435
|
+
catch (_a) {
|
|
707
436
|
return this.createPeer();
|
|
708
437
|
}
|
|
438
|
+
finally {
|
|
439
|
+
this._reconnecting = false;
|
|
440
|
+
}
|
|
709
441
|
});
|
|
710
442
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
const peerIds = Array.from(this.connectPool.keys());
|
|
722
|
-
for (const pId of peerIds) {
|
|
723
|
-
this.removeConnection(pId);
|
|
724
|
-
}
|
|
725
|
-
this.requests.clear();
|
|
726
|
-
for (const timer of this.requestTimers.values()) {
|
|
727
|
-
clearTimeout(timer);
|
|
728
|
-
}
|
|
729
|
-
this.requestTimers.clear();
|
|
730
|
-
(_a = this.peer) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
731
|
-
(_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
|
|
732
|
-
this.booted = undefined;
|
|
733
|
-
this.peer = undefined;
|
|
734
|
-
if (this.checkerId) {
|
|
735
|
-
clearInterval(this.checkerId);
|
|
736
|
-
this.checkerId = null;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
destroy() {
|
|
740
|
-
this.clearInstance();
|
|
741
|
-
this.onDestroy();
|
|
443
|
+
// ── Message helpers ─────────────────────────────────────────────
|
|
444
|
+
inheritMessage(receiveMsg) {
|
|
445
|
+
return {
|
|
446
|
+
src: this.peerId,
|
|
447
|
+
id: receiveMsg.id,
|
|
448
|
+
requestId: receiveMsg.requestId,
|
|
449
|
+
route: receiveMsg.route,
|
|
450
|
+
createdAt: receiveMsg.createdAt,
|
|
451
|
+
action: entity_1.PeerAction.RECEIVE,
|
|
452
|
+
};
|
|
742
453
|
}
|
|
454
|
+
// ── Router integration ──────────────────────────────────────────
|
|
743
455
|
onRequest(conn, message) {
|
|
744
456
|
return __awaiter(this, void 0, void 0, function* () {
|
|
745
457
|
try {
|
|
746
|
-
console.log('onRequest@@', conn.peer, message.route);
|
|
747
458
|
yield this.router.run(conn, message);
|
|
748
459
|
}
|
|
749
460
|
catch (err) {
|
|
@@ -751,7 +462,7 @@ class PeerTransfer {
|
|
|
751
462
|
}
|
|
752
463
|
});
|
|
753
464
|
}
|
|
754
|
-
onResponse(
|
|
465
|
+
onResponse(_conn, message) {
|
|
755
466
|
return __awaiter(this, void 0, void 0, function* () {
|
|
756
467
|
const cb = this.requests.get(message.requestId);
|
|
757
468
|
if (cb) {
|
|
@@ -770,37 +481,34 @@ class PeerTransfer {
|
|
|
770
481
|
return this.reply(conn, message, { body: {}, error: err || 'service error' });
|
|
771
482
|
});
|
|
772
483
|
}
|
|
773
|
-
addRequest(id, cb) {
|
|
774
|
-
// 清除已有定时器,避免重复注册时旧定时器误删新回调
|
|
775
|
-
const oldTimer = this.requestTimers.get(id);
|
|
776
|
-
if (oldTimer) {
|
|
777
|
-
clearTimeout(oldTimer);
|
|
778
|
-
}
|
|
779
|
-
this.requests.set(id, cb);
|
|
780
|
-
const timer = setTimeout(() => {
|
|
781
|
-
this.requests.delete(id);
|
|
782
|
-
this.requestTimers.delete(id);
|
|
783
|
-
}, this.timeout);
|
|
784
|
-
this.requestTimers.set(id, timer);
|
|
785
|
-
}
|
|
786
484
|
use(handler, prefix = '') {
|
|
787
485
|
this.router.use(handler, prefix);
|
|
788
486
|
}
|
|
789
487
|
addRoute(route) {
|
|
790
488
|
this.router.add(route);
|
|
791
489
|
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
this.
|
|
490
|
+
// ── Lifecycle ───────────────────────────────────────────────────
|
|
491
|
+
clearInstance() {
|
|
492
|
+
this.destroyed = true;
|
|
493
|
+
for (const peerId of Array.from(this.connectPool.keys())) {
|
|
494
|
+
this.removeConnection(peerId);
|
|
495
|
+
}
|
|
496
|
+
this.requests.clear();
|
|
497
|
+
this.connRequests.clear();
|
|
498
|
+
this.destroyPeer();
|
|
499
|
+
}
|
|
500
|
+
destroy() {
|
|
501
|
+
this.clearInstance();
|
|
502
|
+
this.onDestroy();
|
|
795
503
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
this.
|
|
799
|
-
|
|
504
|
+
destroyPeer() {
|
|
505
|
+
var _a, _b;
|
|
506
|
+
(_a = this.peer) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
507
|
+
(_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
|
|
508
|
+
this.peer = undefined;
|
|
800
509
|
}
|
|
801
510
|
}
|
|
802
511
|
exports.PeerTransfer = PeerTransfer;
|
|
803
|
-
PeerTransfer.connecting = new Map();
|
|
804
512
|
__exportStar(require("./interfaces"), exports);
|
|
805
513
|
__exportStar(require("./handler"), exports);
|
|
806
514
|
__exportStar(require("./file-transfer"), exports);
|