UNPKG

peerjs

Version:
1,049 lines (984 loc) 78.7 kB
var $2QID2$peerjsjsbinarypack = require("peerjs-js-binarypack"); var $2QID2$webrtcadapter = require("webrtc-adapter"); var $2QID2$eventemitter3 = require("eventemitter3"); var $2QID2$msgpackmsgpack = require("@msgpack/msgpack"); function $parcel$defineInteropFlag(a) { Object.defineProperty(a, '__esModule', {value: true, configurable: true}); } function $parcel$exportWildcard(dest, source) { Object.keys(source).forEach(function(key) { if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) { return; } Object.defineProperty(dest, key, { enumerable: true, get: function get() { return source[key]; } }); }); return dest; } function $parcel$export(e, n, v, s) { Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true}); } function $parcel$interopDefault(a) { return a && a.__esModule ? a.default : a; } $parcel$defineInteropFlag(module.exports); $parcel$export(module.exports, "default", () => $8c8bca0fa9aa4b8b$export$2e2bcd8739ae039); $parcel$export(module.exports, "util", () => $b83e6a166cc3008f$export$7debb50ef11d5e0b); $parcel$export(module.exports, "BufferedConnection", () => $8d5124d0cf36ebe0$export$ff7c9d4c11d94e8b); $parcel$export(module.exports, "StreamConnection", () => $544799118fa637e6$export$72aa44612e2200cd); $parcel$export(module.exports, "MsgPack", () => $7e477efb76e02214$export$80f5de1a66c4d624); $parcel$export(module.exports, "Peer", () => $2ddecb16305b5a82$export$ecd1fc136c422448); $parcel$export(module.exports, "MsgPackPeer", () => $8c8805059443e9b3$export$d72c7bf8eef50853); $parcel$export(module.exports, "PeerError", () => $cf62563e7a9fbce5$export$98871882f492de82); class $7ce5389b504cc06c$export$f1c5f4c9cb95390b { constructor(){ this.chunkedMTU = 16300 // The original 60000 bytes setting does not work when sending data from Firefox to Chrome, which is "cut off" after 16384 bytes and delivered individually. ; // Binary stuff this._dataCount = 1; this.chunk = (blob)=>{ const chunks = []; const size = blob.byteLength; const total = Math.ceil(size / this.chunkedMTU); let index = 0; let start = 0; while(start < size){ const end = Math.min(size, start + this.chunkedMTU); const b = blob.slice(start, end); const chunk = { __peerData: this._dataCount, n: index, data: b, total: total }; chunks.push(chunk); start = end; index++; } this._dataCount++; return chunks; }; } } function $7ce5389b504cc06c$export$52c89ebcdc4f53f2(bufs) { let size = 0; for (const buf of bufs)size += buf.byteLength; const result = new Uint8Array(size); let offset = 0; for (const buf of bufs){ result.set(buf, offset); offset += buf.byteLength; } return result; } const $07e4f6a369d1179a$var$webRTCAdapter = //@ts-ignore (0, ($parcel$interopDefault($2QID2$webrtcadapter))).default || (0, ($parcel$interopDefault($2QID2$webrtcadapter))); const $07e4f6a369d1179a$export$25be9502477c137d = new class { isWebRTCSupported() { return typeof RTCPeerConnection !== "undefined"; } isBrowserSupported() { const browser = this.getBrowser(); const version = this.getVersion(); const validBrowser = this.supportedBrowsers.includes(browser); if (!validBrowser) return false; if (browser === "chrome") return version >= this.minChromeVersion; if (browser === "firefox") return version >= this.minFirefoxVersion; if (browser === "safari") return !this.isIOS && version >= this.minSafariVersion; return false; } getBrowser() { return $07e4f6a369d1179a$var$webRTCAdapter.browserDetails.browser; } getVersion() { return $07e4f6a369d1179a$var$webRTCAdapter.browserDetails.version || 0; } isUnifiedPlanSupported() { const browser = this.getBrowser(); const version = $07e4f6a369d1179a$var$webRTCAdapter.browserDetails.version || 0; if (browser === "chrome" && version < this.minChromeVersion) return false; if (browser === "firefox" && version >= this.minFirefoxVersion) return true; if (!window.RTCRtpTransceiver || !("currentDirection" in RTCRtpTransceiver.prototype)) return false; let tempPc; let supported = false; try { tempPc = new RTCPeerConnection(); tempPc.addTransceiver("audio"); supported = true; } catch (e) {} finally{ if (tempPc) tempPc.close(); } return supported; } toString() { return `Supports: browser:${this.getBrowser()} version:${this.getVersion()} isIOS:${this.isIOS} isWebRTCSupported:${this.isWebRTCSupported()} isBrowserSupported:${this.isBrowserSupported()} isUnifiedPlanSupported:${this.isUnifiedPlanSupported()}`; } constructor(){ this.isIOS = typeof navigator !== "undefined" ? [ "iPad", "iPhone", "iPod" ].includes(navigator.platform) : false; this.supportedBrowsers = [ "firefox", "chrome", "safari" ]; this.minFirefoxVersion = 59; this.minChromeVersion = 72; this.minSafariVersion = 605; } }(); const $706cd7d90eca90d6$export$f35f128fd59ea256 = (id)=>{ // Allow empty ids return !id || /^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.test(id); }; const $6a375544f634961e$export$4e61f672936bec77 = ()=>Math.random().toString(36).slice(2); const $b83e6a166cc3008f$var$DEFAULT_CONFIG = { iceServers: [ { urls: "stun:stun.l.google.com:19302" }, { urls: [ "turn:eu-0.turn.peerjs.com:3478", "turn:us-0.turn.peerjs.com:3478" ], username: "peerjs", credential: "peerjsp" } ], sdpSemantics: "unified-plan" }; class $b83e6a166cc3008f$export$f8f26dd395d7e1bd extends (0, $7ce5389b504cc06c$export$f1c5f4c9cb95390b) { noop() {} blobToArrayBuffer(blob, cb) { const fr = new FileReader(); fr.onload = function(evt) { if (evt.target) cb(evt.target.result); }; fr.readAsArrayBuffer(blob); return fr; } binaryStringToArrayBuffer(binary) { const byteArray = new Uint8Array(binary.length); for(let i = 0; i < binary.length; i++)byteArray[i] = binary.charCodeAt(i) & 0xff; return byteArray.buffer; } isSecure() { return location.protocol === "https:"; } constructor(...args){ super(...args); this.CLOUD_HOST = "0.peerjs.com"; this.CLOUD_PORT = 443; // Browsers that need chunking: this.chunkedBrowsers = { Chrome: 1, chrome: 1 }; // Returns browser-agnostic default config this.defaultConfig = $b83e6a166cc3008f$var$DEFAULT_CONFIG; this.browser = (0, $07e4f6a369d1179a$export$25be9502477c137d).getBrowser(); this.browserVersion = (0, $07e4f6a369d1179a$export$25be9502477c137d).getVersion(); this.pack = $2QID2$peerjsjsbinarypack.pack; this.unpack = $2QID2$peerjsjsbinarypack.unpack; /** * A hash of WebRTC features mapped to booleans that correspond to whether the feature is supported by the current browser. * * :::caution * Only the properties documented here are guaranteed to be present on `util.supports` * ::: */ this.supports = function() { const supported = { browser: (0, $07e4f6a369d1179a$export$25be9502477c137d).isBrowserSupported(), webRTC: (0, $07e4f6a369d1179a$export$25be9502477c137d).isWebRTCSupported(), audioVideo: false, data: false, binaryBlob: false, reliable: false }; if (!supported.webRTC) return supported; let pc; try { pc = new RTCPeerConnection($b83e6a166cc3008f$var$DEFAULT_CONFIG); supported.audioVideo = true; let dc; try { dc = pc.createDataChannel("_PEERJSTEST", { ordered: true }); supported.data = true; supported.reliable = !!dc.ordered; // Binary test try { dc.binaryType = "blob"; supported.binaryBlob = !(0, $07e4f6a369d1179a$export$25be9502477c137d).isIOS; } catch (e) {} } catch (e) {} finally{ if (dc) dc.close(); } } catch (e) {} finally{ if (pc) pc.close(); } return supported; }(); // Ensure alphanumeric ids this.validateId = (0, $706cd7d90eca90d6$export$f35f128fd59ea256); this.randomToken = (0, $6a375544f634961e$export$4e61f672936bec77); } } const $b83e6a166cc3008f$export$7debb50ef11d5e0b = new $b83e6a166cc3008f$export$f8f26dd395d7e1bd(); const $df9d8b89ee908b8b$var$LOG_PREFIX = "PeerJS: "; var $df9d8b89ee908b8b$export$243e62d78d3b544d; (function(LogLevel) { /** * Prints no logs. */ LogLevel[LogLevel["Disabled"] = 0] = "Disabled"; /** * Prints only errors. */ LogLevel[LogLevel["Errors"] = 1] = "Errors"; /** * Prints errors and warnings. */ LogLevel[LogLevel["Warnings"] = 2] = "Warnings"; /** * Prints all logs. */ LogLevel[LogLevel["All"] = 3] = "All"; })($df9d8b89ee908b8b$export$243e62d78d3b544d || ($df9d8b89ee908b8b$export$243e62d78d3b544d = {})); class $df9d8b89ee908b8b$var$Logger { get logLevel() { return this._logLevel; } set logLevel(logLevel) { this._logLevel = logLevel; } log(...args) { if (this._logLevel >= 3) this._print(3, ...args); } warn(...args) { if (this._logLevel >= 2) this._print(2, ...args); } error(...args) { if (this._logLevel >= 1) this._print(1, ...args); } setLogFunction(fn) { this._print = fn; } _print(logLevel, ...rest) { const copy = [ $df9d8b89ee908b8b$var$LOG_PREFIX, ...rest ]; for(const i in copy)if (copy[i] instanceof Error) copy[i] = "(" + copy[i].name + ") " + copy[i].message; if (logLevel >= 3) console.log(...copy); else if (logLevel >= 2) console.warn("WARNING", ...copy); else if (logLevel >= 1) console.error("ERROR", ...copy); } constructor(){ this._logLevel = 0; } } var $df9d8b89ee908b8b$export$2e2bcd8739ae039 = new $df9d8b89ee908b8b$var$Logger(); var $1a7e7edd560505fc$exports = {}; $parcel$export($1a7e7edd560505fc$exports, "ConnectionType", () => $1a7e7edd560505fc$export$3157d57b4135e3bc); $parcel$export($1a7e7edd560505fc$exports, "PeerErrorType", () => $1a7e7edd560505fc$export$9547aaa2e39030ff); $parcel$export($1a7e7edd560505fc$exports, "BaseConnectionErrorType", () => $1a7e7edd560505fc$export$7974935686149686); $parcel$export($1a7e7edd560505fc$exports, "DataConnectionErrorType", () => $1a7e7edd560505fc$export$49ae800c114df41d); $parcel$export($1a7e7edd560505fc$exports, "SerializationType", () => $1a7e7edd560505fc$export$89f507cf986a947); $parcel$export($1a7e7edd560505fc$exports, "SocketEventType", () => $1a7e7edd560505fc$export$3b5c4a4b6354f023); $parcel$export($1a7e7edd560505fc$exports, "ServerMessageType", () => $1a7e7edd560505fc$export$adb4a1754da6f10d); var $1a7e7edd560505fc$export$3157d57b4135e3bc; (function(ConnectionType) { ConnectionType["Data"] = "data"; ConnectionType["Media"] = "media"; })($1a7e7edd560505fc$export$3157d57b4135e3bc || ($1a7e7edd560505fc$export$3157d57b4135e3bc = {})); var $1a7e7edd560505fc$export$9547aaa2e39030ff; (function(PeerErrorType) { /** * The client's browser does not support some or all WebRTC features that you are trying to use. */ PeerErrorType["BrowserIncompatible"] = "browser-incompatible"; /** * You've already disconnected this peer from the server and can no longer make any new connections on it. */ PeerErrorType["Disconnected"] = "disconnected"; /** * The ID passed into the Peer constructor contains illegal characters. */ PeerErrorType["InvalidID"] = "invalid-id"; /** * The API key passed into the Peer constructor contains illegal characters or is not in the system (cloud server only). */ PeerErrorType["InvalidKey"] = "invalid-key"; /** * Lost or cannot establish a connection to the signalling server. */ PeerErrorType["Network"] = "network"; /** * The peer you're trying to connect to does not exist. */ PeerErrorType["PeerUnavailable"] = "peer-unavailable"; /** * PeerJS is being used securely, but the cloud server does not support SSL. Use a custom PeerServer. */ PeerErrorType["SslUnavailable"] = "ssl-unavailable"; /** * Unable to reach the server. */ PeerErrorType["ServerError"] = "server-error"; /** * An error from the underlying socket. */ PeerErrorType["SocketError"] = "socket-error"; /** * The underlying socket closed unexpectedly. */ PeerErrorType["SocketClosed"] = "socket-closed"; /** * The ID passed into the Peer constructor is already taken. * * :::caution * This error is not fatal if your peer has open peer-to-peer connections. * This can happen if you attempt to {@apilink Peer.reconnect} a peer that has been disconnected from the server, * but its old ID has now been taken. * ::: */ PeerErrorType["UnavailableID"] = "unavailable-id"; /** * Native WebRTC errors. */ PeerErrorType["WebRTC"] = "webrtc"; })($1a7e7edd560505fc$export$9547aaa2e39030ff || ($1a7e7edd560505fc$export$9547aaa2e39030ff = {})); var $1a7e7edd560505fc$export$7974935686149686; (function(BaseConnectionErrorType) { BaseConnectionErrorType["NegotiationFailed"] = "negotiation-failed"; BaseConnectionErrorType["ConnectionClosed"] = "connection-closed"; })($1a7e7edd560505fc$export$7974935686149686 || ($1a7e7edd560505fc$export$7974935686149686 = {})); var $1a7e7edd560505fc$export$49ae800c114df41d; (function(DataConnectionErrorType) { DataConnectionErrorType["NotOpenYet"] = "not-open-yet"; DataConnectionErrorType["MessageToBig"] = "message-too-big"; })($1a7e7edd560505fc$export$49ae800c114df41d || ($1a7e7edd560505fc$export$49ae800c114df41d = {})); var $1a7e7edd560505fc$export$89f507cf986a947; (function(SerializationType) { SerializationType["Binary"] = "binary"; SerializationType["BinaryUTF8"] = "binary-utf8"; SerializationType["JSON"] = "json"; SerializationType["None"] = "raw"; })($1a7e7edd560505fc$export$89f507cf986a947 || ($1a7e7edd560505fc$export$89f507cf986a947 = {})); var $1a7e7edd560505fc$export$3b5c4a4b6354f023; (function(SocketEventType) { SocketEventType["Message"] = "message"; SocketEventType["Disconnected"] = "disconnected"; SocketEventType["Error"] = "error"; SocketEventType["Close"] = "close"; })($1a7e7edd560505fc$export$3b5c4a4b6354f023 || ($1a7e7edd560505fc$export$3b5c4a4b6354f023 = {})); var $1a7e7edd560505fc$export$adb4a1754da6f10d; (function(ServerMessageType) { ServerMessageType["Heartbeat"] = "HEARTBEAT"; ServerMessageType["Candidate"] = "CANDIDATE"; ServerMessageType["Offer"] = "OFFER"; ServerMessageType["Answer"] = "ANSWER"; ServerMessageType["Open"] = "OPEN"; ServerMessageType["Error"] = "ERROR"; ServerMessageType["IdTaken"] = "ID-TAKEN"; ServerMessageType["InvalidKey"] = "INVALID-KEY"; ServerMessageType["Leave"] = "LEAVE"; ServerMessageType["Expire"] = "EXPIRE"; })($1a7e7edd560505fc$export$adb4a1754da6f10d || ($1a7e7edd560505fc$export$adb4a1754da6f10d = {})); var $9ce0019dcc6afe7d$exports = {}; $9ce0019dcc6afe7d$exports = JSON.parse('{"name":"peerjs","version":"1.5.4","keywords":["peerjs","webrtc","p2p","rtc"],"description":"PeerJS client","homepage":"https://peerjs.com","bugs":{"url":"https://github.com/peers/peerjs/issues"},"repository":{"type":"git","url":"https://github.com/peers/peerjs"},"license":"MIT","contributors":["Michelle Bu <michelle@michellebu.com>","afrokick <devbyru@gmail.com>","ericz <really.ez@gmail.com>","Jairo <kidandcat@gmail.com>","Jonas Gloning <34194370+jonasgloning@users.noreply.github.com>","Jairo Caro-Accino Viciana <jairo@galax.be>","Carlos Caballero <carlos.caballero.gonzalez@gmail.com>","hc <hheennrryy@gmail.com>","Muhammad Asif <capripio@gmail.com>","PrashoonB <prashoonbhattacharjee@gmail.com>","Harsh Bardhan Mishra <47351025+HarshCasper@users.noreply.github.com>","akotynski <aleksanderkotbury@gmail.com>","lmb <i@lmb.io>","Jairooo <jairocaro@msn.com>","Moritz St\xfcckler <moritz.stueckler@gmail.com>","Simon <crydotsnakegithub@gmail.com>","Denis Lukov <denismassters@gmail.com>","Philipp Hancke <fippo@andyet.net>","Hans Oksendahl <hansoksendahl@gmail.com>","Jess <jessachandler@gmail.com>","khankuan <khankuan@gmail.com>","DUODVK <kurmanov.work@gmail.com>","XiZhao <kwang1imsa@gmail.com>","Matthias Lohr <matthias@lohr.me>","=frank tree <=frnktrb@googlemail.com>","Andre Eckardt <aeckardt@outlook.com>","Chris Cowan <agentme49@gmail.com>","Alex Chuev <alex@chuev.com>","alxnull <alxnull@e.mail.de>","Yemel Jardi <angel.jardi@gmail.com>","Ben Parnell <benjaminparnell.94@gmail.com>","Benny Lichtner <bennlich@gmail.com>","fresheneesz <bitetrudpublic@gmail.com>","bob.barstead@exaptive.com <bob.barstead@exaptive.com>","chandika <chandika@gmail.com>","emersion <contact@emersion.fr>","Christopher Van <cvan@users.noreply.github.com>","eddieherm <edhermoso@gmail.com>","Eduardo Pinho <enet4mikeenet@gmail.com>","Evandro Zanatta <ezanatta@tray.net.br>","Gardner Bickford <gardner@users.noreply.github.com>","Gian Luca <gianluca.cecchi@cynny.com>","PatrickJS <github@gdi2290.com>","jonnyf <github@jonathanfoss.co.uk>","Hizkia Felix <hizkifw@gmail.com>","Hristo Oskov <hristo.oskov@gmail.com>","Isaac Madwed <i.madwed@gmail.com>","Ilya Konanykhin <ilya.konanykhin@gmail.com>","jasonbarry <jasbarry@me.com>","Jonathan Burke <jonathan.burke.1311@googlemail.com>","Josh Hamit <josh.hamit@gmail.com>","Jordan Austin <jrax86@gmail.com>","Joel Wetzell <jwetzell@yahoo.com>","xizhao <kevin.wang@cloudera.com>","Alberto Torres <kungfoobar@gmail.com>","Jonathan Mayol <mayoljonathan@gmail.com>","Jefferson Felix <me@jsfelix.dev>","Rolf Erik Lekang <me@rolflekang.com>","Kevin Mai-Husan Chia <mhchia@users.noreply.github.com>","Pepijn de Vos <pepijndevos@gmail.com>","JooYoung <qkdlql@naver.com>","Tobias Speicher <rootcommander@gmail.com>","Steve Blaurock <sblaurock@gmail.com>","Kyrylo Shegeda <shegeda@ualberta.ca>","Diwank Singh Tomer <singh@diwank.name>","So\u0308ren Balko <Soeren.Balko@gmail.com>","Arpit Solanki <solankiarpit1997@gmail.com>","Yuki Ito <yuki@gnnk.net>","Artur Zayats <zag2art@gmail.com>"],"funding":{"type":"opencollective","url":"https://opencollective.com/peer"},"collective":{"type":"opencollective","url":"https://opencollective.com/peer"},"files":["dist/*"],"sideEffects":["lib/global.ts","lib/supports.ts"],"main":"dist/bundler.cjs","module":"dist/bundler.mjs","browser-minified":"dist/peerjs.min.js","browser-unminified":"dist/peerjs.js","browser-minified-msgpack":"dist/serializer.msgpack.mjs","types":"dist/types.d.ts","engines":{"node":">= 14"},"targets":{"types":{"source":"lib/exports.ts"},"main":{"source":"lib/exports.ts","sourceMap":{"inlineSources":true}},"module":{"source":"lib/exports.ts","includeNodeModules":["eventemitter3"],"sourceMap":{"inlineSources":true}},"browser-minified":{"context":"browser","outputFormat":"global","optimize":true,"engines":{"browsers":"chrome >= 83, edge >= 83, firefox >= 80, safari >= 15"},"source":"lib/global.ts"},"browser-unminified":{"context":"browser","outputFormat":"global","optimize":false,"engines":{"browsers":"chrome >= 83, edge >= 83, firefox >= 80, safari >= 15"},"source":"lib/global.ts"},"browser-minified-msgpack":{"context":"browser","outputFormat":"esmodule","isLibrary":true,"optimize":true,"engines":{"browsers":"chrome >= 83, edge >= 83, firefox >= 102, safari >= 15"},"source":"lib/dataconnection/StreamConnection/MsgPack.ts"}},"scripts":{"contributors":"git-authors-cli --print=false && prettier --write package.json && git add package.json package-lock.json && git commit -m \\"chore(contributors): update and sort contributors list\\"","check":"tsc --noEmit && tsc -p e2e/tsconfig.json --noEmit","watch":"parcel watch","build":"rm -rf dist && parcel build","prepublishOnly":"npm run build","test":"jest","test:watch":"jest --watch","coverage":"jest --coverage --collectCoverageFrom=\\"./lib/**\\"","format":"prettier --write .","format:check":"prettier --check .","semantic-release":"semantic-release","e2e":"wdio run e2e/wdio.local.conf.ts","e2e:bstack":"wdio run e2e/wdio.bstack.conf.ts"},"devDependencies":{"@parcel/config-default":"^2.9.3","@parcel/packager-ts":"^2.9.3","@parcel/transformer-typescript-tsc":"^2.9.3","@parcel/transformer-typescript-types":"^2.9.3","@semantic-release/changelog":"^6.0.1","@semantic-release/git":"^10.0.1","@swc/core":"^1.3.27","@swc/jest":"^0.2.24","@types/jasmine":"^4.3.4","@wdio/browserstack-service":"^8.11.2","@wdio/cli":"^8.11.2","@wdio/globals":"^8.11.2","@wdio/jasmine-framework":"^8.11.2","@wdio/local-runner":"^8.11.2","@wdio/spec-reporter":"^8.11.2","@wdio/types":"^8.10.4","http-server":"^14.1.1","jest":"^29.3.1","jest-environment-jsdom":"^29.3.1","mock-socket":"^9.0.0","parcel":"^2.9.3","prettier":"^3.0.0","semantic-release":"^21.0.0","ts-node":"^10.9.1","typescript":"^5.0.0","wdio-geckodriver-service":"^5.0.1"},"dependencies":{"@msgpack/msgpack":"^2.8.0","eventemitter3":"^4.0.7","peerjs-js-binarypack":"^2.1.0","webrtc-adapter":"^9.0.0"},"alias":{"process":false,"buffer":false}}'); class $e5e868bf3ea73e5b$export$4798917dbf149b79 extends (0, $2QID2$eventemitter3.EventEmitter) { constructor(secure, host, port, path, key, pingInterval = 5000){ super(); this.pingInterval = pingInterval; this._disconnected = true; this._messagesQueue = []; const wsProtocol = secure ? "wss://" : "ws://"; this._baseUrl = wsProtocol + host + ":" + port + path + "peerjs?key=" + key; } start(id, token) { this._id = id; const wsUrl = `${this._baseUrl}&id=${id}&token=${token}`; if (!!this._socket || !this._disconnected) return; this._socket = new WebSocket(wsUrl + "&version=" + (0, $9ce0019dcc6afe7d$exports.version)); this._disconnected = false; this._socket.onmessage = (event)=>{ let data; try { data = JSON.parse(event.data); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Server message received:", data); } catch (e) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Invalid server message", event.data); return; } this.emit((0, $1a7e7edd560505fc$export$3b5c4a4b6354f023).Message, data); }; this._socket.onclose = (event)=>{ if (this._disconnected) return; (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Socket closed.", event); this._cleanup(); this._disconnected = true; this.emit((0, $1a7e7edd560505fc$export$3b5c4a4b6354f023).Disconnected); }; // Take care of the queue of connections if necessary and make sure Peer knows // socket is open. this._socket.onopen = ()=>{ if (this._disconnected) return; this._sendQueuedMessages(); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Socket open"); this._scheduleHeartbeat(); }; } _scheduleHeartbeat() { this._wsPingTimer = setTimeout(()=>{ this._sendHeartbeat(); }, this.pingInterval); } _sendHeartbeat() { if (!this._wsOpen()) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`Cannot send heartbeat, because socket closed`); return; } const message = JSON.stringify({ type: (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Heartbeat }); this._socket.send(message); this._scheduleHeartbeat(); } /** Is the websocket currently open? */ _wsOpen() { return !!this._socket && this._socket.readyState === 1; } /** Send queued messages. */ _sendQueuedMessages() { //Create copy of queue and clear it, //because send method push the message back to queue if smth will go wrong const copiedQueue = [ ...this._messagesQueue ]; this._messagesQueue = []; for (const message of copiedQueue)this.send(message); } /** Exposed send for DC & Peer. */ send(data) { if (this._disconnected) return; // If we didn't get an ID yet, we can't yet send anything so we should queue // up these messages. if (!this._id) { this._messagesQueue.push(data); return; } if (!data.type) { this.emit((0, $1a7e7edd560505fc$export$3b5c4a4b6354f023).Error, "Invalid message"); return; } if (!this._wsOpen()) return; const message = JSON.stringify(data); this._socket.send(message); } close() { if (this._disconnected) return; this._cleanup(); this._disconnected = true; } _cleanup() { if (this._socket) { this._socket.onopen = this._socket.onmessage = this._socket.onclose = null; this._socket.close(); this._socket = undefined; } clearTimeout(this._wsPingTimer); } } class $a8347a6741c5df8a$export$89e6bb5ad64bf4a { constructor(connection){ this.connection = connection; } /** Returns a PeerConnection object set up correctly (for data, media). */ startConnection(options) { const peerConnection = this._startPeerConnection(); // Set the connection's PC. this.connection.peerConnection = peerConnection; if (this.connection.type === (0, $1a7e7edd560505fc$export$3157d57b4135e3bc).Media && options._stream) this._addTracksToConnection(options._stream, peerConnection); // What do we need to do now? if (options.originator) { const dataConnection = this.connection; const config = { ordered: !!options.reliable }; const dataChannel = peerConnection.createDataChannel(dataConnection.label, config); dataConnection._initializeDataChannel(dataChannel); this._makeOffer(); } else this.handleSDP("OFFER", options.sdp); } /** Start a PC. */ _startPeerConnection() { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Creating RTCPeerConnection."); const peerConnection = new RTCPeerConnection(this.connection.provider.options.config); this._setupListeners(peerConnection); return peerConnection; } /** Set up various WebRTC listeners. */ _setupListeners(peerConnection) { const peerId = this.connection.peer; const connectionId = this.connection.connectionId; const connectionType = this.connection.type; const provider = this.connection.provider; // ICE CANDIDATES. (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Listening for ICE candidates."); peerConnection.onicecandidate = (evt)=>{ if (!evt.candidate || !evt.candidate.candidate) return; (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`Received ICE candidates for ${peerId}:`, evt.candidate); provider.socket.send({ type: (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Candidate, payload: { candidate: evt.candidate, type: connectionType, connectionId: connectionId }, dst: peerId }); }; peerConnection.oniceconnectionstatechange = ()=>{ switch(peerConnection.iceConnectionState){ case "failed": (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("iceConnectionState is failed, closing connections to " + peerId); this.connection.emitError((0, $1a7e7edd560505fc$export$7974935686149686).NegotiationFailed, "Negotiation of connection to " + peerId + " failed."); this.connection.close(); break; case "closed": (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("iceConnectionState is closed, closing connections to " + peerId); this.connection.emitError((0, $1a7e7edd560505fc$export$7974935686149686).ConnectionClosed, "Connection to " + peerId + " closed."); this.connection.close(); break; case "disconnected": (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("iceConnectionState changed to disconnected on the connection with " + peerId); break; case "completed": peerConnection.onicecandidate = ()=>{}; break; } this.connection.emit("iceStateChanged", peerConnection.iceConnectionState); }; // DATACONNECTION. (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Listening for data channel"); // Fired between offer and answer, so options should already be saved // in the options hash. peerConnection.ondatachannel = (evt)=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Received data channel"); const dataChannel = evt.channel; const connection = provider.getConnection(peerId, connectionId); connection._initializeDataChannel(dataChannel); }; // MEDIACONNECTION. (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Listening for remote stream"); peerConnection.ontrack = (evt)=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Received remote stream"); const stream = evt.streams[0]; const connection = provider.getConnection(peerId, connectionId); if (connection.type === (0, $1a7e7edd560505fc$export$3157d57b4135e3bc).Media) { const mediaConnection = connection; this._addStreamToMediaConnection(stream, mediaConnection); } }; } cleanup() { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Cleaning up PeerConnection to " + this.connection.peer); const peerConnection = this.connection.peerConnection; if (!peerConnection) return; this.connection.peerConnection = null; //unsubscribe from all PeerConnection's events peerConnection.onicecandidate = peerConnection.oniceconnectionstatechange = peerConnection.ondatachannel = peerConnection.ontrack = ()=>{}; const peerConnectionNotClosed = peerConnection.signalingState !== "closed"; let dataChannelNotClosed = false; const dataChannel = this.connection.dataChannel; if (dataChannel) dataChannelNotClosed = !!dataChannel.readyState && dataChannel.readyState !== "closed"; if (peerConnectionNotClosed || dataChannelNotClosed) peerConnection.close(); } async _makeOffer() { const peerConnection = this.connection.peerConnection; const provider = this.connection.provider; try { const offer = await peerConnection.createOffer(this.connection.options.constraints); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Created offer."); if (this.connection.options.sdpTransform && typeof this.connection.options.sdpTransform === "function") offer.sdp = this.connection.options.sdpTransform(offer.sdp) || offer.sdp; try { await peerConnection.setLocalDescription(offer); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Set localDescription:", offer, `for:${this.connection.peer}`); let payload = { sdp: offer, type: this.connection.type, connectionId: this.connection.connectionId, metadata: this.connection.metadata }; if (this.connection.type === (0, $1a7e7edd560505fc$export$3157d57b4135e3bc).Data) { const dataConnection = this.connection; payload = { ...payload, label: dataConnection.label, reliable: dataConnection.reliable, serialization: dataConnection.serialization }; } provider.socket.send({ type: (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Offer, payload: payload, dst: this.connection.peer }); } catch (err) { // TODO: investigate why _makeOffer is being called from the answer if (err != "OperationError: Failed to set local offer sdp: Called in wrong state: kHaveRemoteOffer") { provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to setLocalDescription, ", err); } } } catch (err_1) { provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err_1); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to createOffer, ", err_1); } } async _makeAnswer() { const peerConnection = this.connection.peerConnection; const provider = this.connection.provider; try { const answer = await peerConnection.createAnswer(); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Created answer."); if (this.connection.options.sdpTransform && typeof this.connection.options.sdpTransform === "function") answer.sdp = this.connection.options.sdpTransform(answer.sdp) || answer.sdp; try { await peerConnection.setLocalDescription(answer); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`Set localDescription:`, answer, `for:${this.connection.peer}`); provider.socket.send({ type: (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Answer, payload: { sdp: answer, type: this.connection.type, connectionId: this.connection.connectionId }, dst: this.connection.peer }); } catch (err) { provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to setLocalDescription, ", err); } } catch (err_1) { provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err_1); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to create answer, ", err_1); } } /** Handle an SDP. */ async handleSDP(type, sdp) { sdp = new RTCSessionDescription(sdp); const peerConnection = this.connection.peerConnection; const provider = this.connection.provider; (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Setting remote description", sdp); const self = this; try { await peerConnection.setRemoteDescription(sdp); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`Set remoteDescription:${type} for:${this.connection.peer}`); if (type === "OFFER") await self._makeAnswer(); } catch (err) { provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to setRemoteDescription, ", err); } } /** Handle a candidate. */ async handleCandidate(ice) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`handleCandidate:`, ice); try { await this.connection.peerConnection.addIceCandidate(ice); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`Added ICE candidate for:${this.connection.peer}`); } catch (err) { this.connection.provider.emitError((0, $1a7e7edd560505fc$export$9547aaa2e39030ff).WebRTC, err); (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Failed to handleCandidate, ", err); } } _addTracksToConnection(stream, peerConnection) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`add tracks from stream ${stream.id} to peer connection`); if (!peerConnection.addTrack) return (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).error(`Your browser does't support RTCPeerConnection#addTrack. Ignored.`); stream.getTracks().forEach((track)=>{ peerConnection.addTrack(track, stream); }); } _addStreamToMediaConnection(stream, mediaConnection) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`add stream ${stream.id} to media connection ${mediaConnection.connectionId}`); mediaConnection.addStream(stream); } } class $cf62563e7a9fbce5$export$6a678e589c8a4542 extends (0, $2QID2$eventemitter3.EventEmitter) { /** * Emits a typed error message. * * @internal */ emitError(type, err) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).error("Error:", err); // @ts-ignore this.emit("error", new $cf62563e7a9fbce5$export$98871882f492de82(`${type}`, err)); } } class $cf62563e7a9fbce5$export$98871882f492de82 extends Error { /** * @internal */ constructor(type, err){ if (typeof err === "string") super(err); else { super(); Object.assign(this, err); } this.type = type; } } class $cb834ab0363d9153$export$23a2a68283c24d80 extends (0, $cf62563e7a9fbce5$export$6a678e589c8a4542) { /** * Whether the media connection is active (e.g. your call has been answered). * You can check this if you want to set a maximum wait time for a one-sided call. */ get open() { return this._open; } constructor(/** * The ID of the peer on the other end of this connection. */ peer, provider, options){ super(); this.peer = peer; this.provider = provider; this.options = options; this._open = false; this.metadata = options.metadata; } } class $f3a554d4328c6b5f$export$4a84e95a2324ac29 extends (0, $cb834ab0363d9153$export$23a2a68283c24d80) { static #_ = this.ID_PREFIX = "mc_"; /** * For media connections, this is always 'media'. */ get type() { return (0, $1a7e7edd560505fc$export$3157d57b4135e3bc).Media; } get localStream() { return this._localStream; } get remoteStream() { return this._remoteStream; } constructor(peerId, provider, options){ super(peerId, provider, options); this._localStream = this.options._stream; this.connectionId = this.options.connectionId || $f3a554d4328c6b5f$export$4a84e95a2324ac29.ID_PREFIX + (0, $b83e6a166cc3008f$export$7debb50ef11d5e0b).randomToken(); this._negotiator = new (0, $a8347a6741c5df8a$export$89e6bb5ad64bf4a)(this); if (this._localStream) this._negotiator.startConnection({ _stream: this._localStream, originator: true }); } /** Called by the Negotiator when the DataChannel is ready. */ _initializeDataChannel(dc) { this.dataChannel = dc; this.dataChannel.onopen = ()=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc connection success`); this.emit("willCloseOnRemote"); }; this.dataChannel.onclose = ()=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc closed for:`, this.peer); this.close(); }; } addStream(remoteStream) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log("Receiving stream", remoteStream); this._remoteStream = remoteStream; super.emit("stream", remoteStream); // Should we call this `open`? } /** * @internal */ handleMessage(message) { const type = message.type; const payload = message.payload; switch(message.type){ case (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Answer: // Forward to negotiator this._negotiator.handleSDP(type, payload.sdp); this._open = true; break; case (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Candidate: this._negotiator.handleCandidate(payload.candidate); break; default: (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).warn(`Unrecognized message type:${type} from peer:${this.peer}`); break; } } /** * When receiving a {@apilink PeerEvents | `call`} event on a peer, you can call * `answer` on the media connection provided by the callback to accept the call * and optionally send your own media stream. * * @param stream A WebRTC media stream. * @param options * @returns */ answer(stream, options = {}) { if (this._localStream) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).warn("Local stream already exists on this MediaConnection. Are you answering a call twice?"); return; } this._localStream = stream; if (options && options.sdpTransform) this.options.sdpTransform = options.sdpTransform; this._negotiator.startConnection({ ...this.options._payload, _stream: stream }); // Retrieve lost messages stored because PeerConnection not set up. const messages = this.provider._getMessages(this.connectionId); for (const message of messages)this.handleMessage(message); this._open = true; } /** * Exposed functionality for users. */ /** * Closes the media connection. */ close() { if (this._negotiator) { this._negotiator.cleanup(); this._negotiator = null; } this._localStream = null; this._remoteStream = null; if (this.provider) { this.provider._removeConnection(this); this.provider = null; } if (this.options && this.options._stream) this.options._stream = null; if (!this.open) return; this._open = false; super.emit("close"); } } class $684fc411629b137b$export$2c4e825dc9120f87 { constructor(_options){ this._options = _options; } _buildRequest(method) { const protocol = this._options.secure ? "https" : "http"; const { host: host, port: port, path: path, key: key } = this._options; const url = new URL(`${protocol}://${host}:${port}${path}${key}/${method}`); // TODO: Why timestamp, why random? url.searchParams.set("ts", `${Date.now()}${Math.random()}`); url.searchParams.set("version", (0, $9ce0019dcc6afe7d$exports.version)); return fetch(url.href, { referrerPolicy: this._options.referrerPolicy }); } /** Get a unique ID from the server via XHR and initialize with it. */ async retrieveId() { try { const response = await this._buildRequest("id"); if (response.status !== 200) throw new Error(`Error. Status:${response.status}`); return response.text(); } catch (error) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).error("Error retrieving ID", error); let pathError = ""; if (this._options.path === "/" && this._options.host !== (0, $b83e6a166cc3008f$export$7debb50ef11d5e0b).CLOUD_HOST) pathError = " If you passed in a `path` to your self-hosted PeerServer, you'll also need to pass in that same path when creating a new Peer."; throw new Error("Could not get an ID from the server." + pathError); } } /** @deprecated */ async listAllPeers() { try { const response = await this._buildRequest("peers"); if (response.status !== 200) { if (response.status === 401) { let helpfulError = ""; if (this._options.host === (0, $b83e6a166cc3008f$export$7debb50ef11d5e0b).CLOUD_HOST) helpfulError = "It looks like you're using the cloud server. You can email team@peerjs.com to enable peer listing for your API key."; else helpfulError = "You need to enable `allow_discovery` on your self-hosted PeerServer to use this feature."; throw new Error("It doesn't look like you have permission to list peers IDs. " + helpfulError); } throw new Error(`Error. Status:${response.status}`); } return response.json(); } catch (error) { (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).error("Error retrieving list peers", error); throw new Error("Could not get list peers from the server." + error); } } } class $f188f8cb0f63b180$export$d365f7ad9d7df9c9 extends (0, $cb834ab0363d9153$export$23a2a68283c24d80) { static #_ = this.ID_PREFIX = "dc_"; static #_2 = this.MAX_BUFFERED_AMOUNT = 8388608; get type() { return (0, $1a7e7edd560505fc$export$3157d57b4135e3bc).Data; } constructor(peerId, provider, options){ super(peerId, provider, options); this.connectionId = this.options.connectionId || $f188f8cb0f63b180$export$d365f7ad9d7df9c9.ID_PREFIX + (0, $6a375544f634961e$export$4e61f672936bec77)(); this.label = this.options.label || this.connectionId; this.reliable = !!this.options.reliable; this._negotiator = new (0, $a8347a6741c5df8a$export$89e6bb5ad64bf4a)(this); this._negotiator.startConnection(this.options._payload || { originator: true, reliable: this.reliable }); } /** Called by the Negotiator when the DataChannel is ready. */ _initializeDataChannel(dc) { this.dataChannel = dc; this.dataChannel.onopen = ()=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc connection success`); this._open = true; this.emit("open"); }; this.dataChannel.onmessage = (e)=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc onmessage:`, e.data); // this._handleDataMessage(e); }; this.dataChannel.onclose = ()=>{ (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc closed for:`, this.peer); this.close(); }; } /** * Exposed functionality for users. */ /** Allows user to close connection. */ close(options) { if (options?.flush) { this.send({ __peerData: { type: "close" } }); return; } if (this._negotiator) { this._negotiator.cleanup(); this._negotiator = null; } if (this.provider) { this.provider._removeConnection(this); this.provider = null; } if (this.dataChannel) { this.dataChannel.onopen = null; this.dataChannel.onmessage = null; this.dataChannel.onclose = null; this.dataChannel = null; } if (!this.open) return; this._open = false; super.emit("close"); } /** Allows user to send data. */ send(data, chunked = false) { if (!this.open) { this.emitError((0, $1a7e7edd560505fc$export$49ae800c114df41d).NotOpenYet, "Connection is not open. You should listen for the `open` event before sending messages."); return; } return this._send(data, chunked); } async handleMessage(message) { const payload = message.payload; switch(message.type){ case (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Answer: await this._negotiator.handleSDP(message.type, payload.sdp); break; case (0, $1a7e7edd560505fc$export$adb4a1754da6f10d).Candidate: await this._negotiator.handleCandidate(payload.candidate); break; default: (0, $df9d8b89ee908b8b$export$2e2bcd8739ae039).warn("Unrecognized message type:", message.type, "from peer:", this.peer); break; } } } class $8d5124d0cf36ebe0$export$ff7c9d4c11d94e8b extends (0, $f188f8cb0f63b180$export$d365f7ad9d7df9c9) { get bufferSize() { return this._bufferSize; } _initializeDataChannel(dc) { super._initializeDataChannel(dc); this.dataChannel.binaryType = "arraybuffer"; this.dataChannel.addEventListener("message", (e)=>this._handleDataMessage(e)); } _bufferedSend(msg) { if (this._buffering || !this._trySend(msg)) { this._buffer.push(msg); this._bufferSize = this._buffer.length;