From 70f7daff49abf6263c7da85e77dd995a088904ef Mon Sep 17 00:00:00 2001 From: Greg Fodor Date: Thu, 28 Jul 2022 08:32:13 -0700 Subject: [PATCH] Migrate to simple-peer --- examples/test/index.html | 6 + examples/test/p2pcf.js | 4183 +++++++++++++++++++++++++++++++++++--- p2pcf.js | 500 ++--- package-lock.json | 82 +- package.json | 1 + 5 files changed, 4140 insertions(+), 632 deletions(-) diff --git a/examples/test/index.html b/examples/test/index.html index aadab52..d8db702 100644 --- a/examples/test/index.html +++ b/examples/test/index.html @@ -1,7 +1,13 @@ + +
+
diff --git a/examples/test/p2pcf.js b/examples/test/p2pcf.js index b2841bd..a9c73e6 100644 --- a/examples/test/p2pcf.js +++ b/examples/test/p2pcf.js @@ -2945,6 +2945,3746 @@ var require_browser2 = __commonJS({ } }); +// node_modules/safe-buffer/index.js +var require_safe_buffer = __commonJS({ + "node_modules/safe-buffer/index.js"(exports, module) { + init_esbuild_inject(); + var buffer = require_buffer(); + var Buffer3 = buffer.Buffer; + function copyProps(src, dst) { + for (var key in src) { + dst[key] = src[key]; + } + } + if (Buffer3.from && Buffer3.alloc && Buffer3.allocUnsafe && Buffer3.allocUnsafeSlow) { + module.exports = buffer; + } else { + copyProps(buffer, exports); + exports.Buffer = SafeBuffer; + } + function SafeBuffer(arg, encodingOrOffset, length) { + return Buffer3(arg, encodingOrOffset, length); + } + copyProps(Buffer3, SafeBuffer); + SafeBuffer.from = function(arg, encodingOrOffset, length) { + if (typeof arg === "number") { + throw new TypeError("Argument must not be a number"); + } + return Buffer3(arg, encodingOrOffset, length); + }; + SafeBuffer.alloc = function(size, fill, encoding) { + if (typeof size !== "number") { + throw new TypeError("Argument must be a number"); + } + var buf = Buffer3(size); + if (fill !== void 0) { + if (typeof encoding === "string") { + buf.fill(fill, encoding); + } else { + buf.fill(fill); + } + } else { + buf.fill(0); + } + return buf; + }; + SafeBuffer.allocUnsafe = function(size) { + if (typeof size !== "number") { + throw new TypeError("Argument must be a number"); + } + return Buffer3(size); + }; + SafeBuffer.allocUnsafeSlow = function(size) { + if (typeof size !== "number") { + throw new TypeError("Argument must be a number"); + } + return buffer.SlowBuffer(size); + }; + } +}); + +// node_modules/randombytes/browser.js +var require_browser3 = __commonJS({ + "node_modules/randombytes/browser.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var MAX_BYTES = 65536; + var MAX_UINT32 = 4294967295; + function oldBrowser() { + throw new Error("Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11"); + } + var Buffer3 = require_safe_buffer().Buffer; + var crypto = window.crypto || window.msCrypto; + if (crypto && crypto.getRandomValues) { + module.exports = randomBytes; + } else { + module.exports = oldBrowser; + } + function randomBytes(size, cb) { + if (size > MAX_UINT32) + throw new RangeError("requested too many random bytes"); + var bytes = Buffer3.allocUnsafe(size); + if (size > 0) { + if (size > MAX_BYTES) { + for (var generated = 0; generated < size; generated += MAX_BYTES) { + crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES)); + } + } else { + crypto.getRandomValues(bytes); + } + } + if (typeof cb === "function") { + return process.nextTick(function() { + cb(null, bytes); + }); + } + return bytes; + } + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/stream-browser.js +var require_stream_browser = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/stream-browser.js"(exports, module) { + init_esbuild_inject(); + module.exports = require_events().EventEmitter; + } +}); + +// (disabled):node_modules/util/util.js +var require_util = __commonJS({ + "(disabled):node_modules/util/util.js"() { + init_esbuild_inject(); + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/buffer_list.js +var require_buffer_list = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/buffer_list.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) + symbols = symbols.filter(function(sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + keys.push.apply(keys, symbols); + } + return keys; + } + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + if (i % 2) { + ownKeys(Object(source), true).forEach(function(key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function(key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + return target; + } + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true }); + } else { + obj[key] = value; + } + return obj; + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) + descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) + _defineProperties(Constructor.prototype, protoProps); + if (staticProps) + _defineProperties(Constructor, staticProps); + return Constructor; + } + var _require = require_buffer(); + var Buffer3 = _require.Buffer; + var _require2 = require_util(); + var inspect = _require2.inspect; + var custom = inspect && inspect.custom || "inspect"; + function copyBuffer(src, target, offset) { + Buffer3.prototype.copy.call(src, target, offset); + } + module.exports = /* @__PURE__ */ function() { + function BufferList() { + _classCallCheck(this, BufferList); + this.head = null; + this.tail = null; + this.length = 0; + } + _createClass(BufferList, [{ + key: "push", + value: function push(v) { + var entry = { + data: v, + next: null + }; + if (this.length > 0) + this.tail.next = entry; + else + this.head = entry; + this.tail = entry; + ++this.length; + } + }, { + key: "unshift", + value: function unshift(v) { + var entry = { + data: v, + next: this.head + }; + if (this.length === 0) + this.tail = entry; + this.head = entry; + ++this.length; + } + }, { + key: "shift", + value: function shift() { + if (this.length === 0) + return; + var ret = this.head.data; + if (this.length === 1) + this.head = this.tail = null; + else + this.head = this.head.next; + --this.length; + return ret; + } + }, { + key: "clear", + value: function clear() { + this.head = this.tail = null; + this.length = 0; + } + }, { + key: "join", + value: function join(s) { + if (this.length === 0) + return ""; + var p = this.head; + var ret = "" + p.data; + while (p = p.next) { + ret += s + p.data; + } + return ret; + } + }, { + key: "concat", + value: function concat(n) { + if (this.length === 0) + return Buffer3.alloc(0); + var ret = Buffer3.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + } + }, { + key: "consume", + value: function consume(n, hasStrings) { + var ret; + if (n < this.head.data.length) { + ret = this.head.data.slice(0, n); + this.head.data = this.head.data.slice(n); + } else if (n === this.head.data.length) { + ret = this.shift(); + } else { + ret = hasStrings ? this._getString(n) : this._getBuffer(n); + } + return ret; + } + }, { + key: "first", + value: function first() { + return this.head.data; + } + }, { + key: "_getString", + value: function _getString(n) { + var p = this.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) + ret += str; + else + ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) + this.head = p.next; + else + this.head = this.tail = null; + } else { + this.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + }, { + key: "_getBuffer", + value: function _getBuffer(n) { + var ret = Buffer3.allocUnsafe(n); + var p = this.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) + this.head = p.next; + else + this.head = this.tail = null; + } else { + this.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + }, { + key: custom, + value: function value(_, options) { + return inspect(this, _objectSpread({}, options, { + depth: 0, + customInspect: false + })); + } + }]); + return BufferList; + }(); + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/destroy.js +var require_destroy = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/destroy.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + function destroy(err, cb) { + var _this = this; + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + process.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + process.nextTick(emitErrorNT, this, err); + } + } + return this; + } + if (this._readableState) { + this._readableState.destroyed = true; + } + if (this._writableState) { + this._writableState.destroyed = true; + } + this._destroy(err || null, function(err2) { + if (!cb && err2) { + if (!_this._writableState) { + process.nextTick(emitErrorAndCloseNT, _this, err2); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + process.nextTick(emitErrorAndCloseNT, _this, err2); + } else { + process.nextTick(emitCloseNT, _this); + } + } else if (cb) { + process.nextTick(emitCloseNT, _this); + cb(err2); + } else { + process.nextTick(emitCloseNT, _this); + } + }); + return this; + } + function emitErrorAndCloseNT(self2, err) { + emitErrorNT(self2, err); + emitCloseNT(self2); + } + function emitCloseNT(self2) { + if (self2._writableState && !self2._writableState.emitClose) + return; + if (self2._readableState && !self2._readableState.emitClose) + return; + self2.emit("close"); + } + function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } + } + function emitErrorNT(self2, err) { + self2.emit("error", err); + } + function errorOrDestroy(stream, err) { + var rState = stream._readableState; + var wState = stream._writableState; + if (rState && rState.autoDestroy || wState && wState.autoDestroy) + stream.destroy(err); + else + stream.emit("error", err); + } + module.exports = { + destroy, + undestroy, + errorOrDestroy + }; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/errors-browser.js +var require_errors_browser = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/errors-browser.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } + var codes = {}; + function createErrorType(code, message, Base) { + if (!Base) { + Base = Error; + } + function getMessage(arg1, arg2, arg3) { + if (typeof message === "string") { + return message; + } else { + return message(arg1, arg2, arg3); + } + } + var NodeError = /* @__PURE__ */ function(_Base) { + _inheritsLoose(NodeError2, _Base); + function NodeError2(arg1, arg2, arg3) { + return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; + } + return NodeError2; + }(Base); + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + codes[code] = NodeError; + } + function oneOf(expected, thing) { + if (Array.isArray(expected)) { + var len = expected.length; + expected = expected.map(function(i) { + return String(i); + }); + if (len > 2) { + return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(", "), ", or ") + expected[len - 1]; + } else if (len === 2) { + return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); + } else { + return "of ".concat(thing, " ").concat(expected[0]); + } + } else { + return "of ".concat(thing, " ").concat(String(expected)); + } + } + function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; + } + function endsWith(str, search, this_len) { + if (this_len === void 0 || this_len > str.length) { + this_len = str.length; + } + return str.substring(this_len - search.length, this_len) === search; + } + function includes(str, search, start) { + if (typeof start !== "number") { + start = 0; + } + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } + } + createErrorType("ERR_INVALID_OPT_VALUE", function(name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"'; + }, TypeError); + createErrorType("ERR_INVALID_ARG_TYPE", function(name, expected, actual) { + var determiner; + if (typeof expected === "string" && startsWith(expected, "not ")) { + determiner = "must not be"; + expected = expected.replace(/^not /, ""); + } else { + determiner = "must be"; + } + var msg; + if (endsWith(name, " argument")) { + msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, "type")); + } else { + var type = includes(name, ".") ? "property" : "argument"; + msg = 'The "'.concat(name, '" ').concat(type, " ").concat(determiner, " ").concat(oneOf(expected, "type")); + } + msg += ". Received type ".concat(typeof actual); + return msg; + }, TypeError); + createErrorType("ERR_STREAM_PUSH_AFTER_EOF", "stream.push() after EOF"); + createErrorType("ERR_METHOD_NOT_IMPLEMENTED", function(name) { + return "The " + name + " method is not implemented"; + }); + createErrorType("ERR_STREAM_PREMATURE_CLOSE", "Premature close"); + createErrorType("ERR_STREAM_DESTROYED", function(name) { + return "Cannot call " + name + " after a stream was destroyed"; + }); + createErrorType("ERR_MULTIPLE_CALLBACK", "Callback called multiple times"); + createErrorType("ERR_STREAM_CANNOT_PIPE", "Cannot pipe, not readable"); + createErrorType("ERR_STREAM_WRITE_AFTER_END", "write after end"); + createErrorType("ERR_STREAM_NULL_VALUES", "May not write null values to stream", TypeError); + createErrorType("ERR_UNKNOWN_ENCODING", function(arg) { + return "Unknown encoding: " + arg; + }, TypeError); + createErrorType("ERR_STREAM_UNSHIFT_AFTER_END_EVENT", "stream.unshift() after end event"); + module.exports.codes = codes; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/state.js +var require_state = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/state.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var ERR_INVALID_OPT_VALUE = require_errors_browser().codes.ERR_INVALID_OPT_VALUE; + function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; + } + function getHighWaterMark(state, options, duplexKey, isDuplex) { + var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); + if (hwm != null) { + if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { + var name = isDuplex ? duplexKey : "highWaterMark"; + throw new ERR_INVALID_OPT_VALUE(name, hwm); + } + return Math.floor(hwm); + } + return state.objectMode ? 16 : 16 * 1024; + } + module.exports = { + getHighWaterMark + }; + } +}); + +// node_modules/inherits/inherits_browser.js +var require_inherits_browser = __commonJS({ + "node_modules/inherits/inherits_browser.js"(exports, module) { + init_esbuild_inject(); + if (typeof Object.create === "function") { + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + } + }; + } else { + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor; + var TempCtor = function() { + }; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + }; + } + } +}); + +// node_modules/util-deprecate/browser.js +var require_browser4 = __commonJS({ + "node_modules/util-deprecate/browser.js"(exports, module) { + init_esbuild_inject(); + module.exports = deprecate; + function deprecate(fn, msg) { + if (config("noDeprecation")) { + return fn; + } + var warned = false; + function deprecated() { + if (!warned) { + if (config("throwDeprecation")) { + throw new Error(msg); + } else if (config("traceDeprecation")) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + return deprecated; + } + function config(name) { + try { + if (!window.localStorage) + return false; + } catch (_) { + return false; + } + var val = window.localStorage[name]; + if (null == val) + return false; + return String(val).toLowerCase() === "true"; + } + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/_stream_writable.js +var require_stream_writable = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/_stream_writable.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + module.exports = Writable; + function CorkedRequest(state) { + var _this = this; + this.next = null; + this.entry = null; + this.finish = function() { + onCorkedFinish(_this, state); + }; + } + var Duplex; + Writable.WritableState = WritableState; + var internalUtil = { + deprecate: require_browser4() + }; + var Stream = require_stream_browser(); + var Buffer3 = require_buffer().Buffer; + var OurUint8Array = window.Uint8Array || function() { + }; + function _uint8ArrayToBuffer(chunk) { + return Buffer3.from(chunk); + } + function _isUint8Array(obj) { + return Buffer3.isBuffer(obj) || obj instanceof OurUint8Array; + } + var destroyImpl = require_destroy(); + var _require = require_state(); + var getHighWaterMark = _require.getHighWaterMark; + var _require$codes = require_errors_browser().codes; + var ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE; + var ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED; + var ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK; + var ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE; + var ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; + var ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES; + var ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END; + var ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; + var errorOrDestroy = destroyImpl.errorOrDestroy; + require_inherits_browser()(Writable, Stream); + function nop() { + } + function WritableState(options, stream, isDuplex) { + Duplex = Duplex || require_stream_duplex(); + options = options || {}; + if (typeof isDuplex !== "boolean") + isDuplex = stream instanceof Duplex; + this.objectMode = !!options.objectMode; + if (isDuplex) + this.objectMode = this.objectMode || !!options.writableObjectMode; + this.highWaterMark = getHighWaterMark(this, options, "writableHighWaterMark", isDuplex); + this.finalCalled = false; + this.needDrain = false; + this.ending = false; + this.ended = false; + this.finished = false; + this.destroyed = false; + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + this.defaultEncoding = options.defaultEncoding || "utf8"; + this.length = 0; + this.writing = false; + this.corked = 0; + this.sync = true; + this.bufferProcessing = false; + this.onwrite = function(er) { + onwrite(stream, er); + }; + this.writecb = null; + this.writelen = 0; + this.bufferedRequest = null; + this.lastBufferedRequest = null; + this.pendingcb = 0; + this.prefinished = false; + this.errorEmitted = false; + this.emitClose = options.emitClose !== false; + this.autoDestroy = !!options.autoDestroy; + this.bufferedRequestCount = 0; + this.corkedRequestsFree = new CorkedRequest(this); + } + WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; + }; + (function() { + try { + Object.defineProperty(WritableState.prototype, "buffer", { + get: internalUtil.deprecate(function writableStateBufferGetter() { + return this.getBuffer(); + }, "_writableState.buffer is deprecated. Use _writableState.getBuffer instead.", "DEP0003") + }); + } catch (_) { + } + })(); + var realHasInstance; + if (typeof Symbol === "function" && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === "function") { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function value(object) { + if (realHasInstance.call(this, object)) + return true; + if (this !== Writable) + return false; + return object && object._writableState instanceof WritableState; + } + }); + } else { + realHasInstance = function realHasInstance2(object) { + return object instanceof this; + }; + } + function Writable(options) { + Duplex = Duplex || require_stream_duplex(); + var isDuplex = this instanceof Duplex; + if (!isDuplex && !realHasInstance.call(Writable, this)) + return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex); + this.writable = true; + if (options) { + if (typeof options.write === "function") + this._write = options.write; + if (typeof options.writev === "function") + this._writev = options.writev; + if (typeof options.destroy === "function") + this._destroy = options.destroy; + if (typeof options.final === "function") + this._final = options.final; + } + Stream.call(this); + } + Writable.prototype.pipe = function() { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); + }; + function writeAfterEnd(stream, cb) { + var er = new ERR_STREAM_WRITE_AFTER_END(); + errorOrDestroy(stream, er); + process.nextTick(cb, er); + } + function validChunk(stream, state, chunk, cb) { + var er; + if (chunk === null) { + er = new ERR_STREAM_NULL_VALUES(); + } else if (typeof chunk !== "string" && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE("chunk", ["string", "Buffer"], chunk); + } + if (er) { + errorOrDestroy(stream, er); + process.nextTick(cb, er); + return false; + } + return true; + } + Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + if (isBuf && !Buffer3.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (typeof encoding === "function") { + cb = encoding; + encoding = null; + } + if (isBuf) + encoding = "buffer"; + else if (!encoding) + encoding = state.defaultEncoding; + if (typeof cb !== "function") + cb = nop; + if (state.ending) + writeAfterEnd(this, cb); + else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + return ret; + }; + Writable.prototype.cork = function() { + this._writableState.corked++; + }; + Writable.prototype.uncork = function() { + var state = this._writableState; + if (state.corked) { + state.corked--; + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) + clearBuffer(this, state); + } + }; + Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + if (typeof encoding === "string") + encoding = encoding.toLowerCase(); + if (!(["hex", "utf8", "utf-8", "ascii", "binary", "base64", "ucs2", "ucs-2", "utf16le", "utf-16le", "raw"].indexOf((encoding + "").toLowerCase()) > -1)) + throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; + }; + Object.defineProperty(Writable.prototype, "writableBuffer", { + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } + }); + function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === "string") { + chunk = Buffer3.from(chunk, encoding); + } + return chunk; + } + Object.defineProperty(Writable.prototype, "writableHighWaterMark", { + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } + }); + function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = "buffer"; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + state.length += len; + var ret = state.length < state.highWaterMark; + if (!ret) + state.needDrain = true; + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk, + encoding, + isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + return ret; + } + function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) + state.onwrite(new ERR_STREAM_DESTROYED("write")); + else if (writev) + stream._writev(chunk, state.onwrite); + else + stream._write(chunk, encoding, state.onwrite); + state.sync = false; + } + function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + if (sync) { + process.nextTick(cb, er); + process.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + } else { + cb(er); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + finishMaybe(stream, state); + } + } + function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; + } + function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + if (typeof cb !== "function") + throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); + if (er) + onwriteError(stream, state, sync, er, cb); + else { + var finished = needFinish(state) || stream.destroyed; + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + if (sync) { + process.nextTick(afterWrite, stream, state, finished, cb); + } else { + afterWrite(stream, state, finished, cb); + } + } + } + function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); + } + function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit("drain"); + } + } + function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + if (stream._writev && entry && entry.next) { + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) + allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + doWrite(stream, state, true, state.length, buffer, "", holder.finish); + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + if (state.writing) { + break; + } + } + if (entry === null) + state.lastBufferedRequest = null; + } + state.bufferedRequest = entry; + state.bufferProcessing = false; + } + Writable.prototype._write = function(chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED("_write()")); + }; + Writable.prototype._writev = null; + Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + if (typeof chunk === "function") { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === "function") { + cb = encoding; + encoding = null; + } + if (chunk !== null && chunk !== void 0) + this.write(chunk, encoding); + if (state.corked) { + state.corked = 1; + this.uncork(); + } + if (!state.ending) + endWritable(this, state, cb); + return this; + }; + Object.defineProperty(Writable.prototype, "writableLength", { + enumerable: false, + get: function get() { + return this._writableState.length; + } + }); + function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; + } + function callFinal(stream, state) { + stream._final(function(err) { + state.pendingcb--; + if (err) { + errorOrDestroy(stream, err); + } + state.prefinished = true; + stream.emit("prefinish"); + finishMaybe(stream, state); + }); + } + function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === "function" && !state.destroyed) { + state.pendingcb++; + state.finalCalled = true; + process.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit("prefinish"); + } + } + } + function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit("finish"); + if (state.autoDestroy) { + var rState = stream._readableState; + if (!rState || rState.autoDestroy && rState.endEmitted) { + stream.destroy(); + } + } + } + } + return need; + } + function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once("finish", cb); + } + state.ended = true; + stream.writable = false; + } + function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + state.corkedRequestsFree.next = corkReq; + } + Object.defineProperty(Writable.prototype, "destroyed", { + enumerable: false, + get: function get() { + if (this._writableState === void 0) { + return false; + } + return this._writableState.destroyed; + }, + set: function set(value) { + if (!this._writableState) { + return; + } + this._writableState.destroyed = value; + } + }); + Writable.prototype.destroy = destroyImpl.destroy; + Writable.prototype._undestroy = destroyImpl.undestroy; + Writable.prototype._destroy = function(err, cb) { + cb(err); + }; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/_stream_duplex.js +var require_stream_duplex = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/_stream_duplex.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var objectKeys = Object.keys || function(obj) { + var keys2 = []; + for (var key in obj) { + keys2.push(key); + } + return keys2; + }; + module.exports = Duplex; + var Readable = require_stream_readable(); + var Writable = require_stream_writable(); + require_inherits_browser()(Duplex, Readable); + { + keys = objectKeys(Writable.prototype); + for (v = 0; v < keys.length; v++) { + method = keys[v]; + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; + } + } + var keys; + var method; + var v; + function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + this.allowHalfOpen = true; + if (options) { + if (options.readable === false) + this.readable = false; + if (options.writable === false) + this.writable = false; + if (options.allowHalfOpen === false) { + this.allowHalfOpen = false; + this.once("end", onend); + } + } + } + Object.defineProperty(Duplex.prototype, "writableHighWaterMark", { + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } + }); + Object.defineProperty(Duplex.prototype, "writableBuffer", { + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } + }); + Object.defineProperty(Duplex.prototype, "writableLength", { + enumerable: false, + get: function get() { + return this._writableState.length; + } + }); + function onend() { + if (this._writableState.ended) + return; + process.nextTick(onEndNT, this); + } + function onEndNT(self2) { + self2.end(); + } + Object.defineProperty(Duplex.prototype, "destroyed", { + enumerable: false, + get: function get() { + if (this._readableState === void 0 || this._writableState === void 0) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function set(value) { + if (this._readableState === void 0 || this._writableState === void 0) { + return; + } + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } + }); + } +}); + +// node_modules/string_decoder/lib/string_decoder.js +var require_string_decoder = __commonJS({ + "node_modules/string_decoder/lib/string_decoder.js"(exports) { + "use strict"; + init_esbuild_inject(); + var Buffer3 = require_safe_buffer().Buffer; + var isEncoding = Buffer3.isEncoding || function(encoding) { + encoding = "" + encoding; + switch (encoding && encoding.toLowerCase()) { + case "hex": + case "utf8": + case "utf-8": + case "ascii": + case "binary": + case "base64": + case "ucs2": + case "ucs-2": + case "utf16le": + case "utf-16le": + case "raw": + return true; + default: + return false; + } + }; + function _normalizeEncoding(enc) { + if (!enc) + return "utf8"; + var retried; + while (true) { + switch (enc) { + case "utf8": + case "utf-8": + return "utf8"; + case "ucs2": + case "ucs-2": + case "utf16le": + case "utf-16le": + return "utf16le"; + case "latin1": + case "binary": + return "latin1"; + case "base64": + case "ascii": + case "hex": + return enc; + default: + if (retried) + return; + enc = ("" + enc).toLowerCase(); + retried = true; + } + } + } + function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== "string" && (Buffer3.isEncoding === isEncoding || !isEncoding(enc))) + throw new Error("Unknown encoding: " + enc); + return nenc || enc; + } + exports.StringDecoder = StringDecoder; + function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case "utf16le": + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case "utf8": + this.fillLast = utf8FillLast; + nb = 4; + break; + case "base64": + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer3.allocUnsafe(nb); + } + StringDecoder.prototype.write = function(buf) { + if (buf.length === 0) + return ""; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === void 0) + return ""; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) + return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ""; + }; + StringDecoder.prototype.end = utf8End; + StringDecoder.prototype.text = utf8Text; + StringDecoder.prototype.fillLast = function(buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; + }; + function utf8CheckByte(byte) { + if (byte <= 127) + return 0; + else if (byte >> 5 === 6) + return 2; + else if (byte >> 4 === 14) + return 3; + else if (byte >> 3 === 30) + return 4; + return byte >> 6 === 2 ? -1 : -2; + } + function utf8CheckIncomplete(self2, buf, i) { + var j = buf.length - 1; + if (j < i) + return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) + self2.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) + return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) + self2.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) + return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) + nb = 0; + else + self2.lastNeed = nb - 3; + } + return nb; + } + return 0; + } + function utf8CheckExtraBytes(self2, buf, p) { + if ((buf[0] & 192) !== 128) { + self2.lastNeed = 0; + return "\uFFFD"; + } + if (self2.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 192) !== 128) { + self2.lastNeed = 1; + return "\uFFFD"; + } + if (self2.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 192) !== 128) { + self2.lastNeed = 2; + return "\uFFFD"; + } + } + } + } + function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== void 0) + return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; + } + function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) + return buf.toString("utf8", i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString("utf8", i, end); + } + function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ""; + if (this.lastNeed) + return r + "\uFFFD"; + return r; + } + function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString("utf16le", i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 55296 && c <= 56319) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString("utf16le", i, buf.length - 1); + } + function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ""; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString("utf16le", 0, end); + } + return r; + } + function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) + return buf.toString("base64", i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString("base64", i, buf.length - n); + } + function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ""; + if (this.lastNeed) + return r + this.lastChar.toString("base64", 0, 3 - this.lastNeed); + return r; + } + function simpleWrite(buf) { + return buf.toString(this.encoding); + } + function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ""; + } + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +var require_end_of_stream = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/end-of-stream.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var ERR_STREAM_PREMATURE_CLOSE = require_errors_browser().codes.ERR_STREAM_PREMATURE_CLOSE; + function once(callback) { + var called = false; + return function() { + if (called) + return; + called = true; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + callback.apply(this, args); + }; + } + function noop() { + } + function isRequest(stream) { + return stream.setHeader && typeof stream.abort === "function"; + } + function eos(stream, opts, callback) { + if (typeof opts === "function") + return eos(stream, null, opts); + if (!opts) + opts = {}; + callback = once(callback || noop); + var readable = opts.readable || opts.readable !== false && stream.readable; + var writable = opts.writable || opts.writable !== false && stream.writable; + var onlegacyfinish = function onlegacyfinish2() { + if (!stream.writable) + onfinish(); + }; + var writableEnded = stream._writableState && stream._writableState.finished; + var onfinish = function onfinish2() { + writable = false; + writableEnded = true; + if (!readable) + callback.call(stream); + }; + var readableEnded = stream._readableState && stream._readableState.endEmitted; + var onend = function onend2() { + readable = false; + readableEnded = true; + if (!writable) + callback.call(stream); + }; + var onerror = function onerror2(err) { + callback.call(stream, err); + }; + var onclose = function onclose2() { + var err; + if (readable && !readableEnded) { + if (!stream._readableState || !stream._readableState.ended) + err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + if (writable && !writableEnded) { + if (!stream._writableState || !stream._writableState.ended) + err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + }; + var onrequest = function onrequest2() { + stream.req.on("finish", onfinish); + }; + if (isRequest(stream)) { + stream.on("complete", onfinish); + stream.on("abort", onclose); + if (stream.req) + onrequest(); + else + stream.on("request", onrequest); + } else if (writable && !stream._writableState) { + stream.on("end", onlegacyfinish); + stream.on("close", onlegacyfinish); + } + stream.on("end", onend); + stream.on("finish", onfinish); + if (opts.error !== false) + stream.on("error", onerror); + stream.on("close", onclose); + return function() { + stream.removeListener("complete", onfinish); + stream.removeListener("abort", onclose); + stream.removeListener("request", onrequest); + if (stream.req) + stream.req.removeListener("finish", onfinish); + stream.removeListener("end", onlegacyfinish); + stream.removeListener("close", onlegacyfinish); + stream.removeListener("finish", onfinish); + stream.removeListener("end", onend); + stream.removeListener("error", onerror); + stream.removeListener("close", onclose); + }; + } + module.exports = eos; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/async_iterator.js +var require_async_iterator = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/async_iterator.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var _Object$setPrototypeO; + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true }); + } else { + obj[key] = value; + } + return obj; + } + var finished = require_end_of_stream(); + var kLastResolve = Symbol("lastResolve"); + var kLastReject = Symbol("lastReject"); + var kError = Symbol("error"); + var kEnded = Symbol("ended"); + var kLastPromise = Symbol("lastPromise"); + var kHandlePromise = Symbol("handlePromise"); + var kStream = Symbol("stream"); + function createIterResult(value, done) { + return { + value, + done + }; + } + function readAndResolve(iter) { + var resolve = iter[kLastResolve]; + if (resolve !== null) { + var data = iter[kStream].read(); + if (data !== null) { + iter[kLastPromise] = null; + iter[kLastResolve] = null; + iter[kLastReject] = null; + resolve(createIterResult(data, false)); + } + } + } + function onReadable(iter) { + process.nextTick(readAndResolve, iter); + } + function wrapForNext(lastPromise, iter) { + return function(resolve, reject) { + lastPromise.then(function() { + if (iter[kEnded]) { + resolve(createIterResult(void 0, true)); + return; + } + iter[kHandlePromise](resolve, reject); + }, reject); + }; + } + var AsyncIteratorPrototype = Object.getPrototypeOf(function() { + }); + var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { + get stream() { + return this[kStream]; + }, + next: function next() { + var _this = this; + var error = this[kError]; + if (error !== null) { + return Promise.reject(error); + } + if (this[kEnded]) { + return Promise.resolve(createIterResult(void 0, true)); + } + if (this[kStream].destroyed) { + return new Promise(function(resolve, reject) { + process.nextTick(function() { + if (_this[kError]) { + reject(_this[kError]); + } else { + resolve(createIterResult(void 0, true)); + } + }); + }); + } + var lastPromise = this[kLastPromise]; + var promise; + if (lastPromise) { + promise = new Promise(wrapForNext(lastPromise, this)); + } else { + var data = this[kStream].read(); + if (data !== null) { + return Promise.resolve(createIterResult(data, false)); + } + promise = new Promise(this[kHandlePromise]); + } + this[kLastPromise] = promise; + return promise; + } + }, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function() { + return this; + }), _defineProperty(_Object$setPrototypeO, "return", function _return() { + var _this2 = this; + return new Promise(function(resolve, reject) { + _this2[kStream].destroy(null, function(err) { + if (err) { + reject(err); + return; + } + resolve(createIterResult(void 0, true)); + }); + }); + }), _Object$setPrototypeO), AsyncIteratorPrototype); + var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator2(stream) { + var _Object$create; + var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { + value: stream, + writable: true + }), _defineProperty(_Object$create, kLastResolve, { + value: null, + writable: true + }), _defineProperty(_Object$create, kLastReject, { + value: null, + writable: true + }), _defineProperty(_Object$create, kError, { + value: null, + writable: true + }), _defineProperty(_Object$create, kEnded, { + value: stream._readableState.endEmitted, + writable: true + }), _defineProperty(_Object$create, kHandlePromise, { + value: function value(resolve, reject) { + var data = iterator[kStream].read(); + if (data) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(data, false)); + } else { + iterator[kLastResolve] = resolve; + iterator[kLastReject] = reject; + } + }, + writable: true + }), _Object$create)); + iterator[kLastPromise] = null; + finished(stream, function(err) { + if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") { + var reject = iterator[kLastReject]; + if (reject !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + reject(err); + } + iterator[kError] = err; + return; + } + var resolve = iterator[kLastResolve]; + if (resolve !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(void 0, true)); + } + iterator[kEnded] = true; + }); + stream.on("readable", onReadable.bind(null, iterator)); + return iterator; + }; + module.exports = createReadableStreamAsyncIterator; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/from-browser.js +var require_from_browser = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/from-browser.js"(exports, module) { + init_esbuild_inject(); + module.exports = function() { + throw new Error("Readable.from is not available in the browser"); + }; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/_stream_readable.js +var require_stream_readable = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/_stream_readable.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + module.exports = Readable; + var Duplex; + Readable.ReadableState = ReadableState; + var EE = require_events().EventEmitter; + var EElistenerCount = function EElistenerCount2(emitter, type) { + return emitter.listeners(type).length; + }; + var Stream = require_stream_browser(); + var Buffer3 = require_buffer().Buffer; + var OurUint8Array = window.Uint8Array || function() { + }; + function _uint8ArrayToBuffer(chunk) { + return Buffer3.from(chunk); + } + function _isUint8Array(obj) { + return Buffer3.isBuffer(obj) || obj instanceof OurUint8Array; + } + var debugUtil = require_util(); + var debug; + if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog("stream"); + } else { + debug = function debug2() { + }; + } + var BufferList = require_buffer_list(); + var destroyImpl = require_destroy(); + var _require = require_state(); + var getHighWaterMark = _require.getHighWaterMark; + var _require$codes = require_errors_browser().codes; + var ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE; + var ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF; + var ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED; + var ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; + var StringDecoder; + var createReadableStreamAsyncIterator; + var from; + require_inherits_browser()(Readable, Stream); + var errorOrDestroy = destroyImpl.errorOrDestroy; + var kProxyEvents = ["error", "close", "destroy", "pause", "resume"]; + function prependListener(emitter, event, fn) { + if (typeof emitter.prependListener === "function") + return emitter.prependListener(event, fn); + if (!emitter._events || !emitter._events[event]) + emitter.on(event, fn); + else if (Array.isArray(emitter._events[event])) + emitter._events[event].unshift(fn); + else + emitter._events[event] = [fn, emitter._events[event]]; + } + function ReadableState(options, stream, isDuplex) { + Duplex = Duplex || require_stream_duplex(); + options = options || {}; + if (typeof isDuplex !== "boolean") + isDuplex = stream instanceof Duplex; + this.objectMode = !!options.objectMode; + if (isDuplex) + this.objectMode = this.objectMode || !!options.readableObjectMode; + this.highWaterMark = getHighWaterMark(this, options, "readableHighWaterMark", isDuplex); + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + this.sync = true; + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this.paused = true; + this.emitClose = options.emitClose !== false; + this.autoDestroy = !!options.autoDestroy; + this.destroyed = false; + this.defaultEncoding = options.defaultEncoding || "utf8"; + this.awaitDrain = 0; + this.readingMore = false; + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = require_string_decoder().StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } + } + function Readable(options) { + Duplex = Duplex || require_stream_duplex(); + if (!(this instanceof Readable)) + return new Readable(options); + var isDuplex = this instanceof Duplex; + this._readableState = new ReadableState(options, this, isDuplex); + this.readable = true; + if (options) { + if (typeof options.read === "function") + this._read = options.read; + if (typeof options.destroy === "function") + this._destroy = options.destroy; + } + Stream.call(this); + } + Object.defineProperty(Readable.prototype, "destroyed", { + enumerable: false, + get: function get() { + if (this._readableState === void 0) { + return false; + } + return this._readableState.destroyed; + }, + set: function set(value) { + if (!this._readableState) { + return; + } + this._readableState.destroyed = value; + } + }); + Readable.prototype.destroy = destroyImpl.destroy; + Readable.prototype._undestroy = destroyImpl.undestroy; + Readable.prototype._destroy = function(err, cb) { + cb(err); + }; + Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + if (!state.objectMode) { + if (typeof chunk === "string") { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer3.from(chunk, encoding); + encoding = ""; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); + }; + Readable.prototype.unshift = function(chunk) { + return readableAddChunk(this, chunk, null, true, false); + }; + function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + debug("readableAddChunk", chunk); + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) + er = chunkInvalid(state, chunk); + if (er) { + errorOrDestroy(stream, er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== "string" && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer3.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (addToFront) { + if (state.endEmitted) + errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT()); + else + addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed) { + return false; + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) + addChunk(stream, state, chunk, false); + else + maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); + } + } + return !state.ended && (state.length < state.highWaterMark || state.length === 0); + } + function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + state.awaitDrain = 0; + stream.emit("data", chunk); + } else { + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) + state.buffer.unshift(chunk); + else + state.buffer.push(chunk); + if (state.needReadable) + emitReadable(stream); + } + maybeReadMore(stream, state); + } + function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== "string" && chunk !== void 0 && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE("chunk", ["string", "Buffer", "Uint8Array"], chunk); + } + return er; + } + Readable.prototype.isPaused = function() { + return this._readableState.flowing === false; + }; + Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require_string_decoder().StringDecoder; + var decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; + this._readableState.encoding = this._readableState.decoder.encoding; + var p = this._readableState.buffer.head; + var content = ""; + while (p !== null) { + content += decoder.write(p.data); + p = p.next; + } + this._readableState.buffer.clear(); + if (content !== "") + this._readableState.buffer.push(content); + this._readableState.length = content.length; + return this; + }; + var MAX_HWM = 1073741824; + function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; + } + function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) + return 0; + if (state.objectMode) + return 1; + if (n !== n) { + if (state.flowing && state.length) + return state.buffer.head.data.length; + else + return state.length; + } + if (n > state.highWaterMark) + state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) + return n; + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; + } + Readable.prototype.read = function(n) { + debug("read", n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + if (n !== 0) + state.emittedReadable = false; + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + debug("read: emitReadable", state.length, state.ended); + if (state.length === 0 && state.ended) + endReadable(this); + else + emitReadable(this); + return null; + } + n = howMuchToRead(n, state); + if (n === 0 && state.ended) { + if (state.length === 0) + endReadable(this); + return null; + } + var doRead = state.needReadable; + debug("need readable", doRead); + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug("length less than watermark", doRead); + } + if (state.ended || state.reading) { + doRead = false; + debug("reading or ended", doRead); + } else if (doRead) { + debug("do read"); + state.reading = true; + state.sync = true; + if (state.length === 0) + state.needReadable = true; + this._read(state.highWaterMark); + state.sync = false; + if (!state.reading) + n = howMuchToRead(nOrig, state); + } + var ret; + if (n > 0) + ret = fromList(n, state); + else + ret = null; + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + state.awaitDrain = 0; + } + if (state.length === 0) { + if (!state.ended) + state.needReadable = true; + if (nOrig !== n && state.ended) + endReadable(this); + } + if (ret !== null) + this.emit("data", ret); + return ret; + }; + function onEofChunk(stream, state) { + debug("onEofChunk"); + if (state.ended) + return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + if (state.sync) { + emitReadable(stream); + } else { + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } + } + } + function emitReadable(stream) { + var state = stream._readableState; + debug("emitReadable", state.needReadable, state.emittedReadable); + state.needReadable = false; + if (!state.emittedReadable) { + debug("emitReadable", state.flowing); + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); + } + } + function emitReadable_(stream) { + var state = stream._readableState; + debug("emitReadable_", state.destroyed, state.length, state.ended); + if (!state.destroyed && (state.length || state.ended)) { + stream.emit("readable"); + state.emittedReadable = false; + } + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); + } + function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } + } + function maybeReadMore_(stream, state) { + while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { + var len = state.length; + debug("maybeReadMore read 0"); + stream.read(0); + if (len === state.length) + break; + } + state.readingMore = false; + } + Readable.prototype._read = function(n) { + errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED("_read()")); + }; + Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug("pipe count=%d opts=%j", state.pipesCount, pipeOpts); + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once("end", endFn); + dest.on("unpipe", onunpipe); + function onunpipe(readable, unpipeInfo) { + debug("onunpipe"); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + function onend() { + debug("onend"); + dest.end(); + } + var ondrain = pipeOnDrain(src); + dest.on("drain", ondrain); + var cleanedUp = false; + function cleanup() { + debug("cleanup"); + dest.removeListener("close", onclose); + dest.removeListener("finish", onfinish); + dest.removeListener("drain", ondrain); + dest.removeListener("error", onerror); + dest.removeListener("unpipe", onunpipe); + src.removeListener("end", onend); + src.removeListener("end", unpipe); + src.removeListener("data", ondata); + cleanedUp = true; + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) + ondrain(); + } + src.on("data", ondata); + function ondata(chunk) { + debug("ondata"); + var ret = dest.write(chunk); + debug("dest.write", ret); + if (ret === false) { + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug("false write response, pause", state.awaitDrain); + state.awaitDrain++; + } + src.pause(); + } + } + function onerror(er) { + debug("onerror", er); + unpipe(); + dest.removeListener("error", onerror); + if (EElistenerCount(dest, "error") === 0) + errorOrDestroy(dest, er); + } + prependListener(dest, "error", onerror); + function onclose() { + dest.removeListener("finish", onfinish); + unpipe(); + } + dest.once("close", onclose); + function onfinish() { + debug("onfinish"); + dest.removeListener("close", onclose); + unpipe(); + } + dest.once("finish", onfinish); + function unpipe() { + debug("unpipe"); + src.unpipe(dest); + } + dest.emit("pipe", src); + if (!state.flowing) { + debug("pipe resume"); + src.resume(); + } + return dest; + }; + function pipeOnDrain(src) { + return function pipeOnDrainFunctionResult() { + var state = src._readableState; + debug("pipeOnDrain", state.awaitDrain); + if (state.awaitDrain) + state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, "data")) { + state.flowing = true; + flow(src); + } + }; + } + Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + var unpipeInfo = { + hasUnpiped: false + }; + if (state.pipesCount === 0) + return this; + if (state.pipesCount === 1) { + if (dest && dest !== state.pipes) + return this; + if (!dest) + dest = state.pipes; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) + dest.emit("unpipe", this, unpipeInfo); + return this; + } + if (!dest) { + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + for (var i = 0; i < len; i++) { + dests[i].emit("unpipe", this, { + hasUnpiped: false + }); + } + return this; + } + var index = indexOf(state.pipes, dest); + if (index === -1) + return this; + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + dest.emit("unpipe", this, unpipeInfo); + return this; + }; + Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + var state = this._readableState; + if (ev === "data") { + state.readableListening = this.listenerCount("readable") > 0; + if (state.flowing !== false) + this.resume(); + } else if (ev === "readable") { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + debug("on readable", state.length, state.reading); + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + return res; + }; + Readable.prototype.addListener = Readable.prototype.on; + Readable.prototype.removeListener = function(ev, fn) { + var res = Stream.prototype.removeListener.call(this, ev, fn); + if (ev === "readable") { + process.nextTick(updateReadableListening, this); + } + return res; + }; + Readable.prototype.removeAllListeners = function(ev) { + var res = Stream.prototype.removeAllListeners.apply(this, arguments); + if (ev === "readable" || ev === void 0) { + process.nextTick(updateReadableListening, this); + } + return res; + }; + function updateReadableListening(self2) { + var state = self2._readableState; + state.readableListening = self2.listenerCount("readable") > 0; + if (state.resumeScheduled && !state.paused) { + state.flowing = true; + } else if (self2.listenerCount("data") > 0) { + self2.resume(); + } + } + function nReadingNextTick(self2) { + debug("readable nexttick read 0"); + self2.read(0); + } + Readable.prototype.resume = function() { + var state = this._readableState; + if (!state.flowing) { + debug("resume"); + state.flowing = !state.readableListening; + resume(this, state); + } + state.paused = false; + return this; + }; + function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } + } + function resume_(stream, state) { + debug("resume", state.reading); + if (!state.reading) { + stream.read(0); + } + state.resumeScheduled = false; + stream.emit("resume"); + flow(stream); + if (state.flowing && !state.reading) + stream.read(0); + } + Readable.prototype.pause = function() { + debug("call pause flowing=%j", this._readableState.flowing); + if (this._readableState.flowing !== false) { + debug("pause"); + this._readableState.flowing = false; + this.emit("pause"); + } + this._readableState.paused = true; + return this; + }; + function flow(stream) { + var state = stream._readableState; + debug("flow", state.flowing); + while (state.flowing && stream.read() !== null) { + ; + } + } + Readable.prototype.wrap = function(stream) { + var _this = this; + var state = this._readableState; + var paused = false; + stream.on("end", function() { + debug("wrapped end"); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + _this.push(chunk); + } + _this.push(null); + }); + stream.on("data", function(chunk) { + debug("wrapped data"); + if (state.decoder) + chunk = state.decoder.write(chunk); + if (state.objectMode && (chunk === null || chunk === void 0)) + return; + else if (!state.objectMode && (!chunk || !chunk.length)) + return; + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + for (var i in stream) { + if (this[i] === void 0 && typeof stream[i] === "function") { + this[i] = function methodWrap(method) { + return function methodWrapReturnFunction() { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + this._read = function(n2) { + debug("wrapped _read", n2); + if (paused) { + paused = false; + stream.resume(); + } + }; + return this; + }; + if (typeof Symbol === "function") { + Readable.prototype[Symbol.asyncIterator] = function() { + if (createReadableStreamAsyncIterator === void 0) { + createReadableStreamAsyncIterator = require_async_iterator(); + } + return createReadableStreamAsyncIterator(this); + }; + } + Object.defineProperty(Readable.prototype, "readableHighWaterMark", { + enumerable: false, + get: function get() { + return this._readableState.highWaterMark; + } + }); + Object.defineProperty(Readable.prototype, "readableBuffer", { + enumerable: false, + get: function get() { + return this._readableState && this._readableState.buffer; + } + }); + Object.defineProperty(Readable.prototype, "readableFlowing", { + enumerable: false, + get: function get() { + return this._readableState.flowing; + }, + set: function set(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } + }); + Readable._fromList = fromList; + Object.defineProperty(Readable.prototype, "readableLength", { + enumerable: false, + get: function get() { + return this._readableState.length; + } + }); + function fromList(n, state) { + if (state.length === 0) + return null; + var ret; + if (state.objectMode) + ret = state.buffer.shift(); + else if (!n || n >= state.length) { + if (state.decoder) + ret = state.buffer.join(""); + else if (state.buffer.length === 1) + ret = state.buffer.first(); + else + ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + ret = state.buffer.consume(n, state.decoder); + } + return ret; + } + function endReadable(stream) { + var state = stream._readableState; + debug("endReadable", state.endEmitted); + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } + } + function endReadableNT(state, stream) { + debug("endReadableNT", state.endEmitted, state.length); + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit("end"); + if (state.autoDestroy) { + var wState = stream._writableState; + if (!wState || wState.autoDestroy && wState.finished) { + stream.destroy(); + } + } + } + } + if (typeof Symbol === "function") { + Readable.from = function(iterable, opts) { + if (from === void 0) { + from = require_from_browser(); + } + return from(Readable, iterable, opts); + }; + } + function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) + return i; + } + return -1; + } + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/_stream_transform.js +var require_stream_transform = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/_stream_transform.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + module.exports = Transform; + var _require$codes = require_errors_browser().codes; + var ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED; + var ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK; + var ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING; + var ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; + var Duplex = require_stream_duplex(); + require_inherits_browser()(Transform, Duplex); + function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + var cb = ts.writecb; + if (cb === null) { + return this.emit("error", new ERR_MULTIPLE_CALLBACK()); + } + ts.writechunk = null; + ts.writecb = null; + if (data != null) + this.push(data); + cb(er); + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } + } + function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + Duplex.call(this, options); + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + this._readableState.needReadable = true; + this._readableState.sync = false; + if (options) { + if (typeof options.transform === "function") + this._transform = options.transform; + if (typeof options.flush === "function") + this._flush = options.flush; + } + this.on("prefinish", prefinish); + } + function prefinish() { + var _this = this; + if (typeof this._flush === "function" && !this._readableState.destroyed) { + this._flush(function(er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } + } + Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); + }; + Transform.prototype._transform = function(chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED("_transform()")); + }; + Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } + }; + Transform.prototype._read = function(n) { + var ts = this._transformState; + if (ts.writechunk !== null && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + ts.needTransform = true; + } + }; + Transform.prototype._destroy = function(err, cb) { + Duplex.prototype._destroy.call(this, err, function(err2) { + cb(err2); + }); + }; + function done(stream, er, data) { + if (er) + return stream.emit("error", er); + if (data != null) + stream.push(data); + if (stream._writableState.length) + throw new ERR_TRANSFORM_WITH_LENGTH_0(); + if (stream._transformState.transforming) + throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); + return stream.push(null); + } + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/_stream_passthrough.js +var require_stream_passthrough = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/_stream_passthrough.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + module.exports = PassThrough; + var Transform = require_stream_transform(); + require_inherits_browser()(PassThrough, Transform); + function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + Transform.call(this, options); + } + PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); + }; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/pipeline.js +var require_pipeline = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/lib/internal/streams/pipeline.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + var eos; + function once(callback) { + var called = false; + return function() { + if (called) + return; + called = true; + callback.apply(void 0, arguments); + }; + } + var _require$codes = require_errors_browser().codes; + var ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS; + var ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; + function noop(err) { + if (err) + throw err; + } + function isRequest(stream) { + return stream.setHeader && typeof stream.abort === "function"; + } + function destroyer(stream, reading, writing, callback) { + callback = once(callback); + var closed = false; + stream.on("close", function() { + closed = true; + }); + if (eos === void 0) + eos = require_end_of_stream(); + eos(stream, { + readable: reading, + writable: writing + }, function(err) { + if (err) + return callback(err); + closed = true; + callback(); + }); + var destroyed = false; + return function(err) { + if (closed) + return; + if (destroyed) + return; + destroyed = true; + if (isRequest(stream)) + return stream.abort(); + if (typeof stream.destroy === "function") + return stream.destroy(); + callback(err || new ERR_STREAM_DESTROYED("pipe")); + }; + } + function call(fn) { + fn(); + } + function pipe(from, to) { + return from.pipe(to); + } + function popCallback(streams) { + if (!streams.length) + return noop; + if (typeof streams[streams.length - 1] !== "function") + return noop; + return streams.pop(); + } + function pipeline() { + for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { + streams[_key] = arguments[_key]; + } + var callback = popCallback(streams); + if (Array.isArray(streams[0])) + streams = streams[0]; + if (streams.length < 2) { + throw new ERR_MISSING_ARGS("streams"); + } + var error; + var destroys = streams.map(function(stream, i) { + var reading = i < streams.length - 1; + var writing = i > 0; + return destroyer(stream, reading, writing, function(err) { + if (!error) + error = err; + if (err) + destroys.forEach(call); + if (reading) + return; + destroys.forEach(call); + callback(error); + }); + }); + return streams.reduce(pipe); + } + module.exports = pipeline; + } +}); + +// node_modules/simple-peer/node_modules/readable-stream/readable-browser.js +var require_readable_browser = __commonJS({ + "node_modules/simple-peer/node_modules/readable-stream/readable-browser.js"(exports, module) { + init_esbuild_inject(); + exports = module.exports = require_stream_readable(); + exports.Stream = exports; + exports.Readable = exports; + exports.Writable = require_stream_writable(); + exports.Duplex = require_stream_duplex(); + exports.Transform = require_stream_transform(); + exports.PassThrough = require_stream_passthrough(); + exports.finished = require_end_of_stream(); + exports.pipeline = require_pipeline(); + } +}); + +// node_modules/queue-microtask/index.js +var require_queue_microtask = __commonJS({ + "node_modules/queue-microtask/index.js"(exports, module) { + init_esbuild_inject(); + var promise; + module.exports = typeof queueMicrotask === "function" ? queueMicrotask.bind(typeof window !== "undefined" ? window : window) : (cb) => (promise || (promise = Promise.resolve())).then(cb).catch((err) => setTimeout(() => { + throw err; + }, 0)); + } +}); + +// node_modules/err-code/index.js +var require_err_code = __commonJS({ + "node_modules/err-code/index.js"(exports, module) { + "use strict"; + init_esbuild_inject(); + function assign(obj, props) { + for (const key in props) { + Object.defineProperty(obj, key, { + value: props[key], + enumerable: true, + configurable: true + }); + } + return obj; + } + function createError(err, code, props) { + if (!err || typeof err === "string") { + throw new TypeError("Please pass an Error to err-code"); + } + if (!props) { + props = {}; + } + if (typeof code === "object") { + props = code; + code = ""; + } + if (code) { + props.code = code; + } + try { + return assign(err, props); + } catch (_) { + props.message = err.message; + props.stack = err.stack; + const ErrClass = function() { + }; + ErrClass.prototype = Object.create(Object.getPrototypeOf(err)); + const output = assign(new ErrClass(), props); + return output; + } + } + module.exports = createError; + } +}); + +// node_modules/simple-peer/index.js +var require_simple_peer = __commonJS({ + "node_modules/simple-peer/index.js"(exports, module) { + init_esbuild_inject(); + var debug = require_browser2()("simple-peer"); + var getBrowserRTC = require_get_browser_rtc(); + var randombytes = require_browser3(); + var stream = require_readable_browser(); + var queueMicrotask2 = require_queue_microtask(); + var errCode = require_err_code(); + var { Buffer: Buffer3 } = require_buffer(); + var MAX_BUFFERED_AMOUNT = 64 * 1024; + var ICECOMPLETE_TIMEOUT = 5 * 1e3; + var CHANNEL_CLOSING_TIMEOUT = 5 * 1e3; + function filterTrickle(sdp) { + return sdp.replace(/a=ice-options:trickle\s\n/g, ""); + } + function warn(message) { + console.warn(message); + } + var Peer = class extends stream.Duplex { + constructor(opts) { + opts = Object.assign({ + allowHalfOpen: false + }, opts); + super(opts); + this._id = randombytes(4).toString("hex").slice(0, 7); + this._debug("new peer %o", opts); + this.channelName = opts.initiator ? opts.channelName || randombytes(20).toString("hex") : null; + this.initiator = opts.initiator || false; + this.channelConfig = opts.channelConfig || Peer.channelConfig; + this.channelNegotiated = this.channelConfig.negotiated; + this.config = Object.assign({}, Peer.config, opts.config); + this.offerOptions = opts.offerOptions || {}; + this.answerOptions = opts.answerOptions || {}; + this.sdpTransform = opts.sdpTransform || ((sdp) => sdp); + this.streams = opts.streams || (opts.stream ? [opts.stream] : []); + this.trickle = opts.trickle !== void 0 ? opts.trickle : true; + this.allowHalfTrickle = opts.allowHalfTrickle !== void 0 ? opts.allowHalfTrickle : false; + this.iceCompleteTimeout = opts.iceCompleteTimeout || ICECOMPLETE_TIMEOUT; + this.destroyed = false; + this.destroying = false; + this._connected = false; + this.remoteAddress = void 0; + this.remoteFamily = void 0; + this.remotePort = void 0; + this.localAddress = void 0; + this.localFamily = void 0; + this.localPort = void 0; + this._wrtc = opts.wrtc && typeof opts.wrtc === "object" ? opts.wrtc : getBrowserRTC(); + if (!this._wrtc) { + if (typeof window === "undefined") { + throw errCode(new Error("No WebRTC support: Specify `opts.wrtc` option in this environment"), "ERR_WEBRTC_SUPPORT"); + } else { + throw errCode(new Error("No WebRTC support: Not a supported browser"), "ERR_WEBRTC_SUPPORT"); + } + } + this._pcReady = false; + this._channelReady = false; + this._iceComplete = false; + this._iceCompleteTimer = null; + this._channel = null; + this._pendingCandidates = []; + this._isNegotiating = false; + this._firstNegotiation = true; + this._batchedNegotiation = false; + this._queuedNegotiation = false; + this._sendersAwaitingStable = []; + this._senderMap = /* @__PURE__ */ new Map(); + this._closingInterval = null; + this._remoteTracks = []; + this._remoteStreams = []; + this._chunk = null; + this._cb = null; + this._interval = null; + try { + this._pc = new this._wrtc.RTCPeerConnection(this.config); + } catch (err) { + this.destroy(errCode(err, "ERR_PC_CONSTRUCTOR")); + return; + } + this._isReactNativeWebrtc = typeof this._pc._peerConnectionId === "number"; + this._pc.oniceconnectionstatechange = () => { + this._onIceStateChange(); + }; + this._pc.onicegatheringstatechange = () => { + this._onIceStateChange(); + }; + this._pc.onconnectionstatechange = () => { + this._onConnectionStateChange(); + }; + this._pc.onsignalingstatechange = () => { + this._onSignalingStateChange(); + }; + this._pc.onicecandidate = (event) => { + this._onIceCandidate(event); + }; + if (typeof this._pc.peerIdentity === "object") { + this._pc.peerIdentity.catch((err) => { + this.destroy(errCode(err, "ERR_PC_PEER_IDENTITY")); + }); + } + if (this.initiator || this.channelNegotiated) { + this._setupData({ + channel: this._pc.createDataChannel(this.channelName, this.channelConfig) + }); + } else { + this._pc.ondatachannel = (event) => { + this._setupData(event); + }; + } + if (this.streams) { + this.streams.forEach((stream2) => { + this.addStream(stream2); + }); + } + this._pc.ontrack = (event) => { + this._onTrack(event); + }; + this._debug("initial negotiation"); + this._needsNegotiation(); + this._onFinishBound = () => { + this._onFinish(); + }; + this.once("finish", this._onFinishBound); + } + get bufferSize() { + return this._channel && this._channel.bufferedAmount || 0; + } + get connected() { + return this._connected && this._channel.readyState === "open"; + } + address() { + return { port: this.localPort, family: this.localFamily, address: this.localAddress }; + } + signal(data) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot signal after peer is destroyed"), "ERR_DESTROYED"); + if (typeof data === "string") { + try { + data = JSON.parse(data); + } catch (err) { + data = {}; + } + } + this._debug("signal()"); + if (data.renegotiate && this.initiator) { + this._debug("got request to renegotiate"); + this._needsNegotiation(); + } + if (data.transceiverRequest && this.initiator) { + this._debug("got request for transceiver"); + this.addTransceiver(data.transceiverRequest.kind, data.transceiverRequest.init); + } + if (data.candidate) { + if (this._pc.remoteDescription && this._pc.remoteDescription.type) { + this._addIceCandidate(data.candidate); + } else { + this._pendingCandidates.push(data.candidate); + } + } + if (data.sdp) { + this._pc.setRemoteDescription(new this._wrtc.RTCSessionDescription(data)).then(() => { + if (this.destroyed) + return; + this._pendingCandidates.forEach((candidate) => { + this._addIceCandidate(candidate); + }); + this._pendingCandidates = []; + if (this._pc.remoteDescription.type === "offer") + this._createAnswer(); + }).catch((err) => { + this.destroy(errCode(err, "ERR_SET_REMOTE_DESCRIPTION")); + }); + } + if (!data.sdp && !data.candidate && !data.renegotiate && !data.transceiverRequest) { + this.destroy(errCode(new Error("signal() called with invalid signal data"), "ERR_SIGNALING")); + } + } + _addIceCandidate(candidate) { + const iceCandidateObj = new this._wrtc.RTCIceCandidate(candidate); + this._pc.addIceCandidate(iceCandidateObj).catch((err) => { + if (!iceCandidateObj.address || iceCandidateObj.address.endsWith(".local")) { + warn("Ignoring unsupported ICE candidate."); + } else { + this.destroy(errCode(err, "ERR_ADD_ICE_CANDIDATE")); + } + }); + } + send(chunk) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot send after peer is destroyed"), "ERR_DESTROYED"); + this._channel.send(chunk); + } + addTransceiver(kind, init) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot addTransceiver after peer is destroyed"), "ERR_DESTROYED"); + this._debug("addTransceiver()"); + if (this.initiator) { + try { + this._pc.addTransceiver(kind, init); + this._needsNegotiation(); + } catch (err) { + this.destroy(errCode(err, "ERR_ADD_TRANSCEIVER")); + } + } else { + this.emit("signal", { + type: "transceiverRequest", + transceiverRequest: { kind, init } + }); + } + } + addStream(stream2) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot addStream after peer is destroyed"), "ERR_DESTROYED"); + this._debug("addStream()"); + stream2.getTracks().forEach((track) => { + this.addTrack(track, stream2); + }); + } + addTrack(track, stream2) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot addTrack after peer is destroyed"), "ERR_DESTROYED"); + this._debug("addTrack()"); + const submap = this._senderMap.get(track) || /* @__PURE__ */ new Map(); + let sender = submap.get(stream2); + if (!sender) { + sender = this._pc.addTrack(track, stream2); + submap.set(stream2, sender); + this._senderMap.set(track, submap); + this._needsNegotiation(); + } else if (sender.removed) { + throw errCode(new Error("Track has been removed. You should enable/disable tracks that you want to re-add."), "ERR_SENDER_REMOVED"); + } else { + throw errCode(new Error("Track has already been added to that stream."), "ERR_SENDER_ALREADY_ADDED"); + } + } + replaceTrack(oldTrack, newTrack, stream2) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot replaceTrack after peer is destroyed"), "ERR_DESTROYED"); + this._debug("replaceTrack()"); + const submap = this._senderMap.get(oldTrack); + const sender = submap ? submap.get(stream2) : null; + if (!sender) { + throw errCode(new Error("Cannot replace track that was never added."), "ERR_TRACK_NOT_ADDED"); + } + if (newTrack) + this._senderMap.set(newTrack, submap); + if (sender.replaceTrack != null) { + sender.replaceTrack(newTrack); + } else { + this.destroy(errCode(new Error("replaceTrack is not supported in this browser"), "ERR_UNSUPPORTED_REPLACETRACK")); + } + } + removeTrack(track, stream2) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot removeTrack after peer is destroyed"), "ERR_DESTROYED"); + this._debug("removeSender()"); + const submap = this._senderMap.get(track); + const sender = submap ? submap.get(stream2) : null; + if (!sender) { + throw errCode(new Error("Cannot remove track that was never added."), "ERR_TRACK_NOT_ADDED"); + } + try { + sender.removed = true; + this._pc.removeTrack(sender); + } catch (err) { + if (err.name === "NS_ERROR_UNEXPECTED") { + this._sendersAwaitingStable.push(sender); + } else { + this.destroy(errCode(err, "ERR_REMOVE_TRACK")); + } + } + this._needsNegotiation(); + } + removeStream(stream2) { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot removeStream after peer is destroyed"), "ERR_DESTROYED"); + this._debug("removeSenders()"); + stream2.getTracks().forEach((track) => { + this.removeTrack(track, stream2); + }); + } + _needsNegotiation() { + this._debug("_needsNegotiation"); + if (this._batchedNegotiation) + return; + this._batchedNegotiation = true; + queueMicrotask2(() => { + this._batchedNegotiation = false; + if (this.initiator || !this._firstNegotiation) { + this._debug("starting batched negotiation"); + this.negotiate(); + } else { + this._debug("non-initiator initial negotiation request discarded"); + } + this._firstNegotiation = false; + }); + } + negotiate() { + if (this.destroying) + return; + if (this.destroyed) + throw errCode(new Error("cannot negotiate after peer is destroyed"), "ERR_DESTROYED"); + if (this.initiator) { + if (this._isNegotiating) { + this._queuedNegotiation = true; + this._debug("already negotiating, queueing"); + } else { + this._debug("start negotiation"); + setTimeout(() => { + this._createOffer(); + }, 0); + } + } else { + if (this._isNegotiating) { + this._queuedNegotiation = true; + this._debug("already negotiating, queueing"); + } else { + this._debug("requesting negotiation from initiator"); + this.emit("signal", { + type: "renegotiate", + renegotiate: true + }); + } + } + this._isNegotiating = true; + } + destroy(err) { + this._destroy(err, () => { + }); + } + _destroy(err, cb) { + if (this.destroyed || this.destroying) + return; + this.destroying = true; + this._debug("destroying (error: %s)", err && (err.message || err)); + queueMicrotask2(() => { + this.destroyed = true; + this.destroying = false; + this._debug("destroy (error: %s)", err && (err.message || err)); + this.readable = this.writable = false; + if (!this._readableState.ended) + this.push(null); + if (!this._writableState.finished) + this.end(); + this._connected = false; + this._pcReady = false; + this._channelReady = false; + this._remoteTracks = null; + this._remoteStreams = null; + this._senderMap = null; + clearInterval(this._closingInterval); + this._closingInterval = null; + clearInterval(this._interval); + this._interval = null; + this._chunk = null; + this._cb = null; + if (this._onFinishBound) + this.removeListener("finish", this._onFinishBound); + this._onFinishBound = null; + if (this._channel) { + try { + this._channel.close(); + } catch (err2) { + } + this._channel.onmessage = null; + this._channel.onopen = null; + this._channel.onclose = null; + this._channel.onerror = null; + } + if (this._pc) { + try { + this._pc.close(); + } catch (err2) { + } + this._pc.oniceconnectionstatechange = null; + this._pc.onicegatheringstatechange = null; + this._pc.onsignalingstatechange = null; + this._pc.onicecandidate = null; + this._pc.ontrack = null; + this._pc.ondatachannel = null; + } + this._pc = null; + this._channel = null; + if (err) + this.emit("error", err); + this.emit("close"); + cb(); + }); + } + _setupData(event) { + if (!event.channel) { + return this.destroy(errCode(new Error("Data channel event is missing `channel` property"), "ERR_DATA_CHANNEL")); + } + this._channel = event.channel; + this._channel.binaryType = "arraybuffer"; + if (typeof this._channel.bufferedAmountLowThreshold === "number") { + this._channel.bufferedAmountLowThreshold = MAX_BUFFERED_AMOUNT; + } + this.channelName = this._channel.label; + this._channel.onmessage = (event2) => { + this._onChannelMessage(event2); + }; + this._channel.onbufferedamountlow = () => { + this._onChannelBufferedAmountLow(); + }; + this._channel.onopen = () => { + this._onChannelOpen(); + }; + this._channel.onclose = () => { + this._onChannelClose(); + }; + this._channel.onerror = (event2) => { + const err = event2.error instanceof Error ? event2.error : new Error(`Datachannel error: ${event2.message} ${event2.filename}:${event2.lineno}:${event2.colno}`); + this.destroy(errCode(err, "ERR_DATA_CHANNEL")); + }; + let isClosing = false; + this._closingInterval = setInterval(() => { + if (this._channel && this._channel.readyState === "closing") { + if (isClosing) + this._onChannelClose(); + isClosing = true; + } else { + isClosing = false; + } + }, CHANNEL_CLOSING_TIMEOUT); + } + _read() { + } + _write(chunk, encoding, cb) { + if (this.destroyed) + return cb(errCode(new Error("cannot write after peer is destroyed"), "ERR_DATA_CHANNEL")); + if (this._connected) { + try { + this.send(chunk); + } catch (err) { + return this.destroy(errCode(err, "ERR_DATA_CHANNEL")); + } + if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) { + this._debug("start backpressure: bufferedAmount %d", this._channel.bufferedAmount); + this._cb = cb; + } else { + cb(null); + } + } else { + this._debug("write before connect"); + this._chunk = chunk; + this._cb = cb; + } + } + _onFinish() { + if (this.destroyed) + return; + const destroySoon = () => { + setTimeout(() => this.destroy(), 1e3); + }; + if (this._connected) { + destroySoon(); + } else { + this.once("connect", destroySoon); + } + } + _startIceCompleteTimeout() { + if (this.destroyed) + return; + if (this._iceCompleteTimer) + return; + this._debug("started iceComplete timeout"); + this._iceCompleteTimer = setTimeout(() => { + if (!this._iceComplete) { + this._iceComplete = true; + this._debug("iceComplete timeout completed"); + this.emit("iceTimeout"); + this.emit("_iceComplete"); + } + }, this.iceCompleteTimeout); + } + _createOffer() { + if (this.destroyed) + return; + this._pc.createOffer(this.offerOptions).then((offer) => { + if (this.destroyed) + return; + if (!this.trickle && !this.allowHalfTrickle) + offer.sdp = filterTrickle(offer.sdp); + offer.sdp = this.sdpTransform(offer.sdp); + const sendOffer = () => { + if (this.destroyed) + return; + const signal = this._pc.localDescription || offer; + this._debug("signal"); + this.emit("signal", { + type: signal.type, + sdp: signal.sdp + }); + }; + const onSuccess = () => { + this._debug("createOffer success"); + if (this.destroyed) + return; + if (this.trickle || this._iceComplete) + sendOffer(); + else + this.once("_iceComplete", sendOffer); + }; + const onError = (err) => { + this.destroy(errCode(err, "ERR_SET_LOCAL_DESCRIPTION")); + }; + this._pc.setLocalDescription(offer).then(onSuccess).catch(onError); + }).catch((err) => { + this.destroy(errCode(err, "ERR_CREATE_OFFER")); + }); + } + _requestMissingTransceivers() { + if (this._pc.getTransceivers) { + this._pc.getTransceivers().forEach((transceiver) => { + if (!transceiver.mid && transceiver.sender.track && !transceiver.requested) { + transceiver.requested = true; + this.addTransceiver(transceiver.sender.track.kind); + } + }); + } + } + _createAnswer() { + if (this.destroyed) + return; + this._pc.createAnswer(this.answerOptions).then((answer) => { + if (this.destroyed) + return; + if (!this.trickle && !this.allowHalfTrickle) + answer.sdp = filterTrickle(answer.sdp); + answer.sdp = this.sdpTransform(answer.sdp); + const sendAnswer = () => { + if (this.destroyed) + return; + const signal = this._pc.localDescription || answer; + this._debug("signal"); + this.emit("signal", { + type: signal.type, + sdp: signal.sdp + }); + if (!this.initiator) + this._requestMissingTransceivers(); + }; + const onSuccess = () => { + if (this.destroyed) + return; + if (this.trickle || this._iceComplete) + sendAnswer(); + else + this.once("_iceComplete", sendAnswer); + }; + const onError = (err) => { + this.destroy(errCode(err, "ERR_SET_LOCAL_DESCRIPTION")); + }; + this._pc.setLocalDescription(answer).then(onSuccess).catch(onError); + }).catch((err) => { + this.destroy(errCode(err, "ERR_CREATE_ANSWER")); + }); + } + _onConnectionStateChange() { + if (this.destroyed) + return; + if (this._pc.connectionState === "failed") { + this.destroy(errCode(new Error("Connection failed."), "ERR_CONNECTION_FAILURE")); + } + } + _onIceStateChange() { + if (this.destroyed) + return; + const iceConnectionState = this._pc.iceConnectionState; + const iceGatheringState = this._pc.iceGatheringState; + this._debug( + "iceStateChange (connection: %s) (gathering: %s)", + iceConnectionState, + iceGatheringState + ); + this.emit("iceStateChange", iceConnectionState, iceGatheringState); + if (iceConnectionState === "connected" || iceConnectionState === "completed") { + this._pcReady = true; + this._maybeReady(); + } + if (iceConnectionState === "failed") { + this.destroy(errCode(new Error("Ice connection failed."), "ERR_ICE_CONNECTION_FAILURE")); + } + if (iceConnectionState === "closed") { + this.destroy(errCode(new Error("Ice connection closed."), "ERR_ICE_CONNECTION_CLOSED")); + } + } + getStats(cb) { + const flattenValues = (report) => { + if (Object.prototype.toString.call(report.values) === "[object Array]") { + report.values.forEach((value) => { + Object.assign(report, value); + }); + } + return report; + }; + if (this._pc.getStats.length === 0 || this._isReactNativeWebrtc) { + this._pc.getStats().then((res) => { + const reports = []; + res.forEach((report) => { + reports.push(flattenValues(report)); + }); + cb(null, reports); + }, (err) => cb(err)); + } else if (this._pc.getStats.length > 0) { + this._pc.getStats((res) => { + if (this.destroyed) + return; + const reports = []; + res.result().forEach((result) => { + const report = {}; + result.names().forEach((name) => { + report[name] = result.stat(name); + }); + report.id = result.id; + report.type = result.type; + report.timestamp = result.timestamp; + reports.push(flattenValues(report)); + }); + cb(null, reports); + }, (err) => cb(err)); + } else { + cb(null, []); + } + } + _maybeReady() { + this._debug("maybeReady pc %s channel %s", this._pcReady, this._channelReady); + if (this._connected || this._connecting || !this._pcReady || !this._channelReady) + return; + this._connecting = true; + const findCandidatePair = () => { + if (this.destroyed) + return; + this.getStats((err, items) => { + if (this.destroyed) + return; + if (err) + items = []; + const remoteCandidates = {}; + const localCandidates = {}; + const candidatePairs = {}; + let foundSelectedCandidatePair = false; + items.forEach((item) => { + if (item.type === "remotecandidate" || item.type === "remote-candidate") { + remoteCandidates[item.id] = item; + } + if (item.type === "localcandidate" || item.type === "local-candidate") { + localCandidates[item.id] = item; + } + if (item.type === "candidatepair" || item.type === "candidate-pair") { + candidatePairs[item.id] = item; + } + }); + const setSelectedCandidatePair = (selectedCandidatePair) => { + foundSelectedCandidatePair = true; + let local = localCandidates[selectedCandidatePair.localCandidateId]; + if (local && (local.ip || local.address)) { + this.localAddress = local.ip || local.address; + this.localPort = Number(local.port); + } else if (local && local.ipAddress) { + this.localAddress = local.ipAddress; + this.localPort = Number(local.portNumber); + } else if (typeof selectedCandidatePair.googLocalAddress === "string") { + local = selectedCandidatePair.googLocalAddress.split(":"); + this.localAddress = local[0]; + this.localPort = Number(local[1]); + } + if (this.localAddress) { + this.localFamily = this.localAddress.includes(":") ? "IPv6" : "IPv4"; + } + let remote = remoteCandidates[selectedCandidatePair.remoteCandidateId]; + if (remote && (remote.ip || remote.address)) { + this.remoteAddress = remote.ip || remote.address; + this.remotePort = Number(remote.port); + } else if (remote && remote.ipAddress) { + this.remoteAddress = remote.ipAddress; + this.remotePort = Number(remote.portNumber); + } else if (typeof selectedCandidatePair.googRemoteAddress === "string") { + remote = selectedCandidatePair.googRemoteAddress.split(":"); + this.remoteAddress = remote[0]; + this.remotePort = Number(remote[1]); + } + if (this.remoteAddress) { + this.remoteFamily = this.remoteAddress.includes(":") ? "IPv6" : "IPv4"; + } + this._debug( + "connect local: %s:%s remote: %s:%s", + this.localAddress, + this.localPort, + this.remoteAddress, + this.remotePort + ); + }; + items.forEach((item) => { + if (item.type === "transport" && item.selectedCandidatePairId) { + setSelectedCandidatePair(candidatePairs[item.selectedCandidatePairId]); + } + if (item.type === "googCandidatePair" && item.googActiveConnection === "true" || (item.type === "candidatepair" || item.type === "candidate-pair") && item.selected) { + setSelectedCandidatePair(item); + } + }); + if (!foundSelectedCandidatePair && (!Object.keys(candidatePairs).length || Object.keys(localCandidates).length)) { + setTimeout(findCandidatePair, 100); + return; + } else { + this._connecting = false; + this._connected = true; + } + if (this._chunk) { + try { + this.send(this._chunk); + } catch (err2) { + return this.destroy(errCode(err2, "ERR_DATA_CHANNEL")); + } + this._chunk = null; + this._debug('sent chunk from "write before connect"'); + const cb = this._cb; + this._cb = null; + cb(null); + } + if (typeof this._channel.bufferedAmountLowThreshold !== "number") { + this._interval = setInterval(() => this._onInterval(), 150); + if (this._interval.unref) + this._interval.unref(); + } + this._debug("connect"); + this.emit("connect"); + }); + }; + findCandidatePair(); + } + _onInterval() { + if (!this._cb || !this._channel || this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) { + return; + } + this._onChannelBufferedAmountLow(); + } + _onSignalingStateChange() { + if (this.destroyed) + return; + if (this._pc.signalingState === "stable") { + this._isNegotiating = false; + this._debug("flushing sender queue", this._sendersAwaitingStable); + this._sendersAwaitingStable.forEach((sender) => { + this._pc.removeTrack(sender); + this._queuedNegotiation = true; + }); + this._sendersAwaitingStable = []; + if (this._queuedNegotiation) { + this._debug("flushing negotiation queue"); + this._queuedNegotiation = false; + this._needsNegotiation(); + } else { + this._debug("negotiated"); + this.emit("negotiated"); + } + } + this._debug("signalingStateChange %s", this._pc.signalingState); + this.emit("signalingStateChange", this._pc.signalingState); + } + _onIceCandidate(event) { + if (this.destroyed) + return; + if (event.candidate && this.trickle) { + this.emit("signal", { + type: "candidate", + candidate: { + candidate: event.candidate.candidate, + sdpMLineIndex: event.candidate.sdpMLineIndex, + sdpMid: event.candidate.sdpMid + } + }); + } else if (!event.candidate && !this._iceComplete) { + this._iceComplete = true; + this.emit("_iceComplete"); + } + if (event.candidate) { + this._startIceCompleteTimeout(); + } + } + _onChannelMessage(event) { + if (this.destroyed) + return; + let data = event.data; + if (data instanceof ArrayBuffer) + data = Buffer3.from(data); + this.push(data); + } + _onChannelBufferedAmountLow() { + if (this.destroyed || !this._cb) + return; + this._debug("ending backpressure: bufferedAmount %d", this._channel.bufferedAmount); + const cb = this._cb; + this._cb = null; + cb(null); + } + _onChannelOpen() { + if (this._connected || this.destroyed) + return; + this._debug("on channel open"); + this._channelReady = true; + this._maybeReady(); + } + _onChannelClose() { + if (this.destroyed) + return; + this._debug("on channel close"); + this.destroy(); + } + _onTrack(event) { + if (this.destroyed) + return; + event.streams.forEach((eventStream) => { + this._debug("on track"); + this.emit("track", event.track, eventStream); + this._remoteTracks.push({ + track: event.track, + stream: eventStream + }); + if (this._remoteStreams.some((remoteStream) => { + return remoteStream.id === eventStream.id; + })) + return; + this._remoteStreams.push(eventStream); + queueMicrotask2(() => { + this._debug("on stream"); + this.emit("stream", eventStream); + }); + }); + } + _debug() { + const args = [].slice.call(arguments); + args[0] = "[" + this._id + "] " + args[0]; + debug.apply(null, args); + } + }; + Peer.WEBRTC_SUPPORT = !!getBrowserRTC(); + Peer.config = { + iceServers: [ + { + urls: [ + "stun:stun.l.google.com:19302", + "stun:global.stun.twilio.com:3478" + ] + } + ], + sdpSemantics: "unified-plan" + }; + Peer.channelConfig = {}; + module.exports = Peer; + } +}); + // node_modules/pako/lib/zlib/trees.js var require_trees = __commonJS({ "node_modules/pako/lib/zlib/trees.js"(exports, module) { @@ -7171,7 +10911,7 @@ var require_utils = __commonJS({ }); // node_modules/randomstring/node_modules/randombytes/browser.js -var require_browser3 = __commonJS({ +var require_browser5 = __commonJS({ "node_modules/randomstring/node_modules/randombytes/browser.js"(exports, module) { "use strict"; init_esbuild_inject(); @@ -7309,7 +11049,7 @@ var require_randomstring = __commonJS({ "node_modules/randomstring/lib/randomstring.js"(exports) { "use strict"; init_esbuild_inject(); - var randomBytes = require_browser3(); + var randomBytes = require_browser5(); var Charset = require_charset(); function safeRandomBytes(length) { while (true) { @@ -7395,6 +11135,7 @@ var require_p2pcf = __commonJS({ init_esbuild_inject(); var getBrowserRTC = require_get_browser_rtc(); var EventEmitter = require_events(); + var Peer = require_simple_peer(); var debug = require_browser2()("p2pcf"); var pako = require_pako(); var { encode: arrayBufferToBase64 } = require_base64_arraybuffer_umd(); @@ -7451,6 +11192,36 @@ var require_p2pcf = __commonJS({ var webkit = !!ua.match(/WebKit/i); var iOSSafari = !!(iOS && webkit && !ua.match(/CriOS/i)); var isFirefox = !!(navigator?.userAgent.toLowerCase().indexOf("firefox") > -1); + var removePeerUi = (clientId) => { + document.getElementById(clientId)?.remove(); + }; + var initPeerUi = (sessionId) => { + if (document.getElementById(sessionId)) + return; + const peerEl = document.createElement("div"); + peerEl.style = "display: flex;"; + const name = document.createElement("div"); + name.innerText = sessionId.substring(0, 5); + peerEl.appendChild(name); + const st = document.createElement("div"); + st.id = `${sessionId}-ice-status`; + st.style = "width: 32px; height 32px; background-color: blue;"; + peerEl.appendChild(st); + const cst = document.createElement("div"); + cst.id = `${sessionId}-conn-status`; + cst.style = "width: 32px; height 32px; background-color: blue;"; + peerEl.appendChild(cst); + const type = document.createElement("div"); + type.id = `${sessionId}-type`; + type.innerText = "?"; + peerEl.appendChild(type); + const icetype = document.createElement("div"); + icetype.id = `${sessionId}-ice-type`; + icetype.innerText = ""; + peerEl.appendChild(icetype); + peerEl.id = sessionId; + document.getElementById("peers").appendChild(peerEl); + }; var parseCandidate = (line) => { let parts; if (line.indexOf("a=candidate:") === 0) { @@ -7704,8 +11475,7 @@ var require_p2pcf = __commonJS({ lastReceivedDataTimestamps, packageReceivedFromPeers, stunIceServers, - turnIceServers, - wrtc + turnIceServers } = this; const [localSessionId, , localSymmetric] = localPeerData; const localClientId = this.clientId; @@ -7724,6 +11494,7 @@ var require_p2pcf = __commonJS({ continue; } lastReceivedDataTimestamps.set(remoteSessionId, remoteDataTimestamp); + initPeerUi(remoteSessionId); const isPeerA = localSymmetric === remoteSymmetric ? localStartedAtTimestamp === remoteStartedAtTimestamp ? localSessionId > remoteSessionId : localStartedAtTimestamp > remoteStartedAtTimestamp : localSymmetric; console.log( localSymmetric === remoteSymmetric, @@ -7784,9 +11555,27 @@ var require_p2pcf = __commonJS({ , remoteCandidates ] = remotePackage; - const pc = new wrtc.RTCPeerConnection(peerOptions); - pc.createDataChannel("p2pcf_signalling"); - peers.set(remoteSessionId, pc); + initPeerUi(remoteSessionId); + const peer = new Peer({ + config: peerOptions, + initiator: false, + iceCompleteTimeout: 3e3, + sdpTransform: (sdp) => { + const lines = []; + for (const l of sdp.split("\r\n")) { + if (l.startsWith("a=ice-ufrag")) { + lines.push(`a=ice-ufrag:${localIceUFrag}`); + } else if (l.startsWith("a=ice-pwd")) { + lines.push(`a=ice-pwd:${localIcePwd}`); + } else { + lines.push(l); + } + } + return lines.join("\r\n"); + } + }); + peers.set(remoteSessionId, peer); + peer.on("error", (e) => this._handlePeerError(peer, e)); const pkg = [ remoteSessionId, localSessionId, @@ -7799,146 +11588,52 @@ var require_p2pcf = __commonJS({ [] ]; const pkgCandidates = pkg[pkg.length - 1]; + const initialCandidateSignalling = (e) => { + if (!e.candidate?.candidate) + return; + pkgCandidates.push(e.candidate.candidate); + }; + peer.on("signal", initialCandidateSignalling); const finishIce = () => { + peer.removeListener("signal", initialCandidateSignalling); if (localPackages.includes(pkg)) return; if (pkgCandidates.length === 0) return; localPackages.push(pkg); }; - pc.onicecandidate = (e) => { - const timeout = setTimeout(finishIce, window ? 5e3 : 500); - if (!e.candidate) { - clearTimeout(timeout); - return finishIce(); - } - if (!e.candidate.candidate) - return; - pkgCandidates.push(e.candidate.candidate); - }; - pc.oniceconnectionstatechange = () => { - const iceConnectionState = pc.iceConnectionState; - const iceGatheringState = pc.iceGatheringState; - if (iceConnectionState === "connected") { - console.log( - isPeerA ? "A" : "B", - localClientId, - localSessionId, - "ice connected to", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId - ); - } else if (iceConnectionState === "failed") { - this._removePeerBySessionId(remoteSessionId); - } - console.log( - "iceconnectionstatechange", - isPeerA ? "A" : "B", - localClientId, - localSessionId, - "to", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ); - }; - pc.onicegatheringstatechange = () => { - const iceConnectionState = pc.iceConnectionState; - const iceGatheringState = pc.iceGatheringState; - console.log( - "icegatheringstatechange", - isPeerA ? "A" : "B", - localClientId, - localSessionId, - "to", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ); - }; - pc.onconnectionstatechange = () => { - const connectionState = pc.connectionState; - if (connectionState === "connected") { - console.log( - localClientId, - localSessionId, - " full connected to peer B", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId - ); - } else if (connectionState === "failed") { - this._removePeerBySessionId(remoteSessionId); - } - console.log( - "connectionstatechange", - isPeerA ? "A" : "B", - localClientId, - localSessionId, - "to", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - connectionState - ); - }; - pc.onsignalingstatechange = () => { - const signalingState = pc.signalingState; - console.log( - "signalingstatechange", - localClientId, - localSessionId, - " to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - signalingState + peer.once("_iceComplete", finishIce); + peer.on("iceStateChange", (e) => { + console.log("ice state change", e); + }); + peer.on("connect", () => { + document.getElementById(`${remoteSessionId}-ice-status`).setAttribute( + "style", + "width: 32px; height: 32px; background-color: green;" ); - }; + }); + peer.on("close", () => this._removePeerBySessionId(remoteSessionId)); const remoteSdp = createSdp( true, remoteIceUFrag, remoteIcePwd, remoteDtlsFingerprintBase642 ); - pc.setRemoteDescription({ type: "offer", sdp: remoteSdp }); - pc.createAnswer().then((answer) => { - const lines = []; - for (const l of answer.sdp.split("\r\n")) { - if (l.startsWith("a=ice-ufrag")) { - lines.push(`a=ice-ufrag:${localIceUFrag}`); - } else if (l.startsWith("a=ice-pwd")) { - lines.push(`a=ice-pwd:${localIcePwd}`); - } else { - lines.push(l); - } - } - pc.setLocalDescription({ type: "answer", sdp: lines.join("\r\n") }); - for (const candidate of remoteCandidates) { - console.log( - localClientId, - localSessionId, - " adding candidate ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - candidate - ); - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }); - } - }); + for (const candidate of remoteCandidates) { + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }); + } + peer.signal({ type: "offer", sdp: remoteSdp }); } else { if (!peers.has(remoteSessionId)) { - const pc2 = new wrtc.RTCPeerConnection(peerOptions); - pc2.createDataChannel("p2pcf_signalling"); - peers.set(remoteSessionId, pc2); const remoteUfrag = randomstring.generate({ length: 12 }); const remotePwd = randomstring.generate({ length: 32 }); + const peer2 = new Peer({ + config: peerOptions, + iceCompleteTimeout: 3e3, + initiator: true + }); + peers.set(remoteSessionId, peer2); + peer2.on("error", (e) => this._handlePeerError(peer2, e)); const pkg = [ remoteSessionId, localSessionId, @@ -7951,124 +11646,33 @@ var require_p2pcf = __commonJS({ [] ]; const pkgCandidates = pkg[pkg.length - 1]; - let remoteSdp = createSdp( - false, - remoteUfrag, - remotePwd, - remoteDtlsFingerprintBase64 - ); - for (let i = 0; i < remoteReflexiveIps.length; i++) { - remoteSdp += `a=candidate:0 1 udp ${i + 1} ${remoteReflexiveIps[i]} 30000 typ srflx\r -`; - } + const initialCandidateSignalling = (e) => { + if (!e.candidate?.candidate) + return; + pkgCandidates.push(e.candidate.candidate); + }; + peer2.on("signal", initialCandidateSignalling); const finishIce = () => { + peer2.removeListener("signal", initialCandidateSignalling); if (localPackages.includes(pkg)) return; - console.log( - localClientId, - localSessionId, - " pushing package to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - pkg - ); - localPackages.push(pkg); - }; - pc2.onicecandidate = (e) => { - const timeout = setTimeout(finishIce, 5e3); - if (!e.candidate) { - clearTimeout(timeout); - return finishIce(); - } - if (!e.candidate.candidate) + if (pkgCandidates.length === 0) return; - pkgCandidates.push(e.candidate.candidate); - }; - pc2.oniceconnectionstatechange = () => { - const iceConnectionState = pc2.iceConnectionState; - const iceGatheringState = pc2.iceGatheringState; - if (iceConnectionState === "connected") { - console.log( - localClientId, - localSessionId, - " ice connected to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId - ); - } else if (iceConnectionState === "failed") { - this._removePeerBySessionId(remoteSessionId); - } - console.log( - "iceconnectionstatechange", - isPeerA ? "A" : "B", - localClientId, - localSessionId, - " to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ); - }; - pc2.onicegatheringstatechange = () => { - const iceConnectionState = pc2.iceConnectionState; - const iceGatheringState = pc2.iceGatheringState; - console.log( - "icegatheringstatechange", - localClientId, - localSessionId, - " to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ); - }; - pc2.onconnectionstatechange = () => { - const connectionState = pc2.connectionState; - console.log( - "connectionstatechange", - localClientId, - localSessionId, - " to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - connectionState - ); - if (connectionState === "connected") { - console.log( - localClientId, - localSessionId, - " full connected to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId - ); - } else if (connectionState === "failed") { - this._removePeerBySessionId(remoteSessionId); - } + localPackages.push(pkg); }; - pc2.onsignalingstatechange = () => { - const signalingState = pc2.signalingState; - console.log( - "signalingstatechange", - localClientId, - localSessionId, - " to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - signalingState + peer2.once("_iceComplete", finishIce); + peer2.on("close", () => this._removePeerBySessionId(remoteSessionId)); + peer2.on("connect", () => { + document.getElementById(`${remoteSessionId}-ice-status`).setAttribute( + "style", + "width: 32px; height: 32px; background-color: green;" ); - }; - pc2.createOffer().then((offer) => { - pc2.setLocalDescription(offer); - for (const l of offer.sdp.split("\r\n")) { + }); + const enqueuePackageFromOffer = (e) => { + if (e.type !== "offer") + return; + peer2.removeListener("signal", enqueuePackageFromOffer); + for (const l of e.sdp.split("\r\n")) { switch (l.split(":")[0]) { case "a=ice-ufrag": pkg[2] = l.substring(12); @@ -8081,12 +11685,24 @@ var require_p2pcf = __commonJS({ break; } } + let remoteSdp = createSdp( + false, + remoteUfrag, + remotePwd, + remoteDtlsFingerprintBase64 + ); + for (let i = 0; i < remoteReflexiveIps.length; i++) { + remoteSdp += `a=candidate:0 1 udp ${i + 1} ${remoteReflexiveIps[i]} 30000 typ srflx\r +`; + } if (!delaySetRemoteUntilReceiveCandidates) { - pc2.setRemoteDescription({ type: "answer", sdp: remoteSdp }); + peer2.signal({ type: "answer", sdp: remoteSdp }); } else { - pc2._pendingRemoteSdp = remoteSdp; + peer2._pendingRemoteSdp = remoteSdp; } - }); + }; + peer2.once("signal", enqueuePackageFromOffer); + peer2.negotiate(); } if (!remotePackage) continue; @@ -8095,8 +11711,9 @@ var require_p2pcf = __commonJS({ continue; if (!peers.has(remoteSessionId)) continue; - const pc = peers.get(remoteSessionId); - if (delaySetRemoteUntilReceiveCandidates && !pc.remoteDescription && pc._pendingRemoteSdp) { + initPeerUi(remoteSessionId); + const peer = peers.get(remoteSessionId); + if (delaySetRemoteUntilReceiveCandidates && !peer._pc.remoteDescription && peer._pendingRemoteSdp) { console.log( localClientId, localSessionId, @@ -8106,62 +11723,19 @@ var require_p2pcf = __commonJS({ remoteSessionId, remoteCandidates.length ); - pc.setRemoteDescription({ - type: "answer", - sdp: pc._pendingRemoteSdp - }).then(() => { - delete pc._pendingRemoteSdp; - console.log( - isPeerA ? "A" : "B", - localClientId, - localSessionId, - " checking connection state to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - pc.iceConnectionState - ); - if (pc.iceConnectionState !== "connected") { - for (const candidate of remoteCandidates) { - console.log("B", candidate); - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }); - } + if (!peer.connected) { + for (const candidate of remoteCandidates) { + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }); } - packageReceivedFromPeers.add(remoteSessionId); - }); + } + peer.signal({ type: "answer", sdp: peer._pendingRemoteSdp }); + delete peer._pendingRemoteSdp; packageReceivedFromPeers.add(remoteSessionId); } - if (!delaySetRemoteUntilReceiveCandidates && pc.remoteDescription && remoteCandidates.length > 0) { - console.log( - localClientId, - localSessionId, - " 1add remote candidates from ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - remoteCandidates.length - ); - console.log( - localClientId, - localSessionId, - " checking connection state to ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - pc.iceConnectionState - ); - if (pc.iceConnectionState !== "connected") { + if (!delaySetRemoteUntilReceiveCandidates && peer._pc.remoteDescription && remoteCandidates.length > 0) { + if (!peer.connected) { for (const candidate of remoteCandidates) { - console.log( - localClientId, - localSessionId, - " 2add remote candidate from ", - isPeerA ? "B" : "A", - remoteClientId, - remoteSessionId, - candidate - ); - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }); + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }); } } packageReceivedFromPeers.add(remoteSessionId); @@ -8252,10 +11826,9 @@ var require_p2pcf = __commonJS({ const { peers, packageReceivedFromPeers, packages } = this; if (!peers.has(sessionId)) return; - console.log(this.clientId, this.sessionId, "closing", sessionId); - console.trace(); const peer = peers.get(sessionId); - peer.close(); + peer.destroy(); + removePeerUi(sessionId); packageReceivedFromPeers.delete(sessionId); peers.delete(sessionId); for (let i = 0; i < packages.length; i++) { @@ -8448,6 +12021,12 @@ var require_p2pcf = __commonJS({ } return [udpEnabled, isSymmetric, reflexiveIps, dtlsFingerprint]; } + _handlePeerError(peer, err) { + if (err.errorDetail === "sctp-failure" && err.message.indexOf("User-Initiated Abort") >= 0) { + return; + } + console.error(err); + } }; module.exports = P2PCF; } @@ -8460,3 +12039,5 @@ export default require_p2pcf(); * @license MIT */ /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ +/*! queue-microtask. MIT License. Feross Aboukhadijeh */ +/*! simple-peer. MIT License. Feross Aboukhadijeh */ diff --git a/p2pcf.js b/p2pcf.js index 91ef7fa..94445a4 100644 --- a/p2pcf.js +++ b/p2pcf.js @@ -6,6 +6,7 @@ const getBrowserRTC = require('get-browser-rtc') const EventEmitter = require('events') +const Peer = require('simple-peer') const debug = require('debug')('p2pcf') const pako = require('pako') const { encode: arrayBufferToBase64 } = require('base64-arraybuffer') @@ -73,6 +74,46 @@ const webkit = !!ua.match(/WebKit/i) const iOSSafari = !!(iOS && webkit && !ua.match(/CriOS/i)) const isFirefox = !!(navigator?.userAgent.toLowerCase().indexOf('firefox') > -1) +const removePeerUi = clientId => { + document.getElementById(clientId)?.remove() +} + +const initPeerUi = sessionId => { + if (document.getElementById(sessionId)) return + + const peerEl = document.createElement('div') + peerEl.style = 'display: flex;' + + const name = document.createElement('div') + name.innerText = sessionId.substring(0, 5) + + peerEl.appendChild(name) + + const st = document.createElement('div') + st.id = `${sessionId}-ice-status` + st.style = 'width: 32px; height 32px; background-color: blue;' + peerEl.appendChild(st) + + const cst = document.createElement('div') + cst.id = `${sessionId}-conn-status` + cst.style = 'width: 32px; height 32px; background-color: blue;' + peerEl.appendChild(cst) + + const type = document.createElement('div') + type.id = `${sessionId}-type` + type.innerText = '?' + peerEl.appendChild(type) + + const icetype = document.createElement('div') + icetype.id = `${sessionId}-ice-type` + icetype.innerText = '' + peerEl.appendChild(icetype) + + peerEl.id = sessionId + + document.getElementById('peers').appendChild(peerEl) +} + // parseCandidate from https://github.com/fippo/sdp const parseCandidate = line => { let parts @@ -404,8 +445,7 @@ class P2PCF extends EventEmitter { lastReceivedDataTimestamps, packageReceivedFromPeers, stunIceServers, - turnIceServers, - wrtc + turnIceServers } = this const [localSessionId, , localSymmetric] = localPeerData const localClientId = this.clientId @@ -430,6 +470,7 @@ class P2PCF extends EventEmitter { } lastReceivedDataTimestamps.set(remoteSessionId, remoteDataTimestamp) + initPeerUi(remoteSessionId) // Peer A is: // - if both not symmetric or both symmetric, whoever has the most recent data is peer A, since we want Peer B created faster, @@ -519,9 +560,32 @@ class P2PCF extends EventEmitter { remoteCandidates ] = remotePackage - const pc = new wrtc.RTCPeerConnection(peerOptions) - pc.createDataChannel('p2pcf_signalling') - peers.set(remoteSessionId, pc) + initPeerUi(remoteSessionId) + + const peer = new Peer({ + config: peerOptions, + initiator: false, + iceCompleteTimeout: 3000, + sdpTransform: sdp => { + const lines = [] + + for (const l of sdp.split('\r\n')) { + if (l.startsWith('a=ice-ufrag')) { + lines.push(`a=ice-ufrag:${localIceUFrag}`) + } else if (l.startsWith('a=ice-pwd')) { + lines.push(`a=ice-pwd:${localIcePwd}`) + } else { + lines.push(l) + } + } + + return lines.join('\r\n') + } + }) + + peers.set(remoteSessionId, peer) + + peer.on('error', e => this._handlePeerError(peer, e)) // Special case if both behind sym NAT or other hole punching isn't working: peer A needs to send its candidates as well. const pkg = [ @@ -538,115 +602,37 @@ class P2PCF extends EventEmitter { const pkgCandidates = pkg[pkg.length - 1] + const initialCandidateSignalling = e => { + if (!e.candidate?.candidate) return + pkgCandidates.push(e.candidate.candidate) + } + + peer.on('signal', initialCandidateSignalling) + const finishIce = () => { + peer.removeListener('signal', initialCandidateSignalling) if (localPackages.includes(pkg)) return if (pkgCandidates.length === 0) return - // If hole punch hasn't worked after two seconds, send these candidates back to B to help it punch through. localPackages.push(pkg) } - pc.onicecandidate = e => { - const timeout = setTimeout(finishIce, window ? 5000 : 500) - - if (!e.candidate) { - clearTimeout(timeout) - return finishIce() - } + peer.once('_iceComplete', finishIce) - if (!e.candidate.candidate) return - pkgCandidates.push(e.candidate.candidate) - } - - pc.oniceconnectionstatechange = () => { - const iceConnectionState = pc.iceConnectionState - const iceGatheringState = pc.iceGatheringState - - if (iceConnectionState === 'connected') { - console.log( - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - 'ice connected to', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId - ) - } else if (iceConnectionState === 'failed') { - this._removePeerBySessionId(remoteSessionId) - } - - console.log( - 'iceconnectionstatechange', - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - 'to', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ) - } - - pc.onicegatheringstatechange = () => { - const iceConnectionState = pc.iceConnectionState - const iceGatheringState = pc.iceGatheringState - console.log( - 'icegatheringstatechange', - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - 'to', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ) - } + peer.on('iceStateChange', e => { + console.log('ice state change', e) + }) - pc.onconnectionstatechange = () => { - const connectionState = pc.connectionState - if (connectionState === 'connected') { - console.log( - localClientId, - localSessionId, - ' full connected to peer B', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId + peer.on('connect', () => { + document + .getElementById(`${remoteSessionId}-ice-status`) + .setAttribute( + 'style', + 'width: 32px; height: 32px; background-color: green;' ) - } else if (connectionState === 'failed') { - this._removePeerBySessionId(remoteSessionId) - } - console.log( - 'connectionstatechange', - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - 'to', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - connectionState - ) - } + }) - pc.onsignalingstatechange = () => { - const signalingState = pc.signalingState - console.log( - 'signalingstatechange', - localClientId, - localSessionId, - ' to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - signalingState - ) - } + peer.on('close', () => this._removePeerBySessionId(remoteSessionId)) const remoteSdp = createSdp( true, @@ -655,39 +641,11 @@ class P2PCF extends EventEmitter { remoteDtlsFingerprintBase64 ) - // console.log('peer A', localSessionId, 'remote offer', remoteSdp) - pc.setRemoteDescription({ type: 'offer', sdp: remoteSdp }) - - pc.createAnswer().then(answer => { - const lines = [] - - for (const l of answer.sdp.split('\r\n')) { - if (l.startsWith('a=ice-ufrag')) { - lines.push(`a=ice-ufrag:${localIceUFrag}`) - } else if (l.startsWith('a=ice-pwd')) { - lines.push(`a=ice-pwd:${localIcePwd}`) - } else { - lines.push(l) - } - } - - // console.log('A local answer', this.sessionId, lines.join('\r\n')) - pc.setLocalDescription({ type: 'answer', sdp: lines.join('\r\n') }) - - for (const candidate of remoteCandidates) { - console.log( - localClientId, - localSessionId, - ' adding candidate ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - candidate - ) + for (const candidate of remoteCandidates) { + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }) + } - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }) - } - }) + peer.signal({ type: 'offer', sdp: remoteSdp }) } else { // I am peer B, I need to create a peer first if none exists, and send a package. // - Create PC @@ -701,12 +659,16 @@ class P2PCF extends EventEmitter { // - Let trickle run, then once trickle finishes send a package for A to pick up = [my session id, my offer sdp, generated ufrag/pwd, dtls fingerprint, ice candidates] // - keep the icecandidate listener active, and add the pfrlx candidates when they arrive (but don't send another package) if (!peers.has(remoteSessionId)) { - const pc = new wrtc.RTCPeerConnection(peerOptions) - pc.createDataChannel('p2pcf_signalling') - peers.set(remoteSessionId, pc) - const remoteUfrag = randomstring.generate({ length: 12 }) const remotePwd = randomstring.generate({ length: 32 }) + const peer = new Peer({ + config: peerOptions, + iceCompleteTimeout: 3000, + initiator: true + }) + + peers.set(remoteSessionId, peer) + peer.on('error', e => this._handlePeerError(peer, e)) // This is the 'package' sent to peer A that it needs to start ICE const pkg = [ @@ -723,140 +685,40 @@ class P2PCF extends EventEmitter { const pkgCandidates = pkg[pkg.length - 1] - // Peer A posted its reflexive IPs to try to speed up hole punching by B. - let remoteSdp = createSdp( - false, - remoteUfrag, - remotePwd, - remoteDtlsFingerprintBase64 - ) - - for (let i = 0; i < remoteReflexiveIps.length; i++) { - remoteSdp += `a=candidate:0 1 udp ${i + 1} ${ - remoteReflexiveIps[i] - } 30000 typ srflx\r\n` - } - - const finishIce = () => { - if (localPackages.includes(pkg)) return - console.log( - localClientId, - localSessionId, - ' pushing package to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - pkg - ) - localPackages.push(pkg) - } - - pc.onicecandidate = e => { - const timeout = setTimeout(finishIce, 5000) - + const initialCandidateSignalling = e => { // Push package onto the given package list, so it will be sent in next polling step. - if (!e.candidate) { - clearTimeout(timeout) - return finishIce() - } - - if (!e.candidate.candidate) return + if (!e.candidate?.candidate) return pkgCandidates.push(e.candidate.candidate) } - pc.oniceconnectionstatechange = () => { - const iceConnectionState = pc.iceConnectionState - const iceGatheringState = pc.iceGatheringState - - if (iceConnectionState === 'connected') { - console.log( - localClientId, - localSessionId, - ' ice connected to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId - ) - } else if (iceConnectionState === 'failed') { - this._removePeerBySessionId(remoteSessionId) - } + peer.on('signal', initialCandidateSignalling) - console.log( - 'iceconnectionstatechange', - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - ' to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ) - } + const finishIce = () => { + peer.removeListener('signal', initialCandidateSignalling) + if (localPackages.includes(pkg)) return + if (pkgCandidates.length === 0) return - pc.onicegatheringstatechange = () => { - const iceConnectionState = pc.iceConnectionState - const iceGatheringState = pc.iceGatheringState - console.log( - 'icegatheringstatechange', - localClientId, - localSessionId, - ' to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - iceConnectionState, - iceGatheringState - ) + localPackages.push(pkg) } - pc.onconnectionstatechange = () => { - const connectionState = pc.connectionState - console.log( - 'connectionstatechange', - localClientId, - localSessionId, - ' to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - connectionState - ) + peer.once('_iceComplete', finishIce) - if (connectionState === 'connected') { - console.log( - localClientId, - localSessionId, - ' full connected to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId - ) - } else if (connectionState === 'failed') { - this._removePeerBySessionId(remoteSessionId) - } - } + peer.on('close', () => this._removePeerBySessionId(remoteSessionId)) - pc.onsignalingstatechange = () => { - const signalingState = pc.signalingState - console.log( - 'signalingstatechange', - localClientId, - localSessionId, - ' to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - signalingState - ) - } + peer.on('connect', () => { + document + .getElementById(`${remoteSessionId}-ice-status`) + .setAttribute( + 'style', + 'width: 32px; height: 32px; background-color: green;' + ) + }) - pc.createOffer().then(offer => { - pc.setLocalDescription(offer) - // console.log('B local offer', offer.sdp) + const enqueuePackageFromOffer = e => { + if (e.type !== 'offer') return + peer.removeListener('signal', enqueuePackageFromOffer) - for (const l of offer.sdp.split('\r\n')) { + for (const l of e.sdp.split('\r\n')) { switch (l.split(':')[0]) { case 'a=ice-ufrag': pkg[2] = l.substring(12) @@ -870,13 +732,29 @@ class P2PCF extends EventEmitter { } } + // Peer A posted its reflexive IPs to try to speed up hole punching by B. + let remoteSdp = createSdp( + false, + remoteUfrag, + remotePwd, + remoteDtlsFingerprintBase64 + ) + + for (let i = 0; i < remoteReflexiveIps.length; i++) { + remoteSdp += `a=candidate:0 1 udp ${i + 1} ${ + remoteReflexiveIps[i] + } 30000 typ srflx\r\n` + } + if (!delaySetRemoteUntilReceiveCandidates) { - // console.log('B remote answer', remoteSdp) - pc.setRemoteDescription({ type: 'answer', sdp: remoteSdp }) + peer.signal({ type: 'answer', sdp: remoteSdp }) } else { - pc._pendingRemoteSdp = remoteSdp + peer._pendingRemoteSdp = remoteSdp } - }) + } + + peer.once('signal', enqueuePackageFromOffer) + peer.negotiate() } if (!remotePackage) continue @@ -886,12 +764,14 @@ class P2PCF extends EventEmitter { const [, , , , , , , , remoteCandidates] = remotePackage if (packageReceivedFromPeers.has(remoteSessionId)) continue if (!peers.has(remoteSessionId)) continue + initPeerUi(remoteSessionId) + + const peer = peers.get(remoteSessionId) - const pc = peers.get(remoteSessionId) if ( delaySetRemoteUntilReceiveCandidates && - !pc.remoteDescription && - pc._pendingRemoteSdp + !peer._pc.remoteDescription && + peer._pendingRemoteSdp ) { console.log( localClientId, @@ -903,73 +783,25 @@ class P2PCF extends EventEmitter { remoteCandidates.length ) - pc.setRemoteDescription({ - type: 'answer', - sdp: pc._pendingRemoteSdp - }).then(() => { - delete pc._pendingRemoteSdp - - console.log( - isPeerA ? 'A' : 'B', - localClientId, - localSessionId, - ' checking connection state to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - pc.iceConnectionState - ) - - if (pc.iceConnectionState !== 'connected') { - for (const candidate of remoteCandidates) { - console.log('B', candidate) - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }) - } + if (!peer.connected) { + for (const candidate of remoteCandidates) { + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }) } + } - packageReceivedFromPeers.add(remoteSessionId) - }) - + peer.signal({ type: 'answer', sdp: peer._pendingRemoteSdp }) + delete peer._pendingRemoteSdp packageReceivedFromPeers.add(remoteSessionId) } if ( !delaySetRemoteUntilReceiveCandidates && - pc.remoteDescription && + peer._pc.remoteDescription && remoteCandidates.length > 0 ) { - console.log( - localClientId, - localSessionId, - ' 1add remote candidates from ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - remoteCandidates.length - ) - - console.log( - localClientId, - localSessionId, - ' checking connection state to ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - pc.iceConnectionState - ) - - if (pc.iceConnectionState !== 'connected') { + if (!peer.connected) { for (const candidate of remoteCandidates) { - console.log( - localClientId, - localSessionId, - ' 2add remote candidate from ', - isPeerA ? 'B' : 'A', - remoteClientId, - remoteSessionId, - candidate - ) - pc.addIceCandidate({ candidate, sdpMLineIndex: 0 }) + peer.signal({ candidate: { candidate, sdpMLineIndex: 0 } }) } } @@ -981,6 +813,7 @@ class P2PCF extends EventEmitter { const remoteSessionIds = remotePeerDatas.map(p => p[0]) // Remove all peers no longer in the peer list. + // TODO deal with simple peer for (const sessionId of peers.keys()) { if (remoteSessionIds.includes(sessionId)) continue console.log( @@ -991,6 +824,7 @@ class P2PCF extends EventEmitter { ' removing', JSON.stringify(remoteSessionIds) ) + this._removePeerBySessionId(sessionId) } } @@ -1172,11 +1006,10 @@ class P2PCF extends EventEmitter { async _removePeerBySessionId (sessionId) { const { peers, packageReceivedFromPeers, packages } = this if (!peers.has(sessionId)) return - console.log(this.clientId, this.sessionId, 'closing', sessionId) - console.trace() const peer = peers.get(sessionId) - peer.close() + peer.destroy() + removePeerUi(sessionId) packageReceivedFromPeers.delete(sessionId) peers.delete(sessionId) @@ -1454,6 +1287,17 @@ class P2PCF extends EventEmitter { return [udpEnabled, isSymmetric, reflexiveIps, dtlsFingerprint] } + + _handlePeerError (peer, err) { + if ( + err.errorDetail === 'sctp-failure' && + err.message.indexOf('User-Initiated Abort') >= 0 + ) { + return // Benign shutdown + } + + console.error(err) + } } module.exports = P2PCF diff --git a/package-lock.json b/package-lock.json index 27aa1fe..2aba95d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "pako": "^2.0.4", "process": "^0.11.10", "randomstring": "^1.2.2", + "simple-peer": "^9.11.1", "stream-browserify": "^3.0.0" }, "devDependencies": { @@ -3119,6 +3120,11 @@ "node": ">=10.0.0" } }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9143,7 +9149,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -9704,6 +9709,47 @@ } ] }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -13830,6 +13876,11 @@ "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", "dev": true }, + "err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -18307,8 +18358,7 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, "queue-tick": { "version": "1.0.0", @@ -18754,6 +18804,32 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true }, + "simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "requires": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index 641bcf2..1abff12 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "pako": "^2.0.4", "process": "^0.11.10", "randomstring": "^1.2.2", + "simple-peer": "^9.11.1", "stream-browserify": "^3.0.0" }, "devDependencies": {