egos-transfer 0.1.4 → 0.1.7
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/dist/constant.d.ts +1 -1
- package/dist/constant.js +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +171 -157
- package/dist/router.js +1 -1
- package/package.json +1 -1
- package/src/constant.ts +1 -1
- package/src/index.ts +179 -165
- package/src/router.ts +1 -3
package/dist/constant.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare const REQUEST_TIMEOUT = 18000;
|
|
|
2
2
|
export declare const HEARTBEAT_INTERVAL = 12000;
|
|
3
3
|
export declare const TRANSFER_TIMEOUT = 300000;
|
|
4
4
|
export declare const PING_TIMEOUT = 5000;
|
|
5
|
-
export declare const CONNECTION_TIMEOUT =
|
|
5
|
+
export declare const CONNECTION_TIMEOUT = 6000;
|
|
6
6
|
export declare const LOCKER_TIMEOUT = 15000;
|
|
7
7
|
export declare const RECONNECT_TIMEOUT = 5000;
|
|
8
8
|
export declare const PEER_OPEN_TIMEOUT = 15000;
|
package/dist/constant.js
CHANGED
|
@@ -5,7 +5,7 @@ exports.REQUEST_TIMEOUT = 18000;
|
|
|
5
5
|
exports.HEARTBEAT_INTERVAL = 12000;
|
|
6
6
|
exports.TRANSFER_TIMEOUT = 300000;
|
|
7
7
|
exports.PING_TIMEOUT = 5000;
|
|
8
|
-
exports.CONNECTION_TIMEOUT =
|
|
8
|
+
exports.CONNECTION_TIMEOUT = 6000;
|
|
9
9
|
exports.LOCKER_TIMEOUT = 15000;
|
|
10
10
|
exports.RECONNECT_TIMEOUT = 5000;
|
|
11
11
|
exports.PEER_OPEN_TIMEOUT = 15000;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,8 +12,6 @@ type PeerTransferOptions = PeerOptions & {
|
|
|
12
12
|
};
|
|
13
13
|
export declare abstract class PeerTransfer {
|
|
14
14
|
protected peer: Peer | undefined;
|
|
15
|
-
protected peerPool: Map<string, Peer>;
|
|
16
|
-
protected peerIdMap: Map<string, string>;
|
|
17
15
|
protected connectPool: Map<string, DataConnection>;
|
|
18
16
|
static connecting: Map<string, {
|
|
19
17
|
promise: Promise<any>;
|
|
@@ -26,11 +24,12 @@ export declare abstract class PeerTransfer {
|
|
|
26
24
|
protected requests: Map<string, ResponseCb>;
|
|
27
25
|
protected timeout: number;
|
|
28
26
|
protected router: PeerRouter;
|
|
29
|
-
protected booted: Promise<
|
|
27
|
+
protected booted: Promise<Peer | undefined>;
|
|
30
28
|
protected reconnectingPromise: Promise<Peer | undefined> | undefined;
|
|
31
29
|
protected checkerId: ReturnType<typeof setInterval>;
|
|
32
30
|
isPaused: boolean;
|
|
33
31
|
peerId: string;
|
|
32
|
+
private inRequest;
|
|
34
33
|
constructor(deviceId: string, config: PeerTransferOptions, isRadomPeerId?: boolean);
|
|
35
34
|
abstract getStore(): any;
|
|
36
35
|
abstract online(deviceId: string): void;
|
|
@@ -42,14 +41,15 @@ export declare abstract class PeerTransfer {
|
|
|
42
41
|
abstract requireAuth(): Promise<void>;
|
|
43
42
|
abstract onConnectLimit(): void;
|
|
44
43
|
abstract reloadConfig(config?: Record<string, any>): Promise<void>;
|
|
45
|
-
|
|
44
|
+
createPeer(force?: boolean): Promise<Peer | undefined>;
|
|
45
|
+
initialize(peer: Peer): Promise<void>;
|
|
46
46
|
handleSocketMessage(message: IMessage): void;
|
|
47
47
|
onHeartbeat(message: IMessage): void;
|
|
48
48
|
onError(message: IMessage): void;
|
|
49
49
|
onOpen(message: IMessage): void;
|
|
50
50
|
onDeviceOnline(message: IMessage): Promise<void>;
|
|
51
51
|
onDeviceOffline(message: IMessage): void;
|
|
52
|
-
removeConnection(peerId: string): void;
|
|
52
|
+
removeConnection(peerId: string, connectionId?: string): void;
|
|
53
53
|
addConnection(conn: DataConnection): void;
|
|
54
54
|
checkConnection(): void;
|
|
55
55
|
getApiHost(): string;
|
|
@@ -74,8 +74,8 @@ export declare abstract class PeerTransfer {
|
|
|
74
74
|
action: PeerAction;
|
|
75
75
|
};
|
|
76
76
|
reconnect(): Promise<Peer | undefined>;
|
|
77
|
+
isValidConnection(conn: DataConnection): boolean;
|
|
77
78
|
private doReconnect;
|
|
78
|
-
createPeer(force?: boolean): Promise<Peer | undefined>;
|
|
79
79
|
clearInstance(): void;
|
|
80
80
|
destroy(): void;
|
|
81
81
|
onRequest(conn: DataConnection, message: PeerMessage): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -32,100 +32,112 @@ const peerjs_1 = require("peerjs");
|
|
|
32
32
|
const entity_1 = require("./entity");
|
|
33
33
|
const router_1 = require("./router");
|
|
34
34
|
const axios_1 = __importDefault(require("axios"));
|
|
35
|
-
const helper_1 = require("./helper");
|
|
36
35
|
class PeerTransfer {
|
|
37
36
|
constructor(deviceId, config, isRadomPeerId = false) {
|
|
38
|
-
this.peerIdMap = new Map();
|
|
39
37
|
this.retry = 0;
|
|
38
|
+
this.inRequest = new Map();
|
|
40
39
|
this.connectPool = new Map();
|
|
41
40
|
this.peerConfig = Object.assign(Object.assign({}, config), { key: String(Date.now()) });
|
|
42
41
|
this.requests = new Map();
|
|
43
42
|
this.timeout = entity_1.REQUEST_TIMEOUT;
|
|
44
43
|
this.router = new router_1.PeerRouter();
|
|
45
|
-
this.peerPool = new Map();
|
|
46
44
|
this.isPaused = false;
|
|
47
45
|
this.peerId = isRadomPeerId ? deviceId + '_' + Date.now() : deviceId;
|
|
48
46
|
this.deviceId = deviceId;
|
|
49
47
|
}
|
|
48
|
+
createPeer() {
|
|
49
|
+
return __awaiter(this, arguments, void 0, function* (force = false) {
|
|
50
|
+
var _a;
|
|
51
|
+
if (this.isPaused) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (this.booted) {
|
|
55
|
+
return this.booted;
|
|
56
|
+
}
|
|
57
|
+
if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && !force) {
|
|
58
|
+
return this.peer;
|
|
59
|
+
}
|
|
60
|
+
this.destroy();
|
|
61
|
+
yield this.reloadConfig();
|
|
62
|
+
const peer = new peerjs_1.Peer(this.peerId, Object.assign(Object.assign({}, this.peerConfig), { pingInterval: 15000 }));
|
|
63
|
+
this.peer = peer;
|
|
64
|
+
yield this.initialize(this.peer);
|
|
65
|
+
this.checkConnection();
|
|
66
|
+
return this.peer;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
50
69
|
initialize(peer) {
|
|
51
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
52
71
|
try {
|
|
72
|
+
if (this.checkerId) {
|
|
73
|
+
clearInterval(this.checkerId);
|
|
74
|
+
}
|
|
53
75
|
this.booted = new Promise((resolve) => {
|
|
54
76
|
const timer = setTimeout(() => {
|
|
55
|
-
|
|
56
|
-
if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
|
|
57
|
-
this.createPeer(true);
|
|
58
|
-
}
|
|
59
|
-
// reject('peer open timeout');
|
|
77
|
+
resolve(null);
|
|
60
78
|
}, constant_1.PEER_OPEN_TIMEOUT);
|
|
79
|
+
const done = (peer) => {
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
resolve(peer);
|
|
82
|
+
};
|
|
61
83
|
peer.on('open', (id) => {
|
|
62
|
-
this.booted = undefined;
|
|
63
84
|
clearTimeout(timer);
|
|
64
|
-
|
|
85
|
+
done(peer);
|
|
65
86
|
});
|
|
87
|
+
peer.on('disconnected', () => {
|
|
88
|
+
if (!this.isPaused) {
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
if (!this.isPaused) {
|
|
91
|
+
this.reconnect();
|
|
92
|
+
}
|
|
93
|
+
}, constant_1.CONNECTION_RETRY);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
// duplicated with close event
|
|
97
|
+
peer.on('close', (...args) => { });
|
|
98
|
+
peer.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
if (err.message === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
100
|
+
this.stop();
|
|
101
|
+
done(null);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (err.message === constant_1.CONNECTION_LIMIT_EXCEED) {
|
|
105
|
+
this.stop();
|
|
106
|
+
this.onConnectLimit();
|
|
107
|
+
return done(null);
|
|
108
|
+
}
|
|
109
|
+
if (err.message == constant_1.UNAUTHORIZED) {
|
|
110
|
+
done(null);
|
|
111
|
+
return this.requireAuth();
|
|
112
|
+
}
|
|
113
|
+
if (err.type === 'network') {
|
|
114
|
+
done(null);
|
|
115
|
+
return this.reconnect();
|
|
116
|
+
}
|
|
117
|
+
if (err.type === 'server-error') {
|
|
118
|
+
done(null);
|
|
119
|
+
return this.reconnect();
|
|
120
|
+
}
|
|
121
|
+
done(null);
|
|
122
|
+
return this.reconnect();
|
|
123
|
+
}));
|
|
66
124
|
});
|
|
67
125
|
peer.on('connection', (conn) => {
|
|
126
|
+
conn.label = 'incoming';
|
|
68
127
|
this.onConnect(conn);
|
|
69
128
|
});
|
|
70
|
-
peer.on('disconnected', () => {
|
|
71
|
-
if (!this.isPaused) {
|
|
72
|
-
setTimeout(() => {
|
|
73
|
-
if (!this.isPaused) {
|
|
74
|
-
this.reconnect();
|
|
75
|
-
}
|
|
76
|
-
}, constant_1.CONNECTION_RETRY);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
peer.on('call', (mConn) => { });
|
|
80
|
-
peer.on('close', (...args) => {
|
|
81
|
-
if (this.isPaused) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
setTimeout(() => {
|
|
85
|
-
this.reconnect();
|
|
86
|
-
}, constant_1.CONNECTION_RETRY);
|
|
87
|
-
});
|
|
88
|
-
peer.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
|
|
89
|
-
if (err.message === constant_1.CONNECTION_PEER_CONFLICT) {
|
|
90
|
-
this.stop();
|
|
91
|
-
}
|
|
92
|
-
if (err.message === constant_1.CONNECTION_LIMIT_EXCEED) {
|
|
93
|
-
this.stop();
|
|
94
|
-
this.onConnectLimit();
|
|
95
|
-
}
|
|
96
|
-
if (err.message == constant_1.UNAUTHORIZED) {
|
|
97
|
-
yield this.requireAuth();
|
|
98
|
-
}
|
|
99
|
-
if (err.type === 'network') {
|
|
100
|
-
this.reconnect();
|
|
101
|
-
}
|
|
102
|
-
if (err.type === 'server-error') {
|
|
103
|
-
if (err.message === constant_1.UNAUTHORIZED) {
|
|
104
|
-
yield this.requireAuth();
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
this.reconnect();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}));
|
|
111
129
|
const socket = peer.socket;
|
|
112
130
|
socket === null || socket === void 0 ? void 0 : socket.on('message', (message) => {
|
|
113
131
|
this.handleSocketMessage(message);
|
|
114
132
|
});
|
|
115
|
-
socket === null || socket === void 0 ? void 0 : socket.on('error', (err) => {
|
|
116
|
-
console.log('socket@error', err);
|
|
117
|
-
});
|
|
118
|
-
socket.on('close', () => {
|
|
119
|
-
console.log('socket@close');
|
|
120
|
-
setTimeout(() => {
|
|
121
|
-
this.reconnect();
|
|
122
|
-
}, constant_1.CONNECTION_RETRY);
|
|
123
|
-
});
|
|
124
133
|
this.onHeartbeat({ type: 'HEARTBEAT' });
|
|
125
|
-
|
|
134
|
+
yield this.booted;
|
|
126
135
|
}
|
|
127
136
|
catch (err) {
|
|
128
|
-
|
|
137
|
+
this.booted = undefined;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
this.booted = undefined;
|
|
129
141
|
}
|
|
130
142
|
});
|
|
131
143
|
}
|
|
@@ -164,7 +176,6 @@ class PeerTransfer {
|
|
|
164
176
|
});
|
|
165
177
|
return;
|
|
166
178
|
}
|
|
167
|
-
this.reconnect();
|
|
168
179
|
}
|
|
169
180
|
onOpen(message) {
|
|
170
181
|
if (message.type !== 'OPEN') {
|
|
@@ -185,21 +196,29 @@ class PeerTransfer {
|
|
|
185
196
|
return;
|
|
186
197
|
}
|
|
187
198
|
const deviceId = message.payload.deviceId;
|
|
188
|
-
this.offline(deviceId);
|
|
189
199
|
this.ping(deviceId);
|
|
190
200
|
}
|
|
191
|
-
removeConnection(peerId) {
|
|
192
|
-
var _a
|
|
201
|
+
removeConnection(peerId, connectionId) {
|
|
202
|
+
var _a;
|
|
193
203
|
const conn = this.connectPool.get(peerId);
|
|
194
204
|
if (conn) {
|
|
195
|
-
if (
|
|
196
|
-
|
|
205
|
+
if (connectionId && conn.connectionId !== connectionId) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const sending = this.inRequest.get(conn.connectionId);
|
|
209
|
+
if (sending) {
|
|
210
|
+
// 提前结束request,避免关闭连接时触发反馈
|
|
211
|
+
sending.feedback();
|
|
212
|
+
this.inRequest.delete(conn.connectionId);
|
|
197
213
|
}
|
|
198
214
|
this.connectPool.delete(peerId);
|
|
199
|
-
|
|
215
|
+
conn.removeAllListeners();
|
|
216
|
+
conn.close();
|
|
217
|
+
(_a = this.peer) === null || _a === void 0 ? void 0 : _a._removeConnection(conn);
|
|
200
218
|
}
|
|
201
219
|
}
|
|
202
220
|
addConnection(conn) {
|
|
221
|
+
// console.log('addConnection@', conn.label);
|
|
203
222
|
this.connectPool.set(conn.peer, conn);
|
|
204
223
|
const connecting = PeerTransfer.connecting.get(conn.peer);
|
|
205
224
|
if (connecting) {
|
|
@@ -217,17 +236,20 @@ class PeerTransfer {
|
|
|
217
236
|
}
|
|
218
237
|
// turn credential expires
|
|
219
238
|
if (this.peerConfig.turnExpiredAt && Date.now() - 30000 > this.peerConfig.turnExpiredAt) {
|
|
239
|
+
// this.connectPool.clear();
|
|
220
240
|
yield this.createPeer(true);
|
|
221
|
-
this.connectPool.clear();
|
|
222
241
|
return;
|
|
223
242
|
}
|
|
224
|
-
const deviceIds = this.connectPool.keys();
|
|
225
|
-
for (const deviceId of deviceIds) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
243
|
+
// const deviceIds = this.connectPool.keys();
|
|
244
|
+
// for (const deviceId of deviceIds) {
|
|
245
|
+
// const conn = this.connectPool.get(deviceId);
|
|
246
|
+
// if (!this.isValidConnection(conn)) {
|
|
247
|
+
// this.removeConnection(conn.peer);
|
|
248
|
+
// this.peer?._removeConnection(conn);
|
|
249
|
+
// } else {
|
|
250
|
+
// this.ping(conn.peer);
|
|
251
|
+
// }
|
|
252
|
+
// }
|
|
231
253
|
}), constant_1.HEARTBEAT_INTERVAL);
|
|
232
254
|
}
|
|
233
255
|
getApiHost() {
|
|
@@ -257,22 +279,16 @@ class PeerTransfer {
|
|
|
257
279
|
if (deviceId === this.deviceId) {
|
|
258
280
|
return;
|
|
259
281
|
}
|
|
260
|
-
|
|
261
|
-
const pdId = (0, helper_1.purifyDeviceId)(deviceId);
|
|
262
|
-
if (this.peerIdMap.has(pdId)) {
|
|
263
|
-
peerId = this.peerIdMap.get(pdId) || '';
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
const status = yield this.getDeviceStatus(deviceId);
|
|
267
|
-
if (!status || !status.isOnline) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
peerId = status.deviceId;
|
|
271
|
-
this.peerIdMap.set(pdId, peerId);
|
|
272
|
-
}
|
|
282
|
+
const peerId = deviceId;
|
|
273
283
|
const existingConn = this.connectPool.get(peerId);
|
|
274
|
-
|
|
275
|
-
|
|
284
|
+
// console.log('connectToPeer', peerId, existingConn, this.connectPool);
|
|
285
|
+
if (existingConn) {
|
|
286
|
+
if (this.isValidConnection(existingConn)) {
|
|
287
|
+
return existingConn;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
this.removeConnection(peerId);
|
|
291
|
+
}
|
|
276
292
|
}
|
|
277
293
|
if (PeerTransfer.connecting.has(peerId)) {
|
|
278
294
|
const entry = PeerTransfer.connecting.get(peerId);
|
|
@@ -303,11 +319,14 @@ class PeerTransfer {
|
|
|
303
319
|
yield this.reconnect();
|
|
304
320
|
}
|
|
305
321
|
const cur = this.connectPool.get(peerId);
|
|
306
|
-
if (cur
|
|
322
|
+
if (this.isValidConnection(cur)) {
|
|
307
323
|
resolve(cur);
|
|
308
324
|
return cur;
|
|
309
325
|
}
|
|
310
|
-
const conn = (_b = this.peer) === null || _b === void 0 ? void 0 : _b.connect(peerId
|
|
326
|
+
const conn = (_b = this.peer) === null || _b === void 0 ? void 0 : _b.connect(peerId, {
|
|
327
|
+
label: 'outgoing',
|
|
328
|
+
metadata: { time: Date.now() },
|
|
329
|
+
});
|
|
311
330
|
if (!conn) {
|
|
312
331
|
continue;
|
|
313
332
|
}
|
|
@@ -322,7 +341,6 @@ class PeerTransfer {
|
|
|
322
341
|
}
|
|
323
342
|
catch (err) {
|
|
324
343
|
reject(err);
|
|
325
|
-
throw err;
|
|
326
344
|
}
|
|
327
345
|
finally {
|
|
328
346
|
PeerTransfer.connecting.delete(peerId);
|
|
@@ -335,7 +353,8 @@ class PeerTransfer {
|
|
|
335
353
|
return;
|
|
336
354
|
}
|
|
337
355
|
const conn = this.connectPool.get(peerId);
|
|
338
|
-
if (!conn) {
|
|
356
|
+
if (!this.isValidConnection(conn)) {
|
|
357
|
+
this.removeConnection(conn === null || conn === void 0 ? void 0 : conn.peer);
|
|
339
358
|
return;
|
|
340
359
|
}
|
|
341
360
|
const res = yield this.request(conn.peer, {
|
|
@@ -356,6 +375,19 @@ class PeerTransfer {
|
|
|
356
375
|
if (!conn) {
|
|
357
376
|
return;
|
|
358
377
|
}
|
|
378
|
+
const exists = this.connectPool.get(conn.peer);
|
|
379
|
+
// console.log('onConnect', conn.label, exists);
|
|
380
|
+
if (exists) {
|
|
381
|
+
if (exists.metadata.time > conn.metadata.time) {
|
|
382
|
+
this.removeConnection(conn.peer);
|
|
383
|
+
if (this.isValidConnection(exists)) {
|
|
384
|
+
return exists;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
this.removeConnection(exists.peer);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
359
391
|
return new Promise((resolve) => {
|
|
360
392
|
const done = (connection) => {
|
|
361
393
|
if (connection) {
|
|
@@ -365,57 +397,54 @@ class PeerTransfer {
|
|
|
365
397
|
resolve(connection);
|
|
366
398
|
};
|
|
367
399
|
const timer = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
368
|
-
if (conn
|
|
400
|
+
if (this.isValidConnection(conn)) {
|
|
369
401
|
this.addConnection(conn);
|
|
370
402
|
done(conn);
|
|
371
403
|
}
|
|
372
404
|
else {
|
|
373
405
|
conn.close();
|
|
374
406
|
this.removeConnection(conn.peer);
|
|
375
|
-
yield this.createPeer();
|
|
376
407
|
done(undefined);
|
|
377
408
|
}
|
|
378
409
|
}), constant_1.CONNECTION_TIMEOUT);
|
|
379
410
|
conn.on('data', (message) => {
|
|
380
411
|
switch (message.scope) {
|
|
381
412
|
case entity_1.PeerScope.REQUEST:
|
|
382
|
-
// console.log('peer@onRequest', message.route);
|
|
383
413
|
return this.onRequest(conn, message);
|
|
384
414
|
case entity_1.PeerScope.RESPONSE:
|
|
385
|
-
// console.log('peer@onResponse', message.route);
|
|
386
415
|
return this.onResponse(conn, message);
|
|
387
416
|
default:
|
|
388
417
|
return this.responseFail(conn, message, 'unknown scope');
|
|
389
418
|
}
|
|
390
419
|
});
|
|
391
420
|
conn.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
|
|
392
|
-
|
|
393
|
-
this.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
421
|
+
this.removeConnection(conn.peer, conn.connectionId);
|
|
422
|
+
// if (!this.peer?.open) {
|
|
423
|
+
// await this.reconnect();
|
|
424
|
+
// }
|
|
425
|
+
done(null);
|
|
397
426
|
}));
|
|
398
427
|
conn.on('close', () => __awaiter(this, void 0, void 0, function* () {
|
|
399
|
-
|
|
400
|
-
this.
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
428
|
+
this.removeConnection(conn.peer, conn.connectionId);
|
|
429
|
+
// if (!this.peer?.open) {
|
|
430
|
+
// await this.reconnect();
|
|
431
|
+
// }
|
|
432
|
+
done(null);
|
|
404
433
|
}));
|
|
405
434
|
conn.on('open', () => __awaiter(this, void 0, void 0, function* () {
|
|
406
|
-
this.addConnection(conn);
|
|
407
435
|
clearTimeout(timer);
|
|
408
436
|
done(conn);
|
|
409
437
|
}));
|
|
410
|
-
|
|
438
|
+
if (this.isValidConnection(conn)) {
|
|
439
|
+
done(conn);
|
|
440
|
+
}
|
|
411
441
|
});
|
|
412
442
|
});
|
|
413
443
|
}
|
|
414
444
|
request(peerId, payload) {
|
|
415
445
|
return __awaiter(this, void 0, void 0, function* () {
|
|
416
446
|
const conn = yield this.connectToPeer(peerId);
|
|
417
|
-
|
|
418
|
-
if (!conn) {
|
|
447
|
+
if (!this.isValidConnection(conn)) {
|
|
419
448
|
return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'build connection failed', code: -1 } });
|
|
420
449
|
}
|
|
421
450
|
const requestId = payload.requestId || (yield this.genRequestId());
|
|
@@ -425,15 +454,24 @@ class PeerTransfer {
|
|
|
425
454
|
body: {},
|
|
426
455
|
error: { message: 'request timeout' },
|
|
427
456
|
};
|
|
428
|
-
this.removeConnection(
|
|
457
|
+
this.removeConnection(conn.peer);
|
|
429
458
|
resolve(msg);
|
|
430
459
|
}, payload.timeout || entity_1.REQUEST_TIMEOUT);
|
|
460
|
+
this.inRequest.set(conn.connectionId, {
|
|
461
|
+
conn,
|
|
462
|
+
message: payload,
|
|
463
|
+
feedback: () => resolve({
|
|
464
|
+
body: {},
|
|
465
|
+
error: { message: 'send failed' },
|
|
466
|
+
}),
|
|
467
|
+
});
|
|
431
468
|
this.addRequest(requestId, (message) => {
|
|
432
469
|
clearTimeout(timeout);
|
|
433
470
|
const now = Date.now();
|
|
434
471
|
if (now - message.createdAt > 3000) {
|
|
435
472
|
console.warn('[egos] slow peer request:', message.route, now - message.createdAt);
|
|
436
473
|
}
|
|
474
|
+
this.inRequest.delete(conn.connectionId);
|
|
437
475
|
resolve(message);
|
|
438
476
|
});
|
|
439
477
|
});
|
|
@@ -445,7 +483,7 @@ class PeerTransfer {
|
|
|
445
483
|
reply(conn, oldMessage, message) {
|
|
446
484
|
return __awaiter(this, void 0, void 0, function* () {
|
|
447
485
|
const data = Object.assign(Object.assign(Object.assign({}, this.inheritMessage(oldMessage)), message), { dest: conn.peer, scope: entity_1.PeerScope.RESPONSE, updatedAt: Date.now() });
|
|
448
|
-
if (!conn
|
|
486
|
+
if (!this.isValidConnection(conn)) {
|
|
449
487
|
const connection = yield this.connectToPeer(conn.peer);
|
|
450
488
|
return connection === null || connection === void 0 ? void 0 : connection.send(data);
|
|
451
489
|
}
|
|
@@ -456,7 +494,7 @@ class PeerTransfer {
|
|
|
456
494
|
return __awaiter(this, void 0, void 0, function* () {
|
|
457
495
|
const internalApi = yield this.getApi(conn.peer);
|
|
458
496
|
let connection = conn;
|
|
459
|
-
if (!
|
|
497
|
+
if (!this.isValidConnection) {
|
|
460
498
|
const con = yield this.connectToPeer(conn.peer);
|
|
461
499
|
if (!con) {
|
|
462
500
|
return this.responseFail(conn, message, 'send with invalid connection');
|
|
@@ -492,27 +530,32 @@ class PeerTransfer {
|
|
|
492
530
|
});
|
|
493
531
|
});
|
|
494
532
|
}
|
|
533
|
+
isValidConnection(conn) {
|
|
534
|
+
if (!(conn === null || conn === void 0 ? void 0 : conn.open)) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
if (!(conn === null || conn === void 0 ? void 0 : conn.peerConnection)) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
|
|
541
|
+
}
|
|
495
542
|
doReconnect() {
|
|
496
543
|
return __awaiter(this, void 0, void 0, function* () {
|
|
497
|
-
var _a, _b;
|
|
544
|
+
var _a, _b, _c, _d;
|
|
498
545
|
try {
|
|
499
546
|
if (this.isPaused) {
|
|
500
547
|
return;
|
|
501
548
|
}
|
|
502
|
-
if ((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) {
|
|
549
|
+
if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && this.peerConfig.token === ((_b = this.peer) === null || _b === void 0 ? void 0 : _b.options.token)) {
|
|
503
550
|
return this.peer;
|
|
504
551
|
}
|
|
505
|
-
|
|
506
|
-
if ((
|
|
552
|
+
// return this.createPeer();
|
|
553
|
+
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) {
|
|
507
554
|
this.peer.reconnect();
|
|
508
|
-
return;
|
|
555
|
+
return this.peer;
|
|
509
556
|
}
|
|
510
557
|
else {
|
|
511
|
-
yield
|
|
512
|
-
setTimeout(() => {
|
|
513
|
-
resolve(undefined);
|
|
514
|
-
}, constant_1.RECONNECT_TIMEOUT);
|
|
515
|
-
});
|
|
558
|
+
yield this.reloadConfig();
|
|
516
559
|
return this.createPeer();
|
|
517
560
|
}
|
|
518
561
|
}
|
|
@@ -521,34 +564,6 @@ class PeerTransfer {
|
|
|
521
564
|
}
|
|
522
565
|
});
|
|
523
566
|
}
|
|
524
|
-
createPeer() {
|
|
525
|
-
return __awaiter(this, arguments, void 0, function* (force = false) {
|
|
526
|
-
var _a, _b;
|
|
527
|
-
if (this.isPaused) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
if (this.booted) {
|
|
531
|
-
yield this.booted;
|
|
532
|
-
if ((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) {
|
|
533
|
-
return this.peer;
|
|
534
|
-
}
|
|
535
|
-
this.booted = undefined;
|
|
536
|
-
}
|
|
537
|
-
if (((_b = this.peer) === null || _b === void 0 ? void 0 : _b.open) && !force) {
|
|
538
|
-
return this.peer;
|
|
539
|
-
}
|
|
540
|
-
this.destroy();
|
|
541
|
-
yield this.reloadConfig();
|
|
542
|
-
const peer = new peerjs_1.Peer(this.peerId, Object.assign(Object.assign({}, this.peerConfig), { pingInterval: 15000 }));
|
|
543
|
-
this.peer = peer;
|
|
544
|
-
if (this.checkerId) {
|
|
545
|
-
clearInterval(this.checkerId);
|
|
546
|
-
}
|
|
547
|
-
this.checkConnection();
|
|
548
|
-
yield this.initialize(peer);
|
|
549
|
-
return this.peer;
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
567
|
clearInstance() {
|
|
553
568
|
var _a, _b;
|
|
554
569
|
PeerTransfer.connecting.clear();
|
|
@@ -557,8 +572,7 @@ class PeerTransfer {
|
|
|
557
572
|
this.removeConnection(pId);
|
|
558
573
|
}
|
|
559
574
|
(_a = this.peer) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
560
|
-
(_b = this.peer) === null || _b === void 0 ? void 0 : _b.
|
|
561
|
-
this.peerPool.clear();
|
|
575
|
+
(_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
|
|
562
576
|
this.booted = undefined;
|
|
563
577
|
this.peer = undefined;
|
|
564
578
|
if (this.checkerId) {
|
package/dist/router.js
CHANGED
|
@@ -118,7 +118,7 @@ class PeerRouter {
|
|
|
118
118
|
.sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
119
119
|
const res = yield this.compose(stack)(conn, message);
|
|
120
120
|
// Execute route handler with timeout
|
|
121
|
-
const routePromise = Promise.resolve(route.callback.apply(
|
|
121
|
+
const routePromise = Promise.resolve(route.callback.apply(null, [conn, message]));
|
|
122
122
|
const timeoutPromise = new Promise((_, reject) => {
|
|
123
123
|
setTimeout(() => reject(new Error('Request timeout')), route.timeout || 30000);
|
|
124
124
|
});
|
package/package.json
CHANGED
package/src/constant.ts
CHANGED
|
@@ -2,7 +2,7 @@ export const REQUEST_TIMEOUT = 18000;
|
|
|
2
2
|
export const HEARTBEAT_INTERVAL = 12000;
|
|
3
3
|
export const TRANSFER_TIMEOUT = 300000;
|
|
4
4
|
export const PING_TIMEOUT = 5000;
|
|
5
|
-
export const CONNECTION_TIMEOUT =
|
|
5
|
+
export const CONNECTION_TIMEOUT = 6000;
|
|
6
6
|
export const LOCKER_TIMEOUT = 15000;
|
|
7
7
|
export const RECONNECT_TIMEOUT = 5000;
|
|
8
8
|
export const PEER_OPEN_TIMEOUT = 15000;
|
package/src/index.ts
CHANGED
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
HEARTBEAT_INTERVAL,
|
|
7
7
|
PEER_OPEN_TIMEOUT,
|
|
8
8
|
PING_TIMEOUT,
|
|
9
|
-
RECONNECT_TIMEOUT,
|
|
10
9
|
UNAUTHORIZED,
|
|
11
10
|
} from './constant';
|
|
12
11
|
import { DataConnection, MediaConnection, Peer, PeerOptions } from 'peerjs';
|
|
13
12
|
import {
|
|
13
|
+
DataMessage,
|
|
14
14
|
IDeviceStatus,
|
|
15
15
|
IMessage,
|
|
16
16
|
PeerMessage,
|
|
@@ -22,7 +22,6 @@ import { InternalApi, PeerAction, PeerRoutes, PeerScope, REQUEST_TIMEOUT } from
|
|
|
22
22
|
|
|
23
23
|
import { PeerRouter } from './router';
|
|
24
24
|
import axios from 'axios';
|
|
25
|
-
import { purifyDeviceId } from './helper';
|
|
26
25
|
|
|
27
26
|
export interface ContentPayload {
|
|
28
27
|
file: string;
|
|
@@ -36,11 +35,7 @@ type PeerTransferOptions = PeerOptions & {
|
|
|
36
35
|
|
|
37
36
|
export abstract class PeerTransfer {
|
|
38
37
|
protected peer: Peer | undefined;
|
|
39
|
-
protected peerPool: Map<string, Peer>;
|
|
40
|
-
protected peerIdMap: Map<string, string> = new Map();
|
|
41
|
-
|
|
42
38
|
protected connectPool: Map<string, DataConnection>;
|
|
43
|
-
|
|
44
39
|
static connecting: Map<
|
|
45
40
|
string,
|
|
46
41
|
{
|
|
@@ -57,11 +52,15 @@ export abstract class PeerTransfer {
|
|
|
57
52
|
protected requests: Map<string, ResponseCb>;
|
|
58
53
|
protected timeout: number;
|
|
59
54
|
protected router: PeerRouter;
|
|
60
|
-
protected booted: Promise<
|
|
55
|
+
protected booted: Promise<Peer | undefined>;
|
|
61
56
|
protected reconnectingPromise: Promise<Peer | undefined> | undefined;
|
|
62
57
|
protected checkerId!: ReturnType<typeof setInterval>;
|
|
63
58
|
public isPaused: boolean;
|
|
64
|
-
peerId: string;
|
|
59
|
+
public peerId: string;
|
|
60
|
+
private inRequest: Map<
|
|
61
|
+
string,
|
|
62
|
+
{ conn: DataConnection; message: Record<string, any>; feedback: () => void }
|
|
63
|
+
> = new Map();
|
|
65
64
|
|
|
66
65
|
constructor(deviceId: string, config: PeerTransferOptions, isRadomPeerId = false) {
|
|
67
66
|
this.connectPool = new Map<string, DataConnection>();
|
|
@@ -72,7 +71,6 @@ export abstract class PeerTransfer {
|
|
|
72
71
|
this.requests = new Map();
|
|
73
72
|
this.timeout = REQUEST_TIMEOUT;
|
|
74
73
|
this.router = new PeerRouter();
|
|
75
|
-
this.peerPool = new Map();
|
|
76
74
|
this.isPaused = false;
|
|
77
75
|
this.peerId = isRadomPeerId ? deviceId + '_' + Date.now() : deviceId;
|
|
78
76
|
this.deviceId = deviceId;
|
|
@@ -88,82 +86,98 @@ export abstract class PeerTransfer {
|
|
|
88
86
|
abstract requireAuth(): Promise<void>;
|
|
89
87
|
abstract onConnectLimit(): void;
|
|
90
88
|
abstract reloadConfig(config?: Record<string, any>): Promise<void>;
|
|
89
|
+
|
|
90
|
+
async createPeer(force = false): Promise<Peer | undefined> {
|
|
91
|
+
if (this.isPaused) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (this.booted) {
|
|
95
|
+
return this.booted;
|
|
96
|
+
}
|
|
97
|
+
if (this.peer?.open && !force) {
|
|
98
|
+
return this.peer;
|
|
99
|
+
}
|
|
100
|
+
this.destroy();
|
|
101
|
+
await this.reloadConfig();
|
|
102
|
+
const peer = new Peer(this.peerId, {
|
|
103
|
+
...this.peerConfig,
|
|
104
|
+
pingInterval: 15000,
|
|
105
|
+
});
|
|
106
|
+
this.peer = peer;
|
|
107
|
+
await this.initialize(this.peer);
|
|
108
|
+
this.checkConnection();
|
|
109
|
+
return this.peer;
|
|
110
|
+
}
|
|
91
111
|
async initialize(peer: Peer) {
|
|
92
112
|
try {
|
|
113
|
+
if (this.checkerId) {
|
|
114
|
+
clearInterval(this.checkerId);
|
|
115
|
+
}
|
|
116
|
+
|
|
93
117
|
this.booted = new Promise((resolve) => {
|
|
94
118
|
const timer = setTimeout(() => {
|
|
95
|
-
|
|
96
|
-
this.createPeer(true);
|
|
97
|
-
}
|
|
98
|
-
// reject('peer open timeout');
|
|
119
|
+
resolve(null);
|
|
99
120
|
}, PEER_OPEN_TIMEOUT);
|
|
121
|
+
const done = (peer?: Peer) => {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
resolve(peer);
|
|
124
|
+
};
|
|
100
125
|
peer.on('open', (id) => {
|
|
101
|
-
this.booted = undefined;
|
|
102
126
|
clearTimeout(timer);
|
|
103
|
-
|
|
127
|
+
done(peer);
|
|
128
|
+
});
|
|
129
|
+
peer.on('disconnected', () => {
|
|
130
|
+
if (!this.isPaused) {
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
if (!this.isPaused) {
|
|
133
|
+
this.reconnect();
|
|
134
|
+
}
|
|
135
|
+
}, CONNECTION_RETRY);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
// duplicated with close event
|
|
139
|
+
peer.on('close', (...args) => {});
|
|
140
|
+
peer.on('error', async (err) => {
|
|
141
|
+
if (err.message === CONNECTION_PEER_CONFLICT) {
|
|
142
|
+
this.stop();
|
|
143
|
+
done(null);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (err.message === CONNECTION_LIMIT_EXCEED) {
|
|
147
|
+
this.stop();
|
|
148
|
+
this.onConnectLimit();
|
|
149
|
+
return done(null);
|
|
150
|
+
}
|
|
151
|
+
if (err.message == UNAUTHORIZED) {
|
|
152
|
+
done(null);
|
|
153
|
+
return this.requireAuth();
|
|
154
|
+
}
|
|
155
|
+
if (err.type === 'network') {
|
|
156
|
+
done(null);
|
|
157
|
+
return this.reconnect();
|
|
158
|
+
}
|
|
159
|
+
if (err.type === 'server-error') {
|
|
160
|
+
done(null);
|
|
161
|
+
return this.reconnect();
|
|
162
|
+
}
|
|
163
|
+
done(null);
|
|
164
|
+
return this.reconnect();
|
|
104
165
|
});
|
|
105
166
|
});
|
|
106
|
-
peer.on('connection', (conn) => {
|
|
167
|
+
peer.on('connection', (conn: DataConnection) => {
|
|
168
|
+
conn.label = 'incoming';
|
|
107
169
|
this.onConnect(conn);
|
|
108
170
|
});
|
|
109
|
-
peer.on('disconnected', () => {
|
|
110
|
-
if (!this.isPaused) {
|
|
111
|
-
setTimeout(() => {
|
|
112
|
-
if (!this.isPaused) {
|
|
113
|
-
this.reconnect();
|
|
114
|
-
}
|
|
115
|
-
}, CONNECTION_RETRY);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
peer.on('call', (mConn: MediaConnection) => {});
|
|
119
|
-
peer.on('close', (...args) => {
|
|
120
|
-
if (this.isPaused) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
this.reconnect();
|
|
125
|
-
}, CONNECTION_RETRY);
|
|
126
|
-
});
|
|
127
|
-
peer.on('error', async (err) => {
|
|
128
|
-
if (err.message === CONNECTION_PEER_CONFLICT) {
|
|
129
|
-
this.stop();
|
|
130
|
-
}
|
|
131
|
-
if (err.message === CONNECTION_LIMIT_EXCEED) {
|
|
132
|
-
this.stop();
|
|
133
|
-
this.onConnectLimit();
|
|
134
|
-
}
|
|
135
|
-
if (err.message == UNAUTHORIZED) {
|
|
136
|
-
await this.requireAuth();
|
|
137
|
-
}
|
|
138
|
-
if (err.type === 'network') {
|
|
139
|
-
this.reconnect();
|
|
140
|
-
}
|
|
141
|
-
if (err.type === 'server-error') {
|
|
142
|
-
if (err.message === UNAUTHORIZED) {
|
|
143
|
-
await this.requireAuth();
|
|
144
|
-
} else {
|
|
145
|
-
this.reconnect();
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
171
|
const socket = peer.socket;
|
|
150
172
|
socket?.on('message', (message: IMessage) => {
|
|
151
173
|
this.handleSocketMessage(message);
|
|
152
174
|
});
|
|
153
|
-
socket?.on('error', (err) => {
|
|
154
|
-
console.log('socket@error', err);
|
|
155
|
-
});
|
|
156
|
-
socket.on('close', () => {
|
|
157
|
-
console.log('socket@close');
|
|
158
|
-
setTimeout(() => {
|
|
159
|
-
this.reconnect();
|
|
160
|
-
}, CONNECTION_RETRY);
|
|
161
|
-
});
|
|
162
175
|
this.onHeartbeat({ type: 'HEARTBEAT' } as IMessage);
|
|
163
|
-
|
|
164
|
-
return this.booted;
|
|
176
|
+
await this.booted;
|
|
165
177
|
} catch (err) {
|
|
166
|
-
|
|
178
|
+
this.booted = undefined;
|
|
179
|
+
} finally {
|
|
180
|
+
this.booted = undefined;
|
|
167
181
|
}
|
|
168
182
|
}
|
|
169
183
|
|
|
@@ -203,7 +217,6 @@ export abstract class PeerTransfer {
|
|
|
203
217
|
});
|
|
204
218
|
return;
|
|
205
219
|
}
|
|
206
|
-
this.reconnect();
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
onOpen(message: IMessage) {
|
|
@@ -225,22 +238,31 @@ export abstract class PeerTransfer {
|
|
|
225
238
|
return;
|
|
226
239
|
}
|
|
227
240
|
const deviceId = message.payload.deviceId;
|
|
228
|
-
this.offline(deviceId);
|
|
229
241
|
this.ping(deviceId);
|
|
230
242
|
}
|
|
231
243
|
|
|
232
|
-
removeConnection(peerId: string) {
|
|
244
|
+
removeConnection(peerId: string, connectionId?: string) {
|
|
233
245
|
const conn = this.connectPool.get(peerId);
|
|
234
246
|
if (conn) {
|
|
235
|
-
if (conn.
|
|
236
|
-
|
|
247
|
+
if (connectionId && conn.connectionId !== connectionId) {
|
|
248
|
+
return;
|
|
237
249
|
}
|
|
250
|
+
const sending = this.inRequest.get(conn.connectionId);
|
|
251
|
+
if (sending) {
|
|
252
|
+
// 提前结束request,避免关闭连接时触发反馈
|
|
253
|
+
sending.feedback();
|
|
254
|
+
this.inRequest.delete(conn.connectionId);
|
|
255
|
+
}
|
|
256
|
+
|
|
238
257
|
this.connectPool.delete(peerId);
|
|
239
|
-
|
|
258
|
+
conn.removeAllListeners();
|
|
259
|
+
conn.close();
|
|
260
|
+
this.peer?._removeConnection(conn);
|
|
240
261
|
}
|
|
241
262
|
}
|
|
242
263
|
|
|
243
264
|
addConnection(conn: DataConnection) {
|
|
265
|
+
// console.log('addConnection@', conn.label);
|
|
244
266
|
this.connectPool.set(conn.peer, conn);
|
|
245
267
|
const connecting = PeerTransfer.connecting.get(conn.peer);
|
|
246
268
|
if (connecting) {
|
|
@@ -258,17 +280,20 @@ export abstract class PeerTransfer {
|
|
|
258
280
|
}
|
|
259
281
|
// turn credential expires
|
|
260
282
|
if (this.peerConfig.turnExpiredAt && Date.now() - 30000 > this.peerConfig.turnExpiredAt) {
|
|
283
|
+
// this.connectPool.clear();
|
|
261
284
|
await this.createPeer(true);
|
|
262
|
-
this.connectPool.clear();
|
|
263
285
|
return;
|
|
264
286
|
}
|
|
265
|
-
const deviceIds = this.connectPool.keys();
|
|
266
|
-
for (const deviceId of deviceIds) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
287
|
+
// const deviceIds = this.connectPool.keys();
|
|
288
|
+
// for (const deviceId of deviceIds) {
|
|
289
|
+
// const conn = this.connectPool.get(deviceId);
|
|
290
|
+
// if (!this.isValidConnection(conn)) {
|
|
291
|
+
// this.removeConnection(conn.peer);
|
|
292
|
+
// this.peer?._removeConnection(conn);
|
|
293
|
+
// } else {
|
|
294
|
+
// this.ping(conn.peer);
|
|
295
|
+
// }
|
|
296
|
+
// }
|
|
272
297
|
}, HEARTBEAT_INTERVAL);
|
|
273
298
|
}
|
|
274
299
|
|
|
@@ -296,23 +321,15 @@ export abstract class PeerTransfer {
|
|
|
296
321
|
return;
|
|
297
322
|
}
|
|
298
323
|
|
|
299
|
-
|
|
300
|
-
const pdId = purifyDeviceId(deviceId);
|
|
301
|
-
|
|
302
|
-
if (this.peerIdMap.has(pdId)) {
|
|
303
|
-
peerId = this.peerIdMap.get(pdId) || '';
|
|
304
|
-
} else {
|
|
305
|
-
const status = await this.getDeviceStatus(deviceId);
|
|
306
|
-
if (!status || !status.isOnline) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
peerId = status.deviceId;
|
|
310
|
-
this.peerIdMap.set(pdId, peerId);
|
|
311
|
-
}
|
|
312
|
-
|
|
324
|
+
const peerId = deviceId;
|
|
313
325
|
const existingConn = this.connectPool.get(peerId);
|
|
314
|
-
|
|
315
|
-
|
|
326
|
+
// console.log('connectToPeer', peerId, existingConn, this.connectPool);
|
|
327
|
+
if (existingConn) {
|
|
328
|
+
if (this.isValidConnection(existingConn)) {
|
|
329
|
+
return existingConn;
|
|
330
|
+
} else {
|
|
331
|
+
this.removeConnection(peerId);
|
|
332
|
+
}
|
|
316
333
|
}
|
|
317
334
|
|
|
318
335
|
if (PeerTransfer.connecting.has(peerId)) {
|
|
@@ -336,7 +353,6 @@ export abstract class PeerTransfer {
|
|
|
336
353
|
});
|
|
337
354
|
|
|
338
355
|
PeerTransfer.connecting.set(peerId, { promise: connectionPromise, resolve, reject });
|
|
339
|
-
|
|
340
356
|
try {
|
|
341
357
|
for (let retry = 0; retry < 3; retry++) {
|
|
342
358
|
if (!this.peer) {
|
|
@@ -347,16 +363,18 @@ export abstract class PeerTransfer {
|
|
|
347
363
|
}
|
|
348
364
|
|
|
349
365
|
const cur = this.connectPool.get(peerId);
|
|
350
|
-
if (cur
|
|
366
|
+
if (this.isValidConnection(cur)) {
|
|
351
367
|
resolve(cur);
|
|
352
368
|
return cur;
|
|
353
369
|
}
|
|
354
370
|
|
|
355
|
-
const conn = this.peer?.connect(peerId
|
|
371
|
+
const conn = this.peer?.connect(peerId, {
|
|
372
|
+
label: 'outgoing',
|
|
373
|
+
metadata: { time: Date.now() },
|
|
374
|
+
});
|
|
356
375
|
if (!conn) {
|
|
357
376
|
continue;
|
|
358
377
|
}
|
|
359
|
-
|
|
360
378
|
const connection = await this.onConnect(conn as DataConnection).catch(() => {});
|
|
361
379
|
if (connection) {
|
|
362
380
|
resolve(conn);
|
|
@@ -367,7 +385,6 @@ export abstract class PeerTransfer {
|
|
|
367
385
|
return undefined;
|
|
368
386
|
} catch (err) {
|
|
369
387
|
reject(err);
|
|
370
|
-
throw err;
|
|
371
388
|
} finally {
|
|
372
389
|
PeerTransfer.connecting.delete(peerId);
|
|
373
390
|
}
|
|
@@ -378,7 +395,8 @@ export abstract class PeerTransfer {
|
|
|
378
395
|
return;
|
|
379
396
|
}
|
|
380
397
|
const conn = this.connectPool.get(peerId);
|
|
381
|
-
if (!conn) {
|
|
398
|
+
if (!this.isValidConnection(conn)) {
|
|
399
|
+
this.removeConnection(conn?.peer);
|
|
382
400
|
return;
|
|
383
401
|
}
|
|
384
402
|
const res = await this.request(conn.peer, {
|
|
@@ -398,6 +416,18 @@ export abstract class PeerTransfer {
|
|
|
398
416
|
if (!conn) {
|
|
399
417
|
return;
|
|
400
418
|
}
|
|
419
|
+
const exists = this.connectPool.get(conn.peer);
|
|
420
|
+
// console.log('onConnect', conn.label, exists);
|
|
421
|
+
if (exists) {
|
|
422
|
+
if (exists.metadata.time > conn.metadata.time) {
|
|
423
|
+
this.removeConnection(conn.peer);
|
|
424
|
+
if (this.isValidConnection(exists)) {
|
|
425
|
+
return exists;
|
|
426
|
+
}
|
|
427
|
+
} else {
|
|
428
|
+
this.removeConnection(exists.peer);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
401
431
|
return new Promise((resolve) => {
|
|
402
432
|
const done = (connection?: DataConnection) => {
|
|
403
433
|
if (connection) {
|
|
@@ -407,59 +437,59 @@ export abstract class PeerTransfer {
|
|
|
407
437
|
resolve(connection);
|
|
408
438
|
};
|
|
409
439
|
const timer = setTimeout(async () => {
|
|
410
|
-
if (conn
|
|
440
|
+
if (this.isValidConnection(conn)) {
|
|
411
441
|
this.addConnection(conn);
|
|
412
442
|
done(conn);
|
|
413
443
|
} else {
|
|
414
444
|
conn.close();
|
|
415
445
|
this.removeConnection(conn.peer);
|
|
416
|
-
await this.createPeer();
|
|
417
446
|
done(undefined);
|
|
418
447
|
}
|
|
419
448
|
}, CONNECTION_TIMEOUT);
|
|
420
449
|
conn.on('data', (message: any) => {
|
|
421
450
|
switch (message.scope) {
|
|
422
451
|
case PeerScope.REQUEST:
|
|
423
|
-
// console.log('peer@onRequest', message.route);
|
|
424
452
|
return this.onRequest(conn, message);
|
|
425
453
|
case PeerScope.RESPONSE:
|
|
426
|
-
// console.log('peer@onResponse', message.route);
|
|
427
454
|
return this.onResponse(conn, message);
|
|
428
455
|
default:
|
|
429
456
|
return this.responseFail(conn, message, 'unknown scope');
|
|
430
457
|
}
|
|
431
458
|
});
|
|
432
459
|
conn.on('error', async (err) => {
|
|
433
|
-
this.removeConnection(conn.peer);
|
|
434
|
-
if (!this.peer?.open) {
|
|
435
|
-
|
|
436
|
-
}
|
|
460
|
+
this.removeConnection(conn.peer, conn.connectionId);
|
|
461
|
+
// if (!this.peer?.open) {
|
|
462
|
+
// await this.reconnect();
|
|
463
|
+
// }
|
|
464
|
+
done(null);
|
|
437
465
|
});
|
|
438
466
|
conn.on('close', async () => {
|
|
439
|
-
this.removeConnection(conn.peer);
|
|
440
|
-
if (!this.peer?.open) {
|
|
441
|
-
|
|
442
|
-
}
|
|
467
|
+
this.removeConnection(conn.peer, conn.connectionId);
|
|
468
|
+
// if (!this.peer?.open) {
|
|
469
|
+
// await this.reconnect();
|
|
470
|
+
// }
|
|
471
|
+
done(null);
|
|
443
472
|
});
|
|
444
473
|
conn.on('open', async () => {
|
|
445
|
-
this.addConnection(conn);
|
|
446
474
|
clearTimeout(timer);
|
|
447
475
|
done(conn);
|
|
448
476
|
});
|
|
449
|
-
|
|
477
|
+
if (this.isValidConnection(conn)) {
|
|
478
|
+
done(conn);
|
|
479
|
+
}
|
|
450
480
|
});
|
|
451
481
|
}
|
|
452
482
|
|
|
453
483
|
async request(peerId: string, payload: PeerRequestPayload): Promise<PeerMessage> {
|
|
454
484
|
const conn = await this.connectToPeer(peerId);
|
|
455
|
-
|
|
456
|
-
if (!conn) {
|
|
485
|
+
if (!this.isValidConnection(conn)) {
|
|
457
486
|
return {
|
|
458
487
|
...payload,
|
|
459
488
|
body: {},
|
|
460
489
|
error: { message: 'build connection failed', code: -1 },
|
|
461
490
|
} as any;
|
|
462
491
|
}
|
|
492
|
+
|
|
463
493
|
const requestId = payload.requestId || (await this.genRequestId());
|
|
464
494
|
const q = new Promise<Record<string, any>>((resolve) => {
|
|
465
495
|
const timeout = setTimeout(() => {
|
|
@@ -467,15 +497,25 @@ export abstract class PeerTransfer {
|
|
|
467
497
|
body: {},
|
|
468
498
|
error: { message: 'request timeout' },
|
|
469
499
|
};
|
|
470
|
-
this.removeConnection(
|
|
500
|
+
this.removeConnection(conn.peer);
|
|
471
501
|
resolve(msg);
|
|
472
502
|
}, payload.timeout || REQUEST_TIMEOUT);
|
|
503
|
+
this.inRequest.set(conn.connectionId, {
|
|
504
|
+
conn,
|
|
505
|
+
message: payload,
|
|
506
|
+
feedback: () =>
|
|
507
|
+
resolve({
|
|
508
|
+
body: {},
|
|
509
|
+
error: { message: 'send failed' },
|
|
510
|
+
}),
|
|
511
|
+
});
|
|
473
512
|
this.addRequest(requestId, (message: Record<string, any>) => {
|
|
474
513
|
clearTimeout(timeout);
|
|
475
514
|
const now = Date.now();
|
|
476
515
|
if (now - message.createdAt > 3000) {
|
|
477
516
|
console.warn('[egos] slow peer request:', message.route, now - message.createdAt);
|
|
478
517
|
}
|
|
518
|
+
this.inRequest.delete(conn.connectionId);
|
|
479
519
|
resolve(message);
|
|
480
520
|
});
|
|
481
521
|
});
|
|
@@ -504,7 +544,7 @@ export abstract class PeerTransfer {
|
|
|
504
544
|
scope: PeerScope.RESPONSE,
|
|
505
545
|
updatedAt: Date.now(),
|
|
506
546
|
};
|
|
507
|
-
if (!conn
|
|
547
|
+
if (!this.isValidConnection(conn)) {
|
|
508
548
|
const connection = await this.connectToPeer(conn.peer);
|
|
509
549
|
return connection?.send(data);
|
|
510
550
|
}
|
|
@@ -515,7 +555,7 @@ export abstract class PeerTransfer {
|
|
|
515
555
|
async send(conn: DataConnection, message: PeerRequestPayload) {
|
|
516
556
|
const internalApi = await this.getApi(conn.peer);
|
|
517
557
|
let connection = conn;
|
|
518
|
-
if (!
|
|
558
|
+
if (!this.isValidConnection) {
|
|
519
559
|
const con = await this.connectToPeer(conn.peer);
|
|
520
560
|
if (!con) {
|
|
521
561
|
return this.responseFail(conn, message as PeerMessage, 'send with invalid connection');
|
|
@@ -567,25 +607,30 @@ export abstract class PeerTransfer {
|
|
|
567
607
|
});
|
|
568
608
|
}
|
|
569
609
|
|
|
610
|
+
isValidConnection(conn: DataConnection) {
|
|
611
|
+
if (!conn?.open) {
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
if (!conn?.peerConnection) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
|
|
618
|
+
}
|
|
619
|
+
|
|
570
620
|
private async doReconnect(): Promise<Peer | undefined> {
|
|
571
621
|
try {
|
|
572
622
|
if (this.isPaused) {
|
|
573
623
|
return;
|
|
574
624
|
}
|
|
575
|
-
if (this.peer?.open) {
|
|
625
|
+
if (this.peer?.open && this.peerConfig.token === this.peer?.options.token) {
|
|
576
626
|
return this.peer;
|
|
577
627
|
}
|
|
578
|
-
|
|
579
|
-
if (this.peer?.disconnected) {
|
|
628
|
+
// return this.createPeer();
|
|
629
|
+
if (this.peer?.disconnected && this.peer?.options.token === this.peerConfig.token) {
|
|
580
630
|
this.peer.reconnect();
|
|
581
|
-
return;
|
|
631
|
+
return this.peer;
|
|
582
632
|
} else {
|
|
583
|
-
await
|
|
584
|
-
setTimeout(() => {
|
|
585
|
-
resolve(undefined);
|
|
586
|
-
}, RECONNECT_TIMEOUT);
|
|
587
|
-
});
|
|
588
|
-
|
|
633
|
+
await this.reloadConfig();
|
|
589
634
|
return this.createPeer();
|
|
590
635
|
}
|
|
591
636
|
} catch (err) {
|
|
@@ -593,36 +638,6 @@ export abstract class PeerTransfer {
|
|
|
593
638
|
}
|
|
594
639
|
}
|
|
595
640
|
|
|
596
|
-
async createPeer(force = false): Promise<Peer | undefined> {
|
|
597
|
-
if (this.isPaused) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
if (this.booted) {
|
|
601
|
-
await this.booted;
|
|
602
|
-
if (this.peer?.open) {
|
|
603
|
-
return this.peer;
|
|
604
|
-
}
|
|
605
|
-
this.booted = undefined;
|
|
606
|
-
}
|
|
607
|
-
if (this.peer?.open && !force) {
|
|
608
|
-
return this.peer;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
this.destroy();
|
|
612
|
-
await this.reloadConfig();
|
|
613
|
-
const peer = new Peer(this.peerId, {
|
|
614
|
-
...this.peerConfig,
|
|
615
|
-
pingInterval: 15000,
|
|
616
|
-
});
|
|
617
|
-
this.peer = peer;
|
|
618
|
-
if (this.checkerId) {
|
|
619
|
-
clearInterval(this.checkerId);
|
|
620
|
-
}
|
|
621
|
-
this.checkConnection();
|
|
622
|
-
await this.initialize(peer);
|
|
623
|
-
return this.peer;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
641
|
clearInstance() {
|
|
627
642
|
PeerTransfer.connecting.clear();
|
|
628
643
|
const peerIds = this.connectPool.keys();
|
|
@@ -630,8 +645,7 @@ export abstract class PeerTransfer {
|
|
|
630
645
|
this.removeConnection(pId);
|
|
631
646
|
}
|
|
632
647
|
this.peer?.destroy();
|
|
633
|
-
this.peer?.
|
|
634
|
-
this.peerPool.clear();
|
|
648
|
+
this.peer?.removeAllListeners();
|
|
635
649
|
this.booted = undefined;
|
|
636
650
|
this.peer = undefined;
|
|
637
651
|
if (this.checkerId) {
|
package/src/router.ts
CHANGED
|
@@ -149,15 +149,13 @@ export class PeerRouter {
|
|
|
149
149
|
.sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
150
150
|
|
|
151
151
|
const res = await this.compose(stack)(conn, message);
|
|
152
|
-
|
|
153
152
|
// Execute route handler with timeout
|
|
154
|
-
const routePromise = Promise.resolve(route.callback.apply(
|
|
153
|
+
const routePromise = Promise.resolve(route.callback.apply(null, [conn, message]));
|
|
155
154
|
const timeoutPromise = new Promise((_, reject) => {
|
|
156
155
|
setTimeout(() => reject(new Error('Request timeout')), route.timeout || 30000);
|
|
157
156
|
});
|
|
158
157
|
|
|
159
158
|
await Promise.race([routePromise, timeoutPromise]);
|
|
160
|
-
|
|
161
159
|
// Update performance metrics
|
|
162
160
|
const responseTime = this.performanceMonitor.endTimer(routeKey);
|
|
163
161
|
this.updateRouteStats(routeKey, 'responseTime', responseTime);
|