UNPKG

@mothepro/fancy-p2p

Version:

A quick and efficient way to form p2p groups in the browser

114 lines 4.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockPeer = void 0; const fancy_emitter_1 = require("fancy-emitter"); /** Simple class that can be used as a local feedback peer. */ class MockPeer { constructor(name) { this.name = name; this.isYou = true; this.message = new fancy_emitter_1.Emitter; // Convert ArrayBufferView's to their raw buffer to match how it is over the wire. this.send = (data) => this.message.activate( // @ts-ignore Type 'ArrayBuffer' **is** assignable to type 'Exclude<T, ArrayBufferView>' since T mustin include Buffers and their views together ArrayBuffer.isView(data) ? data.buffer : data); this.close = this.message.cancel; this.ready = Promise.resolve(true); } } exports.MockPeer = MockPeer; class default_1 { constructor(stuns, client, retries = 1, timeout = -1, fallback) { this.fallback = fallback; this.isYou = false; this.message = new fancy_emitter_1.Emitter; this.send = (data) => { if (this.rtc) this.rtc.send(data); // this is fine since browser handles casting else if (this.fallback) { let val; if (data instanceof ArrayBuffer) val = data; else if (ArrayBuffer.isView(data)) val = data.buffer; // TODO transform strings into buffers else throw Error('Only buffers can be used when sending data thru fallback server'); this.fallback.sendFallback(this.fallbackId, val); } else throw Error('Unable to send data to peer directly nor thru server'); }; // TODO closing all peers should close the fallback as well this.close = () => { if (this.rtc) this.rtc.destroy(); this.message.cancel(); }; this.name = client.name; this.fallbackId = client.id; this.ready = this.makeRtc(stuns, client, retries, timeout) .then(() => { this.rtc.once('close', this.message.cancel); this.rtc.once('error', this.message.deactivate); this.rtc.on('data', data => this.message.activate(ArrayBuffer.isView(data) ? data.buffer : data)); // TODO get rid of this.fallback? return true; }).catch((reason) => { delete this.rtc; // Switch to fallback if the direct connection still isn't made if (this.fallback) { this.fallback.fallbackMessage // @ts-ignore support all T in fallback messages .on(({ from, data }) => from == this.fallbackId && this.message.activate(data)) .then(this.close); return false; } else { // Cancel early since no events will ever occur. this.message.cancel(); throw reason; } }); } async makeRtc(stuns, client, retries, timeout) { if (retries < 0) throw Error('Not attempting to create a p2p connection'); // @ts-ignore from the `import 'simple-peer'` this.rtc = new SimplePeer({ initiator: client.isOpener, config: { iceServers: [{ urls: stuns }] }, trickle: false, offerConstraints: { iceRestart: true, offerToReceiveAudio: false, offerToReceiveVideo: false, voiceActivityDetection: false, }, answerConstraints: { iceRestart: true, offerToReceiveAudio: false, offerToReceiveVideo: false, voiceActivityDetection: false, }, }); // Exchange the SDPs // If using trickle, listen to more than just 1 event from each this.rtc.once('signal', client.creator.activate); client.acceptor.next.then(sdp => this.rtc.signal(sdp)); // This looks weird, but is how to handle optional chaining a set number of times (retries) return new Promise((resolve, reject) => { if (timeout > 0) setTimeout(() => reject(Error(`Connection with "${this.name}" didn't become ready in ${timeout}ms`)), timeout); this.rtc .once('connect', resolve) .once('error', reject); }).catch(reason => retries > 0 ? this.makeRtc(stuns, client, retries - 1, timeout) : Promise.reject(reason)); } } exports.default = default_1; //# sourceMappingURL=Peer.js.map