(() => { 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; } class $616ebdf1c4998439$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 $616ebdf1c4998439$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; } class $bf7fb46c6d68ead7$var$$e8379818650e2442$export$93654d4f2d6cd524 { append_buffer(data) { this.flush(); this._parts.push(data); } append(data) { this._pieces.push(data); } flush() { if (this._pieces.length > 0) { const buf = new Uint8Array(this._pieces); this._parts.push(buf); this._pieces = []; } } toArrayBuffer() { const buffer = []; for (const part of this._parts)buffer.push(part); return $bf7fb46c6d68ead7$var$$e8379818650e2442$var$concatArrayBuffers(buffer).buffer; } constructor(){ this.encoder = new TextEncoder(); this._pieces = []; this._parts = []; } } function $bf7fb46c6d68ead7$var$$e8379818650e2442$var$concatArrayBuffers(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){ const view = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); result.set(view, offset); offset += buf.byteLength; } return result; } function $bf7fb46c6d68ead7$export$417857010dc9287f(data) { const unpacker = new $bf7fb46c6d68ead7$var$$0cfd7828ad59115f$var$Unpacker(data); return unpacker.unpack(); } function $bf7fb46c6d68ead7$export$2a703dbb0cb35339(data) { const packer = new $bf7fb46c6d68ead7$export$b9ec4b114aa40074(); const res = packer.pack(data); if (res instanceof Promise) return res.then(()=>packer.getBuffer()); return packer.getBuffer(); } class $bf7fb46c6d68ead7$var$$0cfd7828ad59115f$var$Unpacker { unpack() { const type = this.unpack_uint8(); if (type < 0x80) return type; else if ((type ^ 0xe0) < 0x20) return (type ^ 0xe0) - 0x20; let size; if ((size = type ^ 0xa0) <= 0x0f) return this.unpack_raw(size); else if ((size = type ^ 0xb0) <= 0x0f) return this.unpack_string(size); else if ((size = type ^ 0x90) <= 0x0f) return this.unpack_array(size); else if ((size = type ^ 0x80) <= 0x0f) return this.unpack_map(size); switch(type){ case 0xc0: return null; case 0xc1: return undefined; case 0xc2: return false; case 0xc3: return true; case 0xca: return this.unpack_float(); case 0xcb: return this.unpack_double(); case 0xcc: return this.unpack_uint8(); case 0xcd: return this.unpack_uint16(); case 0xce: return this.unpack_uint32(); case 0xcf: return this.unpack_uint64(); case 0xd0: return this.unpack_int8(); case 0xd1: return this.unpack_int16(); case 0xd2: return this.unpack_int32(); case 0xd3: return this.unpack_int64(); case 0xd4: return undefined; case 0xd5: return undefined; case 0xd6: return undefined; case 0xd7: return undefined; case 0xd8: size = this.unpack_uint16(); return this.unpack_string(size); case 0xd9: size = this.unpack_uint32(); return this.unpack_string(size); case 0xda: size = this.unpack_uint16(); return this.unpack_raw(size); case 0xdb: size = this.unpack_uint32(); return this.unpack_raw(size); case 0xdc: size = this.unpack_uint16(); return this.unpack_array(size); case 0xdd: size = this.unpack_uint32(); return this.unpack_array(size); case 0xde: size = this.unpack_uint16(); return this.unpack_map(size); case 0xdf: size = this.unpack_uint32(); return this.unpack_map(size); } } unpack_uint8() { const byte = this.dataView[this.index] & 0xff; this.index++; return byte; } unpack_uint16() { const bytes = this.read(2); const uint16 = (bytes[0] & 0xff) * 256 + (bytes[1] & 0xff); this.index += 2; return uint16; } unpack_uint32() { const bytes = this.read(4); const uint32 = ((bytes[0] * 256 + bytes[1]) * 256 + bytes[2]) * 256 + bytes[3]; this.index += 4; return uint32; } unpack_uint64() { const bytes = this.read(8); const uint64 = ((((((bytes[0] * 256 + bytes[1]) * 256 + bytes[2]) * 256 + bytes[3]) * 256 + bytes[4]) * 256 + bytes[5]) * 256 + bytes[6]) * 256 + bytes[7]; this.index += 8; return uint64; } unpack_int8() { const uint8 = this.unpack_uint8(); return uint8 < 0x80 ? uint8 : uint8 - 256; } unpack_int16() { const uint16 = this.unpack_uint16(); return uint16 < 0x8000 ? uint16 : uint16 - 65536; } unpack_int32() { const uint32 = this.unpack_uint32(); return uint32 < 2 ** 31 ? uint32 : uint32 - 2 ** 32; } unpack_int64() { const uint64 = this.unpack_uint64(); return uint64 < 2 ** 63 ? uint64 : uint64 - 2 ** 64; } unpack_raw(size) { if (this.length < this.index + size) throw new Error(`BinaryPackFailure: index is out of range ${this.index} ${size} ${this.length}`); const buf = this.dataBuffer.slice(this.index, this.index + size); this.index += size; return buf; } unpack_string(size) { const bytes = this.read(size); let i = 0; let str = ""; let c; let code; while(i < size){ c = bytes[i]; // The length of a UTF-8 sequence is specified in the first byte: // 0xxxxxxx means length 1, // 110xxxxx means length 2, // 1110xxxx means length 3, // 11110xxx means length 4. // 10xxxxxx is for non-initial bytes. if (c < 0xa0) { // One-byte sequence: bits 0xxxxxxx code = c; i++; } else if ((c ^ 0xc0) < 0x20) { // Two-byte sequence: bits 110xxxxx 10xxxxxx code = (c & 0x1f) << 6 | bytes[i + 1] & 0x3f; i += 2; } else if ((c ^ 0xe0) < 0x10) { // Three-byte sequence: bits 1110xxxx 10xxxxxx 10xxxxxx code = (c & 0x0f) << 12 | (bytes[i + 1] & 0x3f) << 6 | bytes[i + 2] & 0x3f; i += 3; } else { // Four-byte sequence: bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx code = (c & 0x07) << 18 | (bytes[i + 1] & 0x3f) << 12 | (bytes[i + 2] & 0x3f) << 6 | bytes[i + 3] & 0x3f; i += 4; } str += String.fromCodePoint(code); } this.index += size; return str; } unpack_array(size) { const objects = new Array(size); for(let i = 0; i < size; i++)objects[i] = this.unpack(); return objects; } unpack_map(size) { const map = {}; for(let i = 0; i < size; i++){ const key = this.unpack(); map[key] = this.unpack(); } return map; } unpack_float() { const uint32 = this.unpack_uint32(); const sign = uint32 >> 31; const exp = (uint32 >> 23 & 0xff) - 127; const fraction = uint32 & 0x7fffff | 0x800000; return (sign === 0 ? 1 : -1) * fraction * 2 ** (exp - 23); } unpack_double() { const h32 = this.unpack_uint32(); const l32 = this.unpack_uint32(); const sign = h32 >> 31; const exp = (h32 >> 20 & 0x7ff) - 1023; const hfrac = h32 & 0xfffff | 0x100000; const frac = hfrac * 2 ** (exp - 20) + l32 * 2 ** (exp - 52); return (sign === 0 ? 1 : -1) * frac; } read(length) { const j = this.index; if (j + length <= this.length) return this.dataView.subarray(j, j + length); else throw new Error("BinaryPackFailure: read index out of range"); } constructor(data){ this.index = 0; this.dataBuffer = data; this.dataView = new Uint8Array(this.dataBuffer); this.length = this.dataBuffer.byteLength; } } class $bf7fb46c6d68ead7$export$b9ec4b114aa40074 { getBuffer() { return this._bufferBuilder.toArrayBuffer(); } pack(value) { if (typeof value === "string") this.pack_string(value); else if (typeof value === "number") { if (Math.floor(value) === value) this.pack_integer(value); else this.pack_double(value); } else if (typeof value === "boolean") { if (value === true) this._bufferBuilder.append(0xc3); else if (value === false) this._bufferBuilder.append(0xc2); } else if (value === undefined) this._bufferBuilder.append(0xc0); else if (typeof value === "object") { if (value === null) this._bufferBuilder.append(0xc0); else { const constructor = value.constructor; if (value instanceof Array) { const res = this.pack_array(value); if (res instanceof Promise) return res.then(()=>this._bufferBuilder.flush()); } else if (value instanceof ArrayBuffer) this.pack_bin(new Uint8Array(value)); else if ("BYTES_PER_ELEMENT" in value) { const v = value; this.pack_bin(new Uint8Array(v.buffer, v.byteOffset, v.byteLength)); } else if (value instanceof Date) this.pack_string(value.toString()); else if (value instanceof Blob) return value.arrayBuffer().then((buffer)=>{ this.pack_bin(new Uint8Array(buffer)); this._bufferBuilder.flush(); }); else if (constructor == Object || constructor.toString().startsWith("class")) { const res = this.pack_object(value); if (res instanceof Promise) return res.then(()=>this._bufferBuilder.flush()); } else throw new Error(`Type "${constructor.toString()}" not yet supported`); } } else throw new Error(`Type "${typeof value}" not yet supported`); this._bufferBuilder.flush(); } pack_bin(blob) { const length = blob.length; if (length <= 0x0f) this.pack_uint8(0xa0 + length); else if (length <= 0xffff) { this._bufferBuilder.append(0xda); this.pack_uint16(length); } else if (length <= 0xffffffff) { this._bufferBuilder.append(0xdb); this.pack_uint32(length); } else throw new Error("Invalid length"); this._bufferBuilder.append_buffer(blob); } pack_string(str) { const encoded = this._textEncoder.encode(str); const length = encoded.length; if (length <= 0x0f) this.pack_uint8(0xb0 + length); else if (length <= 0xffff) { this._bufferBuilder.append(0xd8); this.pack_uint16(length); } else if (length <= 0xffffffff) { this._bufferBuilder.append(0xd9); this.pack_uint32(length); } else throw new Error("Invalid length"); this._bufferBuilder.append_buffer(encoded); } pack_array(ary) { const length = ary.length; if (length <= 0x0f) this.pack_uint8(0x90 + length); else if (length <= 0xffff) { this._bufferBuilder.append(0xdc); this.pack_uint16(length); } else if (length <= 0xffffffff) { this._bufferBuilder.append(0xdd); this.pack_uint32(length); } else throw new Error("Invalid length"); const packNext = (index)=>{ if (index < length) { const res = this.pack(ary[index]); if (res instanceof Promise) return res.then(()=>packNext(index + 1)); return packNext(index + 1); } }; return packNext(0); } pack_integer(num) { if (num >= -32 && num <= 0x7f) this._bufferBuilder.append(num & 0xff); else if (num >= 0x00 && num <= 0xff) { this._bufferBuilder.append(0xcc); this.pack_uint8(num); } else if (num >= -128 && num <= 0x7f) { this._bufferBuilder.append(0xd0); this.pack_int8(num); } else if (num >= 0x0000 && num <= 0xffff) { this._bufferBuilder.append(0xcd); this.pack_uint16(num); } else if (num >= -32768 && num <= 0x7fff) { this._bufferBuilder.append(0xd1); this.pack_int16(num); } else if (num >= 0x00000000 && num <= 0xffffffff) { this._bufferBuilder.append(0xce); this.pack_uint32(num); } else if (num >= -2147483648 && num <= 0x7fffffff) { this._bufferBuilder.append(0xd2); this.pack_int32(num); } else if (num >= -9223372036854776000 && num <= 0x7fffffffffffffff) { this._bufferBuilder.append(0xd3); this.pack_int64(num); } else if (num >= 0x0000000000000000 && num <= 0xffffffffffffffff) { this._bufferBuilder.append(0xcf); this.pack_uint64(num); } else throw new Error("Invalid integer"); } pack_double(num) { let sign = 0; if (num < 0) { sign = 1; num = -num; } const exp = Math.floor(Math.log(num) / Math.LN2); const frac0 = num / 2 ** exp - 1; const frac1 = Math.floor(frac0 * 2 ** 52); const b32 = 2 ** 32; const h32 = sign << 31 | exp + 1023 << 20 | frac1 / b32 & 0x0fffff; const l32 = frac1 % b32; this._bufferBuilder.append(0xcb); this.pack_int32(h32); this.pack_int32(l32); } pack_object(obj) { const keys = Object.keys(obj); const length = keys.length; if (length <= 0x0f) this.pack_uint8(0x80 + length); else if (length <= 0xffff) { this._bufferBuilder.append(0xde); this.pack_uint16(length); } else if (length <= 0xffffffff) { this._bufferBuilder.append(0xdf); this.pack_uint32(length); } else throw new Error("Invalid length"); const packNext = (index)=>{ if (index < keys.length) { const prop = keys[index]; // eslint-disable-next-line no-prototype-builtins if (obj.hasOwnProperty(prop)) { this.pack(prop); const res = this.pack(obj[prop]); if (res instanceof Promise) return res.then(()=>packNext(index + 1)); } return packNext(index + 1); } }; return packNext(0); } pack_uint8(num) { this._bufferBuilder.append(num); } pack_uint16(num) { this._bufferBuilder.append(num >> 8); this._bufferBuilder.append(num & 0xff); } pack_uint32(num) { const n = num & 0xffffffff; this._bufferBuilder.append((n & 0xff000000) >>> 24); this._bufferBuilder.append((n & 0x00ff0000) >>> 16); this._bufferBuilder.append((n & 0x0000ff00) >>> 8); this._bufferBuilder.append(n & 0x000000ff); } pack_uint64(num) { const high = num / 2 ** 32; const low = num % 2 ** 32; this._bufferBuilder.append((high & 0xff000000) >>> 24); this._bufferBuilder.append((high & 0x00ff0000) >>> 16); this._bufferBuilder.append((high & 0x0000ff00) >>> 8); this._bufferBuilder.append(high & 0x000000ff); this._bufferBuilder.append((low & 0xff000000) >>> 24); this._bufferBuilder.append((low & 0x00ff0000) >>> 16); this._bufferBuilder.append((low & 0x0000ff00) >>> 8); this._bufferBuilder.append(low & 0x000000ff); } pack_int8(num) { this._bufferBuilder.append(num & 0xff); } pack_int16(num) { this._bufferBuilder.append((num & 0xff00) >> 8); this._bufferBuilder.append(num & 0xff); } pack_int32(num) { this._bufferBuilder.append(num >>> 24 & 0xff); this._bufferBuilder.append((num & 0x00ff0000) >>> 16); this._bufferBuilder.append((num & 0x0000ff00) >>> 8); this._bufferBuilder.append(num & 0x000000ff); } pack_int64(num) { const high = Math.floor(num / 2 ** 32); const low = num % 2 ** 32; this._bufferBuilder.append((high & 0xff000000) >>> 24); this._bufferBuilder.append((high & 0x00ff0000) >>> 16); this._bufferBuilder.append((high & 0x0000ff00) >>> 8); this._bufferBuilder.append(high & 0x000000ff); this._bufferBuilder.append((low & 0xff000000) >>> 24); this._bufferBuilder.append((low & 0x00ff0000) >>> 16); this._bufferBuilder.append((low & 0x0000ff00) >>> 8); this._bufferBuilder.append(low & 0x000000ff); } constructor(){ this._bufferBuilder = new $bf7fb46c6d68ead7$var$$e8379818650e2442$export$93654d4f2d6cd524(); this._textEncoder = new TextEncoder(); } } /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ 'use strict'; let $9fea4db837311579$var$logDisabled_ = true; let $9fea4db837311579$var$deprecationWarnings_ = true; function $9fea4db837311579$export$e3c02be309be1f23(uastring, expr, pos) { const match = uastring.match(expr); return match && match.length >= pos && parseInt(match[pos], 10); } function $9fea4db837311579$export$1f48841962b828b1(window1, eventNameToWrap, wrapper) { if (!window1.RTCPeerConnection) return; const proto = window1.RTCPeerConnection.prototype; const nativeAddEventListener = proto.addEventListener; proto.addEventListener = function(nativeEventName, cb) { if (nativeEventName !== eventNameToWrap) return nativeAddEventListener.apply(this, arguments); const wrappedCallback = (e)=>{ const modifiedEvent = wrapper(e); if (modifiedEvent) { if (cb.handleEvent) cb.handleEvent(modifiedEvent); else cb(modifiedEvent); } }; this._eventMap = this._eventMap || {}; if (!this._eventMap[eventNameToWrap]) this._eventMap[eventNameToWrap] = new Map(); this._eventMap[eventNameToWrap].set(cb, wrappedCallback); return nativeAddEventListener.apply(this, [ nativeEventName, wrappedCallback ]); }; const nativeRemoveEventListener = proto.removeEventListener; proto.removeEventListener = function(nativeEventName, cb) { if (nativeEventName !== eventNameToWrap || !this._eventMap || !this._eventMap[eventNameToWrap]) return nativeRemoveEventListener.apply(this, arguments); if (!this._eventMap[eventNameToWrap].has(cb)) return nativeRemoveEventListener.apply(this, arguments); const unwrappedCb = this._eventMap[eventNameToWrap].get(cb); this._eventMap[eventNameToWrap].delete(cb); if (this._eventMap[eventNameToWrap].size === 0) delete this._eventMap[eventNameToWrap]; if (Object.keys(this._eventMap).length === 0) delete this._eventMap; return nativeRemoveEventListener.apply(this, [ nativeEventName, unwrappedCb ]); }; Object.defineProperty(proto, 'on' + eventNameToWrap, { get () { return this['_on' + eventNameToWrap]; }, set (cb) { if (this['_on' + eventNameToWrap]) { this.removeEventListener(eventNameToWrap, this['_on' + eventNameToWrap]); delete this['_on' + eventNameToWrap]; } if (cb) this.addEventListener(eventNameToWrap, this['_on' + eventNameToWrap] = cb); }, enumerable: true, configurable: true }); } function $9fea4db837311579$export$afbfee8cc06fd3e4(bool) { if (typeof bool !== 'boolean') return new Error('Argument type: ' + typeof bool + '. Please use a boolean.'); $9fea4db837311579$var$logDisabled_ = bool; return bool ? 'adapter.js logging disabled' : 'adapter.js logging enabled'; } function $9fea4db837311579$export$51516be4b019e41e(bool) { if (typeof bool !== 'boolean') return new Error('Argument type: ' + typeof bool + '. Please use a boolean.'); $9fea4db837311579$var$deprecationWarnings_ = !bool; return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled'); } function $9fea4db837311579$export$bef1f36f5486a6a3() { if (typeof window === 'object') { if ($9fea4db837311579$var$logDisabled_) return; if (typeof console !== 'undefined' && typeof console.log === 'function') console.log.apply(console, arguments); } } function $9fea4db837311579$export$cdd73fc4100a6ef4(oldMethod, newMethod) { if (!$9fea4db837311579$var$deprecationWarnings_) return; console.warn(oldMethod + ' is deprecated, please use ' + newMethod + ' instead.'); } function $9fea4db837311579$export$2d31490a0c05f094(window1) { // Returned result object. const result = { browser: null, version: null }; // Fail early if it's not a browser if (typeof window1 === 'undefined' || !window1.navigator || !window1.navigator.userAgent) { result.browser = 'Not a browser.'; return result; } const { navigator: navigator } = window1; // Prefer navigator.userAgentData. if (navigator.userAgentData && navigator.userAgentData.brands) { const chromium = navigator.userAgentData.brands.find((brand)=>{ return brand.brand === 'Chromium'; }); if (chromium) return { browser: 'chrome', version: parseInt(chromium.version, 10) }; } if (navigator.mozGetUserMedia) { result.browser = 'firefox'; result.version = $9fea4db837311579$export$e3c02be309be1f23(navigator.userAgent, /Firefox\/(\d+)\./, 1); } else if (navigator.webkitGetUserMedia || window1.isSecureContext === false && window1.webkitRTCPeerConnection) { // Chrome, Chromium, Webview, Opera. // Version matches Chrome/WebRTC version. // Chrome 74 removed webkitGetUserMedia on http as well so we need the // more complicated fallback to webkitRTCPeerConnection. result.browser = 'chrome'; result.version = $9fea4db837311579$export$e3c02be309be1f23(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2); } else if (window1.RTCPeerConnection && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { result.browser = 'safari'; result.version = $9fea4db837311579$export$e3c02be309be1f23(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1); result.supportsUnifiedPlan = window1.RTCRtpTransceiver && 'currentDirection' in window1.RTCRtpTransceiver.prototype; } else { result.browser = 'Not a supported browser.'; return result; } return result; } /** * Checks if something is an object. * * @param {*} val The something you want to check. * @return true if val is an object, false otherwise. */ function $9fea4db837311579$var$isObject(val) { return Object.prototype.toString.call(val) === '[object Object]'; } function $9fea4db837311579$export$15384eac40dc88c8(data) { if (!$9fea4db837311579$var$isObject(data)) return data; return Object.keys(data).reduce(function(accumulator, key) { const isObj = $9fea4db837311579$var$isObject(data[key]); const value = isObj ? $9fea4db837311579$export$15384eac40dc88c8(data[key]) : data[key]; const isEmptyObject = isObj && !Object.keys(value).length; if (value === undefined || isEmptyObject) return accumulator; return Object.assign(accumulator, { [key]: value }); }, {}); } function $9fea4db837311579$export$571b373e75babb58(stats, base, resultSet) { if (!base || resultSet.has(base.id)) return; resultSet.set(base.id, base); Object.keys(base).forEach((name)=>{ if (name.endsWith('Id')) $9fea4db837311579$export$571b373e75babb58(stats, stats.get(base[name]), resultSet); else if (name.endsWith('Ids')) base[name].forEach((id)=>{ $9fea4db837311579$export$571b373e75babb58(stats, stats.get(id), resultSet); }); }); } function $9fea4db837311579$export$93439ffc3f787d51(result, track, outbound) { const streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp'; const filteredResult = new Map(); if (track === null) return filteredResult; const trackStats = []; result.forEach((value)=>{ if (value.type === 'track' && value.trackIdentifier === track.id) trackStats.push(value); }); trackStats.forEach((trackStat)=>{ result.forEach((stats)=>{ if (stats.type === streamStatsType && stats.trackId === trackStat.id) $9fea4db837311579$export$571b373e75babb58(result, stats, filteredResult); }); }); return filteredResult; } var $fb04e59b477f17ce$exports = {}; $parcel$export($fb04e59b477f17ce$exports, "shimMediaStream", () => $fb04e59b477f17ce$export$33ee24e7a300bcd1); $parcel$export($fb04e59b477f17ce$exports, "shimOnTrack", () => $fb04e59b477f17ce$export$f358708f68ab068); $parcel$export($fb04e59b477f17ce$exports, "shimGetSendersWithDtmf", () => $fb04e59b477f17ce$export$a41a030a2842f5d6); $parcel$export($fb04e59b477f17ce$exports, "shimSenderReceiverGetStats", () => $fb04e59b477f17ce$export$f2f0f2338114eb4b); $parcel$export($fb04e59b477f17ce$exports, "shimAddTrackRemoveTrackWithNative", () => $fb04e59b477f17ce$export$30e3cdd46f8d5100); $parcel$export($fb04e59b477f17ce$exports, "shimAddTrackRemoveTrack", () => $fb04e59b477f17ce$export$9588259fcf4ebc91); $parcel$export($fb04e59b477f17ce$exports, "shimPeerConnection", () => $fb04e59b477f17ce$export$852a08dda9a55ea7); $parcel$export($fb04e59b477f17ce$exports, "fixNegotiationNeeded", () => $fb04e59b477f17ce$export$341293bbeaae37cb); $parcel$export($fb04e59b477f17ce$exports, "shimGetUserMedia", () => $de41d89a4eaa283f$export$1ed4910f4d37dc5e); /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ 'use strict'; const $de41d89a4eaa283f$var$logging = $9fea4db837311579$export$bef1f36f5486a6a3; function $de41d89a4eaa283f$export$1ed4910f4d37dc5e(window, browserDetails) { const navigator = window && window.navigator; if (!navigator.mediaDevices) return; const constraintsToChrome_ = function(c) { if (typeof c !== 'object' || c.mandatory || c.optional) return c; const cc = {}; Object.keys(c).forEach((key)=>{ if (key === 'require' || key === 'advanced' || key === 'mediaSource') return; const r = typeof c[key] === 'object' ? c[key] : { ideal: c[key] }; if (r.exact !== undefined && typeof r.exact === 'number') r.min = r.max = r.exact; const oldname_ = function(prefix, name) { if (prefix) return prefix + name.charAt(0).toUpperCase() + name.slice(1); return name === 'deviceId' ? 'sourceId' : name; }; if (r.ideal !== undefined) { cc.optional = cc.optional || []; let oc = {}; if (typeof r.ideal === 'number') { oc[oldname_('min', key)] = r.ideal; cc.optional.push(oc); oc = {}; oc[oldname_('max', key)] = r.ideal; cc.optional.push(oc); } else { oc[oldname_('', key)] = r.ideal; cc.optional.push(oc); } } if (r.exact !== undefined && typeof r.exact !== 'number') { cc.mandatory = cc.mandatory || {}; cc.mandatory[oldname_('', key)] = r.exact; } else [ 'min', 'max' ].forEach((mix)=>{ if (r[mix] !== undefined) { cc.mandatory = cc.mandatory || {}; cc.mandatory[oldname_(mix, key)] = r[mix]; } }); }); if (c.advanced) cc.optional = (cc.optional || []).concat(c.advanced); return cc; }; const shimConstraints_ = function(constraints, func) { if (browserDetails.version >= 61) return func(constraints); constraints = JSON.parse(JSON.stringify(constraints)); if (constraints && typeof constraints.audio === 'object') { const remap = function(obj, a, b) { if (a in obj && !(b in obj)) { obj[b] = obj[a]; delete obj[a]; } }; constraints = JSON.parse(JSON.stringify(constraints)); remap(constraints.audio, 'autoGainControl', 'googAutoGainControl'); remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression'); constraints.audio = constraintsToChrome_(constraints.audio); } if (constraints && typeof constraints.video === 'object') { // Shim facingMode for mobile & surface pro. let face = constraints.video.facingMode; face = face && (typeof face === 'object' ? face : { ideal: face }); const getSupportedFacingModeLies = browserDetails.version < 66; if (face && (face.exact === 'user' || face.exact === 'environment' || face.ideal === 'user' || face.ideal === 'environment') && !(navigator.mediaDevices.getSupportedConstraints && navigator.mediaDevices.getSupportedConstraints().facingMode && !getSupportedFacingModeLies)) { delete constraints.video.facingMode; let matches; if (face.exact === 'environment' || face.ideal === 'environment') matches = [ 'back', 'rear' ]; else if (face.exact === 'user' || face.ideal === 'user') matches = [ 'front' ]; if (matches) // Look for matches in label, or use last cam for back (typical). return navigator.mediaDevices.enumerateDevices().then((devices)=>{ devices = devices.filter((d)=>d.kind === 'videoinput'); let dev = devices.find((d)=>matches.some((match)=>d.label.toLowerCase().includes(match))); if (!dev && devices.length && matches.includes('back')) dev = devices[devices.length - 1]; // more likely the back cam if (dev) constraints.video.deviceId = face.exact ? { exact: dev.deviceId } : { ideal: dev.deviceId }; constraints.video = constraintsToChrome_(constraints.video); $de41d89a4eaa283f$var$logging('chrome: ' + JSON.stringify(constraints)); return func(constraints); }); } constraints.video = constraintsToChrome_(constraints.video); } $de41d89a4eaa283f$var$logging('chrome: ' + JSON.stringify(constraints)); return func(constraints); }; const shimError_ = function(e) { if (browserDetails.version >= 64) return e; return { name: ({ PermissionDeniedError: 'NotAllowedError', PermissionDismissedError: 'NotAllowedError', InvalidStateError: 'NotAllowedError', DevicesNotFoundError: 'NotFoundError', ConstraintNotSatisfiedError: 'OverconstrainedError', TrackStartError: 'NotReadableError', MediaDeviceFailedDueToShutdown: 'NotAllowedError', MediaDeviceKillSwitchOn: 'NotAllowedError', TabCaptureError: 'AbortError', ScreenCaptureError: 'AbortError', DeviceCaptureError: 'AbortError' })[e.name] || e.name, message: e.message, constraint: e.constraint || e.constraintName, toString () { return this.name + (this.message && ': ') + this.message; } }; }; const getUserMedia_ = function(constraints, onSuccess, onError) { shimConstraints_(constraints, (c)=>{ navigator.webkitGetUserMedia(c, onSuccess, (e)=>{ if (onError) onError(shimError_(e)); }); }); }; navigator.getUserMedia = getUserMedia_.bind(navigator); // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia // function which returns a Promise, it does not accept spec-style // constraints. if (navigator.mediaDevices.getUserMedia) { const origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices); navigator.mediaDevices.getUserMedia = function(cs) { return shimConstraints_(cs, (c)=>origGetUserMedia(c).then((stream)=>{ if (c.audio && !stream.getAudioTracks().length || c.video && !stream.getVideoTracks().length) { stream.getTracks().forEach((track)=>{ track.stop(); }); throw new DOMException('', 'NotFoundError'); } return stream; }, (e)=>Promise.reject(shimError_(e)))); }; } } 'use strict'; function $fb04e59b477f17ce$export$33ee24e7a300bcd1(window) { window.MediaStream = window.MediaStream || window.webkitMediaStream; } function $fb04e59b477f17ce$export$f358708f68ab068(window) { if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in window.RTCPeerConnection.prototype)) { Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { get () { return this._ontrack; }, set (f) { if (this._ontrack) this.removeEventListener('track', this._ontrack); this.addEventListener('track', this._ontrack = f); }, enumerable: true, configurable: true }); const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() { if (!this._ontrackpoly) { this._ontrackpoly = (e)=>{ // onaddstream does not fire when a track is added to an existing // stream. But stream.onaddtrack is implemented so we use that. e.stream.addEventListener('addtrack', (te)=>{ let receiver; if (window.RTCPeerConnection.prototype.getReceivers) receiver = this.getReceivers().find((r)=>r.track && r.track.id === te.track.id); else receiver = { track: te.track }; const event = new Event('track'); event.track = te.track; event.receiver = receiver; event.transceiver = { receiver: receiver }; event.streams = [ e.stream ]; this.dispatchEvent(event); }); e.stream.getTracks().forEach((track)=>{ let receiver; if (window.RTCPeerConnection.prototype.getReceivers) receiver = this.getReceivers().find((r)=>r.track && r.track.id === track.id); else receiver = { track: track }; const event = new Event('track'); event.track = track; event.receiver = receiver; event.transceiver = { receiver: receiver }; event.streams = [ e.stream ]; this.dispatchEvent(event); }); }; this.addEventListener('addstream', this._ontrackpoly); } return origSetRemoteDescription.apply(this, arguments); }; } else // even if RTCRtpTransceiver is in window, it is only used and // emitted in unified-plan. Unfortunately this means we need // to unconditionally wrap the event. $9fea4db837311579$export$1f48841962b828b1(window, 'track', (e)=>{ if (!e.transceiver) Object.defineProperty(e, 'transceiver', { value: { receiver: e.receiver } }); return e; }); } function $fb04e59b477f17ce$export$a41a030a2842f5d6(window) { // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack. if (typeof window === 'object' && window.RTCPeerConnection && !('getSenders' in window.RTCPeerConnection.prototype) && 'createDTMFSender' in window.RTCPeerConnection.prototype) { const shimSenderWithDtmf = function(pc, track) { return { track: track, get dtmf () { if (this._dtmf === undefined) { if (track.kind === 'audio') this._dtmf = pc.createDTMFSender(track); else this._dtmf = null; } return this._dtmf; }, _pc: pc }; }; // augment addTrack when getSenders is not available. if (!window.RTCPeerConnection.prototype.getSenders) { window.RTCPeerConnection.prototype.getSenders = function getSenders() { this._senders = this._senders || []; return this._senders.slice(); // return a copy of the internal state. }; const origAddTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) { let sender = origAddTrack.apply(this, arguments); if (!sender) { sender = shimSenderWithDtmf(this, track); this._senders.push(sender); } return sender; }; const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { origRemoveTrack.apply(this, arguments); const idx = this._senders.indexOf(sender); if (idx !== -1) this._senders.splice(idx, 1); }; } const origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { this._senders = this._senders || []; origAddStream.apply(this, [ stream ]); stream.getTracks().forEach((track)=>{ this._senders.push(shimSenderWithDtmf(this, track)); }); }; const origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { this._senders = this._senders || []; origRemoveStream.apply(this, [ stream ]); stream.getTracks().forEach((track)=>{ const sender = this._senders.find((s)=>s.track === track); if (sender) this._senders.splice(this._senders.indexOf(sender), 1); }); }; } else if (typeof window === 'object' && window.RTCPeerConnection && 'getSenders' in window.RTCPeerConnection.prototype && 'createDTMFSender' in window.RTCPeerConnection.prototype && window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) { const origGetSenders = window.RTCPeerConnection.prototype.getSenders; window.RTCPeerConnection.prototype.getSenders = function getSenders() { const senders = origGetSenders.apply(this, []); senders.forEach((sender)=>sender._pc = this); return senders; }; Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { get () { if (this._dtmf === undefined) { if (this.track.kind === 'audio') this._dtmf = this._pc.createDTMFSender(this.track); else this._dtmf = null; } return this._dtmf; } }); } } function $fb04e59b477f17ce$export$f2f0f2338114eb4b(window) { if (!(typeof window === 'object' && window.RTCPeerConnection && window.RTCRtpSender && window.RTCRtpReceiver)) return; // shim sender stats. if (!('getStats' in window.RTCRtpSender.prototype)) { const origGetSenders = window.RTCPeerConnection.prototype.getSenders; if (origGetSenders) window.RTCPeerConnection.prototype.getSenders = function getSenders() { const senders = origGetSenders.apply(this, []); senders.forEach((sender)=>sender._pc = this); return senders; }; const origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) window.RTCPeerConnection.prototype.addTrack = function addTrack() { const sender = origAddTrack.apply(this, arguments); sender._pc = this; return sender; }; window.RTCRtpSender.prototype.getStats = function getStats() { const sender = this; return this._pc.getStats().then((result)=>/* Note: this will include stats of all senders that * send a track with the same id as sender.track as * it is not possible to identify the RTCRtpSender. */ $9fea4db837311579$export$93439ffc3f787d51(result, sender.track, true)); }; } // shim receiver stats. if (!('getStats' in window.RTCRtpReceiver.prototype)) { const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers; if (origGetReceivers) window.RTCPeerConnection.prototype.getReceivers = function getReceivers() { const receivers = origGetReceivers.apply(this, []); receivers.forEach((receiver)=>receiver._pc = this); return receivers; }; $9fea4db837311579$export$1f48841962b828b1(window, 'track', (e)=>{ e.receiver._pc = e.srcElement; return e; }); window.RTCRtpReceiver.prototype.getStats = function getStats() { const receiver = this; return this._pc.getStats().then((result)=>$9fea4db837311579$export$93439ffc3f787d51(result, receiver.track, false)); }; } if (!('getStats' in window.RTCRtpSender.prototype && 'getStats' in window.RTCRtpReceiver.prototype)) return; // shim RTCPeerConnection.getStats(track). const origGetStats = window.RTCPeerConnection.prototype.getStats; window.RTCPeerConnection.prototype.getStats = function getStats() { if (arguments.length > 0 && arguments[0] instanceof window.MediaStreamTrack) { const track = arguments[0]; let sender; let receiver; let err; this.getSenders().forEach((s)=>{ if (s.track === track) { if (sender) err = true; else sender = s; } }); this.getReceivers().forEach((r)=>{ if (r.track === track) { if (receiver) err = true; else receiver = r; } return r.track === track; }); if (err || sender && receiver) return Promise.reject(new DOMException('There are more than one sender or receiver for the track.', 'InvalidAccessError')); else if (sender) return sender.getStats(); else if (receiver) return receiver.getStats(); return Promise.reject(new DOMException('There is no sender or receiver for the track.', 'InvalidAccessError')); } return origGetStats.apply(this, arguments); }; } function $fb04e59b477f17ce$export$30e3cdd46f8d5100(window) { // shim addTrack/removeTrack with native variants in order to make // the interactions with legacy getLocalStreams behave as in other browsers. // Keeps a mapping stream.id => [stream, rtpsenders...] window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; return Object.keys(this._shimmedLocalStreams).map((streamId)=>this._shimmedLocalStreams[streamId][0]); }; const origAddTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) { if (!stream) return origAddTrack.apply(this, arguments); this._shimmedLocalStreams = this._shimmedLocalStreams || {}; const sender = origAddTrack.apply(this, arguments); if (!this._shimmedLocalStreams[stream.id]) this._shimmedLocalStreams[stream.id] = [ stream, sender ]; else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) this._shimmedLocalStreams[stream.id].push(sender); return sender; }; const origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; stream.getTracks().forEach((track)=>{ const alreadyExists = this.getSenders().find((s)=>s.track === track); if (alreadyExists) throw new DOMException('Track already exists.', 'InvalidAccessError'); }); const existingSenders = this.getSenders(); origAddStream.apply(this, arguments); const newSenders = this.getSenders().filter((newSender)=>existingSenders.indexOf(newSender) === -1); this._shimmedLocalStreams[stream.id] = [ stream ].concat(newSenders); }; const origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; delete this._shimmedLocalStreams[stream.id]; return origRemoveStream.apply(this, arguments); }; const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; if (sender) Object.keys(this._shimmedLocalStreams).forEach((streamId)=>{ const idx = this._shimmedLocalStreams[streamId].indexOf(sender); if (idx !== -1) this._shimmedLocalStreams[streamId].splice(idx, 1); if (this._shimmedLocalStreams[streamId].length === 1) delete this._shimmedLocalStreams[streamId]; }); return origRemoveTrack.apply(this, arguments); }; } function $fb04e59b477f17ce$export$9588259fcf4ebc91(window, browserDetails) { if (!window.RTCPeerConnection) return; // shim addTrack and removeTrack. if (window.RTCPeerConnection.prototype.addTrack && browserDetails.version >= 65) return $fb04e59b477f17ce$export$30e3cdd46f8d5100(window); // also shim pc.getLocalStreams when addTrack is shimmed // to return the original streams. const origGetLocalStreams = window.RTCPeerConnection.prototype.getLocalStreams; window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() { const nativeStreams = origGetLocalStreams.apply(this); this._reverseStreams = this._reverseStreams || {}; return nativeStreams.map((stream)=>this._reverseStreams[stream.id]); }; const origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; stream.getTracks().forEach((track)=>{ const alreadyExists = this.getSenders().find((s)=>s.track === track); if (alreadyExists) throw new DOMException('Track already exists.', 'InvalidAccessError'); }); // Add identity mapping for consistency with addTrack. // Unless this is being used with a stream from addTrack. if (!this._reverseStreams[stream.id]) { const newStream = new window.MediaStream(stream.getTracks()); this._streams[stream.id] = newStream; this._reverseStreams[newStream.id] = stream; stream = newStream; } origAddStream.apply(this, [ stream ]); }; const origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; origRemoveStream.apply(this, [ this._streams[stream.id] || stream ]); delete this._reverseStreams[this._streams[stream.id] ? this._streams[stream.id].id : stream.id]; delete this._streams[stream.id]; }; window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) { if (this.signalingState === 'closed') throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError'); const streams = [].slice.call(arguments, 1); if (streams.length !== 1 || !streams[0].getTracks().find((t)=>t === track)) // this is not fully correct but all we can manage without // [[associated MediaStreams]] internal slot. throw new DOMException("The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.", 'NotSupportedError'); const alreadyExists = this.getSenders().find((s)=>s.track === track); if (alreadyExists) throw new DOMException('Track already exists.', 'InvalidAccessError'); this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; const oldStream = this._streams[stream.id]; if (oldStream) { // this is using odd Chrome behaviour, use with caution: // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815 // Note: we rely on the high-level addTrack/dtmf shim to // create the sender with a dtmf sender. oldStream.addTrack(track); // Trigger ONN async. Promise.resolve().then(()=>{ this.dispatchEvent(new Event('negotiationneeded')); }); } else { const newStream = new window.MediaStream([ track ]); this._streams[stream.id] = newStream; this._reverseStreams[newStream.id] = stream; this.addStream(newStream); } return this.getSenders().find((s)=>s.track === track); }; // replace the internal stream id with the external one and // vice versa. function replaceInternalStreamId(pc, description) { let sdp = description.sdp; Object.keys(pc._reverseStreams || []).forEach((internalId)=>{ const externalStream = pc._reverseStreams[internalId]; const internalStream = pc._streams[externalStream.id]; sdp = sdp.replace(new RegExp(internalStream.id, 'g'), externalStream.id); }); return new RTCSessionDescription({ type: description.type, sdp: sdp }); } function replaceExternalStreamId(pc, description) { let sdp = description.sdp; Object.keys(pc._reverseStreams || []).forEach((internalId)=>{ const externalStream = pc._reverseStreams[internalId]; const internalStream = pc._streams[externalStream.id]; sdp = sdp.replace(new RegExp(externalStream.id, 'g'), internalStream.id); }); return new RTCSessionDescription({ type: description.type, sdp: sdp }); } [ 'createOffer', 'createAnswer' ].forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; const methodObj = { [method] () { const args = arguments; const isLegacyCall = arguments.length && typeof arguments[0] === 'function'; if (isLegacyCall) return nativeMethod.apply(this, [ (description)=>{ const desc = replaceInternalStreamId(this, description); args[0].apply(null, [ desc ]); }, (err)=>{ if (args[1]) args[1].apply(null, err); }, arguments[2] ]); return nativeMethod.apply(this, arguments).then((description)=>replaceInternalStreamId(this, description)); } }; window.RTCPeerConnection.prototype[method] = methodObj[method]; }); const origSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription; window.RTCPeerConnection.prototype.setLocalDescription = function setLocalDescription() { if (!arguments.length || !arguments[0].type) return origSetLocalDescription.apply(this, arguments); arguments[0] = replaceExternalStreamId(this, arguments[0]); return origSetLocalDescription.apply(this, arguments); }; // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier const origLocalDescription = Object.getOwnPropertyDescriptor(window.RTCPeerConnection.prototype, 'localDescription'); Object.defineProperty(window.RTCPeerConnection.prototype, 'localDescription', { get () { const description = origLocalDescription.get.apply(this); if (description.type === '') return description; return replaceInternalStreamId(this, description); } }); window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { if (this.signalingState === 'closed') throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError'); // We can not yet check for sender instanceof RTCRtpSender // since we shim RTPSender. So we check if sender._pc is set. if (!sender._pc) throw new DOMException("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.", 'TypeError'); const isLocal = sender._pc === this; if (!isLocal) throw new DOMException('Sender was not created by this connection.', 'InvalidAccessError'); // Search for the native stream the senders track belongs to. this._streams = this._streams || {}; let stream; Object.keys(this._streams).forEach((streamid)=>{ const hasTrack = this._streams[streamid].getTracks().find((track)=>sender.track === track); if (hasTrack) stream = this._streams[streamid]; }); if (stream) { if (stream.getTracks().length === 1) // if this is the last track of the stream, remove the stream. This // takes care of any shimmed _senders. this.removeStream(this._reverseStreams[stream.id]); else // relying on the same odd chrome behaviour as above. stream.removeTrack(sender.track); this.dispatchEvent(new Event('negotiationneeded')); } }; } function $fb04e59b477f17ce$export$852a08dda9a55ea7(window, browserDetails) { if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) // very basic support for old versions. window.RTCPeerConnection = window.webkitRTCPeerConnection; if (!window.RTCPeerConnection) return; // shim implicit creation of RTCSessionDescription/RTCIceCandidate if (browserDetails.version < 53) [ 'setLocalDescription', 'setRemoteDescription', 'addIceCandidate' ].forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; const methodObj = { [method] () { arguments[0] = new (method === 'addIceCandidate' ? window.RTCIceCandidate : window.RTCSessionDescription)(arguments[0]); return nativeMethod.apply(this, arguments); } }; window.RTCPeerConnection.prototype[method] = methodObj[method]; }); } function $fb04e59b477f17ce$export$341293bbeaae37cb(window, browserDetails) { $9fea4db837311579$export$1f48841962b828b1(window, 'negotiationneeded', (e)=>{ const pc = e.target; if (browserDetails.version < 72 || pc.getConfiguration && pc.getConfiguration().sdpSemantics === 'plan-b') { if (pc.signalingState !== 'stable') return; } return e; }); } var $215e6581d7a09c61$exports = {}; $parcel$export($215e6581d7a09c61$exports, "shimOnTrack", () => $215e6581d7a09c61$export$f358708f68ab068); $parcel$export($215e6581d7a09c61$exports, "shimPeerConnection", () => $215e6581d7a09c61$export$852a08dda9a55ea7); $parcel$export($215e6581d7a09c61$exports, "shimSenderGetStats", () => $215e6581d7a09c61$export$f0525502095c04ef); $parcel$export($215e6581d7a09c61$exports, "shimReceiverGetStats", () => $215e6581d7a09c61$export$83d69126527b1171); $parcel$export($215e6581d7a09c61$exports, "shimRemoveStream", () => $215e6581d7a09c61$export$825e523ef749bd8c); $parcel$export($215e6581d7a09c61$exports, "shimRTCDataChannel", () => $215e6581d7a09c61$export$ff9cb3bc8990e8f7); $parcel$export($215e6581d7a09c61$exports, "shimAddTransceiver", () => $215e6581d7a09c61$export$70c77533b6e9908d); $parcel$export($215e6581d7a09c61$exports, "shimGetParameters", () => $215e6581d7a09c61$export$66238223c298fbaa); $parcel$export($215e6581d7a09c61$exports, "shimCreateOffer", () => $215e6581d7a09c61$export$51beccf0e777b843); $parcel$export($215e6581d7a09c61$exports, "shimCreateAnswer", () => $215e6581d7a09c61$export$df0b46e7cef08150); $parcel$export($215e6581d7a09c61$exports, "shimGetUserMedia", () => $6c9e5f7e9edd1e60$export$1ed4910f4d37dc5e); $parcel$export($215e6581d7a09c61$exports, "shimGetDisplayMedia", () => $c12684406b986df8$export$97270b87351d9c04); /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ 'use strict'; function $6c9e5f7e9edd1e60$export$1ed4910f4d37dc5e(window, browserDetails) { const navigator = window && window.navigator; const MediaStreamTrack = window && window.MediaStreamTrack; navigator.getUserMedia = function(constraints, onSuccess, onError) { // Replace Firefox 44+'s deprecation warning with unprefixed version. $9fea4db837311579$export$cdd73fc4100a6ef4('navigator.getUserMedia', 'navigator.mediaDevices.getUserMedia'); navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError); }; if (!(browserDetails.version > 55 && 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) { const remap = function(obj, a, b) { if (a in obj && !(b in obj)) { obj[b] = obj[a]; delete obj[a]; } }; const nativeGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices); navigator.mediaDevices.getUserMedia = function(c) { if (typeof c === 'object' && typeof c.audio === 'object') { c = JSON.parse(JSON.stringify(c)); remap(c.audio, 'autoGainControl', 'mozAutoGainControl'); remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression'); } return nativeGetUserMedia(c); }; if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) { const nativeGetSettings = MediaStreamTrack.prototype.getSettings; MediaStreamTrack.prototype.getSettings = function() { const obj = nativeGetSettings.apply(this, arguments); remap(obj, 'mozAutoGainControl', 'autoGainControl'); remap(obj, 'mozNoiseSuppression', 'noiseSuppression'); return obj; }; } if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) { const nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints; MediaStreamTrack.prototype.applyConstraints = function(c) { if (this.kind === 'audio' && typeof c === 'object') { c = JSON.parse(JSON.stringify(c)); remap(c, 'autoGainControl', 'mozAutoGainControl'); remap(c, 'noiseSuppression', 'mozNoiseSuppression'); } return nativeApplyConstraints.apply(this, [ c ]); }; } } } /* * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ 'use strict'; function $c12684406b986df8$export$97270b87351d9c04(window, preferredMediaSource) { if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) return; if (!window.navigator.mediaDevices) return; window.navigator.mediaDevices.getDisplayMedia = function getDisplayMedia(constraints) { if (!(constraints && constraints.video)) { const err = new DOMException("getDisplayMedia without video constraints is undefined"); err.name = 'NotFoundError'; // from https://heycam.github.io/webidl/#idl-DOMException-error-names err.code = 8; return Promise.reject(err); } if (constraints.video === true) constraints.video = { mediaSource: preferredMediaSource }; else constraints.video.mediaSource = preferredMediaSource; return window.navigator.mediaDevices.getUserMedia(constraints); }; } 'use strict'; function $215e6581d7a09c61$export$f358708f68ab068(window) { if (typeof window === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { get () { return { receiver: this.receiver }; } }); } function $215e6581d7a09c61$export$852a08dda9a55ea7(window, browserDetails) { if (typeof window !== 'object' || !(window.RTCPeerConnection || window.mozRTCPeerConnection)) return; // probably media.peerconnection.enabled=false in about:config if (!window.RTCPeerConnection && window.mozRTCPeerConnection) // very basic support for old versions. window.RTCPeerConnection = window.mozRTCPeerConnection; if (browserDetails.version < 53) // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. [ 'setLocalDescription', 'setRemoteDescription', 'addIceCandidate' ].forEach(function(method) { const nativeMethod = window.RTCPeerConnection.prototype[method]; const methodObj = { [method] () { arguments[0] = new (method === 'addIceCandidate' ? window.RTCIceCandidate : window.RTCSessionDescription)(arguments[0]); return nativeMethod.apply(this, arguments); } }; window.RTCPeerConnection.prototype[method] = methodObj[method]; }); const modernStatsTypes = { inboundrtp: 'inbound-rtp', outboundrtp: 'outbound-rtp', candidatepair: 'candidate-pair', localcandidate: 'local-candidate', remotecandidate: 'remote-candidate' }; const nativeGetStats = window.RTCPeerConnection.prototype.getStats; window.RTCPeerConnection.prototype.getStats = function getStats() { const [selector, onSucc, onErr] = arguments; return nativeGetStats.apply(this, [ selector || null ]).then((stats)=>{ if (browserDetails.version < 53 && !onSucc) // Shim only promise getStats with spec-hyphens in type names // Leave callback version alone; misc old uses of forEach before Map try { stats.forEach((stat)=>{ stat.type = modernStatsTypes[stat.type] || stat.type; }); } catch (e) { if (e.name !== 'TypeError') throw e; // Avoid TypeError: "type" is read-only, in old versions. 34-43ish stats.forEach((stat, i)=>{ stats.set(i, Object.assign({}, stat, { type: modernStatsTypes[stat.type] || stat.type })); }); } return stats; }).then(onSucc, onErr); }; } function $215e6581d7a09c61$export$f0525502095c04ef(window) { if (!(typeof window === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) return; if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) return; const origGetSenders = window.RTCPeerConnection.prototype.getSenders; if (origGetSenders) window.RTCPeerConnection.prototype.getSenders = function getSenders() { const senders = origGetSenders.apply(this, []); senders.forEach((sender)=>sender._pc = this); return senders; }; const origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) window.RTCPeerConnection.prototype.addTrack = function addTrack() { const sender = origAddTrack.apply(this, arguments); sender._pc = this; return sender; }; window.RTCRtpSender.prototype.getStats = function getStats() { return this.track ? this._pc.getStats(this.track) : Promise.resolve(new Map()); }; } function $215e6581d7a09c61$export$83d69126527b1171(window) { if (!(typeof window === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) return; if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) return; const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers; if (origGetReceivers) window.RTCPeerConnection.prototype.getReceivers = function getReceivers() { const receivers = origGetReceivers.apply(this, []); receivers.forEach((receiver)=>receiver._pc = this); return receivers; }; $9fea4db837311579$export$1f48841962b828b1(window, 'track', (e)=>{ e.receiver._pc = e.srcElement; return e; }); window.RTCRtpReceiver.prototype.getStats = function getStats() { return this._pc.getStats(this.track); }; } function $215e6581d7a09c61$export$825e523ef749bd8c(window) { if (!window.RTCPeerConnection || 'removeStream' in window.RTCPeerConnection.prototype) return; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { $9fea4db837311579$export$cdd73fc4100a6ef4('removeStream', 'removeTrack'); this.getSenders().forEach((sender)=>{ if (sender.track && stream.getTracks().includes(sender.track)) this.removeTrack(sender); }); }; } function $215e6581d7a09c61$export$ff9cb3bc8990e8f7(window) { // rename DataChannel to RTCDataChannel (native fix in FF60): // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851 if (window.DataChannel && !window.RTCDataChannel) window.RTCDataChannel = window.DataChannel; } function $215e6581d7a09c61$export$70c77533b6e9908d(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 if (!(typeof window === 'object' && window.RTCPeerConnection)) return; const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver; if (origAddTransceiver) window.RTCPeerConnection.prototype.addTransceiver = function addTransceiver() { this.setParametersPromises = []; // WebIDL input coercion and validation let sendEncodings = arguments[1] && arguments[1].sendEncodings; if (sendEncodings === undefined) sendEncodings = []; sendEncodings = [ ...sendEncodings ]; const shouldPerformCheck = sendEncodings.length > 0; if (shouldPerformCheck) // If sendEncodings params are provided, validate grammar sendEncodings.forEach((encodingParam)=>{ if ('rid' in encodingParam) { const ridRegex = /^[a-z0-9]{0,16}$/i; if (!ridRegex.test(encodingParam.rid)) throw new TypeError('Invalid RID value provided.'); } if ('scaleResolutionDownBy' in encodingParam) { if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) throw new RangeError('scale_resolution_down_by must be >= 1.0'); } if ('maxFramerate' in encodingParam) { if (!(parseFloat(encodingParam.maxFramerate) >= 0)) throw new RangeError('max_framerate must be >= 0.0'); } }); const transceiver = origAddTransceiver.apply(this, arguments); if (shouldPerformCheck) { // Check if the init options were applied. If not we do this in an // asynchronous way and save the promise reference in a global object. // This is an ugly hack, but at the same time is way more robust than // checking the sender parameters before and after the createOffer // Also note that after the createoffer we are not 100% sure that // the params were asynchronously applied so we might miss the // opportunity to recreate offer. const { sender: sender } = transceiver; const params = sender.getParameters(); if (!('encodings' in params) || // Avoid being fooled by patched getParameters() below. params.encodings.length === 1 && Object.keys(params.encodings[0]).length === 0) { params.encodings = sendEncodings; sender.sendEncodings = sendEncodings; this.setParametersPromises.push(sender.setParameters(params).then(()=>{ delete sender.sendEncodings; }).catch(()=>{ delete sender.sendEncodings; })); } } return transceiver; }; } function $215e6581d7a09c61$export$66238223c298fbaa(window) { if (!(typeof window === 'object' && window.RTCRtpSender)) return; const origGetParameters = window.RTCRtpSender.prototype.getParameters; if (origGetParameters) window.RTCRtpSender.prototype.getParameters = function getParameters() { const params = origGetParameters.apply(this, arguments); if (!('encodings' in params)) params.encodings = [].concat(this.sendEncodings || [ {} ]); return params; }; } function $215e6581d7a09c61$export$51beccf0e777b843(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 if (!(typeof window === 'object' && window.RTCPeerConnection)) return; const origCreateOffer = window.RTCPeerConnection.prototype.createOffer; window.RTCPeerConnection.prototype.createOffer = function createOffer() { if (this.setParametersPromises && this.setParametersPromises.length) return Promise.all(this.setParametersPromises).then(()=>{ return origCreateOffer.apply(this, arguments); }).finally(()=>{ this.setParametersPromises = []; }); return origCreateOffer.apply(this, arguments); }; } function $215e6581d7a09c61$export$df0b46e7cef08150(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 if (!(typeof window === 'object' && window.RTCPeerConnection)) return; const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer; window.RTCPeerConnection.prototype.createAnswer = function createAnswer() { if (this.setParametersPromises && this.setParametersPromises.length) return Promise.all(this.setParametersPromises).then(()=>{ return origCreateAnswer.apply(this, arguments); }).finally(()=>{ this.setParametersPromises = []; }); return origCreateAnswer.apply(this, arguments); }; } var $c1f641ee5a6f6c8f$exports = {}; $parcel$export($c1f641ee5a6f6c8f$exports, "shimLocalStreamsAPI", () => $c1f641ee5a6f6c8f$export$8df41282f4fdcea2); $parcel$export($c1f641ee5a6f6c8f$exports, "shimRemoteStreamsAPI", () => $c1f641ee5a6f6c8f$export$762aa4cbb4f2f857); $parcel$export($c1f641ee5a6f6c8f$exports, "shimCallbacksAPI", () => $c1f641ee5a6f6c8f$export$da31df245debdd3); $parcel$export($c1f641ee5a6f6c8f$exports, "shimGetUserMedia", () => $c1f641ee5a6f6c8f$export$1ed4910f4d37dc5e); $parcel$export($c1f641ee5a6f6c8f$exports, "shimConstraints", () => $c1f641ee5a6f6c8f$export$494a01ac68ba81ac); $parcel$export($c1f641ee5a6f6c8f$exports, "shimRTCIceServerUrls", () => $c1f641ee5a6f6c8f$export$671a8b47b41b6f41); $parcel$export($c1f641ee5a6f6c8f$exports, "shimTrackEventTransceiver", () => $c1f641ee5a6f6c8f$export$85d53da088cb1b14); $parcel$export($c1f641ee5a6f6c8f$exports, "shimCreateOfferLegacy", () => $c1f641ee5a6f6c8f$export$d444266503fdd2d4); $parcel$export($c1f641ee5a6f6c8f$exports, "shimAudioContext", () => $c1f641ee5a6f6c8f$export$857cd739a7b795d2); /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ 'use strict'; function $c1f641ee5a6f6c8f$export$8df41282f4fdcea2(window) { if (typeof window !== 'object' || !window.RTCPeerConnection) return; if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() { if (!this._localStreams) this._localStreams = []; return this._localStreams; }; if (!('addStream' in window.RTCPeerConnection.prototype)) { const _addTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { if (!this._localStreams) this._localStreams = []; if (!this._localStreams.includes(stream)) this._localStreams.push(stream); // Try to emulate Chrome's behaviour of adding in audio-video order. // Safari orders by track id. stream.getAudioTracks().forEach((track)=>_addTrack.call(this, track, stream)); stream.getVideoTracks().forEach((track)=>_addTrack.call(this, track, stream)); }; window.RTCPeerConnection.prototype.addTrack = function addTrack(track, ...streams) { if (streams) streams.forEach((stream)=>{ if (!this._localStreams) this._localStreams = [ stream ]; else if (!this._localStreams.includes(stream)) this._localStreams.push(stream); }); return _addTrack.apply(this, arguments); }; } if (!('removeStream' in window.RTCPeerConnection.prototype)) window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { if (!this._localStreams) this._localStreams = []; const index = this._localStreams.indexOf(stream); if (index === -1) return; this._localStreams.splice(index, 1); const tracks = stream.getTracks(); this.getSenders().forEach((sender)=>{ if (tracks.includes(sender.track)) this.removeTrack(sender); }); }; } function $c1f641ee5a6f6c8f$export$762aa4cbb4f2f857(window) { if (typeof window !== 'object' || !window.RTCPeerConnection) return; if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) window.RTCPeerConnection.prototype.getRemoteStreams = function getRemoteStreams() { return this._remoteStreams ? this._remoteStreams : []; }; if (!('onaddstream' in window.RTCPeerConnection.prototype)) { Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', { get () { return this._onaddstream; }, set (f) { if (this._onaddstream) { this.removeEventListener('addstream', this._onaddstream); this.removeEventListener('track', this._onaddstreampoly); } this.addEventListener('addstream', this._onaddstream = f); this.addEventListener('track', this._onaddstreampoly = (e)=>{ e.streams.forEach((stream)=>{ if (!this._remoteStreams) this._remoteStreams = []; if (this._remoteStreams.includes(stream)) return; this._remoteStreams.push(stream); const event = new Event('addstream'); event.stream = stream; this.dispatchEvent(event); }); }); } }); const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() { const pc = this; if (!this._onaddstreampoly) this.addEventListener('track', this._onaddstreampoly = function(e) { e.streams.forEach((stream)=>{ if (!pc._remoteStreams) pc._remoteStreams = []; if (pc._remoteStreams.indexOf(stream) >= 0) return; pc._remoteStreams.push(stream); const event = new Event('addstream'); event.stream = stream; pc.dispatchEvent(event); }); }); return origSetRemoteDescription.apply(pc, arguments); }; } } function $c1f641ee5a6f6c8f$export$da31df245debdd3(window) { if (typeof window !== 'object' || !window.RTCPeerConnection) return; const prototype = window.RTCPeerConnection.prototype; const origCreateOffer = prototype.createOffer; const origCreateAnswer = prototype.createAnswer; const setLocalDescription = prototype.setLocalDescription; const setRemoteDescription = prototype.setRemoteDescription; const addIceCandidate = prototype.addIceCandidate; prototype.createOffer = function createOffer(successCallback, failureCallback) { const options = arguments.length >= 2 ? arguments[2] : arguments[0]; const promise = origCreateOffer.apply(this, [ options ]); if (!failureCallback) return promise; promise.then(successCallback, failureCallback); return Promise.resolve(); }; prototype.createAnswer = function createAnswer(successCallback, failureCallback) { const options = arguments.length >= 2 ? arguments[2] : arguments[0]; const promise = origCreateAnswer.apply(this, [ options ]); if (!failureCallback) return promise; promise.then(successCallback, failureCallback); return Promise.resolve(); }; let withCallback = function(description, successCallback, failureCallback) { const promise = setLocalDescription.apply(this, [ description ]); if (!failureCallback) return promise; promise.then(successCallback, failureCallback); return Promise.resolve(); }; prototype.setLocalDescription = withCallback; withCallback = function(description, successCallback, failureCallback) { const promise = setRemoteDescription.apply(this, [ description ]); if (!failureCallback) return promise; promise.then(successCallback, failureCallback); return Promise.resolve(); }; prototype.setRemoteDescription = withCallback; withCallback = function(candidate, successCallback, failureCallback) { const promise = addIceCandidate.apply(this, [ candidate ]); if (!failureCallback) return promise; promise.then(successCallback, failureCallback); return Promise.resolve(); }; prototype.addIceCandidate = withCallback; } function $c1f641ee5a6f6c8f$export$1ed4910f4d37dc5e(window) { const navigator = window && window.navigator; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { // shim not needed in Safari 12.1 const mediaDevices = navigator.mediaDevices; const _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices); navigator.mediaDevices.getUserMedia = (constraints)=>{ return _getUserMedia($c1f641ee5a6f6c8f$export$494a01ac68ba81ac(constraints)); }; } if (!navigator.getUserMedia && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) navigator.getUserMedia = (function getUserMedia(constraints, cb, errcb) { navigator.mediaDevices.getUserMedia(constraints).then(cb, errcb); }).bind(navigator); } function $c1f641ee5a6f6c8f$export$494a01ac68ba81ac(constraints) { if (constraints && constraints.video !== undefined) return Object.assign({}, constraints, { video: $9fea4db837311579$export$15384eac40dc88c8(constraints.video) }); return constraints; } function $c1f641ee5a6f6c8f$export$671a8b47b41b6f41(window) { if (!window.RTCPeerConnection) return; // migrate from non-spec RTCIceServer.url to RTCIceServer.urls const OrigPeerConnection = window.RTCPeerConnection; window.RTCPeerConnection = function RTCPeerConnection(pcConfig, pcConstraints) { if (pcConfig && pcConfig.iceServers) { const newIceServers = []; for(let i = 0; i < pcConfig.iceServers.length; i++){ let server = pcConfig.iceServers[i]; if (server.urls === undefined && server.url) { $9fea4db837311579$export$cdd73fc4100a6ef4('RTCIceServer.url', 'RTCIceServer.urls'); server = JSON.parse(JSON.stringify(server)); server.urls = server.url; delete server.url; newIceServers.push(server); } else newIceServers.push(pcConfig.iceServers[i]); } pcConfig.iceServers = newIceServers; } return new OrigPeerConnection(pcConfig, pcConstraints); }; window.RTCPeerConnection.prototype = OrigPeerConnection.prototype; // wrap static methods. Currently just generateCertificate. if ('generateCertificate' in OrigPeerConnection) Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { get () { return OrigPeerConnection.generateCertificate; } }); } function $c1f641ee5a6f6c8f$export$85d53da088cb1b14(window) { // Add event.transceiver member over deprecated event.receiver if (typeof window === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { get () { return { receiver: this.receiver }; } }); } function $c1f641ee5a6f6c8f$export$d444266503fdd2d4(window) { const origCreateOffer = window.RTCPeerConnection.prototype.createOffer; window.RTCPeerConnection.prototype.createOffer = function createOffer(offerOptions) { if (offerOptions) { if (typeof offerOptions.offerToReceiveAudio !== 'undefined') // support bit values offerOptions.offerToReceiveAudio = !!offerOptions.offerToReceiveAudio; const audioTransceiver = this.getTransceivers().find((transceiver)=>transceiver.receiver.track.kind === 'audio'); if (offerOptions.offerToReceiveAudio === false && audioTransceiver) { if (audioTransceiver.direction === 'sendrecv') { if (audioTransceiver.setDirection) audioTransceiver.setDirection('sendonly'); else audioTransceiver.direction = 'sendonly'; } else if (audioTransceiver.direction === 'recvonly') { if (audioTransceiver.setDirection) audioTransceiver.setDirection('inactive'); else audioTransceiver.direction = 'inactive'; } } else if (offerOptions.offerToReceiveAudio === true && !audioTransceiver) this.addTransceiver('audio', { direction: 'recvonly' }); if (typeof offerOptions.offerToReceiveVideo !== 'undefined') // support bit values offerOptions.offerToReceiveVideo = !!offerOptions.offerToReceiveVideo; const videoTransceiver = this.getTransceivers().find((transceiver)=>transceiver.receiver.track.kind === 'video'); if (offerOptions.offerToReceiveVideo === false && videoTransceiver) { if (videoTransceiver.direction === 'sendrecv') { if (videoTransceiver.setDirection) videoTransceiver.setDirection('sendonly'); else videoTransceiver.direction = 'sendonly'; } else if (videoTransceiver.direction === 'recvonly') { if (videoTransceiver.setDirection) videoTransceiver.setDirection('inactive'); else videoTransceiver.direction = 'inactive'; } } else if (offerOptions.offerToReceiveVideo === true && !videoTransceiver) this.addTransceiver('video', { direction: 'recvonly' }); } return origCreateOffer.apply(this, arguments); }; } function $c1f641ee5a6f6c8f$export$857cd739a7b795d2(window) { if (typeof window !== 'object' || window.AudioContext) return; window.AudioContext = window.webkitAudioContext; } var $5151b78094cea2ba$exports = {}; $parcel$export($5151b78094cea2ba$exports, "shimRTCIceCandidate", () => $5151b78094cea2ba$export$cf133661e444ccfe); $parcel$export($5151b78094cea2ba$exports, "shimRTCIceCandidateRelayProtocol", () => $5151b78094cea2ba$export$fdafb8d8280e29b5); $parcel$export($5151b78094cea2ba$exports, "shimMaxMessageSize", () => $5151b78094cea2ba$export$a99147c78a56edc4); $parcel$export($5151b78094cea2ba$exports, "shimSendThrowTypeError", () => $5151b78094cea2ba$export$d461c8d5c5db5da7); $parcel$export($5151b78094cea2ba$exports, "shimConnectionState", () => $5151b78094cea2ba$export$63bb816cc75460); $parcel$export($5151b78094cea2ba$exports, "removeExtmapAllowMixed", () => $5151b78094cea2ba$export$a57d114344295149); $parcel$export($5151b78094cea2ba$exports, "shimAddIceCandidateNullOrEmpty", () => $5151b78094cea2ba$export$51d5e40b48c771c7); $parcel$export($5151b78094cea2ba$exports, "shimParameterlessSetLocalDescription", () => $5151b78094cea2ba$export$7170d04e59f9d553); /* * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. */ /* eslint-env node */ var $5d0e6002f6ec24ec$exports = {}; /* eslint-env node */ 'use strict'; // SDP helpers. const $5d0e6002f6ec24ec$var$SDPUtils = {}; // Generate an alphanumeric identifier for cname or mids. // TODO: use UUIDs instead? https://gist.github.com/jed/982883 $5d0e6002f6ec24ec$var$SDPUtils.generateIdentifier = function() { return Math.random().toString(36).substring(2, 12); }; // The RTCP CNAME used by all peerconnections from the same JS. $5d0e6002f6ec24ec$var$SDPUtils.localCName = $5d0e6002f6ec24ec$var$SDPUtils.generateIdentifier(); // Splits SDP into lines, dealing with both CRLF and LF. $5d0e6002f6ec24ec$var$SDPUtils.splitLines = function(blob) { return blob.trim().split('\n').map((line)=>line.trim()); }; // Splits SDP into sessionpart and mediasections. Ensures CRLF. $5d0e6002f6ec24ec$var$SDPUtils.splitSections = function(blob) { const parts = blob.split('\nm='); return parts.map((part, index)=>(index > 0 ? 'm=' + part : part).trim() + '\r\n'); }; // Returns the session description. $5d0e6002f6ec24ec$var$SDPUtils.getDescription = function(blob) { const sections = $5d0e6002f6ec24ec$var$SDPUtils.splitSections(blob); return sections && sections[0]; }; // Returns the individual media sections. $5d0e6002f6ec24ec$var$SDPUtils.getMediaSections = function(blob) { const sections = $5d0e6002f6ec24ec$var$SDPUtils.splitSections(blob); sections.shift(); return sections; }; // Returns lines that start with a certain prefix. $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix = function(blob, prefix) { return $5d0e6002f6ec24ec$var$SDPUtils.splitLines(blob).filter((line)=>line.indexOf(prefix) === 0); }; // Parses an ICE candidate line. Sample input: // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 // rport 55996" // Input can be prefixed with a=. $5d0e6002f6ec24ec$var$SDPUtils.parseCandidate = function(line) { let parts; // Parse both variants. if (line.indexOf('a=candidate:') === 0) parts = line.substring(12).split(' '); else parts = line.substring(10).split(' '); const candidate = { foundation: parts[0], component: { 1: 'rtp', 2: 'rtcp' }[parts[1]] || parts[1], protocol: parts[2].toLowerCase(), priority: parseInt(parts[3], 10), ip: parts[4], address: parts[4], port: parseInt(parts[5], 10), // skip parts[6] == 'typ' type: parts[7] }; for(let i = 8; i < parts.length; i += 2)switch(parts[i]){ case 'raddr': candidate.relatedAddress = parts[i + 1]; break; case 'rport': candidate.relatedPort = parseInt(parts[i + 1], 10); break; case 'tcptype': candidate.tcpType = parts[i + 1]; break; case 'ufrag': candidate.ufrag = parts[i + 1]; // for backward compatibility. candidate.usernameFragment = parts[i + 1]; break; default: if (candidate[parts[i]] === undefined) candidate[parts[i]] = parts[i + 1]; break; } return candidate; }; // Translates a candidate object into SDP candidate attribute. // This does not include the a= prefix! $5d0e6002f6ec24ec$var$SDPUtils.writeCandidate = function(candidate) { const sdp = []; sdp.push(candidate.foundation); const component = candidate.component; if (component === 'rtp') sdp.push(1); else if (component === 'rtcp') sdp.push(2); else sdp.push(component); sdp.push(candidate.protocol.toUpperCase()); sdp.push(candidate.priority); sdp.push(candidate.address || candidate.ip); sdp.push(candidate.port); const type = candidate.type; sdp.push('typ'); sdp.push(type); if (type !== 'host' && candidate.relatedAddress && candidate.relatedPort) { sdp.push('raddr'); sdp.push(candidate.relatedAddress); sdp.push('rport'); sdp.push(candidate.relatedPort); } if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') { sdp.push('tcptype'); sdp.push(candidate.tcpType); } if (candidate.usernameFragment || candidate.ufrag) { sdp.push('ufrag'); sdp.push(candidate.usernameFragment || candidate.ufrag); } return 'candidate:' + sdp.join(' '); }; // Parses an ice-options line, returns an array of option tags. // Sample input: // a=ice-options:foo bar $5d0e6002f6ec24ec$var$SDPUtils.parseIceOptions = function(line) { return line.substring(14).split(' '); }; // Parses a rtpmap line, returns RTCRtpCoddecParameters. Sample input: // a=rtpmap:111 opus/48000/2 $5d0e6002f6ec24ec$var$SDPUtils.parseRtpMap = function(line) { let parts = line.substring(9).split(' '); const parsed = { payloadType: parseInt(parts.shift(), 10) }; parts = parts[0].split('/'); parsed.name = parts[0]; parsed.clockRate = parseInt(parts[1], 10); // was: clockrate parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1; // legacy alias, got renamed back to channels in ORTC. parsed.numChannels = parsed.channels; return parsed; }; // Generates a rtpmap line from RTCRtpCodecCapability or // RTCRtpCodecParameters. $5d0e6002f6ec24ec$var$SDPUtils.writeRtpMap = function(codec) { let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) pt = codec.preferredPayloadType; const channels = codec.channels || codec.numChannels || 1; return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate + (channels !== 1 ? '/' + channels : '') + '\r\n'; }; // Parses a extmap line (headerextension from RFC 5285). Sample input: // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset // a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset $5d0e6002f6ec24ec$var$SDPUtils.parseExtmap = function(line) { const parts = line.substring(9).split(' '); return { id: parseInt(parts[0], 10), direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv', uri: parts[1], attributes: parts.slice(2).join(' ') }; }; // Generates an extmap line from RTCRtpHeaderExtensionParameters or // RTCRtpHeaderExtension. $5d0e6002f6ec24ec$var$SDPUtils.writeExtmap = function(headerExtension) { return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + (headerExtension.direction && headerExtension.direction !== 'sendrecv' ? '/' + headerExtension.direction : '') + ' ' + headerExtension.uri + (headerExtension.attributes ? ' ' + headerExtension.attributes : '') + '\r\n'; }; // Parses a fmtp line, returns dictionary. Sample input: // a=fmtp:96 vbr=on;cng=on // Also deals with vbr=on; cng=on $5d0e6002f6ec24ec$var$SDPUtils.parseFmtp = function(line) { const parsed = {}; let kv; const parts = line.substring(line.indexOf(' ') + 1).split(';'); for(let j = 0; j < parts.length; j++){ kv = parts[j].trim().split('='); parsed[kv[0].trim()] = kv[1]; } return parsed; }; // Generates a fmtp line from RTCRtpCodecCapability or RTCRtpCodecParameters. $5d0e6002f6ec24ec$var$SDPUtils.writeFmtp = function(codec) { let line = ''; let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) pt = codec.preferredPayloadType; if (codec.parameters && Object.keys(codec.parameters).length) { const params = []; Object.keys(codec.parameters).forEach((param)=>{ if (codec.parameters[param] !== undefined) params.push(param + '=' + codec.parameters[param]); else params.push(param); }); line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n'; } return line; }; // Parses a rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: // a=rtcp-fb:98 nack rpsi $5d0e6002f6ec24ec$var$SDPUtils.parseRtcpFb = function(line) { const parts = line.substring(line.indexOf(' ') + 1).split(' '); return { type: parts.shift(), parameter: parts.join(' ') }; }; // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. $5d0e6002f6ec24ec$var$SDPUtils.writeRtcpFb = function(codec) { let lines = ''; let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) pt = codec.preferredPayloadType; if (codec.rtcpFeedback && codec.rtcpFeedback.length) // FIXME: special handling for trr-int? codec.rtcpFeedback.forEach((fb)=>{ lines += 'a=rtcp-fb:' + pt + ' ' + fb.type + (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') + '\r\n'; }); return lines; }; // Parses a RFC 5576 ssrc media attribute. Sample input: // a=ssrc:3735928559 cname:something $5d0e6002f6ec24ec$var$SDPUtils.parseSsrcMedia = function(line) { const sp = line.indexOf(' '); const parts = { ssrc: parseInt(line.substring(7, sp), 10) }; const colon = line.indexOf(':', sp); if (colon > -1) { parts.attribute = line.substring(sp + 1, colon); parts.value = line.substring(colon + 1); } else parts.attribute = line.substring(sp + 1); return parts; }; // Parse a ssrc-group line (see RFC 5576). Sample input: // a=ssrc-group:semantics 12 34 $5d0e6002f6ec24ec$var$SDPUtils.parseSsrcGroup = function(line) { const parts = line.substring(13).split(' '); return { semantics: parts.shift(), ssrcs: parts.map((ssrc)=>parseInt(ssrc, 10)) }; }; // Extracts the MID (RFC 5888) from a media section. // Returns the MID or undefined if no mid line was found. $5d0e6002f6ec24ec$var$SDPUtils.getMid = function(mediaSection) { const mid = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; if (mid) return mid.substring(6); }; // Parses a fingerprint line for DTLS-SRTP. $5d0e6002f6ec24ec$var$SDPUtils.parseFingerprint = function(line) { const parts = line.substring(14).split(' '); return { algorithm: parts[0].toLowerCase(), value: parts[1].toUpperCase() }; }; // Extracts DTLS parameters from SDP media section or sessionpart. // FIXME: for consistency with other functions this should only // get the fingerprint line as input. See also getIceParameters. $5d0e6002f6ec24ec$var$SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) { const lines = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=fingerprint:'); // Note: a=setup line is ignored since we use the 'auto' role in Edge. return { role: 'auto', fingerprints: lines.map($5d0e6002f6ec24ec$var$SDPUtils.parseFingerprint) }; }; // Serializes DTLS parameters to SDP. $5d0e6002f6ec24ec$var$SDPUtils.writeDtlsParameters = function(params, setupType) { let sdp = 'a=setup:' + setupType + '\r\n'; params.fingerprints.forEach((fp)=>{ sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'; }); return sdp; }; // Parses a=crypto lines into // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members $5d0e6002f6ec24ec$var$SDPUtils.parseCryptoLine = function(line) { const parts = line.substring(9).split(' '); return { tag: parseInt(parts[0], 10), cryptoSuite: parts[1], keyParams: parts[2], sessionParams: parts.slice(3) }; }; $5d0e6002f6ec24ec$var$SDPUtils.writeCryptoLine = function(parameters) { return 'a=crypto:' + parameters.tag + ' ' + parameters.cryptoSuite + ' ' + (typeof parameters.keyParams === 'object' ? $5d0e6002f6ec24ec$var$SDPUtils.writeCryptoKeyParams(parameters.keyParams) : parameters.keyParams) + (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') + '\r\n'; }; // Parses the crypto key parameters into // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam* $5d0e6002f6ec24ec$var$SDPUtils.parseCryptoKeyParams = function(keyParams) { if (keyParams.indexOf('inline:') !== 0) return null; const parts = keyParams.substring(7).split('|'); return { keyMethod: 'inline', keySalt: parts[0], lifeTime: parts[1], mkiValue: parts[2] ? parts[2].split(':')[0] : undefined, mkiLength: parts[2] ? parts[2].split(':')[1] : undefined }; }; $5d0e6002f6ec24ec$var$SDPUtils.writeCryptoKeyParams = function(keyParams) { return keyParams.keyMethod + ':' + keyParams.keySalt + (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') + (keyParams.mkiValue && keyParams.mkiLength ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength : ''); }; // Extracts all SDES parameters. $5d0e6002f6ec24ec$var$SDPUtils.getCryptoParameters = function(mediaSection, sessionpart) { const lines = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=crypto:'); return lines.map($5d0e6002f6ec24ec$var$SDPUtils.parseCryptoLine); }; // Parses ICE information from SDP media section or sessionpart. // FIXME: for consistency with other functions this should only // get the ice-ufrag and ice-pwd lines as input. $5d0e6002f6ec24ec$var$SDPUtils.getIceParameters = function(mediaSection, sessionpart) { const ufrag = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-ufrag:')[0]; const pwd = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-pwd:')[0]; if (!(ufrag && pwd)) return null; return { usernameFragment: ufrag.substring(12), password: pwd.substring(10) }; }; // Serializes ICE parameters to SDP. $5d0e6002f6ec24ec$var$SDPUtils.writeIceParameters = function(params) { let sdp = 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + 'a=ice-pwd:' + params.password + '\r\n'; if (params.iceLite) sdp += 'a=ice-lite\r\n'; return sdp; }; // Parses the SDP media section and returns RTCRtpParameters. $5d0e6002f6ec24ec$var$SDPUtils.parseRtpParameters = function(mediaSection) { const description = { codecs: [], headerExtensions: [], fecMechanisms: [], rtcp: [] }; const lines = $5d0e6002f6ec24ec$var$SDPUtils.splitLines(mediaSection); const mline = lines[0].split(' '); description.profile = mline[2]; for(let i = 3; i < mline.length; i++){ const pt = mline[i]; const rtpmapline = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=rtpmap:' + pt + ' ')[0]; if (rtpmapline) { const codec = $5d0e6002f6ec24ec$var$SDPUtils.parseRtpMap(rtpmapline); const fmtps = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=fmtp:' + pt + ' '); // Only the first a=fmtp: is considered. codec.parameters = fmtps.length ? $5d0e6002f6ec24ec$var$SDPUtils.parseFmtp(fmtps[0]) : {}; codec.rtcpFeedback = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=rtcp-fb:' + pt + ' ').map($5d0e6002f6ec24ec$var$SDPUtils.parseRtcpFb); description.codecs.push(codec); // parse FEC mechanisms from rtpmap lines. switch(codec.name.toUpperCase()){ case 'RED': case 'ULPFEC': description.fecMechanisms.push(codec.name.toUpperCase()); break; default: break; } } } $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach((line)=>{ description.headerExtensions.push($5d0e6002f6ec24ec$var$SDPUtils.parseExtmap(line)); }); const wildcardRtcpFb = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=rtcp-fb:* ').map($5d0e6002f6ec24ec$var$SDPUtils.parseRtcpFb); description.codecs.forEach((codec)=>{ wildcardRtcpFb.forEach((fb)=>{ const duplicate = codec.rtcpFeedback.find((existingFeedback)=>{ return existingFeedback.type === fb.type && existingFeedback.parameter === fb.parameter; }); if (!duplicate) codec.rtcpFeedback.push(fb); }); }); // FIXME: parse rtcp. return description; }; // Generates parts of the SDP media section describing the capabilities / // parameters. $5d0e6002f6ec24ec$var$SDPUtils.writeRtpDescription = function(kind, caps) { let sdp = ''; // Build the mline. sdp += 'm=' + kind + ' '; sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs. sdp += ' ' + (caps.profile || 'UDP/TLS/RTP/SAVPF') + ' '; sdp += caps.codecs.map((codec)=>{ if (codec.preferredPayloadType !== undefined) return codec.preferredPayloadType; return codec.payloadType; }).join(' ') + '\r\n'; sdp += 'c=IN IP4 0.0.0.0\r\n'; sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'; // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. caps.codecs.forEach((codec)=>{ sdp += $5d0e6002f6ec24ec$var$SDPUtils.writeRtpMap(codec); sdp += $5d0e6002f6ec24ec$var$SDPUtils.writeFmtp(codec); sdp += $5d0e6002f6ec24ec$var$SDPUtils.writeRtcpFb(codec); }); let maxptime = 0; caps.codecs.forEach((codec)=>{ if (codec.maxptime > maxptime) maxptime = codec.maxptime; }); if (maxptime > 0) sdp += 'a=maxptime:' + maxptime + '\r\n'; if (caps.headerExtensions) caps.headerExtensions.forEach((extension)=>{ sdp += $5d0e6002f6ec24ec$var$SDPUtils.writeExtmap(extension); }); // FIXME: write fecMechanisms. return sdp; }; // Parses the SDP media section and returns an array of // RTCRtpEncodingParameters. $5d0e6002f6ec24ec$var$SDPUtils.parseRtpEncodingParameters = function(mediaSection) { const encodingParameters = []; const description = $5d0e6002f6ec24ec$var$SDPUtils.parseRtpParameters(mediaSection); const hasRed = description.fecMechanisms.indexOf('RED') !== -1; const hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; // filter a=ssrc:... cname:, ignore PlanB-msid const ssrcs = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map((line)=>$5d0e6002f6ec24ec$var$SDPUtils.parseSsrcMedia(line)).filter((parts)=>parts.attribute === 'cname'); const primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; let secondarySsrc; const flows = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID').map((line)=>{ const parts = line.substring(17).split(' '); return parts.map((part)=>parseInt(part, 10)); }); if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) secondarySsrc = flows[0][1]; description.codecs.forEach((codec)=>{ if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) { let encParam = { ssrc: primarySsrc, codecPayloadType: parseInt(codec.parameters.apt, 10) }; if (primarySsrc && secondarySsrc) encParam.rtx = { ssrc: secondarySsrc }; encodingParameters.push(encParam); if (hasRed) { encParam = JSON.parse(JSON.stringify(encParam)); encParam.fec = { ssrc: primarySsrc, mechanism: hasUlpfec ? 'red+ulpfec' : 'red' }; encodingParameters.push(encParam); } } }); if (encodingParameters.length === 0 && primarySsrc) encodingParameters.push({ ssrc: primarySsrc }); // we support both b=AS and b=TIAS but interpret AS as TIAS. let bandwidth = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'b='); if (bandwidth.length) { if (bandwidth[0].indexOf('b=TIAS:') === 0) bandwidth = parseInt(bandwidth[0].substring(7), 10); else if (bandwidth[0].indexOf('b=AS:') === 0) // use formula from JSEP to convert b=AS to TIAS value. bandwidth = parseInt(bandwidth[0].substring(5), 10) * 950 - 16000; else bandwidth = undefined; encodingParameters.forEach((params)=>{ params.maxBitrate = bandwidth; }); } return encodingParameters; }; // parses http://draft.ortc.org/#rtcrtcpparameters* $5d0e6002f6ec24ec$var$SDPUtils.parseRtcpParameters = function(mediaSection) { const rtcpParameters = {}; // Gets the first SSRC. Note that with RTX there might be multiple // SSRCs. const remoteSsrc = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map((line)=>$5d0e6002f6ec24ec$var$SDPUtils.parseSsrcMedia(line)).filter((obj)=>obj.attribute === 'cname')[0]; if (remoteSsrc) { rtcpParameters.cname = remoteSsrc.value; rtcpParameters.ssrc = remoteSsrc.ssrc; } // Edge uses the compound attribute instead of reducedSize // compound is !reducedSize const rsize = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); rtcpParameters.reducedSize = rsize.length > 0; rtcpParameters.compound = rsize.length === 0; // parses the rtcp-mux attrÑ–bute. // Note that Edge does not support unmuxed RTCP. const mux = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); rtcpParameters.mux = mux.length > 0; return rtcpParameters; }; $5d0e6002f6ec24ec$var$SDPUtils.writeRtcpParameters = function(rtcpParameters) { let sdp = ''; if (rtcpParameters.reducedSize) sdp += 'a=rtcp-rsize\r\n'; if (rtcpParameters.mux) sdp += 'a=rtcp-mux\r\n'; if (rtcpParameters.ssrc !== undefined && rtcpParameters.cname) sdp += 'a=ssrc:' + rtcpParameters.ssrc + ' cname:' + rtcpParameters.cname + '\r\n'; return sdp; }; // parses either a=msid: or a=ssrc:... msid lines and returns // the id of the MediaStream and MediaStreamTrack. $5d0e6002f6ec24ec$var$SDPUtils.parseMsid = function(mediaSection) { let parts; const spec = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=msid:'); if (spec.length === 1) { parts = spec[0].substring(7).split(' '); return { stream: parts[0], track: parts[1] }; } const planB = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map((line)=>$5d0e6002f6ec24ec$var$SDPUtils.parseSsrcMedia(line)).filter((msidParts)=>msidParts.attribute === 'msid'); if (planB.length > 0) { parts = planB[0].value.split(' '); return { stream: parts[0], track: parts[1] }; } }; // SCTP // parses draft-ietf-mmusic-sctp-sdp-26 first and falls back // to draft-ietf-mmusic-sctp-sdp-05 $5d0e6002f6ec24ec$var$SDPUtils.parseSctpDescription = function(mediaSection) { const mline = $5d0e6002f6ec24ec$var$SDPUtils.parseMLine(mediaSection); const maxSizeLine = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:'); let maxMessageSize; if (maxSizeLine.length > 0) maxMessageSize = parseInt(maxSizeLine[0].substring(19), 10); if (isNaN(maxMessageSize)) maxMessageSize = 65536; const sctpPort = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:'); if (sctpPort.length > 0) return { port: parseInt(sctpPort[0].substring(12), 10), protocol: mline.fmt, maxMessageSize: maxMessageSize }; const sctpMapLines = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:'); if (sctpMapLines.length > 0) { const parts = sctpMapLines[0].substring(10).split(' '); return { port: parseInt(parts[0], 10), protocol: parts[1], maxMessageSize: maxMessageSize }; } }; // SCTP // outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers // support by now receiving in this format, unless we originally parsed // as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line // protocol of DTLS/SCTP -- without UDP/ or TCP/) $5d0e6002f6ec24ec$var$SDPUtils.writeSctpDescription = function(media, sctp) { let output = []; if (media.protocol !== 'DTLS/SCTP') output = [ 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\r\n', 'c=IN IP4 0.0.0.0\r\n', 'a=sctp-port:' + sctp.port + '\r\n' ]; else output = [ 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\r\n', 'c=IN IP4 0.0.0.0\r\n', 'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\r\n' ]; if (sctp.maxMessageSize !== undefined) output.push('a=max-message-size:' + sctp.maxMessageSize + '\r\n'); return output.join(''); }; // Generate a session ID for SDP. // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1 // recommends using a cryptographically random +ve 64-bit value // but right now this should be acceptable and within the right range $5d0e6002f6ec24ec$var$SDPUtils.generateSessionId = function() { return Math.random().toString().substr(2, 22); }; // Write boiler plate for start of SDP // sessId argument is optional - if not supplied it will // be generated randomly // sessVersion is optional and defaults to 2 // sessUser is optional and defaults to 'thisisadapterortc' $5d0e6002f6ec24ec$var$SDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) { let sessionId; const version = sessVer !== undefined ? sessVer : 2; if (sessId) sessionId = sessId; else sessionId = $5d0e6002f6ec24ec$var$SDPUtils.generateSessionId(); const user = sessUser || 'thisisadapterortc'; // FIXME: sess-id should be an NTP timestamp. return "v=0\r\no=" + user + ' ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' + 's=-\r\n' + 't=0 0\r\n'; }; // Gets the direction from the mediaSection or the sessionpart. $5d0e6002f6ec24ec$var$SDPUtils.getDirection = function(mediaSection, sessionpart) { // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. const lines = $5d0e6002f6ec24ec$var$SDPUtils.splitLines(mediaSection); for(let i = 0; i < lines.length; i++)switch(lines[i]){ case 'a=sendrecv': case 'a=sendonly': case 'a=recvonly': case 'a=inactive': return lines[i].substring(2); default: } if (sessionpart) return $5d0e6002f6ec24ec$var$SDPUtils.getDirection(sessionpart); return 'sendrecv'; }; $5d0e6002f6ec24ec$var$SDPUtils.getKind = function(mediaSection) { const lines = $5d0e6002f6ec24ec$var$SDPUtils.splitLines(mediaSection); const mline = lines[0].split(' '); return mline[0].substring(2); }; $5d0e6002f6ec24ec$var$SDPUtils.isRejected = function(mediaSection) { return mediaSection.split(' ', 2)[1] === '0'; }; $5d0e6002f6ec24ec$var$SDPUtils.parseMLine = function(mediaSection) { const lines = $5d0e6002f6ec24ec$var$SDPUtils.splitLines(mediaSection); const parts = lines[0].substring(2).split(' '); return { kind: parts[0], port: parseInt(parts[1], 10), protocol: parts[2], fmt: parts.slice(3).join(' ') }; }; $5d0e6002f6ec24ec$var$SDPUtils.parseOLine = function(mediaSection) { const line = $5d0e6002f6ec24ec$var$SDPUtils.matchPrefix(mediaSection, 'o=')[0]; const parts = line.substring(2).split(' '); return { username: parts[0], sessionId: parts[1], sessionVersion: parseInt(parts[2], 10), netType: parts[3], addressType: parts[4], address: parts[5] }; }; // a very naive interpretation of a valid SDP. $5d0e6002f6ec24ec$var$SDPUtils.isValidSDP = function(blob) { if (typeof blob !== 'string' || blob.length === 0) return false; const lines = $5d0e6002f6ec24ec$var$SDPUtils.splitLines(blob); for(let i = 0; i < lines.length; i++){ if (lines[i].length < 2 || lines[i].charAt(1) !== '=') return false; // TODO: check the modifier a bit more. } return true; }; $5d0e6002f6ec24ec$exports = $5d0e6002f6ec24ec$var$SDPUtils; 'use strict'; function $5151b78094cea2ba$export$cf133661e444ccfe(window) { // foundation is arbitrarily chosen as an indicator for full support for // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface if (!window.RTCIceCandidate || window.RTCIceCandidate && 'foundation' in window.RTCIceCandidate.prototype) return; const NativeRTCIceCandidate = window.RTCIceCandidate; window.RTCIceCandidate = function RTCIceCandidate(args) { // Remove the a= which shouldn't be part of the candidate string. if (typeof args === 'object' && args.candidate && args.candidate.indexOf('a=') === 0) { args = JSON.parse(JSON.stringify(args)); args.candidate = args.candidate.substring(2); } if (args.candidate && args.candidate.length) { // Augment the native candidate with the parsed fields. const nativeCandidate = new NativeRTCIceCandidate(args); const parsedCandidate = (0, (/*@__PURE__*/$parcel$interopDefault($5d0e6002f6ec24ec$exports))).parseCandidate(args.candidate); for(const key in parsedCandidate)if (!(key in nativeCandidate)) Object.defineProperty(nativeCandidate, key, { value: parsedCandidate[key] }); // Override serializer to not serialize the extra attributes. nativeCandidate.toJSON = function toJSON() { return { candidate: nativeCandidate.candidate, sdpMid: nativeCandidate.sdpMid, sdpMLineIndex: nativeCandidate.sdpMLineIndex, usernameFragment: nativeCandidate.usernameFragment }; }; return nativeCandidate; } return new NativeRTCIceCandidate(args); }; window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype; // Hook up the augmented candidate in onicecandidate and // addEventListener('icecandidate', ...) $9fea4db837311579$export$1f48841962b828b1(window, 'icecandidate', (e)=>{ if (e.candidate) Object.defineProperty(e, 'candidate', { value: new window.RTCIceCandidate(e.candidate), writable: 'false' }); return e; }); } function $5151b78094cea2ba$export$fdafb8d8280e29b5(window) { if (!window.RTCIceCandidate || window.RTCIceCandidate && 'relayProtocol' in window.RTCIceCandidate.prototype) return; // Hook up the augmented candidate in onicecandidate and // addEventListener('icecandidate', ...) $9fea4db837311579$export$1f48841962b828b1(window, 'icecandidate', (e)=>{ if (e.candidate) { const parsedCandidate = (0, (/*@__PURE__*/$parcel$interopDefault($5d0e6002f6ec24ec$exports))).parseCandidate(e.candidate.candidate); if (parsedCandidate.type === 'relay') // This is a libwebrtc-specific mapping of local type preference // to relayProtocol. e.candidate.relayProtocol = ({ 0: 'tls', 1: 'tcp', 2: 'udp' })[parsedCandidate.priority >> 24]; } return e; }); } function $5151b78094cea2ba$export$a99147c78a56edc4(window, browserDetails) { if (!window.RTCPeerConnection) return; if (!('sctp' in window.RTCPeerConnection.prototype)) Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', { get () { return typeof this._sctp === 'undefined' ? null : this._sctp; } }); const sctpInDescription = function(description) { if (!description || !description.sdp) return false; const sections = (0, (/*@__PURE__*/$parcel$interopDefault($5d0e6002f6ec24ec$exports))).splitSections(description.sdp); sections.shift(); return sections.some((mediaSection)=>{ const mLine = (0, (/*@__PURE__*/$parcel$interopDefault($5d0e6002f6ec24ec$exports))).parseMLine(mediaSection); return mLine && mLine.kind === 'application' && mLine.protocol.indexOf('SCTP') !== -1; }); }; const getRemoteFirefoxVersion = function(description) { // TODO: Is there a better solution for detecting Firefox? const match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/); if (match === null || match.length < 2) return -1; const version = parseInt(match[1], 10); // Test for NaN (yes, this is ugly) return version !== version ? -1 : version; }; const getCanSendMaxMessageSize = function(remoteIsFirefox) { // Every implementation we know can send at least 64 KiB. // Note: Although Chrome is technically able to send up to 256 KiB, the // data does not reach the other peer reliably. // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419 let canSendMaxMessageSize = 65536; if (browserDetails.browser === 'firefox') { if (browserDetails.version < 57) { if (remoteIsFirefox === -1) // FF < 57 will send in 16 KiB chunks using the deprecated PPID // fragmentation. canSendMaxMessageSize = 16384; else // However, other FF (and RAWRTC) can reassemble PPID-fragmented // messages. Thus, supporting ~2 GiB when sending. canSendMaxMessageSize = 2147483637; } else if (browserDetails.version < 60) // Currently, all FF >= 57 will reset the remote maximum message size // to the default value when a data channel is created at a later // stage. :( // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 canSendMaxMessageSize = browserDetails.version === 57 ? 65535 : 65536; else // FF >= 60 supports sending ~2 GiB canSendMaxMessageSize = 2147483637; } return canSendMaxMessageSize; }; const getMaxMessageSize = function(description, remoteIsFirefox) { // Note: 65536 bytes is the default value from the SDP spec. Also, // every implementation we know supports receiving 65536 bytes. let maxMessageSize = 65536; // FF 57 has a slightly incorrect default remote max message size, so // we need to adjust it here to avoid a failure when sending. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697 if (browserDetails.browser === 'firefox' && browserDetails.version === 57) maxMessageSize = 65535; const match = (0, (/*@__PURE__*/$parcel$interopDefault($5d0e6002f6ec24ec$exports))).matchPrefix(description.sdp, 'a=max-message-size:'); if (match.length > 0) maxMessageSize = parseInt(match[0].substring(19), 10); else if (browserDetails.browser === 'firefox' && remoteIsFirefox !== -1) // If the maximum message size is not present in the remote SDP and // both local and remote are Firefox, the remote peer can receive // ~2 GiB. maxMessageSize = 2147483637; return maxMessageSize; }; const origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() { this._sctp = null; // Chrome decided to not expose .sctp in plan-b mode. // As usual, adapter.js has to do an 'ugly worakaround' // to cover up the mess. if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) { const { sdpSemantics: sdpSemantics } = this.getConfiguration(); if (sdpSemantics === 'plan-b') Object.defineProperty(this, 'sctp', { get () { return typeof this._sctp === 'undefined' ? null : this._sctp; }, enumerable: true, configurable: true }); } if (sctpInDescription(arguments[0])) { // Check if the remote is FF. const isFirefox = getRemoteFirefoxVersion(arguments[0]); // Get the maximum message size the local peer is capable of sending const canSendMMS = getCanSendMaxMessageSize(isFirefox); // Get the maximum message size of the remote peer. const remoteMMS = getMaxMessageSize(arguments[0], isFirefox); // Determine final maximum message size let maxMessageSize; if (canSendMMS === 0 && remoteMMS === 0) maxMessageSize = Number.POSITIVE_INFINITY; else if (canSendMMS === 0 || remoteMMS === 0) maxMessageSize = Math.max(canSendMMS, remoteMMS); else maxMessageSize = Math.min(canSendMMS, remoteMMS); // Create a dummy RTCSctpTransport object and the 'maxMessageSize' // attribute. const sctp = {}; Object.defineProperty(sctp, 'maxMessageSize', { get () { return maxMessageSize; } }); this._sctp = sctp; } return origSetRemoteDescription.apply(this, arguments); }; } function $5151b78094cea2ba$export$d461c8d5c5db5da7(window) { if (!(window.RTCPeerConnection && 'createDataChannel' in window.RTCPeerConnection.prototype)) return; // Note: Although Firefox >= 57 has a native implementation, the maximum // message size can be reset for all data channels at a later stage. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 function wrapDcSend(dc, pc) { const origDataChannelSend = dc.send; dc.send = function send() { const data = arguments[0]; const length = data.length || data.size || data.byteLength; if (dc.readyState === 'open' && pc.sctp && length > pc.sctp.maxMessageSize) throw new TypeError('Message too large (can send a maximum of ' + pc.sctp.maxMessageSize + ' bytes)'); return origDataChannelSend.apply(dc, arguments); }; } const origCreateDataChannel = window.RTCPeerConnection.prototype.createDataChannel; window.RTCPeerConnection.prototype.createDataChannel = function createDataChannel() { const dataChannel = origCreateDataChannel.apply(this, arguments); wrapDcSend(dataChannel, this); return dataChannel; }; $9fea4db837311579$export$1f48841962b828b1(window, 'datachannel', (e)=>{ wrapDcSend(e.channel, e.target); return e; }); } function $5151b78094cea2ba$export$63bb816cc75460(window) { if (!window.RTCPeerConnection || 'connectionState' in window.RTCPeerConnection.prototype) return; const proto = window.RTCPeerConnection.prototype; Object.defineProperty(proto, 'connectionState', { get () { return ({ completed: 'connected', checking: 'connecting' })[this.iceConnectionState] || this.iceConnectionState; }, enumerable: true, configurable: true }); Object.defineProperty(proto, 'onconnectionstatechange', { get () { return this._onconnectionstatechange || null; }, set (cb) { if (this._onconnectionstatechange) { this.removeEventListener('connectionstatechange', this._onconnectionstatechange); delete this._onconnectionstatechange; } if (cb) this.addEventListener('connectionstatechange', this._onconnectionstatechange = cb); }, enumerable: true, configurable: true }); [ 'setLocalDescription', 'setRemoteDescription' ].forEach((method)=>{ const origMethod = proto[method]; proto[method] = function() { if (!this._connectionstatechangepoly) { this._connectionstatechangepoly = (e)=>{ const pc = e.target; if (pc._lastConnectionState !== pc.connectionState) { pc._lastConnectionState = pc.connectionState; const newEvent = new Event('connectionstatechange', e); pc.dispatchEvent(newEvent); } return e; }; this.addEventListener('iceconnectionstatechange', this._connectionstatechangepoly); } return origMethod.apply(this, arguments); }; }); } function $5151b78094cea2ba$export$a57d114344295149(window, browserDetails) { /* remove a=extmap-allow-mixed for webrtc.org < M71 */ if (!window.RTCPeerConnection) return; if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) return; if (browserDetails.browser === 'safari' && browserDetails.version >= 605) return; const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription(desc) { if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) { const sdp = desc.sdp.split('\n').filter((line)=>{ return line.trim() !== 'a=extmap-allow-mixed'; }).join('\n'); // Safari enforces read-only-ness of RTCSessionDescription fields. if (window.RTCSessionDescription && desc instanceof window.RTCSessionDescription) arguments[0] = new window.RTCSessionDescription({ type: desc.type, sdp: sdp }); else desc.sdp = sdp; } return nativeSRD.apply(this, arguments); }; } function $5151b78094cea2ba$export$51d5e40b48c771c7(window, browserDetails) { // Support for addIceCandidate(null or undefined) // as well as addIceCandidate({candidate: "", ...}) // https://bugs.chromium.org/p/chromium/issues/detail?id=978582 // Note: must be called before other polyfills which change the signature. if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) return; const nativeAddIceCandidate = window.RTCPeerConnection.prototype.addIceCandidate; if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) return; window.RTCPeerConnection.prototype.addIceCandidate = function addIceCandidate() { if (!arguments[0]) { if (arguments[1]) arguments[1].apply(null); return Promise.resolve(); } // Firefox 68+ emits and processes {candidate: "", ...}, ignore // in older versions. // Native support for ignoring exists for Chrome M77+. // Safari ignores as well, exact version unknown but works in the same // version that also ignores addIceCandidate(null). if ((browserDetails.browser === 'chrome' && browserDetails.version < 78 || browserDetails.browser === 'firefox' && browserDetails.version < 68 || browserDetails.browser === 'safari') && arguments[0] && arguments[0].candidate === '') return Promise.resolve(); return nativeAddIceCandidate.apply(this, arguments); }; } function $5151b78094cea2ba$export$7170d04e59f9d553(window, browserDetails) { if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) return; const nativeSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription; if (!nativeSetLocalDescription || nativeSetLocalDescription.length === 0) return; window.RTCPeerConnection.prototype.setLocalDescription = function setLocalDescription() { let desc = arguments[0] || {}; if (typeof desc !== 'object' || desc.type && desc.sdp) return nativeSetLocalDescription.apply(this, arguments); // The remaining steps should technically happen when SLD comes off the // RTCPeerConnection's operations chain (not ahead of going on it), but // this is too difficult to shim. Instead, this shim only covers the // common case where the operations chain is empty. This is imperfect, but // should cover many cases. Rationale: Even if we can't reduce the glare // window to zero on imperfect implementations, there's value in tapping // into the perfect negotiation pattern that several browsers support. desc = { type: desc.type, sdp: desc.sdp }; if (!desc.type) switch(this.signalingState){ case 'stable': case 'have-local-offer': case 'have-remote-pranswer': desc.type = 'offer'; break; default: desc.type = 'answer'; break; } if (desc.sdp || desc.type !== 'offer' && desc.type !== 'answer') return nativeSetLocalDescription.apply(this, [ desc ]); const func = desc.type === 'offer' ? this.createOffer : this.createAnswer; return func.apply(this).then((d)=>nativeSetLocalDescription.apply(this, [ d ])); }; } function $b657217e95eb14d8$export$e77bf46c04ac7d12({ window: window } = {}, options = { shimChrome: true, shimFirefox: true, shimSafari: true }) { // Utils. const logging = $9fea4db837311579$export$bef1f36f5486a6a3; const browserDetails = $9fea4db837311579$export$2d31490a0c05f094(window); const adapter = { browserDetails: browserDetails, commonShim: $5151b78094cea2ba$exports, extractVersion: $9fea4db837311579$export$e3c02be309be1f23, disableLog: $9fea4db837311579$export$afbfee8cc06fd3e4, disableWarnings: $9fea4db837311579$export$51516be4b019e41e, sdp: // Expose sdp as a convenience. For production apps include directly. $5d0e6002f6ec24ec$exports }; // Shim browser if found. switch(browserDetails.browser){ case 'chrome': if (!$fb04e59b477f17ce$exports || !$fb04e59b477f17ce$exports.shimPeerConnection || !options.shimChrome) { logging('Chrome shim is not included in this adapter release.'); return adapter; } if (browserDetails.version === null) { logging('Chrome shim can not determine version, not shimming.'); return adapter; } logging('adapter.js shimming chrome.'); // Export to the adapter global object visible in the browser. adapter.browserShim = $fb04e59b477f17ce$exports; // Must be called before shimPeerConnection. $5151b78094cea2ba$export$51d5e40b48c771c7(window, browserDetails); $5151b78094cea2ba$export$7170d04e59f9d553(window, browserDetails); $fb04e59b477f17ce$exports.shimGetUserMedia(window, browserDetails); $fb04e59b477f17ce$exports.shimMediaStream(window, browserDetails); $fb04e59b477f17ce$exports.shimPeerConnection(window, browserDetails); $fb04e59b477f17ce$exports.shimOnTrack(window, browserDetails); $fb04e59b477f17ce$exports.shimAddTrackRemoveTrack(window, browserDetails); $fb04e59b477f17ce$exports.shimGetSendersWithDtmf(window, browserDetails); $fb04e59b477f17ce$exports.shimSenderReceiverGetStats(window, browserDetails); $fb04e59b477f17ce$exports.fixNegotiationNeeded(window, browserDetails); $5151b78094cea2ba$export$cf133661e444ccfe(window, browserDetails); $5151b78094cea2ba$export$fdafb8d8280e29b5(window, browserDetails); $5151b78094cea2ba$export$63bb816cc75460(window, browserDetails); $5151b78094cea2ba$export$a99147c78a56edc4(window, browserDetails); $5151b78094cea2ba$export$d461c8d5c5db5da7(window, browserDetails); $5151b78094cea2ba$export$a57d114344295149(window, browserDetails); break; case 'firefox': if (!$215e6581d7a09c61$exports || !$215e6581d7a09c61$exports.shimPeerConnection || !options.shimFirefox) { logging('Firefox shim is not included in this adapter release.'); return adapter; } logging('adapter.js shimming firefox.'); // Export to the adapter global object visible in the browser. adapter.browserShim = $215e6581d7a09c61$exports; // Must be called before shimPeerConnection. $5151b78094cea2ba$export$51d5e40b48c771c7(window, browserDetails); $5151b78094cea2ba$export$7170d04e59f9d553(window, browserDetails); $215e6581d7a09c61$exports.shimGetUserMedia(window, browserDetails); $215e6581d7a09c61$exports.shimPeerConnection(window, browserDetails); $215e6581d7a09c61$exports.shimOnTrack(window, browserDetails); $215e6581d7a09c61$exports.shimRemoveStream(window, browserDetails); $215e6581d7a09c61$exports.shimSenderGetStats(window, browserDetails); $215e6581d7a09c61$exports.shimReceiverGetStats(window, browserDetails); $215e6581d7a09c61$exports.shimRTCDataChannel(window, browserDetails); $215e6581d7a09c61$exports.shimAddTransceiver(window, browserDetails); $215e6581d7a09c61$exports.shimGetParameters(window, browserDetails); $215e6581d7a09c61$exports.shimCreateOffer(window, browserDetails); $215e6581d7a09c61$exports.shimCreateAnswer(window, browserDetails); $5151b78094cea2ba$export$cf133661e444ccfe(window, browserDetails); $5151b78094cea2ba$export$63bb816cc75460(window, browserDetails); $5151b78094cea2ba$export$a99147c78a56edc4(window, browserDetails); $5151b78094cea2ba$export$d461c8d5c5db5da7(window, browserDetails); break; case 'safari': if (!$c1f641ee5a6f6c8f$exports || !options.shimSafari) { logging('Safari shim is not included in this adapter release.'); return adapter; } logging('adapter.js shimming safari.'); // Export to the adapter global object visible in the browser. adapter.browserShim = $c1f641ee5a6f6c8f$exports; // Must be called before shimCallbackAPI. $5151b78094cea2ba$export$51d5e40b48c771c7(window, browserDetails); $5151b78094cea2ba$export$7170d04e59f9d553(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimRTCIceServerUrls(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimCreateOfferLegacy(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimCallbacksAPI(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimLocalStreamsAPI(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimRemoteStreamsAPI(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimTrackEventTransceiver(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimGetUserMedia(window, browserDetails); $c1f641ee5a6f6c8f$exports.shimAudioContext(window, browserDetails); $5151b78094cea2ba$export$cf133661e444ccfe(window, browserDetails); $5151b78094cea2ba$export$fdafb8d8280e29b5(window, browserDetails); $5151b78094cea2ba$export$a99147c78a56edc4(window, browserDetails); $5151b78094cea2ba$export$d461c8d5c5db5da7(window, browserDetails); $5151b78094cea2ba$export$a57d114344295149(window, browserDetails); break; default: logging('Unsupported browser!'); break; } return adapter; } 'use strict'; const $90c50c10bd6fa8b4$var$adapter = (0, $b657217e95eb14d8$export$e77bf46c04ac7d12)({ window: typeof window === 'undefined' ? undefined : window }); var $90c50c10bd6fa8b4$export$2e2bcd8739ae039 = $90c50c10bd6fa8b4$var$adapter; const $a9bc9397a7d36afa$var$webRTCAdapter = //@ts-ignore (0, $90c50c10bd6fa8b4$export$2e2bcd8739ae039).default || (0, $90c50c10bd6fa8b4$export$2e2bcd8739ae039); const $a9bc9397a7d36afa$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 $a9bc9397a7d36afa$var$webRTCAdapter.browserDetails.browser; } getVersion() { return $a9bc9397a7d36afa$var$webRTCAdapter.browserDetails.version || 0; } isUnifiedPlanSupported() { const browser = this.getBrowser(); const version = $a9bc9397a7d36afa$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 $fce54fbdd74b2319$export$f35f128fd59ea256 = (id)=>{ // Allow empty ids return !id || /^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.test(id); }; const $008766fe99f03c2f$export$4e61f672936bec77 = ()=>Math.random().toString(36).slice(2); const $01f0d223090cb1f8$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 $01f0d223090cb1f8$export$f8f26dd395d7e1bd extends (0, $616ebdf1c4998439$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 = $01f0d223090cb1f8$var$DEFAULT_CONFIG, this.browser = (0, $a9bc9397a7d36afa$export$25be9502477c137d).getBrowser(), this.browserVersion = (0, $a9bc9397a7d36afa$export$25be9502477c137d).getVersion(), this.pack = $bf7fb46c6d68ead7$export$2a703dbb0cb35339, this.unpack = $bf7fb46c6d68ead7$export$417857010dc9287f, /** * 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, $a9bc9397a7d36afa$export$25be9502477c137d).isBrowserSupported(), webRTC: (0, $a9bc9397a7d36afa$export$25be9502477c137d).isWebRTCSupported(), audioVideo: false, data: false, binaryBlob: false, reliable: false }; if (!supported.webRTC) return supported; let pc; try { pc = new RTCPeerConnection($01f0d223090cb1f8$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, $a9bc9397a7d36afa$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, $fce54fbdd74b2319$export$f35f128fd59ea256), this.randomToken = (0, $008766fe99f03c2f$export$4e61f672936bec77); } } const $01f0d223090cb1f8$export$7debb50ef11d5e0b = new $01f0d223090cb1f8$export$f8f26dd395d7e1bd(); const $d3fc3aacca52312c$var$LOG_PREFIX = "PeerJS: "; var $d3fc3aacca52312c$export$243e62d78d3b544d = /*#__PURE__*/ 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"; return LogLevel; }({}); class $d3fc3aacca52312c$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 = [ $d3fc3aacca52312c$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 $d3fc3aacca52312c$export$2e2bcd8739ae039 = new $d3fc3aacca52312c$var$Logger(); var $f5d7fbd88de797fd$exports = {}; 'use strict'; var $f5d7fbd88de797fd$var$has = Object.prototype.hasOwnProperty, $f5d7fbd88de797fd$var$prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function $f5d7fbd88de797fd$var$Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { $f5d7fbd88de797fd$var$Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new $f5d7fbd88de797fd$var$Events().__proto__) $f5d7fbd88de797fd$var$prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function $f5d7fbd88de797fd$var$EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function $f5d7fbd88de797fd$var$addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') throw new TypeError('The listener must be a function'); var listener = new $f5d7fbd88de797fd$var$EE(fn, context || emitter, once), evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [ emitter._events[evt], listener ]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function $f5d7fbd88de797fd$var$clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new $f5d7fbd88de797fd$var$Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function $f5d7fbd88de797fd$var$EventEmitter() { this._events = new $f5d7fbd88de797fd$var$Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.eventNames = function eventNames() { var names = [], events, name; if (this._eventsCount === 0) return names; for(name in events = this._events)if ($f5d7fbd88de797fd$var$has.call(events, name)) names.push($f5d7fbd88de797fd$var$prefix ? name.slice(1) : name); if (Object.getOwnPropertySymbols) return names.concat(Object.getOwnPropertySymbols(events)); return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.listeners = function listeners(event) { var evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event, handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [ handlers.fn ]; for(var i = 0, l = handlers.length, ee = new Array(l); i < l; i++)ee[i] = handlers[i].fn; return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event, listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt], len = arguments.length, args, i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch(len){ case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for(i = 1, args = new Array(len - 1); i < len; i++)args[i - 1] = arguments[i]; listeners.fn.apply(listeners.context, args); } else { var length = listeners.length, j; for(i = 0; i < length; i++){ if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch(len){ case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for(j = 1, args = new Array(len - 1); j < len; j++)args[j - 1] = arguments[j]; listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.on = function on(event, fn, context) { return $f5d7fbd88de797fd$var$addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.once = function once(event, fn, context) { return $f5d7fbd88de797fd$var$addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event; if (!this._events[evt]) return this; if (!fn) { $f5d7fbd88de797fd$var$clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) $f5d7fbd88de797fd$var$clearEvent(this, evt); } else { for(var i = 0, events = [], length = listeners.length; i < length; i++)if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) events.push(listeners[i]); // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else $f5d7fbd88de797fd$var$clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ $f5d7fbd88de797fd$var$EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = $f5d7fbd88de797fd$var$prefix ? $f5d7fbd88de797fd$var$prefix + event : event; if (this._events[evt]) $f5d7fbd88de797fd$var$clearEvent(this, evt); } else { this._events = new $f5d7fbd88de797fd$var$Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // $f5d7fbd88de797fd$var$EventEmitter.prototype.off = $f5d7fbd88de797fd$var$EventEmitter.prototype.removeListener; $f5d7fbd88de797fd$var$EventEmitter.prototype.addListener = $f5d7fbd88de797fd$var$EventEmitter.prototype.on; // // Expose the prefix. // $f5d7fbd88de797fd$var$EventEmitter.prefixed = $f5d7fbd88de797fd$var$prefix; // // Allow `EventEmitter` to be imported as module namespace. // $f5d7fbd88de797fd$var$EventEmitter.EventEmitter = $f5d7fbd88de797fd$var$EventEmitter; $f5d7fbd88de797fd$exports = $f5d7fbd88de797fd$var$EventEmitter; var $edbcf3072a01d580$export$3157d57b4135e3bc = /*#__PURE__*/ function(ConnectionType) { ConnectionType["Data"] = "data"; ConnectionType["Media"] = "media"; return ConnectionType; }({}); var $edbcf3072a01d580$export$9547aaa2e39030ff = /*#__PURE__*/ 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"; return PeerErrorType; }({}); var $edbcf3072a01d580$export$7974935686149686 = /*#__PURE__*/ function(BaseConnectionErrorType) { BaseConnectionErrorType["NegotiationFailed"] = "negotiation-failed"; BaseConnectionErrorType["ConnectionClosed"] = "connection-closed"; return BaseConnectionErrorType; }({}); var $edbcf3072a01d580$export$49ae800c114df41d = /*#__PURE__*/ function(DataConnectionErrorType) { DataConnectionErrorType["NotOpenYet"] = "not-open-yet"; DataConnectionErrorType["MessageToBig"] = "message-too-big"; return DataConnectionErrorType; }({}); var $edbcf3072a01d580$export$89f507cf986a947 = /*#__PURE__*/ function(SerializationType) { SerializationType["Binary"] = "binary"; SerializationType["BinaryUTF8"] = "binary-utf8"; SerializationType["JSON"] = "json"; SerializationType["None"] = "raw"; return SerializationType; }({}); var $edbcf3072a01d580$export$3b5c4a4b6354f023 = /*#__PURE__*/ function(SocketEventType) { SocketEventType["Message"] = "message"; SocketEventType["Disconnected"] = "disconnected"; SocketEventType["Error"] = "error"; SocketEventType["Close"] = "close"; return SocketEventType; }({}); var $edbcf3072a01d580$export$adb4a1754da6f10d = /*#__PURE__*/ 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"; return ServerMessageType; }({}); const $812644bc8c7ccc3e$export$83d89fbfd8236492 = "1.5.5"; class $5dd3b97502a89fbb$export$4798917dbf149b79 extends (0, $f5d7fbd88de797fd$exports.EventEmitter) { 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, $812644bc8c7ccc3e$export$83d89fbfd8236492)); this._disconnected = false; this._socket.onmessage = (event)=>{ let data; try { data = JSON.parse(event.data); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Server message received:", data); } catch (e) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Invalid server message", event.data); return; } this.emit((0, $edbcf3072a01d580$export$3b5c4a4b6354f023).Message, data); }; this._socket.onclose = (event)=>{ if (this._disconnected) return; (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Socket closed.", event); this._cleanup(); this._disconnected = true; this.emit((0, $edbcf3072a01d580$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Socket open"); this._scheduleHeartbeat(); }; } _scheduleHeartbeat() { this._wsPingTimer = setTimeout(()=>{ this._sendHeartbeat(); }, this.pingInterval); } _sendHeartbeat() { if (!this._wsOpen()) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Cannot send heartbeat, because socket closed`); return; } const message = JSON.stringify({ type: (0, $edbcf3072a01d580$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, $edbcf3072a01d580$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); } 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; } } class $3cabb799c2437cbe$export$89e6bb5ad64bf4a { /** 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, $edbcf3072a01d580$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: true // HACK }; const dataChannel = peerConnection.createDataChannel(dataConnection.label, config); dataConnection._initializeDataChannel(dataChannel); this._makeOffer(); } else this.handleSDP("OFFER", options.sdp); } /** Start a PC. */ _startPeerConnection() { (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Listening for ICE candidates."); peerConnection.onicecandidate = (evt)=>{ if (!evt.candidate || !evt.candidate.candidate) return; (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Received ICE candidates for ${peerId}:`, evt.candidate); provider.socket.send({ type: (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Candidate, payload: { candidate: evt.candidate, type: connectionType, connectionId: connectionId }, dst: peerId }); }; peerConnection.oniceconnectionstatechange = ()=>{ switch(peerConnection.iceConnectionState){ case "failed": (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("iceConnectionState is failed, closing connections to " + peerId); this.connection.emitError((0, $edbcf3072a01d580$export$7974935686149686).NegotiationFailed, "Negotiation of connection to " + peerId + " failed."); this.connection.close(); break; case "closed": (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("iceConnectionState is closed, closing connections to " + peerId); this.connection.emitError((0, $edbcf3072a01d580$export$7974935686149686).ConnectionClosed, "Connection to " + peerId + " closed."); this.connection.close(); break; case "disconnected": (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Received data channel"); const dataChannel = evt.channel; const connection = provider.getConnection(peerId, connectionId); connection._initializeDataChannel(dataChannel); }; // MEDIACONNECTION. (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Listening for remote stream"); peerConnection.ontrack = (evt)=>{ (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Received remote stream"); const stream = evt.streams[0]; const connection = provider.getConnection(peerId, connectionId); if (connection.type === (0, $edbcf3072a01d580$export$3157d57b4135e3bc).Media) { const mediaConnection = connection; this._addStreamToMediaConnection(stream, mediaConnection); } }; } cleanup() { (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$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, $d3fc3aacca52312c$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, $edbcf3072a01d580$export$3157d57b4135e3bc).Data) { const dataConnection = this.connection; payload = { ...payload, label: dataConnection.label, reliable: dataConnection.reliable, serialization: dataConnection.serialization }; } provider.socket.send({ type: (0, $edbcf3072a01d580$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, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Failed to setLocalDescription, ", err); } } } catch (err_1) { provider.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err_1); (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Set localDescription:`, answer, `for:${this.connection.peer}`); provider.socket.send({ type: (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Answer, payload: { sdp: answer, type: this.connection.type, connectionId: this.connection.connectionId }, dst: this.connection.peer }); } catch (err) { provider.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Failed to setLocalDescription, ", err); } } catch (err_1) { provider.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err_1); (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Setting remote description", sdp); const self = this; try { await peerConnection.setRemoteDescription(sdp); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Set remoteDescription:${type} for:${this.connection.peer}`); if (type === "OFFER") await self._makeAnswer(); } catch (err) { provider.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Failed to setRemoteDescription, ", err); } } /** Handle a candidate. */ async handleCandidate(ice) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`handleCandidate:`, ice); try { await this.connection.peerConnection.addIceCandidate(ice); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Added ICE candidate for:${this.connection.peer}`); } catch (err) { this.connection.provider.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).WebRTC, err); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log("Failed to handleCandidate, ", err); } } _addTracksToConnection(stream, peerConnection) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`add tracks from stream ${stream.id} to peer connection`); if (!peerConnection.addTrack) return (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error(`Your browser does't support RTCPeerConnection#addTrack. Ignored.`); stream.getTracks().forEach((track)=>{ peerConnection.addTrack(track, stream); }); } _addStreamToMediaConnection(stream, mediaConnection) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`add stream ${stream.id} to media connection ${mediaConnection.connectionId}`); mediaConnection.addStream(stream); } constructor(connection){ this.connection = connection; } } class $41eb28b5735ed6cf$export$6a678e589c8a4542 extends (0, $f5d7fbd88de797fd$exports.EventEmitter) { /** * Emits a typed error message. * * @internal */ emitError(type, err) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("Error:", err); // @ts-ignore this.emit("error", new $41eb28b5735ed6cf$export$98871882f492de82(`${type}`, err)); } } class $41eb28b5735ed6cf$export$98871882f492de82 extends Error { /** * @internal */ constructor(type, err){ if (typeof err === "string") super(err); else { super(); Object.assign(this, err); } this.type = type; } } class $f06f075a81a8b63e$export$23a2a68283c24d80 extends (0, $41eb28b5735ed6cf$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 $0bc12d7ac26e1491$export$4a84e95a2324ac29 extends (0, $f06f075a81a8b63e$export$23a2a68283c24d80) { /** * For media connections, this is always 'media'. */ get type() { return (0, $edbcf3072a01d580$export$3157d57b4135e3bc).Media; } get localStream() { return this._localStream; } get remoteStream() { return this._remoteStream; } /** Called by the Negotiator when the DataChannel is ready. */ _initializeDataChannel(dc) { this.dataChannel = dc; this.dataChannel.onopen = ()=>{ (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc connection success`); this.emit("willCloseOnRemote"); }; this.dataChannel.onclose = ()=>{ (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc closed for:`, this.peer); this.close(); }; } addStream(remoteStream) { (0, $d3fc3aacca52312c$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, $edbcf3072a01d580$export$adb4a1754da6f10d).Answer: // Forward to negotiator this._negotiator.handleSDP(type, payload.sdp); this._open = true; break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Candidate: this._negotiator.handleCandidate(payload.candidate); break; default: (0, $d3fc3aacca52312c$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, $d3fc3aacca52312c$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"); } constructor(peerId, provider, options){ super(peerId, provider, options); this._localStream = this.options._stream; this.connectionId = this.options.connectionId || $0bc12d7ac26e1491$export$4a84e95a2324ac29.ID_PREFIX + (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).randomToken(); this._negotiator = new (0, $3cabb799c2437cbe$export$89e6bb5ad64bf4a)(this); if (this._localStream) this._negotiator.startConnection({ _stream: this._localStream, originator: true }); } } $0bc12d7ac26e1491$export$4a84e95a2324ac29.ID_PREFIX = "mc_"; class $4c932c6613316196$export$2c4e825dc9120f87 { _buildRequest(method) { const protocol = this._options.secure ? "https" : "http"; // HACKED 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, $812644bc8c7ccc3e$export$83d89fbfd8236492)); 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, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("Error retrieving ID", error); let pathError = ""; if (this._options.path === "/" && this._options.host !== (0, $01f0d223090cb1f8$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, $01f0d223090cb1f8$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, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("Error retrieving list peers", error); throw new Error("Could not get list peers from the server." + error); } } constructor(_options){ this._options = _options; } } class $392ccce28b647101$export$d365f7ad9d7df9c9 extends (0, $f06f075a81a8b63e$export$23a2a68283c24d80) { get type() { return (0, $edbcf3072a01d580$export$3157d57b4135e3bc).Data; } /** Called by the Negotiator when the DataChannel is ready. */ _initializeDataChannel(dc) { this.dataChannel = dc; this.dataChannel.onopen = ()=>{ (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc connection success`); this._open = true; this.emit("open"); }; this.dataChannel.onmessage = (e)=>{ (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`DC#${this.connectionId} dc onmessage:`, e.data); // this._handleDataMessage(e); }; this.dataChannel.onclose = ()=>{ (0, $d3fc3aacca52312c$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, $edbcf3072a01d580$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, $edbcf3072a01d580$export$adb4a1754da6f10d).Answer: await this._negotiator.handleSDP(message.type, payload.sdp); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Candidate: await this._negotiator.handleCandidate(payload.candidate); break; default: (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn("Unrecognized message type:", message.type, "from peer:", this.peer); break; } } constructor(peerId, provider, options){ super(peerId, provider, options); this.connectionId = this.options.connectionId || $392ccce28b647101$export$d365f7ad9d7df9c9.ID_PREFIX + (0, $008766fe99f03c2f$export$4e61f672936bec77)(); this.label = this.options.label || this.connectionId; this.reliable = !!this.options.reliable; this._negotiator = new (0, $3cabb799c2437cbe$export$89e6bb5ad64bf4a)(this); this._negotiator.startConnection(this.options._payload || { originator: true, reliable: this.reliable }); } } $392ccce28b647101$export$d365f7ad9d7df9c9.ID_PREFIX = "dc_"; $392ccce28b647101$export$d365f7ad9d7df9c9.MAX_BUFFERED_AMOUNT = 8388608; class $8d1d5e45d8d6520c$export$ff7c9d4c11d94e8b extends (0, $392ccce28b647101$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; } } // Returns true if the send succeeds. _trySend(msg) { if (!this.open) return false; if (this.dataChannel.bufferedAmount > (0, $392ccce28b647101$export$d365f7ad9d7df9c9).MAX_BUFFERED_AMOUNT) { this._buffering = true; setTimeout(()=>{ this._buffering = false; this._tryBuffer(); }, 50); return false; } try { this.dataChannel.send(msg); } catch (e) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error(`DC#:${this.connectionId} Error when sending:`, e); this._buffering = true; this.close(); return false; } return true; } // Try to send the first message in the buffer. _tryBuffer() { if (!this.open) return; if (this._buffer.length === 0) return; const msg = this._buffer[0]; if (this._trySend(msg)) { this._buffer.shift(); this._bufferSize = this._buffer.length; this._tryBuffer(); } } close(options) { if (options?.flush) { this.send({ __peerData: { type: "close" } }); return; } this._buffer = []; this._bufferSize = 0; super.close(); } constructor(...args){ super(...args), this._buffer = [], this._bufferSize = 0, this._buffering = false; } } class $6b2c8b37149b9a13$export$f0a5a64d5bb37108 extends (0, $8d1d5e45d8d6520c$export$ff7c9d4c11d94e8b) { close(options) { super.close(options); this._chunkedData = {}; } // Handles a DataChannel message. _handleDataMessage({ data: data }) { const deserializedData = (0, $bf7fb46c6d68ead7$export$417857010dc9287f)(data); // PeerJS specific message const peerData = deserializedData["__peerData"]; if (peerData) { if (peerData.type === "close") { this.close(); return; } // Chunked data -- piece things back together. // @ts-ignore this._handleChunk(deserializedData); return; } this.emit("data", deserializedData); } _handleChunk(data) { const id = data.__peerData; const chunkInfo = this._chunkedData[id] || { data: [], count: 0, total: data.total }; chunkInfo.data[data.n] = new Uint8Array(data.data); chunkInfo.count++; this._chunkedData[id] = chunkInfo; if (chunkInfo.total === chunkInfo.count) { // Clean up before making the recursive call to `_handleDataMessage`. delete this._chunkedData[id]; // We've received all the chunks--time to construct the complete data. // const data = new Blob(chunkInfo.data); const data = (0, $616ebdf1c4998439$export$52c89ebcdc4f53f2)(chunkInfo.data); this._handleDataMessage({ data: data }); } } _send(data, chunked) { const blob = (0, $bf7fb46c6d68ead7$export$2a703dbb0cb35339)(data); if (blob instanceof Promise) return this._send_blob(blob); if (!chunked && blob.byteLength > this.chunker.chunkedMTU) { this._sendChunks(blob); return; } this._bufferedSend(blob); } async _send_blob(blobPromise) { const blob = await blobPromise; if (blob.byteLength > this.chunker.chunkedMTU) { this._sendChunks(blob); return; } this._bufferedSend(blob); } _sendChunks(blob) { const blobs = this.chunker.chunk(blob); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`DC#${this.connectionId} Try to send ${blobs.length} chunks...`); for (const blob of blobs)this.send(blob, true); } constructor(peerId, provider, options){ super(peerId, provider, options), this.chunker = new (0, $616ebdf1c4998439$export$f1c5f4c9cb95390b)(), this.serialization = (0, $edbcf3072a01d580$export$89f507cf986a947).Binary, this._chunkedData = {}; } } class $6faa8477ae391a66$export$6f88fe47d32c9c94 extends (0, $8d1d5e45d8d6520c$export$ff7c9d4c11d94e8b) { _handleDataMessage({ data: data }) { super.emit("data", data); } _send(data, _chunked) { this._bufferedSend(data); } constructor(...args){ super(...args), this.serialization = (0, $edbcf3072a01d580$export$89f507cf986a947).None; } } class $b524315f5ff1ee78$export$48880ac635f47186 extends (0, $8d1d5e45d8d6520c$export$ff7c9d4c11d94e8b) { // Handles a DataChannel message. _handleDataMessage({ data: data }) { const deserializedData = this.parse(this.decoder.decode(data)); // PeerJS specific message const peerData = deserializedData["__peerData"]; if (peerData && peerData.type === "close") { this.close(); return; } this.emit("data", deserializedData); } _send(data, _chunked) { const encodedData = this.encoder.encode(this.stringify(data)); if (encodedData.byteLength >= (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).chunkedMTU) { this.emitError((0, $edbcf3072a01d580$export$49ae800c114df41d).MessageToBig, "Message too big for JSON channel"); return; } this._bufferedSend(encodedData); } constructor(...args){ super(...args), this.serialization = (0, $edbcf3072a01d580$export$89f507cf986a947).JSON, this.encoder = new TextEncoder(), this.decoder = new TextDecoder(), this.stringify = JSON.stringify, this.parse = JSON.parse; } } class $11967427976ce06d$var$PeerOptions { } class $11967427976ce06d$export$ecd1fc136c422448 extends (0, $41eb28b5735ed6cf$export$6a678e589c8a4542) { /** * The brokering ID of this peer * * If no ID was specified in {@apilink Peer | the constructor}, * this will be `undefined` until the {@apilink PeerEvents | `open`} event is emitted. */ get id() { return this._id; } get options() { return this._options; } get open() { return this._open; } /** * @internal */ get socket() { return this._socket; } /** * A hash of all connections associated with this peer, keyed by the remote peer's ID. * @deprecated * Return type will change from Object to Map */ get connections() { const plainConnections = Object.create(null); for (const [k, v] of this._connections)plainConnections[k] = v; return plainConnections; } /** * true if this peer and all of its connections can no longer be used. */ get destroyed() { return this._destroyed; } /** * false if there is an active connection to the PeerServer. */ get disconnected() { return this._disconnected; } _createServerConnection() { const socket = new (0, $5dd3b97502a89fbb$export$4798917dbf149b79)(this._options.secure, this._options.host, this._options.port, this._options.path, this._options.key, this._options.pingInterval); socket.on((0, $edbcf3072a01d580$export$3b5c4a4b6354f023).Message, (data)=>{ this._handleMessage(data); }); socket.on((0, $edbcf3072a01d580$export$3b5c4a4b6354f023).Error, (error)=>{ this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).SocketError, error); }); socket.on((0, $edbcf3072a01d580$export$3b5c4a4b6354f023).Disconnected, ()=>{ if (this.disconnected) return; this.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).Network, "Lost connection to server."); this.disconnect(); }); socket.on((0, $edbcf3072a01d580$export$3b5c4a4b6354f023).Close, ()=>{ if (this.disconnected) return; this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).SocketClosed, "Underlying socket is already closed."); }); return socket; } /** Initialize a connection with the server. */ _initialize(id) { this._id = id; this.socket.start(id, this._options.token); } /** Handles messages from the server. */ _handleMessage(message) { const type = message.type; const payload = message.payload; const peerId = message.src; switch(type){ case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Open: this._lastServerId = this.id; this._open = true; this.emit("open", this.id); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Error: this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).ServerError, payload.msg); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).IdTaken: this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).UnavailableID, `ID "${this.id}" is taken`); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).InvalidKey: this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).InvalidKey, `API KEY "${this._options.key}" is invalid`); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Leave: (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Received leave message from ${peerId}`); this._cleanupPeer(peerId); this._connections.delete(peerId); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Expire: this.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).PeerUnavailable, `Could not connect to peer ${peerId}`); break; case (0, $edbcf3072a01d580$export$adb4a1754da6f10d).Offer: { // we should consider switching this to CALL/CONNECT, but this is the least breaking option. const connectionId = payload.connectionId; let connection = this.getConnection(peerId, connectionId); if (connection) { connection.close(); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn(`Offer received for existing Connection ID:${connectionId}`); } // Create a new connection. if (payload.type === (0, $edbcf3072a01d580$export$3157d57b4135e3bc).Media) { const mediaConnection = new (0, $0bc12d7ac26e1491$export$4a84e95a2324ac29)(peerId, this, { connectionId: connectionId, _payload: payload, metadata: payload.metadata }); connection = mediaConnection; this._addConnection(peerId, connection); this.emit("call", mediaConnection); } else if (payload.type === (0, $edbcf3072a01d580$export$3157d57b4135e3bc).Data) { const dataConnection = new this._serializers[payload.serialization](peerId, this, { connectionId: connectionId, _payload: payload, metadata: payload.metadata, label: payload.label, serialization: payload.serialization, reliable: payload.reliable }); connection = dataConnection; this._addConnection(peerId, connection); this.emit("connection", dataConnection); } else { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn(`Received malformed connection type:${payload.type}`); return; } // Find messages. const messages = this._getMessages(connectionId); for (const message of messages)connection.handleMessage(message); break; } default: { if (!payload) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn(`You received a malformed message from ${peerId} of type ${type}`); return; } const connectionId = payload.connectionId; const connection = this.getConnection(peerId, connectionId); if (connection && connection.peerConnection) // Pass it on. connection.handleMessage(message); else if (connectionId) // Store for possible later use this._storeMessage(connectionId, message); else (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn("You received an unrecognized message:", message); break; } } } /** Stores messages without a set up connection, to be claimed later. */ _storeMessage(connectionId, message) { if (!this._lostMessages.has(connectionId)) this._lostMessages.set(connectionId, []); this._lostMessages.get(connectionId).push(message); } /** * Retrieve messages from lost message store * @internal */ //TODO Change it to private _getMessages(connectionId) { const messages = this._lostMessages.get(connectionId); if (messages) { this._lostMessages.delete(connectionId); return messages; } return []; } /** * Connects to the remote peer specified by id and returns a data connection. * @param peer The brokering ID of the remote peer (their {@apilink Peer.id}). * @param options for specifying details about Peer Connection */ connect(peer, options = {}) { options = { serialization: "default", ...options }; if (this.disconnected) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn("You cannot connect to a new Peer because you called .disconnect() on this Peer and ended your connection with the server. You can create a new Peer to reconnect, or call reconnect on this peer if you believe its ID to still be available."); this.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).Disconnected, "Cannot connect to new Peer after disconnecting from server."); return; } console.log('peer sucks', this._serializers) const dataConnection = new this._serializers[options.serialization](peer, this, options); this._addConnection(peer, dataConnection); return dataConnection; } /** * Calls the remote peer specified by id and returns a media connection. * @param peer The brokering ID of the remote peer (their peer.id). * @param stream The caller's media stream * @param options Metadata associated with the connection, passed in by whoever initiated the connection. */ call(peer, stream, options = {}) { if (this.disconnected) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).warn("You cannot connect to a new Peer because you called .disconnect() on this Peer and ended your connection with the server. You can create a new Peer to reconnect."); this.emitError((0, $edbcf3072a01d580$export$9547aaa2e39030ff).Disconnected, "Cannot connect to new Peer after disconnecting from server."); return; } if (!stream) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("To call a peer, you must provide a stream from your browser's `getUserMedia`."); return; } const mediaConnection = new (0, $0bc12d7ac26e1491$export$4a84e95a2324ac29)(peer, this, { ...options, _stream: stream }); this._addConnection(peer, mediaConnection); return mediaConnection; } /** Add a data/media connection to this peer. */ _addConnection(peerId, connection) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`add connection ${connection.type}:${connection.connectionId} to peerId:${peerId}`); if (!this._connections.has(peerId)) this._connections.set(peerId, []); this._connections.get(peerId).push(connection); } //TODO should be private _removeConnection(connection) { const connections = this._connections.get(connection.peer); if (connections) { const index = connections.indexOf(connection); if (index !== -1) connections.splice(index, 1); } //remove from lost messages this._lostMessages.delete(connection.connectionId); } /** Retrieve a data/media connection for this peer. */ getConnection(peerId, connectionId) { const connections = this._connections.get(peerId); if (!connections) return null; for (const connection of connections){ if (connection.connectionId === connectionId) return connection; } return null; } _delayedAbort(type, message) { setTimeout(()=>{ this._abort(type, message); }, 0); } /** * Emits an error message and destroys the Peer. * The Peer is not destroyed if it's in a disconnected state, in which case * it retains its disconnected state and its existing connections. */ _abort(type, message) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("Aborting!"); this.emitError(type, message); if (!this._lastServerId) this.destroy(); else this.disconnect(); } /** * Destroys the Peer: closes all active connections as well as the connection * to the server. * * :::caution * This cannot be undone; the respective peer object will no longer be able * to create or receive any connections, its ID will be forfeited on the server, * and all of its data and media connections will be closed. * ::: */ destroy() { if (this.destroyed) return; (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Destroy peer with ID:${this.id}`); this.disconnect(); this._cleanup(); this._destroyed = true; this.emit("close"); } /** Disconnects every connection on this peer. */ _cleanup() { for (const peerId of this._connections.keys()){ this._cleanupPeer(peerId); this._connections.delete(peerId); } this.socket.removeAllListeners(); } /** Closes all connections to this peer. */ _cleanupPeer(peerId) { const connections = this._connections.get(peerId); if (!connections) return; for (const connection of connections)connection.close(); } /** * Disconnects the Peer's connection to the PeerServer. Does not close any * active connections. * Warning: The peer can no longer create or accept connections after being * disconnected. It also cannot reconnect to the server. */ disconnect() { if (this.disconnected) return; const currentId = this.id; (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Disconnect peer with ID:${currentId}`); this._disconnected = true; this._open = false; this.socket.close(); this._lastServerId = currentId; this._id = null; this.emit("disconnected", currentId); } /** Attempts to reconnect with the same ID. * * Only {@apilink Peer.disconnect | disconnected peers} can be reconnected. * Destroyed peers cannot be reconnected. * If the connection fails (as an example, if the peer's old ID is now taken), * the peer's existing connections will not close, but any associated errors events will fire. */ reconnect() { if (this.disconnected && !this.destroyed) { (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).log(`Attempting reconnection to server with ID ${this._lastServerId}`); this._disconnected = false; this._initialize(this._lastServerId); } else if (this.destroyed) throw new Error("This peer cannot reconnect to the server. It has already been destroyed."); else if (!this.disconnected && !this.open) // Do nothing. We're still connecting the first time. (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).error("In a hurry? We're still trying to make the initial connection!"); else throw new Error(`Peer ${this.id} cannot reconnect because it is not disconnected from the server!`); } /** * Get a list of available peer IDs. If you're running your own server, you'll * want to set allow_discovery: true in the PeerServer options. If you're using * the cloud server, email team@peerjs.com to get the functionality enabled for * your key. */ listAllPeers(cb = (_)=>{}) { this._api.listAllPeers().then((peers)=>cb(peers)).catch((error)=>this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).ServerError, error)); } constructor(id, options){ super(), this._serializers = { raw: (0, $6faa8477ae391a66$export$6f88fe47d32c9c94), json: (0, $b524315f5ff1ee78$export$48880ac635f47186), binary: (0, $6b2c8b37149b9a13$export$f0a5a64d5bb37108), "binary-utf8": (0, $6b2c8b37149b9a13$export$f0a5a64d5bb37108), default: (0, $6b2c8b37149b9a13$export$f0a5a64d5bb37108) }, this._id = null, this._lastServerId = null, // States. this._destroyed = false // Connections have been killed , this._disconnected = false // Connection to PeerServer killed but P2P connections still active , this._open = false // Sockets and such are not yet open. , this._connections = new Map() // All connections for this peer. , this._lostMessages = new Map() // src => [list of messages] ; let userId; // Deal with overloading if (id && id.constructor == Object) options = id; else if (id) userId = id.toString(); // Configurize options options = { debug: 0, host: (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).CLOUD_HOST, port: (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).CLOUD_PORT, path: "/", key: $11967427976ce06d$export$ecd1fc136c422448.DEFAULT_KEY, token: (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).randomToken(), config: (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).defaultConfig, referrerPolicy: "strict-origin-when-cross-origin", serializers: {}, ...options }; this._options = options; this._serializers = { ...this._serializers, ...this.options.serializers }; // Detect relative URL host. if (this._options.host === "/") this._options.host = window.location.hostname; // Set path correctly. if (this._options.path) { if (this._options.path[0] !== "/") this._options.path = "/" + this._options.path; if (this._options.path[this._options.path.length - 1] !== "/") this._options.path += "/"; } // Set whether we use SSL to same as current host if (this._options.secure === undefined && this._options.host !== (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).CLOUD_HOST) this._options.secure = (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).isSecure(); else if (this._options.host == (0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).CLOUD_HOST) this._options.secure = true; // Set a custom log function if present if (this._options.logFunction) (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).setLogFunction(this._options.logFunction); (0, $d3fc3aacca52312c$export$2e2bcd8739ae039).logLevel = this._options.debug || 0; this._api = new (0, $4c932c6613316196$export$2c4e825dc9120f87)(options); this._socket = this._createServerConnection(); // Sanity checks // Ensure WebRTC supported if (!(0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).supports.audioVideo && !(0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).supports.data) { this._delayedAbort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).BrowserIncompatible, "The current browser does not support WebRTC"); return; } // Ensure alphanumeric id if (!!userId && !(0, $01f0d223090cb1f8$export$7debb50ef11d5e0b).validateId(userId)) { this._delayedAbort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).InvalidID, `ID "${userId}" is invalid`); return; } if (userId) this._initialize(userId); else this._api.retrieveId().then((id)=>this._initialize(id)).catch((error)=>this._abort((0, $edbcf3072a01d580$export$9547aaa2e39030ff).ServerError, error)); } } $11967427976ce06d$export$ecd1fc136c422448.DEFAULT_KEY = "peerjs"; window.peerjs = { Peer: $11967427976ce06d$export$ecd1fc136c422448, util: $01f0d223090cb1f8$export$7debb50ef11d5e0b }; /** @deprecated Should use peerjs namespace */ window.Peer = (0, $11967427976ce06d$export$ecd1fc136c422448); })(); //# sourceMappingURL=peerjs.js.map