peerjs
Version:
PeerJS client
1,049 lines (984 loc) • 78.7 kB
JavaScript
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;