@leofcoin/peernet 1.0.8 → 1.0.10
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/exports/browser/{client-bf4b2f00.js → client-bbd6e332.js} +415 -415
- package/exports/browser/{index-03344048.js → index-84ee0e0b.js} +1 -1
- package/exports/browser/{messages-28ebb39b.js → messages-def41fbf.js} +1 -1
- package/exports/browser/{peernet-749c4cfa.js → peernet-7ba6837f.js} +3 -3
- package/exports/browser/peernet.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LittlePubSub } from './peernet-
|
|
1
|
+
import { L as LittlePubSub } from './peernet-7ba6837f.js';
|
|
2
2
|
import './value-157ab062.js';
|
|
3
3
|
|
|
4
4
|
var clientApi = _pubsub => {
|
|
@@ -224,422 +224,422 @@ const socketRequestClient = (url, protocols = 'echo-protocol', options = { retry
|
|
|
224
224
|
});
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
class Peer {
|
|
228
|
-
#connection;
|
|
229
|
-
#connected = false;
|
|
230
|
-
#messageQue = [];
|
|
231
|
-
#chunksQue = {};
|
|
232
|
-
#channel;
|
|
233
|
-
#peerId;
|
|
234
|
-
#channelName;
|
|
235
|
-
#chunkSize = 16 * 1024; // 16384
|
|
236
|
-
#queRunning = false;
|
|
237
|
-
#MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024;
|
|
238
|
-
get connection() {
|
|
239
|
-
return this.#connection;
|
|
240
|
-
}
|
|
241
|
-
get connected() {
|
|
242
|
-
return this.#connected;
|
|
243
|
-
}
|
|
244
|
-
get readyState() {
|
|
245
|
-
return this.#channel?.readyState;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* @params {Object} options
|
|
249
|
-
* @params {string} options.channelName - this peerid : otherpeer id
|
|
250
|
-
*/
|
|
251
|
-
constructor(options = {}) {
|
|
252
|
-
this._in = this._in.bind(this);
|
|
253
|
-
this.offerOptions = options.offerOptions;
|
|
254
|
-
this.initiator = options.initiator;
|
|
255
|
-
this.streams = options.streams;
|
|
256
|
-
this.socketClient = options.socketClient;
|
|
257
|
-
this.id = options.id;
|
|
258
|
-
this.to = options.to;
|
|
259
|
-
this.bw = {
|
|
260
|
-
up: 0,
|
|
261
|
-
down: 0
|
|
262
|
-
};
|
|
263
|
-
this.#channelName = options.channelName;
|
|
264
|
-
this.#peerId = options.peerId;
|
|
265
|
-
this.options = options;
|
|
266
|
-
return this.#init();
|
|
267
|
-
}
|
|
268
|
-
get peerId() {
|
|
269
|
-
return this.#peerId;
|
|
270
|
-
}
|
|
271
|
-
set socketClient(value) {
|
|
272
|
-
// this.socketClient?.pubsub.unsubscribe('signal', this._in)
|
|
273
|
-
this._socketClient = value;
|
|
274
|
-
this._socketClient.pubsub.subscribe('signal', this._in);
|
|
275
|
-
}
|
|
276
|
-
get socketClient() {
|
|
277
|
-
return this._socketClient;
|
|
278
|
-
}
|
|
279
|
-
splitMessage(message) {
|
|
280
|
-
const chunks = [];
|
|
281
|
-
message = pako.deflate(message);
|
|
282
|
-
const size = message.byteLength || message.length;
|
|
283
|
-
let offset = 0;
|
|
284
|
-
return new Promise((resolve, reject) => {
|
|
285
|
-
const splitMessage = () => {
|
|
286
|
-
const chunk = message.slice(offset, offset + this.#chunkSize > size ? size : offset + this.#chunkSize);
|
|
287
|
-
offset += this.#chunkSize;
|
|
288
|
-
chunks.push(chunk);
|
|
289
|
-
if (offset < size)
|
|
290
|
-
return splitMessage();
|
|
291
|
-
else
|
|
292
|
-
resolve({ chunks, size });
|
|
293
|
-
};
|
|
294
|
-
splitMessage();
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
async #runQue() {
|
|
298
|
-
this.#queRunning = true;
|
|
299
|
-
if (this.#messageQue.length > 0 && this.#channel?.bufferedAmount + this.#messageQue[0]?.length < this.#MAX_BUFFERED_AMOUNT) {
|
|
300
|
-
const message = this.#messageQue.shift();
|
|
301
|
-
switch (this.#channel?.readyState) {
|
|
302
|
-
case 'open':
|
|
303
|
-
await this.#channel.send(message);
|
|
304
|
-
if (this.#messageQue.length > 0)
|
|
305
|
-
return this.#runQue();
|
|
306
|
-
else
|
|
307
|
-
this.#queRunning = false;
|
|
308
|
-
break;
|
|
309
|
-
case 'closed':
|
|
310
|
-
case 'closing':
|
|
311
|
-
this.#messageQue = [];
|
|
312
|
-
this.#queRunning = false;
|
|
313
|
-
debug('channel already closed, this usually means a bad implementation, try checking the readyState or check if the peer is connected before sending');
|
|
314
|
-
break;
|
|
315
|
-
case undefined:
|
|
316
|
-
this.#messageQue = [];
|
|
317
|
-
this.#queRunning = false;
|
|
318
|
-
debug(`trying to send before a channel is created`);
|
|
319
|
-
break;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
return setTimeout(() => this.#runQue(), 50);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
#trySend({ size, id, chunks }) {
|
|
327
|
-
let offset = 0;
|
|
328
|
-
for (const chunk of chunks) {
|
|
329
|
-
const start = offset;
|
|
330
|
-
const end = offset + chunk.length;
|
|
331
|
-
const message = new TextEncoder().encode(JSON.stringify({ size, id, chunk, start, end }));
|
|
332
|
-
this.#messageQue.push(message);
|
|
333
|
-
}
|
|
334
|
-
if (!this.queRunning)
|
|
335
|
-
return this.#runQue();
|
|
336
|
-
}
|
|
337
|
-
async send(message, id) {
|
|
338
|
-
const { chunks, size } = await this.splitMessage(message);
|
|
339
|
-
return this.#trySend({ size, id, chunks });
|
|
340
|
-
}
|
|
341
|
-
request(data) {
|
|
342
|
-
return new Promise((resolve, reject) => {
|
|
343
|
-
const id = Math.random().toString(36).slice(-12);
|
|
344
|
-
const _onData = message => {
|
|
345
|
-
if (message.id === id) {
|
|
346
|
-
resolve(message.data);
|
|
347
|
-
pubsub.unsubscribe(`peer:data`, _onData);
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
pubsub.subscribe(`peer:data`, _onData);
|
|
351
|
-
// cleanup subscriptions
|
|
352
|
-
// setTimeout(() => {
|
|
353
|
-
// pubsub.unsubscribe(`peer:data-request-${id}`, _onData)
|
|
354
|
-
// }, 5000);
|
|
355
|
-
this.send(data, id);
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
async #init() {
|
|
359
|
-
try {
|
|
360
|
-
if (!globalThis.pako) {
|
|
361
|
-
const importee = await import('./pako.esm-aa674ebf.js');
|
|
362
|
-
globalThis.pako = importee.default;
|
|
363
|
-
}
|
|
364
|
-
const iceServers = [{
|
|
365
|
-
urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
|
|
366
|
-
}, {
|
|
367
|
-
urls: "stun:openrelay.metered.ca:80",
|
|
368
|
-
}, {
|
|
369
|
-
urls: "turn:openrelay.metered.ca:443",
|
|
370
|
-
username: "openrelayproject",
|
|
371
|
-
credential: "openrelayproject",
|
|
372
|
-
}, {
|
|
373
|
-
urls: "turn:openrelay.metered.ca:443?transport=tcp",
|
|
374
|
-
username: "openrelayproject",
|
|
375
|
-
credential: "openrelayproject",
|
|
376
|
-
}];
|
|
377
|
-
this.#connection = new wrtc.RTCPeerConnection({ iceServers });
|
|
378
|
-
this.#connection.onicecandidate = ({ candidate }) => {
|
|
379
|
-
if (candidate) {
|
|
380
|
-
this.address = candidate.address;
|
|
381
|
-
this.port = candidate.port;
|
|
382
|
-
this.protocol = candidate.protocol;
|
|
383
|
-
this.ipFamily = this.address.includes('::') ? 'ipv6' : 'ipv4';
|
|
384
|
-
this._sendMessage({ candidate });
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
// if (this.initiator) this.#connection.onnegotiationneeded = () => {
|
|
388
|
-
// console.log('create offer');
|
|
389
|
-
this.#connection.ondatachannel = (message) => {
|
|
390
|
-
message.channel.onopen = () => {
|
|
391
|
-
this.#connected = true;
|
|
392
|
-
// debug(`peer:connected ${this}`)
|
|
393
|
-
pubsub.publish('peer:connected', this);
|
|
394
|
-
};
|
|
395
|
-
message.channel.onclose = () => this.close.bind(this);
|
|
396
|
-
message.channel.onmessage = (message) => {
|
|
397
|
-
this._handleMessage(this.id, message);
|
|
398
|
-
};
|
|
399
|
-
this.#channel = message.channel;
|
|
400
|
-
};
|
|
401
|
-
if (this.initiator) {
|
|
402
|
-
this.#channel = this.#connection.createDataChannel('messageChannel');
|
|
403
|
-
this.#channel.onopen = () => {
|
|
404
|
-
this.#connected = true;
|
|
405
|
-
pubsub.publish('peer:connected', this);
|
|
406
|
-
// this.#channel.send('hi')
|
|
407
|
-
};
|
|
408
|
-
this.#channel.onclose = () => this.close.bind(this);
|
|
409
|
-
this.#channel.onmessage = (message) => {
|
|
410
|
-
this._handleMessage(this.peerId, message);
|
|
411
|
-
};
|
|
412
|
-
const offer = await this.#connection.createOffer();
|
|
413
|
-
await this.#connection.setLocalDescription(offer);
|
|
414
|
-
this._sendMessage({ 'sdp': this.#connection.localDescription });
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
catch (e) {
|
|
418
|
-
console.log(e);
|
|
419
|
-
}
|
|
420
|
-
return this;
|
|
421
|
-
}
|
|
422
|
-
_handleMessage(peerId, message) {
|
|
423
|
-
// debug(`incoming message from ${peerId}`)
|
|
424
|
-
message = JSON.parse(new TextDecoder().decode(message.data));
|
|
425
|
-
// allow sharding (multiple peers share data)
|
|
426
|
-
pubsub.publish('peernet:shard', message);
|
|
427
|
-
const { id } = message;
|
|
428
|
-
if (!this.#chunksQue[id])
|
|
429
|
-
this.#chunksQue[id] = [];
|
|
430
|
-
if (message.size > this.#chunksQue[id].length || message.size === this.#chunksQue[id].length) {
|
|
431
|
-
for (const value of Object.values(message.chunk)) {
|
|
432
|
-
this.#chunksQue[id].push(value);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
if (message.size === this.#chunksQue[id].length) {
|
|
436
|
-
let data = new Uint8Array(Object.values(this.#chunksQue[id]));
|
|
437
|
-
delete this.#chunksQue[id];
|
|
438
|
-
data = pako.inflate(data);
|
|
439
|
-
pubsub.publish('peer:data', { id, data, from: this.peerId });
|
|
440
|
-
}
|
|
441
|
-
this.bw.down += message.byteLength || message.length;
|
|
442
|
-
}
|
|
443
|
-
_sendMessage(message) {
|
|
444
|
-
this.socketClient.send({ url: 'signal', params: {
|
|
445
|
-
to: this.to,
|
|
446
|
-
from: this.id,
|
|
447
|
-
channelName: this.options.channelName,
|
|
448
|
-
...message
|
|
449
|
-
} });
|
|
450
|
-
}
|
|
451
|
-
async _in(message, data) {
|
|
452
|
-
// message = JSON.parse(message);
|
|
453
|
-
if (!this.#connection || message.to !== this.id || message.from !== this.#peerId)
|
|
454
|
-
return;
|
|
455
|
-
// if (data.videocall) return this._startStream(true, false); // start video and audio stream
|
|
456
|
-
// if (data.call) return this._startStream(true, true); // start audio stream
|
|
457
|
-
if (this.#connection?.
|
|
458
|
-
return;
|
|
459
|
-
if (message.candidate) {
|
|
460
|
-
// debug(`incoming candidate ${this.#channelName}`)
|
|
461
|
-
// debug(message.candidate.candidate)
|
|
462
|
-
this.remoteAddress = message.candidate.address;
|
|
463
|
-
this.remotePort = message.candidate.port;
|
|
464
|
-
this.remoteProtocol = message.candidate.protocol;
|
|
465
|
-
this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6' : 'ipv4';
|
|
466
|
-
return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
|
|
467
|
-
}
|
|
468
|
-
try {
|
|
469
|
-
if (message.sdp) {
|
|
470
|
-
if (message.sdp.type === 'offer') {
|
|
471
|
-
// debug(`incoming offer ${this.#channelName}`)
|
|
472
|
-
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
473
|
-
const answer = await this.#connection.createAnswer();
|
|
474
|
-
await this.#connection.setLocalDescription(answer);
|
|
475
|
-
this._sendMessage({ 'sdp': this.#connection.localDescription });
|
|
476
|
-
}
|
|
477
|
-
if (message.sdp.type === 'answer') {
|
|
478
|
-
// debug(`incoming answer ${this.#channelName}`)
|
|
479
|
-
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
catch (e) {
|
|
484
|
-
console.log(e);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
close() {
|
|
488
|
-
// debug(`closing ${this.peerId}`)
|
|
489
|
-
this.#connected = false;
|
|
490
|
-
this.#channel?.close();
|
|
491
|
-
this.#connection?.close();
|
|
492
|
-
this.socketClient.pubsub.unsubscribe('signal', this._in);
|
|
493
|
-
}
|
|
227
|
+
class Peer {
|
|
228
|
+
#connection;
|
|
229
|
+
#connected = false;
|
|
230
|
+
#messageQue = [];
|
|
231
|
+
#chunksQue = {};
|
|
232
|
+
#channel;
|
|
233
|
+
#peerId;
|
|
234
|
+
#channelName;
|
|
235
|
+
#chunkSize = 16 * 1024; // 16384
|
|
236
|
+
#queRunning = false;
|
|
237
|
+
#MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024;
|
|
238
|
+
get connection() {
|
|
239
|
+
return this.#connection;
|
|
240
|
+
}
|
|
241
|
+
get connected() {
|
|
242
|
+
return this.#connected;
|
|
243
|
+
}
|
|
244
|
+
get readyState() {
|
|
245
|
+
return this.#channel?.readyState;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* @params {Object} options
|
|
249
|
+
* @params {string} options.channelName - this peerid : otherpeer id
|
|
250
|
+
*/
|
|
251
|
+
constructor(options = {}) {
|
|
252
|
+
this._in = this._in.bind(this);
|
|
253
|
+
this.offerOptions = options.offerOptions;
|
|
254
|
+
this.initiator = options.initiator;
|
|
255
|
+
this.streams = options.streams;
|
|
256
|
+
this.socketClient = options.socketClient;
|
|
257
|
+
this.id = options.id;
|
|
258
|
+
this.to = options.to;
|
|
259
|
+
this.bw = {
|
|
260
|
+
up: 0,
|
|
261
|
+
down: 0
|
|
262
|
+
};
|
|
263
|
+
this.#channelName = options.channelName;
|
|
264
|
+
this.#peerId = options.peerId;
|
|
265
|
+
this.options = options;
|
|
266
|
+
return this.#init();
|
|
267
|
+
}
|
|
268
|
+
get peerId() {
|
|
269
|
+
return this.#peerId;
|
|
270
|
+
}
|
|
271
|
+
set socketClient(value) {
|
|
272
|
+
// this.socketClient?.pubsub.unsubscribe('signal', this._in)
|
|
273
|
+
this._socketClient = value;
|
|
274
|
+
this._socketClient.pubsub.subscribe('signal', this._in);
|
|
275
|
+
}
|
|
276
|
+
get socketClient() {
|
|
277
|
+
return this._socketClient;
|
|
278
|
+
}
|
|
279
|
+
splitMessage(message) {
|
|
280
|
+
const chunks = [];
|
|
281
|
+
message = pako.deflate(message);
|
|
282
|
+
const size = message.byteLength || message.length;
|
|
283
|
+
let offset = 0;
|
|
284
|
+
return new Promise((resolve, reject) => {
|
|
285
|
+
const splitMessage = () => {
|
|
286
|
+
const chunk = message.slice(offset, offset + this.#chunkSize > size ? size : offset + this.#chunkSize);
|
|
287
|
+
offset += this.#chunkSize;
|
|
288
|
+
chunks.push(chunk);
|
|
289
|
+
if (offset < size)
|
|
290
|
+
return splitMessage();
|
|
291
|
+
else
|
|
292
|
+
resolve({ chunks, size });
|
|
293
|
+
};
|
|
294
|
+
splitMessage();
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
async #runQue() {
|
|
298
|
+
this.#queRunning = true;
|
|
299
|
+
if (this.#messageQue.length > 0 && this.#channel?.bufferedAmount + this.#messageQue[0]?.length < this.#MAX_BUFFERED_AMOUNT) {
|
|
300
|
+
const message = this.#messageQue.shift();
|
|
301
|
+
switch (this.#channel?.readyState) {
|
|
302
|
+
case 'open':
|
|
303
|
+
await this.#channel.send(message);
|
|
304
|
+
if (this.#messageQue.length > 0)
|
|
305
|
+
return this.#runQue();
|
|
306
|
+
else
|
|
307
|
+
this.#queRunning = false;
|
|
308
|
+
break;
|
|
309
|
+
case 'closed':
|
|
310
|
+
case 'closing':
|
|
311
|
+
this.#messageQue = [];
|
|
312
|
+
this.#queRunning = false;
|
|
313
|
+
debug('channel already closed, this usually means a bad implementation, try checking the readyState or check if the peer is connected before sending');
|
|
314
|
+
break;
|
|
315
|
+
case undefined:
|
|
316
|
+
this.#messageQue = [];
|
|
317
|
+
this.#queRunning = false;
|
|
318
|
+
debug(`trying to send before a channel is created`);
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
return setTimeout(() => this.#runQue(), 50);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
#trySend({ size, id, chunks }) {
|
|
327
|
+
let offset = 0;
|
|
328
|
+
for (const chunk of chunks) {
|
|
329
|
+
const start = offset;
|
|
330
|
+
const end = offset + chunk.length;
|
|
331
|
+
const message = new TextEncoder().encode(JSON.stringify({ size, id, chunk, start, end }));
|
|
332
|
+
this.#messageQue.push(message);
|
|
333
|
+
}
|
|
334
|
+
if (!this.queRunning)
|
|
335
|
+
return this.#runQue();
|
|
336
|
+
}
|
|
337
|
+
async send(message, id) {
|
|
338
|
+
const { chunks, size } = await this.splitMessage(message);
|
|
339
|
+
return this.#trySend({ size, id, chunks });
|
|
340
|
+
}
|
|
341
|
+
request(data) {
|
|
342
|
+
return new Promise((resolve, reject) => {
|
|
343
|
+
const id = Math.random().toString(36).slice(-12);
|
|
344
|
+
const _onData = message => {
|
|
345
|
+
if (message.id === id) {
|
|
346
|
+
resolve(message.data);
|
|
347
|
+
pubsub.unsubscribe(`peer:data`, _onData);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
pubsub.subscribe(`peer:data`, _onData);
|
|
351
|
+
// cleanup subscriptions
|
|
352
|
+
// setTimeout(() => {
|
|
353
|
+
// pubsub.unsubscribe(`peer:data-request-${id}`, _onData)
|
|
354
|
+
// }, 5000);
|
|
355
|
+
this.send(data, id);
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
async #init() {
|
|
359
|
+
try {
|
|
360
|
+
if (!globalThis.pako) {
|
|
361
|
+
const importee = await import('./pako.esm-aa674ebf.js');
|
|
362
|
+
globalThis.pako = importee.default;
|
|
363
|
+
}
|
|
364
|
+
const iceServers = [{
|
|
365
|
+
urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
|
|
366
|
+
}, {
|
|
367
|
+
urls: "stun:openrelay.metered.ca:80",
|
|
368
|
+
}, {
|
|
369
|
+
urls: "turn:openrelay.metered.ca:443",
|
|
370
|
+
username: "openrelayproject",
|
|
371
|
+
credential: "openrelayproject",
|
|
372
|
+
}, {
|
|
373
|
+
urls: "turn:openrelay.metered.ca:443?transport=tcp",
|
|
374
|
+
username: "openrelayproject",
|
|
375
|
+
credential: "openrelayproject",
|
|
376
|
+
}];
|
|
377
|
+
this.#connection = new wrtc.RTCPeerConnection({ iceServers });
|
|
378
|
+
this.#connection.onicecandidate = ({ candidate }) => {
|
|
379
|
+
if (candidate) {
|
|
380
|
+
this.address = candidate.address;
|
|
381
|
+
this.port = candidate.port;
|
|
382
|
+
this.protocol = candidate.protocol;
|
|
383
|
+
this.ipFamily = this.address.includes('::') ? 'ipv6' : 'ipv4';
|
|
384
|
+
this._sendMessage({ candidate });
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
// if (this.initiator) this.#connection.onnegotiationneeded = () => {
|
|
388
|
+
// console.log('create offer');
|
|
389
|
+
this.#connection.ondatachannel = (message) => {
|
|
390
|
+
message.channel.onopen = () => {
|
|
391
|
+
this.#connected = true;
|
|
392
|
+
// debug(`peer:connected ${this}`)
|
|
393
|
+
pubsub.publish('peer:connected', this);
|
|
394
|
+
};
|
|
395
|
+
message.channel.onclose = () => this.close.bind(this);
|
|
396
|
+
message.channel.onmessage = (message) => {
|
|
397
|
+
this._handleMessage(this.id, message);
|
|
398
|
+
};
|
|
399
|
+
this.#channel = message.channel;
|
|
400
|
+
};
|
|
401
|
+
if (this.initiator) {
|
|
402
|
+
this.#channel = this.#connection.createDataChannel('messageChannel');
|
|
403
|
+
this.#channel.onopen = () => {
|
|
404
|
+
this.#connected = true;
|
|
405
|
+
pubsub.publish('peer:connected', this);
|
|
406
|
+
// this.#channel.send('hi')
|
|
407
|
+
};
|
|
408
|
+
this.#channel.onclose = () => this.close.bind(this);
|
|
409
|
+
this.#channel.onmessage = (message) => {
|
|
410
|
+
this._handleMessage(this.peerId, message);
|
|
411
|
+
};
|
|
412
|
+
const offer = await this.#connection.createOffer();
|
|
413
|
+
await this.#connection.setLocalDescription(offer);
|
|
414
|
+
this._sendMessage({ 'sdp': this.#connection.localDescription });
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (e) {
|
|
418
|
+
console.log(e);
|
|
419
|
+
}
|
|
420
|
+
return this;
|
|
421
|
+
}
|
|
422
|
+
_handleMessage(peerId, message) {
|
|
423
|
+
// debug(`incoming message from ${peerId}`)
|
|
424
|
+
message = JSON.parse(new TextDecoder().decode(message.data));
|
|
425
|
+
// allow sharding (multiple peers share data)
|
|
426
|
+
pubsub.publish('peernet:shard', message);
|
|
427
|
+
const { id } = message;
|
|
428
|
+
if (!this.#chunksQue[id])
|
|
429
|
+
this.#chunksQue[id] = [];
|
|
430
|
+
if (message.size > this.#chunksQue[id].length || message.size === this.#chunksQue[id].length) {
|
|
431
|
+
for (const value of Object.values(message.chunk)) {
|
|
432
|
+
this.#chunksQue[id].push(value);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (message.size === this.#chunksQue[id].length) {
|
|
436
|
+
let data = new Uint8Array(Object.values(this.#chunksQue[id]));
|
|
437
|
+
delete this.#chunksQue[id];
|
|
438
|
+
data = pako.inflate(data);
|
|
439
|
+
pubsub.publish('peer:data', { id, data, from: this.peerId });
|
|
440
|
+
}
|
|
441
|
+
this.bw.down += message.byteLength || message.length;
|
|
442
|
+
}
|
|
443
|
+
_sendMessage(message) {
|
|
444
|
+
this.socketClient.send({ url: 'signal', params: {
|
|
445
|
+
to: this.to,
|
|
446
|
+
from: this.id,
|
|
447
|
+
channelName: this.options.channelName,
|
|
448
|
+
...message
|
|
449
|
+
} });
|
|
450
|
+
}
|
|
451
|
+
async _in(message, data) {
|
|
452
|
+
// message = JSON.parse(message);
|
|
453
|
+
if (!this.#connection || message.to !== this.id || message.from !== this.#peerId)
|
|
454
|
+
return;
|
|
455
|
+
// if (data.videocall) return this._startStream(true, false); // start video and audio stream
|
|
456
|
+
// if (data.call) return this._startStream(true, true); // start audio stream
|
|
457
|
+
if (this.#connection?.signalingState === 'stable' && this.#connection?.remoteDescription !== null && this.#connection?.localDescription !== null)
|
|
458
|
+
return;
|
|
459
|
+
if (message.candidate) {
|
|
460
|
+
// debug(`incoming candidate ${this.#channelName}`)
|
|
461
|
+
// debug(message.candidate.candidate)
|
|
462
|
+
this.remoteAddress = message.candidate.address;
|
|
463
|
+
this.remotePort = message.candidate.port;
|
|
464
|
+
this.remoteProtocol = message.candidate.protocol;
|
|
465
|
+
this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6' : 'ipv4';
|
|
466
|
+
return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
|
|
467
|
+
}
|
|
468
|
+
try {
|
|
469
|
+
if (message.sdp) {
|
|
470
|
+
if (message.sdp.type === 'offer') {
|
|
471
|
+
// debug(`incoming offer ${this.#channelName}`)
|
|
472
|
+
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
473
|
+
const answer = await this.#connection.createAnswer();
|
|
474
|
+
await this.#connection.setLocalDescription(answer);
|
|
475
|
+
this._sendMessage({ 'sdp': this.#connection.localDescription });
|
|
476
|
+
}
|
|
477
|
+
if (message.sdp.type === 'answer') {
|
|
478
|
+
// debug(`incoming answer ${this.#channelName}`)
|
|
479
|
+
await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
catch (e) {
|
|
484
|
+
console.log(e);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
close() {
|
|
488
|
+
// debug(`closing ${this.peerId}`)
|
|
489
|
+
this.#connected = false;
|
|
490
|
+
this.#channel?.close();
|
|
491
|
+
this.#connection?.close();
|
|
492
|
+
this.socketClient.pubsub.unsubscribe('signal', this._in);
|
|
493
|
+
}
|
|
494
494
|
}
|
|
495
495
|
|
|
496
|
-
class Client {
|
|
497
|
-
#peerConnection;
|
|
498
|
-
#connections = {};
|
|
499
|
-
#stars = {};
|
|
500
|
-
id;
|
|
501
|
-
networkVersion;
|
|
502
|
-
starsConfig;
|
|
503
|
-
socketClient;
|
|
504
|
-
get connections() {
|
|
505
|
-
return { ...this.#connections };
|
|
506
|
-
}
|
|
507
|
-
get peers() {
|
|
508
|
-
return Object.entries(this.#connections);
|
|
509
|
-
}
|
|
510
|
-
constructor(id, networkVersion = 'peach', stars = ['wss://peach.leofcoin.org']) {
|
|
511
|
-
this.id = id || Math.random().toString(36).slice(-12);
|
|
512
|
-
this.peerJoined = this.peerJoined.bind(this);
|
|
513
|
-
this.peerLeft = this.peerLeft.bind(this);
|
|
514
|
-
this.starLeft = this.starLeft.bind(this);
|
|
515
|
-
this.starJoined = this.starJoined.bind(this);
|
|
516
|
-
this.networkVersion = networkVersion;
|
|
517
|
-
this._init(stars);
|
|
518
|
-
}
|
|
519
|
-
async _init(stars = []) {
|
|
520
|
-
this.starsConfig = stars;
|
|
521
|
-
// reconnectJob()
|
|
522
|
-
if (!globalThis.RTCPeerConnection)
|
|
523
|
-
globalThis.wrtc = (await import('./browser-10ffabe1.js').then(function (n) { return n.b; })).default;
|
|
524
|
-
else
|
|
525
|
-
globalThis.wrtc = {
|
|
526
|
-
RTCPeerConnection,
|
|
527
|
-
RTCSessionDescription,
|
|
528
|
-
RTCIceCandidate
|
|
529
|
-
};
|
|
530
|
-
for (const star of stars) {
|
|
531
|
-
try {
|
|
532
|
-
this.socketClient = await socketRequestClient(star, this.networkVersion);
|
|
533
|
-
const id = await this.socketClient.request({ url: 'id', params: { from: this.id } });
|
|
534
|
-
this.socketClient.peerId = id;
|
|
535
|
-
this.#stars[id] = this.socketClient;
|
|
536
|
-
}
|
|
537
|
-
catch (e) {
|
|
538
|
-
if (stars.indexOf(star) === stars.length - 1 && !this.socketClient)
|
|
539
|
-
throw new Error(`No star available to connect`);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
const peers = await this.socketClient.peernet.join({ id: this.id });
|
|
543
|
-
for (const id of peers) {
|
|
544
|
-
if (id !== this.id && !this.#connections[id])
|
|
545
|
-
this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
546
|
-
}
|
|
547
|
-
this.setupListeners();
|
|
548
|
-
}
|
|
549
|
-
setupListeners() {
|
|
550
|
-
this.socketClient.subscribe('peer:joined', this.peerJoined);
|
|
551
|
-
this.socketClient.subscribe('peer:left', this.peerLeft);
|
|
552
|
-
this.socketClient.subscribe('star:left', this.starLeft);
|
|
553
|
-
}
|
|
554
|
-
starJoined(id) {
|
|
555
|
-
if (this.#stars[id]) {
|
|
556
|
-
this.#stars[id].close();
|
|
557
|
-
delete this.#stars[id];
|
|
558
|
-
}
|
|
559
|
-
console.log(`star ${id} joined`);
|
|
560
|
-
}
|
|
561
|
-
async starLeft(id) {
|
|
562
|
-
if (this.#stars[id]) {
|
|
563
|
-
this.#stars[id].close();
|
|
564
|
-
delete this.#stars[id];
|
|
565
|
-
}
|
|
566
|
-
if (this.socketClient?.peerId === id) {
|
|
567
|
-
this.socketClient.unsubscribe('peer:joined', this.peerJoined);
|
|
568
|
-
this.socketClient.unsubscribe('peer:left', this.peerLeft);
|
|
569
|
-
this.socketClient.unsubscribe('star:left', this.starLeft);
|
|
570
|
-
this.socketClient.close();
|
|
571
|
-
this.socketClient = undefined;
|
|
572
|
-
for (const star of this.starsConfig) {
|
|
573
|
-
try {
|
|
574
|
-
this.socketClient = await socketRequestClient(star, this.networkVersion);
|
|
575
|
-
if (!this.socketClient?.client?._connection.connected)
|
|
576
|
-
return;
|
|
577
|
-
const id = await this.socketClient.request({ url: 'id', params: { from: this.id } });
|
|
578
|
-
this.#stars[id] = this.socketClient;
|
|
579
|
-
this.socketClient.peerId = id;
|
|
580
|
-
const peers = await this.socketClient.peernet.join({ id: this.id });
|
|
581
|
-
this.setupListeners();
|
|
582
|
-
for (const id of peers) {
|
|
583
|
-
if (id !== this.id) {
|
|
584
|
-
// close connection
|
|
585
|
-
if (this.#connections[id]) {
|
|
586
|
-
if (this.#connections[id].connected)
|
|
587
|
-
await this.#connections[id].close();
|
|
588
|
-
delete this.#connections[id];
|
|
589
|
-
}
|
|
590
|
-
// reconnect
|
|
591
|
-
if (id !== this.id)
|
|
592
|
-
this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
catch (e) {
|
|
597
|
-
console.log(e);
|
|
598
|
-
if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1 && !this.socketClient)
|
|
599
|
-
throw new Error(`No star available to connect`);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
globalThis.debug(`star ${id} left`);
|
|
604
|
-
}
|
|
605
|
-
peerLeft(peer) {
|
|
606
|
-
const id = peer.peerId || peer;
|
|
607
|
-
if (this.#connections[id]) {
|
|
608
|
-
this.#connections[id].close();
|
|
609
|
-
delete this.#connections[id];
|
|
610
|
-
}
|
|
611
|
-
globalThis.debug(`peer ${id} left`);
|
|
612
|
-
}
|
|
613
|
-
async peerJoined(peer, signal) {
|
|
614
|
-
const id = peer.peerId || peer;
|
|
615
|
-
if (this.#connections[id]) {
|
|
616
|
-
if (this.#connections[id].connected)
|
|
617
|
-
this.#connections[id].close();
|
|
618
|
-
delete this.#connections[id];
|
|
619
|
-
}
|
|
620
|
-
// RTCPeerConnection
|
|
621
|
-
this.#connections[id] = await new Peer({ initiator: true, channelName: `${this.id}:${id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
622
|
-
globalThis.debug(`peer ${id} joined`);
|
|
623
|
-
}
|
|
624
|
-
removePeer(peer) {
|
|
625
|
-
const id = peer.peerId || peer;
|
|
626
|
-
if (this.#connections[id]) {
|
|
627
|
-
this.#connections[id].connected && this.#connections[id].close();
|
|
628
|
-
delete this.#connections[id];
|
|
629
|
-
}
|
|
630
|
-
globalThis.debug(`peer ${id} removed`);
|
|
631
|
-
}
|
|
632
|
-
async close() {
|
|
633
|
-
this.socketClient.unsubscribe('peer:joined', this.peerJoined);
|
|
634
|
-
this.socketClient.unsubscribe('peer:left', this.peerLeft);
|
|
635
|
-
this.socketClient.unsubscribe('star:left', this.starLeft);
|
|
636
|
-
const promises = [
|
|
637
|
-
Object.values(this.#connections).map(connection => connection.close()),
|
|
638
|
-
Object.values(this.#stars).map(connection => connection.close()),
|
|
639
|
-
this.socketClient.close()
|
|
640
|
-
];
|
|
641
|
-
return Promise.allSettled(promises);
|
|
642
|
-
}
|
|
496
|
+
class Client {
|
|
497
|
+
#peerConnection;
|
|
498
|
+
#connections = {};
|
|
499
|
+
#stars = {};
|
|
500
|
+
id;
|
|
501
|
+
networkVersion;
|
|
502
|
+
starsConfig;
|
|
503
|
+
socketClient;
|
|
504
|
+
get connections() {
|
|
505
|
+
return { ...this.#connections };
|
|
506
|
+
}
|
|
507
|
+
get peers() {
|
|
508
|
+
return Object.entries(this.#connections);
|
|
509
|
+
}
|
|
510
|
+
constructor(id, networkVersion = 'peach', stars = ['wss://peach.leofcoin.org']) {
|
|
511
|
+
this.id = id || Math.random().toString(36).slice(-12);
|
|
512
|
+
this.peerJoined = this.peerJoined.bind(this);
|
|
513
|
+
this.peerLeft = this.peerLeft.bind(this);
|
|
514
|
+
this.starLeft = this.starLeft.bind(this);
|
|
515
|
+
this.starJoined = this.starJoined.bind(this);
|
|
516
|
+
this.networkVersion = networkVersion;
|
|
517
|
+
this._init(stars);
|
|
518
|
+
}
|
|
519
|
+
async _init(stars = []) {
|
|
520
|
+
this.starsConfig = stars;
|
|
521
|
+
// reconnectJob()
|
|
522
|
+
if (!globalThis.RTCPeerConnection)
|
|
523
|
+
globalThis.wrtc = (await import('./browser-10ffabe1.js').then(function (n) { return n.b; })).default;
|
|
524
|
+
else
|
|
525
|
+
globalThis.wrtc = {
|
|
526
|
+
RTCPeerConnection,
|
|
527
|
+
RTCSessionDescription,
|
|
528
|
+
RTCIceCandidate
|
|
529
|
+
};
|
|
530
|
+
for (const star of stars) {
|
|
531
|
+
try {
|
|
532
|
+
this.socketClient = await socketRequestClient(star, this.networkVersion);
|
|
533
|
+
const id = await this.socketClient.request({ url: 'id', params: { from: this.id } });
|
|
534
|
+
this.socketClient.peerId = id;
|
|
535
|
+
this.#stars[id] = this.socketClient;
|
|
536
|
+
}
|
|
537
|
+
catch (e) {
|
|
538
|
+
if (stars.indexOf(star) === stars.length - 1 && !this.socketClient)
|
|
539
|
+
throw new Error(`No star available to connect`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
const peers = await this.socketClient.peernet.join({ id: this.id });
|
|
543
|
+
for (const id of peers) {
|
|
544
|
+
if (id !== this.id && !this.#connections[id])
|
|
545
|
+
this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
546
|
+
}
|
|
547
|
+
this.setupListeners();
|
|
548
|
+
}
|
|
549
|
+
setupListeners() {
|
|
550
|
+
this.socketClient.subscribe('peer:joined', this.peerJoined);
|
|
551
|
+
this.socketClient.subscribe('peer:left', this.peerLeft);
|
|
552
|
+
this.socketClient.subscribe('star:left', this.starLeft);
|
|
553
|
+
}
|
|
554
|
+
starJoined(id) {
|
|
555
|
+
if (this.#stars[id]) {
|
|
556
|
+
this.#stars[id].close();
|
|
557
|
+
delete this.#stars[id];
|
|
558
|
+
}
|
|
559
|
+
console.log(`star ${id} joined`);
|
|
560
|
+
}
|
|
561
|
+
async starLeft(id) {
|
|
562
|
+
if (this.#stars[id]) {
|
|
563
|
+
this.#stars[id].close();
|
|
564
|
+
delete this.#stars[id];
|
|
565
|
+
}
|
|
566
|
+
if (this.socketClient?.peerId === id) {
|
|
567
|
+
this.socketClient.unsubscribe('peer:joined', this.peerJoined);
|
|
568
|
+
this.socketClient.unsubscribe('peer:left', this.peerLeft);
|
|
569
|
+
this.socketClient.unsubscribe('star:left', this.starLeft);
|
|
570
|
+
this.socketClient.close();
|
|
571
|
+
this.socketClient = undefined;
|
|
572
|
+
for (const star of this.starsConfig) {
|
|
573
|
+
try {
|
|
574
|
+
this.socketClient = await socketRequestClient(star, this.networkVersion);
|
|
575
|
+
if (!this.socketClient?.client?._connection.connected)
|
|
576
|
+
return;
|
|
577
|
+
const id = await this.socketClient.request({ url: 'id', params: { from: this.id } });
|
|
578
|
+
this.#stars[id] = this.socketClient;
|
|
579
|
+
this.socketClient.peerId = id;
|
|
580
|
+
const peers = await this.socketClient.peernet.join({ id: this.id });
|
|
581
|
+
this.setupListeners();
|
|
582
|
+
for (const id of peers) {
|
|
583
|
+
if (id !== this.id) {
|
|
584
|
+
// close connection
|
|
585
|
+
if (this.#connections[id]) {
|
|
586
|
+
if (this.#connections[id].connected)
|
|
587
|
+
await this.#connections[id].close();
|
|
588
|
+
delete this.#connections[id];
|
|
589
|
+
}
|
|
590
|
+
// reconnect
|
|
591
|
+
if (id !== this.id)
|
|
592
|
+
this.#connections[id] = await new Peer({ channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
catch (e) {
|
|
597
|
+
console.log(e);
|
|
598
|
+
if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1 && !this.socketClient)
|
|
599
|
+
throw new Error(`No star available to connect`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
globalThis.debug(`star ${id} left`);
|
|
604
|
+
}
|
|
605
|
+
peerLeft(peer) {
|
|
606
|
+
const id = peer.peerId || peer;
|
|
607
|
+
if (this.#connections[id]) {
|
|
608
|
+
this.#connections[id].close();
|
|
609
|
+
delete this.#connections[id];
|
|
610
|
+
}
|
|
611
|
+
globalThis.debug(`peer ${id} left`);
|
|
612
|
+
}
|
|
613
|
+
async peerJoined(peer, signal) {
|
|
614
|
+
const id = peer.peerId || peer;
|
|
615
|
+
if (this.#connections[id]) {
|
|
616
|
+
if (this.#connections[id].connected)
|
|
617
|
+
this.#connections[id].close();
|
|
618
|
+
delete this.#connections[id];
|
|
619
|
+
}
|
|
620
|
+
// RTCPeerConnection
|
|
621
|
+
this.#connections[id] = await new Peer({ initiator: true, channelName: `${this.id}:${id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id });
|
|
622
|
+
globalThis.debug(`peer ${id} joined`);
|
|
623
|
+
}
|
|
624
|
+
removePeer(peer) {
|
|
625
|
+
const id = peer.peerId || peer;
|
|
626
|
+
if (this.#connections[id]) {
|
|
627
|
+
this.#connections[id].connected && this.#connections[id].close();
|
|
628
|
+
delete this.#connections[id];
|
|
629
|
+
}
|
|
630
|
+
globalThis.debug(`peer ${id} removed`);
|
|
631
|
+
}
|
|
632
|
+
async close() {
|
|
633
|
+
this.socketClient.unsubscribe('peer:joined', this.peerJoined);
|
|
634
|
+
this.socketClient.unsubscribe('peer:left', this.peerLeft);
|
|
635
|
+
this.socketClient.unsubscribe('star:left', this.starLeft);
|
|
636
|
+
const promises = [
|
|
637
|
+
Object.values(this.#connections).map(connection => connection.close()),
|
|
638
|
+
Object.values(this.#stars).map(connection => connection.close()),
|
|
639
|
+
this.socketClient.close()
|
|
640
|
+
];
|
|
641
|
+
return Promise.allSettled(promises);
|
|
642
|
+
}
|
|
643
643
|
}
|
|
644
644
|
|
|
645
645
|
export { Client as default };
|
|
@@ -16082,7 +16082,7 @@ class Identity {
|
|
|
16082
16082
|
globalThis.peernet.selectedAccount = new TextDecoder().decode(selected);
|
|
16083
16083
|
}
|
|
16084
16084
|
else {
|
|
16085
|
-
const importee = await import(/* webpackChunkName: "generate-account" */ './index-
|
|
16085
|
+
const importee = await import(/* webpackChunkName: "generate-account" */ './index-84ee0e0b.js');
|
|
16086
16086
|
const { identity, accounts } = await importee.default(password, this.network);
|
|
16087
16087
|
await globalThis.accountStore.put('public', JSON.stringify({ walletId: identity.walletId }));
|
|
16088
16088
|
await globalThis.walletStore.put('version', String(1));
|
|
@@ -16248,7 +16248,7 @@ class Peernet {
|
|
|
16248
16248
|
this.root = options.root;
|
|
16249
16249
|
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
16250
16250
|
// FolderMessageResponse
|
|
16251
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
16251
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-def41fbf.js');
|
|
16252
16252
|
/**
|
|
16253
16253
|
* proto Object containing protos
|
|
16254
16254
|
* @type {Object}
|
|
@@ -16297,7 +16297,7 @@ class Peernet {
|
|
|
16297
16297
|
* @see DataHandler
|
|
16298
16298
|
*/
|
|
16299
16299
|
pubsub.subscribe('peer:data', dataHandler);
|
|
16300
|
-
const importee = await import('./client-
|
|
16300
|
+
const importee = await import('./client-bbd6e332.js');
|
|
16301
16301
|
/**
|
|
16302
16302
|
* @access public
|
|
16303
16303
|
* @type {PeernetClient}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { P as default } from './peernet-
|
|
1
|
+
export { P as default } from './peernet-7ba6837f.js';
|
|
2
2
|
import './value-157ab062.js';
|