egos-transfer 0.2.5 → 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 +284 -590
- package/package.json +1 -1
- package/src/connection-manager.ts +223 -0
- package/src/file-transfer.ts +0 -1
- package/src/index.ts +2 -938
- 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.once('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,395 +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
|
-
// 重试前检查:对方可能已经建连成功(duplicate 场景)
|
|
394
|
-
const cur = this.connectPool.get(peerId);
|
|
395
|
-
if (this.isValidConnection(cur)) {
|
|
396
|
-
clearTimeout(guardTimer);
|
|
397
|
-
return resolve(cur);
|
|
398
|
-
}
|
|
399
|
-
const conn = (_b = this.peer) === null || _b === void 0 ? void 0 : _b.connect(peerId, {
|
|
400
|
-
label: 'outgoing',
|
|
401
|
-
metadata: { time: Date.now() },
|
|
402
|
-
});
|
|
403
|
-
if (!conn) {
|
|
404
|
-
continue;
|
|
405
|
-
}
|
|
406
|
-
const connection = yield this.onConnect(conn).catch(() => { });
|
|
407
|
-
if (connection) {
|
|
408
|
-
clearTimeout(guardTimer);
|
|
409
|
-
return resolve(connection);
|
|
410
|
-
}
|
|
411
|
-
// duplicate 场景:onConnect 返回 undefined 但连接池可能已有对方建的连接
|
|
412
|
-
const pooled = this.connectPool.get(peerId);
|
|
413
|
-
if (this.isValidConnection(pooled)) {
|
|
414
|
-
clearTimeout(guardTimer);
|
|
415
|
-
return resolve(pooled);
|
|
416
|
-
}
|
|
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();
|
|
417
156
|
}
|
|
418
|
-
|
|
419
|
-
resolve(undefined);
|
|
420
|
-
return undefined;
|
|
421
|
-
}
|
|
422
|
-
catch (err) {
|
|
423
|
-
reject(err);
|
|
424
|
-
}
|
|
425
|
-
finally {
|
|
426
|
-
PeerTransfer.connecting.delete(peerId);
|
|
157
|
+
catch ( /* fall through */_c) { /* fall through */ }
|
|
427
158
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
*/
|
|
437
|
-
ping(peerId) {
|
|
438
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
439
|
-
if (this.deviceId === peerId) {
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
const conn = this.connectPool.get(peerId);
|
|
443
|
-
if (!this.isValidConnection(conn)) {
|
|
444
|
-
this.removeConnection(peerId, conn === null || conn === void 0 ? void 0 : conn.connectionId);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
try {
|
|
448
|
-
const requestId = yield this.genRequestId();
|
|
449
|
-
return new Promise((resolve) => {
|
|
450
|
-
const timer = setTimeout(() => {
|
|
451
|
-
this.requests.delete(requestId);
|
|
452
|
-
resolve(false);
|
|
453
|
-
}, constant_1.PING_TIMEOUT);
|
|
454
|
-
this.requests.set(requestId, () => {
|
|
455
|
-
clearTimeout(timer);
|
|
456
|
-
resolve(true);
|
|
457
|
-
});
|
|
458
|
-
conn.send({
|
|
459
|
-
route: entity_1.PeerRoutes.HEARTBEAT,
|
|
460
|
-
method: 'get',
|
|
461
|
-
body: {},
|
|
462
|
-
requestId,
|
|
463
|
-
scope: entity_1.PeerScope.REQUEST,
|
|
464
|
-
action: entity_1.PeerAction.SEND,
|
|
465
|
-
src: this.peerId,
|
|
466
|
-
dest: peerId,
|
|
467
|
-
headers: {},
|
|
468
|
-
createdAt: Date.now(),
|
|
469
|
-
});
|
|
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() },
|
|
470
167
|
});
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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;
|
|
475
178
|
});
|
|
476
179
|
}
|
|
477
180
|
onConnect(conn) {
|
|
478
181
|
return __awaiter(this, void 0, void 0, function* () {
|
|
479
|
-
if (!conn)
|
|
182
|
+
if (!conn)
|
|
480
183
|
return;
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
// 双方同时建连时,保留 peerId 字典序大的那条(确定性,不依赖时间戳)
|
|
485
|
-
if (exists.connectionId > conn.connectionId) {
|
|
184
|
+
const existing = this.connectPool.get(conn.peer);
|
|
185
|
+
if (existing) {
|
|
186
|
+
if (existing.connectionId > conn.connectionId) {
|
|
486
187
|
this.removeConnection(conn.peer, conn.connectionId);
|
|
487
|
-
if (this.isValidConnection(
|
|
488
|
-
return
|
|
489
|
-
}
|
|
188
|
+
if (this.isValidConnection(existing))
|
|
189
|
+
return existing;
|
|
490
190
|
}
|
|
491
191
|
else {
|
|
492
|
-
this.removeConnection(
|
|
192
|
+
this.removeConnection(existing.peer, existing.connectionId);
|
|
493
193
|
}
|
|
494
194
|
}
|
|
495
195
|
if (conn.open) {
|
|
496
|
-
this.
|
|
497
|
-
this.bindConnectionData(conn);
|
|
196
|
+
this.setupConnection(conn);
|
|
498
197
|
return conn;
|
|
499
198
|
}
|
|
500
199
|
return new Promise((resolve) => {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
if (connection) {
|
|
508
|
-
this.addConnection(connection);
|
|
509
|
-
}
|
|
510
|
-
resolve(connection);
|
|
511
|
-
};
|
|
512
|
-
timer = setTimeout(() => {
|
|
513
|
-
if (this.isValidConnection(conn)) {
|
|
514
|
-
this.addConnection(conn);
|
|
515
|
-
done(conn);
|
|
516
|
-
}
|
|
517
|
-
else {
|
|
518
|
-
this.removeConnection(conn.peer, conn.connectionId);
|
|
519
|
-
done(undefined);
|
|
520
|
-
}
|
|
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);
|
|
521
205
|
}, constant_1.CONNECTION_TIMEOUT);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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);
|
|
525
216
|
const pooled = this.connectPool.get(conn.peer);
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
});
|
|
538
|
-
conn.on('open', () => {
|
|
539
|
-
done(conn);
|
|
540
|
-
});
|
|
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);
|
|
541
228
|
});
|
|
542
229
|
});
|
|
543
230
|
}
|
|
544
|
-
|
|
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
|
+
}
|
|
545
280
|
bindConnectionData(conn) {
|
|
546
281
|
conn.on('data', (message) => {
|
|
547
282
|
switch (message.scope) {
|
|
@@ -554,39 +289,29 @@ class PeerTransfer {
|
|
|
554
289
|
}
|
|
555
290
|
});
|
|
556
291
|
}
|
|
292
|
+
// ── Request / Reply ─────────────────────────────────────────────
|
|
557
293
|
request(peerId, payload) {
|
|
558
294
|
return __awaiter(this, void 0, void 0, function* () {
|
|
559
295
|
var _a;
|
|
560
296
|
const requestId = payload.requestId || (yield this.genRequestId());
|
|
561
|
-
const maxRetry = 2;
|
|
562
297
|
let res;
|
|
563
|
-
for (let attempt = 0; attempt <=
|
|
298
|
+
for (let attempt = 0; attempt <= 2; attempt++) {
|
|
564
299
|
res = yield this.doRequestOnce(peerId, payload, requestId);
|
|
565
|
-
console.log('request once', res);
|
|
566
300
|
const code = (_a = res.error) === null || _a === void 0 ? void 0 : _a.code;
|
|
567
|
-
if (!res.error || (code !== 'CONN_CLOSED' && code !== 'CONN_FAILED'))
|
|
301
|
+
if (!res.error || (code !== 'CONN_CLOSED' && code !== 'CONN_FAILED'))
|
|
568
302
|
return res;
|
|
569
|
-
}
|
|
570
303
|
}
|
|
571
304
|
return res;
|
|
572
305
|
});
|
|
573
306
|
}
|
|
574
|
-
/**
|
|
575
|
-
* 执行一次请求,返回带错误码的结果供外层判断是否重试
|
|
576
|
-
* @param peerId - 目标 peerId
|
|
577
|
-
* @param payload - 请求负载
|
|
578
|
-
* @param requestId - 请求ID(重试时复用)
|
|
579
|
-
* @returns error.code: CONN_CLOSED/CONN_FAILED(可重试)、TIMEOUT(不重试)
|
|
580
|
-
*/
|
|
581
307
|
doRequestOnce(peerId, payload, requestId) {
|
|
582
308
|
return __awaiter(this, void 0, void 0, function* () {
|
|
583
|
-
console.log('doRequestOnce@@', peerId, this.destroyed, payload.route);
|
|
584
309
|
if (this.destroyed) {
|
|
585
310
|
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'destroyed', code: 'CONN_CLOSED' } });
|
|
586
311
|
}
|
|
587
312
|
const conn = yield this.connectToPeer(peerId);
|
|
588
313
|
if (!this.isValidConnection(conn)) {
|
|
589
|
-
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: '
|
|
314
|
+
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'connection failed', code: 'CONN_FAILED' } });
|
|
590
315
|
}
|
|
591
316
|
return new Promise((resolve) => {
|
|
592
317
|
let timeout = null;
|
|
@@ -595,39 +320,30 @@ class PeerTransfer {
|
|
|
595
320
|
clearTimeout(timeout);
|
|
596
321
|
timeout = null;
|
|
597
322
|
}
|
|
598
|
-
this.inRequest.delete(requestId);
|
|
599
323
|
this.requests.delete(requestId);
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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);
|
|
605
329
|
}
|
|
606
330
|
};
|
|
607
331
|
timeout = setTimeout(() => {
|
|
608
|
-
// 先清理,避免 removeConnection 触发 feedback 二次 resolve
|
|
609
332
|
cleanup();
|
|
610
333
|
this.removeConnection(conn.peer, conn.connectionId);
|
|
611
|
-
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: '
|
|
334
|
+
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'timeout', code: 'TIMEOUT' } }));
|
|
612
335
|
}, payload.timeout || entity_1.REQUEST_TIMEOUT);
|
|
613
|
-
this.
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
},
|
|
620
|
-
});
|
|
621
|
-
// 直接 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);
|
|
622
342
|
this.requests.set(requestId, (message) => {
|
|
623
343
|
cleanup();
|
|
624
|
-
const now = Date.now();
|
|
625
|
-
if (now - message.createdAt > 3000) {
|
|
626
|
-
console.warn('[egos] slow peer request:', message.route, now - message.createdAt);
|
|
627
|
-
}
|
|
628
344
|
resolve(message);
|
|
629
345
|
});
|
|
630
|
-
this.send(conn, Object.assign(Object.assign({}, payload), { requestId
|
|
346
|
+
this.send(conn, Object.assign(Object.assign({}, payload), { requestId })).catch(() => {
|
|
631
347
|
cleanup();
|
|
632
348
|
resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'send failed', code: 'CONN_CLOSED' } }));
|
|
633
349
|
});
|
|
@@ -638,8 +354,8 @@ class PeerTransfer {
|
|
|
638
354
|
return __awaiter(this, void 0, void 0, function* () {
|
|
639
355
|
const data = Object.assign(Object.assign(Object.assign({}, this.inheritMessage(oldMessage)), message), { dest: conn.peer, scope: entity_1.PeerScope.RESPONSE, updatedAt: Date.now() });
|
|
640
356
|
if (!this.isValidConnection(conn)) {
|
|
641
|
-
const
|
|
642
|
-
return
|
|
357
|
+
const c = yield this.connectToPeer(conn.peer);
|
|
358
|
+
return c === null || c === void 0 ? void 0 : c.send(data);
|
|
643
359
|
}
|
|
644
360
|
return conn.send(data);
|
|
645
361
|
});
|
|
@@ -649,115 +365,96 @@ class PeerTransfer {
|
|
|
649
365
|
const internalApi = yield this.getApi(conn.peer);
|
|
650
366
|
let connection = conn;
|
|
651
367
|
if (!this.isValidConnection(conn)) {
|
|
652
|
-
const
|
|
653
|
-
if (!
|
|
368
|
+
const c = yield this.connectToPeer(conn.peer);
|
|
369
|
+
if (!c)
|
|
654
370
|
return this.responseFail(conn, message, 'send with invalid connection');
|
|
655
|
-
|
|
656
|
-
connection = con;
|
|
371
|
+
connection = c;
|
|
657
372
|
}
|
|
658
373
|
const requestId = message.requestId || (yield this.genRequestId());
|
|
659
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);
|
|
660
375
|
});
|
|
661
376
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
src: this.peerId,
|
|
665
|
-
id: receiveMsg.id,
|
|
666
|
-
requestId: receiveMsg.requestId,
|
|
667
|
-
route: receiveMsg.route,
|
|
668
|
-
createdAt: receiveMsg.createdAt,
|
|
669
|
-
action: entity_1.PeerAction.RECEIVE,
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
reconnect() {
|
|
377
|
+
// ── Ping ────────────────────────────────────────────────────────
|
|
378
|
+
ping(peerId) {
|
|
673
379
|
return __awaiter(this, void 0, void 0, function* () {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
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;
|
|
677
386
|
}
|
|
678
|
-
|
|
679
|
-
|
|
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
|
+
});
|
|
398
|
+
}
|
|
399
|
+
catch (_a) {
|
|
400
|
+
return false;
|
|
680
401
|
}
|
|
681
|
-
this.reconnectingPromise = this.doReconnect();
|
|
682
|
-
return yield this.reconnectingPromise.finally(() => {
|
|
683
|
-
this.reconnectingPromise = undefined;
|
|
684
|
-
});
|
|
685
402
|
});
|
|
686
403
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
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}`;
|
|
695
411
|
}
|
|
696
|
-
|
|
412
|
+
getDeviceStatus(peerId) {
|
|
697
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
698
|
-
var _a, _b, _c, _d;
|
|
699
414
|
try {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
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 {
|
|
708
429
|
this.reconnectAttempt++;
|
|
709
430
|
const backoff = Math.min(BASE_RECONNECT_BACKOFF * Math.pow(2, this.reconnectAttempt - 1), MAX_RECONNECT_BACKOFF);
|
|
710
431
|
yield (0, delay_1.default)(backoff);
|
|
711
432
|
yield this.reloadConfig();
|
|
712
|
-
|
|
713
|
-
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) {
|
|
714
|
-
this.peer.reconnect();
|
|
715
|
-
return this.peer;
|
|
716
|
-
}
|
|
717
|
-
return this.createPeer();
|
|
433
|
+
return yield this.createPeer();
|
|
718
434
|
}
|
|
719
|
-
catch (
|
|
435
|
+
catch (_a) {
|
|
720
436
|
return this.createPeer();
|
|
721
437
|
}
|
|
438
|
+
finally {
|
|
439
|
+
this._reconnecting = false;
|
|
440
|
+
}
|
|
722
441
|
});
|
|
723
442
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
const peerIds = Array.from(this.connectPool.keys());
|
|
735
|
-
for (const pId of peerIds) {
|
|
736
|
-
this.removeConnection(pId);
|
|
737
|
-
}
|
|
738
|
-
this.requests.clear();
|
|
739
|
-
for (const timer of this.requestTimers.values()) {
|
|
740
|
-
clearTimeout(timer);
|
|
741
|
-
}
|
|
742
|
-
this.requestTimers.clear();
|
|
743
|
-
(_a = this.peer) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
744
|
-
(_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
|
|
745
|
-
this.booted = undefined;
|
|
746
|
-
this.peer = undefined;
|
|
747
|
-
if (this.checkerId) {
|
|
748
|
-
clearInterval(this.checkerId);
|
|
749
|
-
this.checkerId = null;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
destroy() {
|
|
753
|
-
this.clearInstance();
|
|
754
|
-
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
|
+
};
|
|
755
453
|
}
|
|
454
|
+
// ── Router integration ──────────────────────────────────────────
|
|
756
455
|
onRequest(conn, message) {
|
|
757
456
|
return __awaiter(this, void 0, void 0, function* () {
|
|
758
|
-
var _a;
|
|
759
457
|
try {
|
|
760
|
-
console.log('onRequest@@', (_a = conn.peer) === null || _a === void 0 ? void 0 : _a.substring(0, 4), message.route);
|
|
761
458
|
yield this.router.run(conn, message);
|
|
762
459
|
}
|
|
763
460
|
catch (err) {
|
|
@@ -765,7 +462,7 @@ class PeerTransfer {
|
|
|
765
462
|
}
|
|
766
463
|
});
|
|
767
464
|
}
|
|
768
|
-
onResponse(
|
|
465
|
+
onResponse(_conn, message) {
|
|
769
466
|
return __awaiter(this, void 0, void 0, function* () {
|
|
770
467
|
const cb = this.requests.get(message.requestId);
|
|
771
468
|
if (cb) {
|
|
@@ -784,37 +481,34 @@ class PeerTransfer {
|
|
|
784
481
|
return this.reply(conn, message, { body: {}, error: err || 'service error' });
|
|
785
482
|
});
|
|
786
483
|
}
|
|
787
|
-
addRequest(id, cb) {
|
|
788
|
-
// 清除已有定时器,避免重复注册时旧定时器误删新回调
|
|
789
|
-
const oldTimer = this.requestTimers.get(id);
|
|
790
|
-
if (oldTimer) {
|
|
791
|
-
clearTimeout(oldTimer);
|
|
792
|
-
}
|
|
793
|
-
this.requests.set(id, cb);
|
|
794
|
-
const timer = setTimeout(() => {
|
|
795
|
-
this.requests.delete(id);
|
|
796
|
-
this.requestTimers.delete(id);
|
|
797
|
-
}, this.timeout);
|
|
798
|
-
this.requestTimers.set(id, timer);
|
|
799
|
-
}
|
|
800
484
|
use(handler, prefix = '') {
|
|
801
485
|
this.router.use(handler, prefix);
|
|
802
486
|
}
|
|
803
487
|
addRoute(route) {
|
|
804
488
|
this.router.add(route);
|
|
805
489
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
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();
|
|
809
503
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
this.
|
|
813
|
-
|
|
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;
|
|
814
509
|
}
|
|
815
510
|
}
|
|
816
511
|
exports.PeerTransfer = PeerTransfer;
|
|
817
|
-
PeerTransfer.connecting = new Map();
|
|
818
512
|
__exportStar(require("./interfaces"), exports);
|
|
819
513
|
__exportStar(require("./handler"), exports);
|
|
820
514
|
__exportStar(require("./file-transfer"), exports);
|