@zoom/probesdk
Version:
Zoom ProbeSDK tests the end user device and network capabilities, and the Zoom server connection.
1,256 lines (1,233 loc) • 281 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.probesdk = {}));
})(this, (function (exports) { 'use strict';
function _assertClassBrand(e, t, n) {
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
throw new TypeError("Private element is not present on this object");
}
function _classPrivateFieldGet2(s, a) {
return s.get(_assertClassBrand(s, a));
}
function _classPrivateFieldSet2(s, a, r) {
return s.set(_assertClassBrand(s, a), r), r;
}
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return e;
};
var t,
e = {},
r = Object.prototype,
n = r.hasOwnProperty,
o = Object.defineProperty || function (t, e, r) {
t[e] = r.value;
},
i = "function" == typeof Symbol ? Symbol : {},
a = i.iterator || "@@iterator",
c = i.asyncIterator || "@@asyncIterator",
u = i.toStringTag || "@@toStringTag";
function define(t, e, r) {
return Object.defineProperty(t, e, {
value: r,
enumerable: !0,
configurable: !0,
writable: !0
}), t[e];
}
try {
define({}, "");
} catch (t) {
define = function (t, e, r) {
return t[e] = r;
};
}
function wrap(t, e, r, n) {
var i = e && e.prototype instanceof Generator ? e : Generator,
a = Object.create(i.prototype),
c = new Context(n || []);
return o(a, "_invoke", {
value: makeInvokeMethod(t, r, c)
}), a;
}
function tryCatch(t, e, r) {
try {
return {
type: "normal",
arg: t.call(e, r)
};
} catch (t) {
return {
type: "throw",
arg: t
};
}
}
e.wrap = wrap;
var h = "suspendedStart",
l = "suspendedYield",
f = "executing",
s = "completed",
y = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var p = {};
define(p, a, function () {
return this;
});
var d = Object.getPrototypeOf,
v = d && d(d(values([])));
v && v !== r && n.call(v, a) && (p = v);
var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
function defineIteratorMethods(t) {
["next", "throw", "return"].forEach(function (e) {
define(t, e, function (t) {
return this._invoke(e, t);
});
});
}
function AsyncIterator(t, e) {
function invoke(r, o, i, a) {
var c = tryCatch(t[r], t, o);
if ("throw" !== c.type) {
var u = c.arg,
h = u.value;
return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
invoke("next", t, i, a);
}, function (t) {
invoke("throw", t, i, a);
}) : e.resolve(h).then(function (t) {
u.value = t, i(u);
}, function (t) {
return invoke("throw", t, i, a);
});
}
a(c.arg);
}
var r;
o(this, "_invoke", {
value: function (t, n) {
function callInvokeWithMethodAndArg() {
return new e(function (e, r) {
invoke(t, n, e, r);
});
}
return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(e, r, n) {
var o = h;
return function (i, a) {
if (o === f) throw Error("Generator is already running");
if (o === s) {
if ("throw" === i) throw a;
return {
value: t,
done: !0
};
}
for (n.method = i, n.arg = a;;) {
var c = n.delegate;
if (c) {
var u = maybeInvokeDelegate(c, n);
if (u) {
if (u === y) continue;
return u;
}
}
if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
if (o === h) throw o = s, n.arg;
n.dispatchException(n.arg);
} else "return" === n.method && n.abrupt("return", n.arg);
o = f;
var p = tryCatch(e, r, n);
if ("normal" === p.type) {
if (o = n.done ? s : l, p.arg === y) continue;
return {
value: p.arg,
done: n.done
};
}
"throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
}
};
}
function maybeInvokeDelegate(e, r) {
var n = r.method,
o = e.iterator[n];
if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
var i = tryCatch(o, e.iterator, r.arg);
if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
var a = i.arg;
return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
}
function pushTryEntry(t) {
var e = {
tryLoc: t[0]
};
1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
}
function resetTryEntry(t) {
var e = t.completion || {};
e.type = "normal", delete e.arg, t.completion = e;
}
function Context(t) {
this.tryEntries = [{
tryLoc: "root"
}], t.forEach(pushTryEntry, this), this.reset(!0);
}
function values(e) {
if (e || "" === e) {
var r = e[a];
if (r) return r.call(e);
if ("function" == typeof e.next) return e;
if (!isNaN(e.length)) {
var o = -1,
i = function next() {
for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
return next.value = t, next.done = !0, next;
};
return i.next = i;
}
}
throw new TypeError(typeof e + " is not iterable");
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), o(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
var e = "function" == typeof t && t.constructor;
return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
}, e.mark = function (t) {
return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
}, e.awrap = function (t) {
return {
__await: t
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
return this;
}), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
void 0 === i && (i = Promise);
var a = new AsyncIterator(wrap(t, r, n, o), i);
return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
return t.done ? t.value : a.next();
});
}, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
return this;
}), define(g, "toString", function () {
return "[object Generator]";
}), e.keys = function (t) {
var e = Object(t),
r = [];
for (var n in e) r.push(n);
return r.reverse(), function next() {
for (; r.length;) {
var t = r.pop();
if (t in e) return next.value = t, next.done = !1, next;
}
return next.done = !0, next;
};
}, e.values = values, Context.prototype = {
constructor: Context,
reset: function (e) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
},
stop: function () {
this.done = !0;
var t = this.tryEntries[0].completion;
if ("throw" === t.type) throw t.arg;
return this.rval;
},
dispatchException: function (e) {
if (this.done) throw e;
var r = this;
function handle(n, o) {
return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
}
for (var o = this.tryEntries.length - 1; o >= 0; --o) {
var i = this.tryEntries[o],
a = i.completion;
if ("root" === i.tryLoc) return handle("end");
if (i.tryLoc <= this.prev) {
var c = n.call(i, "catchLoc"),
u = n.call(i, "finallyLoc");
if (c && u) {
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
} else if (c) {
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
} else {
if (!u) throw Error("try statement without catch or finally");
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
}
}
}
},
abrupt: function (t, e) {
for (var r = this.tryEntries.length - 1; r >= 0; --r) {
var o = this.tryEntries[r];
if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
var i = o;
break;
}
}
i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
var a = i ? i.completion : {};
return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
},
complete: function (t, e) {
if ("throw" === t.type) throw t.arg;
return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
},
finish: function (t) {
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
var r = this.tryEntries[e];
if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
}
},
catch: function (t) {
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
var r = this.tryEntries[e];
if (r.tryLoc === t) {
var n = r.completion;
if ("throw" === n.type) {
var o = n.arg;
resetTryEntry(r);
}
return o;
}
}
throw Error("illegal catch attempt");
},
delegateYield: function (e, r, n) {
return this.delegate = {
iterator: values(e),
resultName: r,
nextLoc: n
}, "next" === this.method && (this.arg = t), y;
}
}, e;
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
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, _toPropertyKey(descriptor.key), descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (!it) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
var F = function () {};
return {
s: F,
n: function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
},
e: function (e) {
throw e;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
return {
s: function () {
it = it.call(o);
},
n: function () {
var step = it.next();
normalCompletion = step.done;
return step;
},
e: function (e) {
didErr = true;
err = e;
},
f: function () {
try {
if (!normalCompletion && it.return != null) it.return();
} finally {
if (didErr) throw err;
}
}
};
}
function _checkPrivateRedeclaration(obj, privateCollection) {
if (privateCollection.has(obj)) {
throw new TypeError("Cannot initialize the same private elements twice on an object");
}
}
function _classPrivateFieldInitSpec(obj, privateMap, value) {
_checkPrivateRedeclaration(obj, privateMap);
privateMap.set(obj, value);
}
function _classPrivateMethodInitSpec(obj, privateSet) {
_checkPrivateRedeclaration(obj, privateSet);
privateSet.add(obj);
}
/**
* Enumeration of a collection of customized error codes defined and used by ProberSDK.
* @enum {number}
* @property {number} OK Indicates a successful operation. Default value is 0.
* @property {number} INVALID_ARGS Indicates invalid arguments passed to a function. Default value is -1.
* @property {number} API_NOT_SUPPORTED Indicates that a specific API is not supported. Default value is -2.
* @constant
*/
var ERR_CODE = {
OK: 0,
INVALID_ARGS: -1,
API_NOT_SUPPORTED: -2
};
/**
* Enumeration of the rendering types supported by ProbeSDK.
*
* @enum {number}
* @property {number} VIDEO_TAG a video stream will be rendered on the {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video|video} tag. Default value is 1.
* @property {number} WEBGL a video stream will be rendered on a canvas with a {@link https://developer.mozilla.org/en-US/docs/Glossary/WebGL|WebGL} renderer. Default value is 2.
* @property {number} WEBGL_2 a video stream will be rendered on a canvas with a {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API#webgl_2|WebGL2} renderer. Default value is 3.
* @property {number} WEBGPU a video stream will be rendered on a canvas with a {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API|WebGPU} renderer. Default value is 4.
* @constant
*/
var RENDERER_TYPE = {
VIDEO_TAG: 1,
WEBGL: 2,
WEBGL_2: 3,
WEBGPU: 4
};
/**
* Enumeration of the data type of the network diagnostic.
* It will be used to determine the type of data you received and how to handle them.
*
* @enum {number}
* @property {number} STATS indicates the realtime statistics of the network diagnostic. Default value is 1.
* @property {number} REPORT indicates the final report of diagnostic, basic information and supported features. Default value is 2.
* @constant
*/
var NET_PROBING_DATA_TYPE = {
STATS: 1,
REPORT: 2
};
/**
* Enumeration of the protocol type that ProbeSDK checks in a network diagnostic.
*
* @enum {number}
* @property {number} HTTPS https(https://) protocol. Default value is 1.
* @property {number} WEB_SOCKET WebSocket(wss:// ws://) protocol. Default value is 2.
* @property {number} DATA_CHANNEL the data channel which is used for media communication. Default value is 3.
* @property {number} WEB_TRANSPORT WebTransport protocol(not supported now). Default value is 4.
* @constant
*/
var PROTOCOL_TYPE = {
HTTPS: 1,
WEB_SOCKET: 2,
DATA_CHANNEL: 3,
WEB_TRANSPORT: 4
};
/**
* Enumeration of the network quality level.
*
* @enum {number}
* @property {number} VERY_BAD network quality is very bad. Default value is 0.
* @property {number} BAD network quality is bad. Default value is 1.
* @property {number} NOT_GOOD network quality is not good enough. Default value is 2.
* @property {number} FAIR network quality is fine. Default value is 3.
* @property {number} GOOD network quality is good. Default value is 4.
* @property {number} EXCELLENT network quality is excellent. Default value is 5.
* @property {number} UNDEFINED network quality is unknown. If get this value, means the network diagnostic is not started yet or gets some exceptions. Default value is 255.
* @constant
*/
var NETWORK_QUALITY_LEVEL = {
VERY_BAD: 0,
BAD: 1,
NOT_GOOD: 2,
FAIR: 3,
GOOD: 4,
EXCELLENT: 5,
UNDEFINED: 255
};
/**
* Enumeration of the bandwidth quality level.
*
* @enum {number}
* @property {number} VERY_LOW bandwidth quality is very low. Default value is 0.
* @property {number} LOW bandwidth quality is low. Default value is 1.
* @property {number} NORMAL bandwidth quality is normal. Default value is 2.
* @property {number} UNDEFINED bandwidth quality is unknown. If get this value, means the network diagnostic is not started yet or gets some exceptions. Default value is 255.
* @constant
*/
var BANDWIDTH_QUALITY_LEVEL = {
VERY_LOW: 0,
LOW: 1,
NORMAL: 2,
UNDEFINED: 255
};
/**
* Enumeration of attribute index of the basic information.
*
* @enum {number}
* @property {number} BROWSER_NAME represents the name of the browser. Default value is 0.
* @property {number} BROWSER_VERSION represents the version of the browser. Default value is 1.
* @property {number} OS_NAME represents the name of the OS. Default value is 2.
* @property {number} USER_AGENT represents the user agent. Default value is 3.
* @property {number} HW_CONCURRENCY represents the hardware concurrency. Default value is 4.
* @property {number} GPU_VENDOR represents the GPU vendor. Default value is 5.
* @property {number} GPU_RENDERER represents the GPU renderer information. Default value is 6.
* @property {number} VIDEOFRAME represents the VideoFrame API. Default value is 7.
* @property {number} OFFSCREENCANVAS represents the OffscreenCanvas API. Default value is 8.
* @property {number} SIMD represents the SIMD feature. Default value is 9.
* @property {number} WEB_CODEC represents the web codec feature. Default value is 10.
* @property {number} HW_ACC represents the hardware acceleration. Default value is 11.
* @property {number} GRAPHICS_ACC represents the graphics acceleration in chromium system settings. Default value is 12.
* @property {number} MIN_BROWSER_VERSION represents the minimum browser version. Default value is 13.
* @property {number} SHARED_ARRAY_BUFFER represents the SharedArrayBuffer. Default value is 14.
* @property {number} BUILD_BITNESS represents the build bitness(32bit or 64bit). Default value is 15.
* @constant
*/
var BASIC_INFO_ATTR_INDEX = {
BROWSER_NAME: 0,
BROWSER_VERSION: 1,
OS_NAME: 2,
OS_VERSION: 3,
USER_AGENT: 4,
HW_CONCURRENCY: 5,
GPU_VENDOR: 6,
GPU_RENDERER: 7,
VIDEOFRAME: 8,
OFFSCREENCANVAS: 9,
SIMD: 10,
WEB_CODEC: 11,
HW_ACC: 12,
GRAPHICS_ACC: 13,
MIN_BROWSER_VERSION: 14,
SHARED_ARRAY_BUFFER: 15,
BUILD_BITNESS: 16
};
/**
* Enumeration of index of the supported features.
*
* @enum {number}
* @property {number} AUDIO_DENOISE feature index of audio denoise. Default value is 0.
* @property {number} AEC feature index of audio echo cancellation. Default value is 1.
* @property {number} AUDIO_STEREO feature index of audio stereo. Default value is 2.
* @property {number} VIRTUAL_BACKGROUND feature index of video virtual background. Default value is 3.
* @property {number} VIDEO_MASK feature index of video mask. Default value is 4.
* @property {number} WEBGPU feature index of video WebGPU rendering. Default value is 5.
* @property {number} VIDEO_SEND_HD feature index of video sending HD. Default value is 6.
* @property {number} VIDEO_SEND_FULL_HD feature index of video sending full HD. Default value is 7.
* @property {number} DT_GALLERY_VIEW_3x3 feature index of desktop supporting 3x3 gallery view. Default value is 8.
* @property {number} DT_GALLERY_VIEW_5x5 feature index of desktop supporting 5x5 gallery view. Default value is 9.
* @property {number} SCREEN_SHARING feature index of screen sharing. Default value is 10.
* @constant
*/
var SUPPORTED_FEATURE_INDEX = {
AUDIO_DENOISE: 0,
AEC: 1,
AUDIO_STEREO: 2,
VIRTUAL_BACKGROUND: 3,
VIDEO_MASK: 4,
WEBGPU: 5,
VIDEO_SEND_HD: 6,
VIDEO_SEND_FULL_HD: 7,
DT_GALLERY_VIEW_3x3: 8,
DT_GALLERY_VIEW_5x5: 9,
SCREEN_SHARING: 10
};
/**
* The default probing duration, 120 seconds.
*/
var DEF_PROBE_DURATION = 2 * 60 * 1000;
/**
* The default connection timeout, 20 seconds.
*/
var DEF_CONNECT_TIMEOUT = 2 * 10 * 1000;
var JWT_DOMAINS = {
PROD: "zoom.us",
GO: "go.zoom.us",
DEV: "zoomdev.us",
DEV_EP: "devep.zoomdev.us",
DEV_INT: "dev-integration.zoomdev.us"
};
function checkType(obj, targetType) {
return !!(obj instanceof targetType);
}
function isDebugMode() {
return process.env.NODE_ENV === "development";
}
function getJWTPayload(token) {
var base64Url = token.split(".")[1];
var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
var jsonPayload = decodeURIComponent(window.atob(base64).split("").map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
}).join(""));
return JSON.parse(jsonPayload);
}
function isInUserAgent(userAgent) {
for (var _len = arguments.length, tags = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
tags[_key - 1] = arguments[_key];
}
if (!userAgent || userAgent === "") {
console.error("isInUserAgent() userAgent is invalid! userAgent: ".concat(userAgent));
return false;
}
if (!tags || tags.length <= 0) {
console.error("isInUserAgent() tag is invalid! tags: ".concat(tags));
return false;
}
return tags.some(function (tag) {
return userAgent.includes(tag);
});
}
function saveKvToLocalStorage(key, value) {
if (isDebugMode()) {
console.log("saveKvToLocalStorage() key: ".concat(key, ", val:").concat(value));
}
localStorage.setItem(key, value);
}
function readValueFromLocalStorage(key) {
return localStorage.getItem(key);
}
/**
* Test whether can allocate a string of a given length.
* @param {Number} len a length of string to be allocated.
* @returns {boolean} true if the string can be allocated, false otherwise.
*/
function canSupportStringLength(len) {
try {
return new Array(len + 1).join('x').length === len;
} catch (e) {
return false;
}
}
var GLOBAL_SEQ = 1;
var KEY_RID = "probing_rid";
function base64ToBytes(base64) {
var binString = atob(base64);
return Uint8Array.from(binString, function (m) {
return m.codePointAt(0);
});
}
function bytesToBase64(bytes) {
var binString = String.fromCodePoint.apply(String, _toConsumableArray(bytes));
return btoa(binString);
}
function getCommandMessage(evt, body) {
var msg = {};
msg["evt"] = evt;
msg["seq"] = GLOBAL_SEQ;
GLOBAL_SEQ += 1;
msg["body"] = body;
return JSON.stringify(msg);
}
function connectWebSocket(_x) {
return _connectWebSocket.apply(this, arguments);
}
function _connectWebSocket() {
_connectWebSocket = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(url) {
return _regeneratorRuntime().wrap(function _callee11$(_context11) {
while (1) switch (_context11.prev = _context11.next) {
case 0:
if (isDebugMode()) {
console.log("connectWebSocket() url=".concat(url));
}
return _context11.abrupt("return", new Promise(function (resolve, reject) {
var socket = new WebSocket(url);
socket.onopen = function () {
resolve({
socket: socket,
result: true,
error: undefined
});
};
socket.onerror = function (error) {
resolve({
socket: socket,
result: false,
error: error
});
};
}));
case 2:
case "end":
return _context11.stop();
}
}, _callee11);
}));
return _connectWebSocket.apply(this, arguments);
}
function js_send_data(prober_instance, buffer, len, send_by_data) {
if (prober_instance) {
var data = new Uint8Array(Module.HEAP8.buffer, buffer, len);
if (send_by_data) {
if (prober_instance.writer !== null && prober_instance.writer !== undefined) {
prober_instance.writer.write(data);
} else if (prober_instance.dataChannelOpened) {
if (prober_instance.videoDataChannel) {
prober_instance.videoDataChannel.send(data);
}
} else if (prober_instance.mediaSocket !== null && prober_instance.mediaSocket !== undefined) {
prober_instance.mediaSocket.send(data);
}
} else {
var binString = bytesToBase64(data);
var body = {};
body["data"] = binString;
if (prober_instance.socket) {
prober_instance.socket.send(getCommandMessage(4106, body));
}
}
}
}
function js_report_qos_info(prober_instance, bandwidth, rate, loss_rate, max_continuous_loss_num, rtt, max_owdelay, jitter, app_score, bw_level) {
// uplink
var uplink_bandwidth = bandwidth / 1024 / 1024;
var uplink_rtt = rtt;
var uplink_lossratio = loss_rate / 10;
var uplink_max_continuous_loss_num = max_continuous_loss_num;
var uplink_rate = rate / 1024 / 1024;
var uplink_owdelay = max_owdelay;
var uplink_jitter = jitter;
if (isDebugMode()) {
console.log("js_report_qos_info: uplink_bandwidth=".concat(uplink_bandwidth, ", uplink_rtt=").concat(uplink_rtt, ", count=").concat(prober_instance === null || prober_instance === void 0 ? void 0 : prober_instance.uplink_count));
}
if (prober_instance) {
prober_instance.on_uplink_report({
bandwidth: uplink_bandwidth,
rtt: uplink_rtt,
loss_rate: uplink_lossratio,
max_continuous_loss_num: uplink_max_continuous_loss_num,
rate: uplink_rate,
max_owdelay: uplink_owdelay,
jitter: uplink_jitter,
network_level: app_score,
bw_level: bw_level
});
prober_instance.uplink_count += 1;
prober_instance.total_ul_rtt += uplink_rtt;
prober_instance.total_ul_loss += uplink_lossratio;
prober_instance.total_ul_jitter += uplink_jitter;
prober_instance.last_ul_bw = uplink_bandwidth;
prober_instance.last_ul_bw_level = bw_level;
prober_instance.last_ul_network_level = app_score;
} else {
console.error("js_report_qos_info: prober_instance is null or undefined!");
}
}
function wcl_trace_log(a, b) {
var n = new Uint8Array(b + 1);
var s = Module.HEAP8.subarray(a + 0, a + b);
n.set(s, 0, b);
n[b] = 10;
}
var _NetworkProberInst_brand = /*#__PURE__*/new WeakSet();
var NetworkProberInst = /*#__PURE__*/function () {
function NetworkProberInst(params) {
var _this = this;
_classCallCheck(this, NetworkProberInst);
_classPrivateMethodInitSpec(this, _NetworkProberInst_brand);
this.dc = "No available service zone.";
this.jwtDomain = params.domain;
this.probeServerDomain = "";
this.geoProbeConnectionList = [];
this.on_uplink_report = params.on_uplink_report;
this.on_downlink_report = params.on_downlink_report;
this.socket = null;
this.connectionId = "";
this.index = -1;
this.worker = null;
this.rid = null;
var Module = params.Module;
this.api = {
create_prober: Module.cwrap("create_prober", "number", []),
destroy_prober: Module.cwrap("destroy_prober", "", ["number"]),
on_prober_timer: Module.cwrap("on_prober_timer", "", ["number"]),
prober_start_send: Module.cwrap("prober_start_send", "", ["number"]),
prober_stop_send: Module.cwrap("prober_stop_send", "", ["number"]),
readPackets: Module.cwrap("readPackets", "number", ["number", "array", "number", "number"])
};
this.prober = null;
this.mediaSocket = null;
this.keepAliveTimer = null;
this.videoPeer = new RTCPeerConnection({
iceCandidatePoolSize: 1
});
this.videoPeer.addEventListener("iceconnectionstatechange", function () {
if (_this.videoPeer.iceConnectionState === "disconnected" || _this.videoPeer.iceConnectionState === "failed" || _this.videoPeer.iceConnectionState === "closed") {
console.log("PeerConnection disconnected, closing DataChannel.");
_this.cleanupDataChannel();
}
});
this.videoDataChannel = this.videoPeer.createDataChannel("prober_datachannel", {
ordered: false,
maxRetransmits: 0,
reliable: false
});
this.dataChannelOpened = false;
this.dc_recv_packets = 0;
this.transport = null;
this.writer = null;
var prober_instance = this;
window.wcl_trace_log = wcl_trace_log;
window.js_send_data = function (buffer, len, send_by_data) {
js_send_data(prober_instance, buffer, len, send_by_data);
};
window.js_report_qos_info = function (bandwidth, rate, loss_rate, max_continuous_loss_num, rtt, max_owdelay, jitter, app_score, bw_level) {
if (isDebugMode()) {
console.log("js_report_qos_info called: bandwidth=".concat(bandwidth, ", app_score=").concat(app_score, ", bw_level=").concat(bw_level));
}
js_report_qos_info(prober_instance, bandwidth, rate, loss_rate, max_continuous_loss_num, rtt, max_owdelay, jitter, app_score, bw_level);
};
this.downlink_count = 0;
this.total_dl_rtt = 0;
this.total_dl_loss = 0;
this.total_dl_jitter = 0;
this.last_dl_bw = 0;
this.last_dl_bw_level = 255;
this.last_dl_network_level = 255;
this.uplink_count = 0;
this.total_ul_rtt = 0;
this.total_ul_loss = 0;
this.total_ul_jitter = 0;
this.last_ul_bw = 0;
this.last_ul_bw_level = 255;
this.last_ul_network_level = 255;
this.httpsProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.HTTPS, false);
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.WEB_SOCKET, true, "", "unchecked");
this.dataChannelProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.DATA_CHANNEL, true, "", "unchecked");
}
return _createClass(NetworkProberInst, [{
key: "connect",
value: function () {
var _connect = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(timeout) {
var _this2 = this;
var _data$result, jwtTokenUrl, tokenRsp, ridPart, rid, data, token, payload, hasGeoProbeConnected, geoProbeList, cmdChannelResult, _iterator, _step, geoProbe, cmdChannelUrl, _yield$this$getConnec, connectionId, index, mediaUrl, mediaChannelResult, isDataChannelEstablished;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
jwtTokenUrl = "https://".concat(this.jwtDomain, "/probe/network/monitor/auth/info");
_context.next = 4;
return fetch(jwtTokenUrl, {
method: "POST",
mode: "cors",
headers: {}
});
case 4:
tokenRsp = _context.sent;
if (tokenRsp.ok) {
_context.next = 8;
break;
}
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.HTTPS, true);
return _context.abrupt("return", false);
case 8:
// get rsp headers
ridPart = "";
if (tokenRsp.headers.has("X-Zm-Trackingid")) {
rid = _assertClassBrand(_NetworkProberInst_brand, this, _extractRid).call(this, tokenRsp.headers.get("X-Zm-Trackingid"));
if (rid !== "") {
this.rid = rid.slice(4, rid.length);
saveKvToLocalStorage(KEY_RID, this.rid);
ridPart = "&".concat(rid);
}
if (isDebugMode()) {
console.log("trackingId: ".concat(tokenRsp.headers.get("X-Zm-Trackingid"), ", finalRid:").concat(ridPart));
}
} else {
console.log("connect() no tid header.");
}
_context.next = 12;
return tokenRsp.json();
case 12:
data = _context.sent;
token = data === null || data === void 0 || (_data$result = data.result) === null || _data$result === void 0 ? void 0 : _data$result.probeToken;
if (token) {
_context.next = 17;
break;
}
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.HTTPS, true, "", "", {
message: "cannot retrieve token from server response!"
});
return _context.abrupt("return", false);
case 17:
payload = getJWTPayload(token);
if (isDebugMode()) {
console.log("jwtToken payload:".concat(JSON.stringify(payload)));
}
hasGeoProbeConnected = false;
geoProbeList = JSON.parse(payload.geoProbeList);
cmdChannelResult = null;
_iterator = _createForOfIteratorHelper(geoProbeList);
_context.prev = 23;
_iterator.s();
case 25:
if ((_step = _iterator.n()).done) {
_context.next = 48;
break;
}
geoProbe = _step.value;
if (isDebugMode()) {
console.log("geoProbeEntry: dc=".concat(geoProbe.dc, ", probe=").concat(geoProbe.probe));
}
this.dc = geoProbe.dc;
this.probeServerDomain = geoProbe.probe;
// this.domain = '10.100.212.157:810';
// 1. Check the command channel whether the connection is established or not.
cmdChannelUrl = "wss://".concat(this.probeServerDomain, "/probe/?token=").concat(token).concat(ridPart);
_context.next = 33;
return connectWebSocket(cmdChannelUrl);
case 33:
cmdChannelResult = _context.sent;
if (cmdChannelResult.result) {
_context.next = 42;
break;
}
if (isDebugMode()) {
console.warn("failed to connect! geoProbeEntry: dc=".concat(geoProbe.dc, ", probe=").concat(geoProbe.probe));
}
// record the failed connection
this.geoProbeConnectionList.push({
dc: geoProbe.dc,
probe: geoProbe.probe,
connected: false
});
if (cmdChannelResult.socket) {
cmdChannelResult.socket.close();
}
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.WEB_SOCKET, true, "", "", cmdChannelResult.error);
return _context.abrupt("continue", 46);
case 42:
hasGeoProbeConnected = true;
// record the successful connection
this.geoProbeConnectionList.push({
dc: geoProbe.dc,
probe: geoProbe.probe,
connected: true
});
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.WEB_SOCKET, false);
return _context.abrupt("break", 48);
case 46:
_context.next = 25;
break;
case 48:
_context.next = 53;
break;
case 50:
_context.prev = 50;
_context.t0 = _context["catch"](23);
_iterator.e(_context.t0);
case 53:
_context.prev = 53;
_iterator.f();
return _context.finish(53);
case 56:
if (!(!hasGeoProbeConnected || !cmdChannelResult)) {
_context.next = 61;
break;
}
if (isDebugMode()) {
console.error("no available geolocation connected!");
}
this.dc = "No available service zone.";
this.killKeepAliveTimer();
return _context.abrupt("return", false);
case 61:
// if goes here, means the command channel is connected
// we need to start a timer with 5 seconds interval to send keep alive message to server
if (!this.keepAliveTimer) {
this.keepAliveTimer = setInterval(function () {
_this2.sendKeepAliveMessage();
}, 5000);
}
this.socket = cmdChannelResult.socket;
_context.next = 65;
return this.getConnectionId();
case 65:
_yield$this$getConnec = _context.sent;
connectionId = _yield$this$getConnec.connectionId;
index = _yield$this$getConnec.index;
this.connectionId = connectionId;
this.index = index;
this.cmdMessageRegister();
// Always create a new prober instance to ensure clean state
if (this.prober) {
this.api.destroy_prober(this.prober);
}
this.prober = this.api.create_prober();
// 2. Media websocket works as the backup of the data channel if fails
mediaUrl = "wss://".concat(this.probeServerDomain, "/media/?cid=").concat(this.connectionId, "&index=").concat(this.index);
_context.next = 76;
return connectWebSocket(mediaUrl);
case 76:
mediaChannelResult = _context.sent;
if (mediaChannelResult.result) {
_context.next = 83;
break;
}
if (mediaChannelResult.socket) {
mediaChannelResult.socket.close();
}
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.WEB_SOCKET, true, "", "", mediaChannelResult.error);
return _context.abrupt("return", false);
case 83:
if (this.wssProtocol == undefined || this.wssProtocol.isBlocked) {
this.wssProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.WEB_SOCKET, false);
}
case 84:
this.mediaSocket = mediaChannelResult.socket;
this.mediaMessageRegister();
// 3. Try to connect data channel
_context.next = 88;
return this.connectDataChannel(timeout);
case 88:
isDataChannelEstablished = _context.sent;
if (!isDataChannelEstablished) {
this.dataChannelProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.DATA_CHANNEL, true, "8801", "Please check the network connectivity and the port which might be blocked", cmdChannelResult.error);
} else {
if (this.dataChannelProtocol == undefined || this.dataChannelProtocol.isBlocked) {
this.dataChannelProtocol = this.assembleProtocolResult(PROTOCOL_TYPE.DATA_CHANNEL, false, "8801");
}
}
return _context.abrupt("return", true);
case 93:
_context.prev = 93;
_context.t1 = _context["catch"](0);
console.error("Error connecting:", _context.t1);
return _context.abrupt("return", false);
case 97:
case "end":
return _context.stop();
}
}, _callee, this, [[0, 93], [23, 50, 53, 56]]);
}));
function connect(_x2) {
return _connect.apply(this, arguments);
}
return connect;
}()
}, {
key: "startUplinkProbe",
value: function () {
var _startUplinkProbe = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
var workerScript, blob, count, interval, probeTime, maxCount, prober_instance;
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
if (this.prober) {
_context2.next = 3;
break;
}
console.error("startUplinkProbe: prober instance is null!");
return _context2.abrupt("return");
case 3:
if (!this.worker) {
workerScript = "\n var worker_active = false;\n\n setInterval(() => {\n if (worker_active) {\n postMessage(worker_active);\n }\n }, 10);\n\n onmessage = (e) => {\n worker_active = e.data;\n };\n ";
blob = new Blob([workerScript], {
type: "application/javascript"
});
this.worker = new Worker(URL.createObjectURL(blob), {
type: "module"
});
}
this.worker.postMessage(true);
this.api.prober_start_send(this.prober);
count = 0;
interval = 10; // Worker sends message every 10ms
probeTime = 300 * 1000; // 300 seconds
maxCount = probeTime / interval; // 30000
prober_instance = this; // console.log(`Worker will send ${maxCount} timer calls over ${probeTime}ms`);
this.worker.onmessage = function (event) {
if (count < maxCount) {
prober_instance.api.on_prober_timer(prober_instance.prober);
count += 1;
// Log progress every 1000 calls
if (count % 1000 === 0) {
console.log("Uplink probe timer called ".concat(count, "/").concat(maxCount, " times"));
}
}
};
case 12:
case "end":
return _context2.stop();
}
}, _callee2, this);
}));
function startUplinkProbe() {
return _startUplinkProbe.apply(this, arguments);
}
return startUplinkProbe;
}()
}, {
key: "stopUplinkProbe",
value: function () {
var _stopUplinkProbe = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
this.api.prober_stop_send(this.prober);
if (this.worker) {
this.worker.postMessage(false);
this.worker.terminate();
this.worker = null;
}
case 2:
case "end":
return _context3.stop();
}
}, _callee3, this);
}));
function stopUplinkProbe() {
return _stopUplinkProbe.apply(this, arguments);
}
return stopUplinkProbe;
}()
}, {
key: "startDownlinkProbe",
value: function () {
var _startDownlinkProbe = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
console.log("startDownlinkProbe");
_context4.next = 3;
return this.socket.send(getCommandMessage(4107, {}));
case 3:
case "end":
return _context4.stop();
}
}, _callee4, this);
}));
function startDownlinkProbe() {
return _startDownlinkProbe.apply(this, arguments);
}
return startDownlinkProbe;
}()
}, {
key: "stopDownlinkProbe",
value: function () {
var _stopDownlinkProbe = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {