@cloudflare/speedtest
Version:
Component to perform network speed tests against Cloudflare's edge network
1,265 lines (1,233 loc) • 99.2 kB
JavaScript
import 'isomorphic-fetch';
import memoize from 'lodash.memoize';
import { scaleThreshold } from 'd3-scale';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
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 _assertThisInitialized(e) {
if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return e;
}
function _callSuper(t, o, e) {
return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _checkPrivateRedeclaration(e, t) {
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _classPrivateFieldGet2(s, a) {
return s.get(_assertClassBrand(s, a));
}
function _classPrivateFieldInitSpec(e, t, a) {
_checkPrivateRedeclaration(e, t), t.set(e, a);
}
function _classPrivateFieldSet2(s, a, r) {
return s.set(_assertClassBrand(s, a), r), r;
}
function _classPrivateMethodInitSpec(e, a) {
_checkPrivateRedeclaration(e, a), a.add(e);
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", {
writable: false
}), e;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: true,
configurable: true,
writable: true
}) : e[r] = t, e;
}
function _get() {
return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
var p = _superPropBase(e, t);
if (p) {
var n = Object.getOwnPropertyDescriptor(p, t);
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
}
}, _get.apply(null, arguments);
}
function _getPrototypeOf(t) {
return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
return t.__proto__ || Object.getPrototypeOf(t);
}, _getPrototypeOf(t);
}
function _inherits(t, e) {
if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
t.prototype = Object.create(e && e.prototype, {
constructor: {
value: t,
writable: true,
configurable: true
}
}), Object.defineProperty(t, "prototype", {
writable: false
}), e && _setPrototypeOf(t, e);
}
function _isNativeReflectConstruct() {
try {
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch (t) {}
return (_isNativeReflectConstruct = function () {
return !!t;
})();
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = true,
o = false;
try {
if (i = (t = t.call(r)).next, 0 === l) {
if (Object(t) !== t) return;
f = !1;
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = true, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
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 ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _objectWithoutProperties(e, t) {
if (null == e) return {};
var o,
r,
i = _objectWithoutPropertiesLoose(e, t);
if (Object.getOwnPropertySymbols) {
var n = Object.getOwnPropertySymbols(e);
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
}
return i;
}
function _objectWithoutPropertiesLoose(r, e) {
if (null == r) return {};
var t = {};
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
if (-1 !== e.indexOf(n)) continue;
t[n] = r[n];
}
return t;
}
function _possibleConstructorReturn(t, e) {
if (e && ("object" == typeof e || "function" == typeof e)) return e;
if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
return _assertThisInitialized(t);
}
function set(e, r, t, o) {
return set = "undefined" != typeof Reflect && Reflect.set ? Reflect.set : function (e, r, t, o) {
var f,
i = _superPropBase(e, r);
if (i) {
if ((f = Object.getOwnPropertyDescriptor(i, r)).set) return f.set.call(o, t), true;
if (!f.writable) return false;
}
if (f = Object.getOwnPropertyDescriptor(o, r)) {
if (!f.writable) return false;
f.value = t, Object.defineProperty(o, r, f);
} else _defineProperty(o, r, t);
return true;
}, set(e, r, t, o);
}
function _set(e, r, t, o, f) {
if (!set(e, r, t, o || e) && f) throw new TypeError("failed to set property");
return t;
}
function _setPrototypeOf(t, e) {
return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
return t.__proto__ = e, t;
}, _setPrototypeOf(t, e);
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _superPropBase(t, o) {
for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t)););
return t;
}
function _superPropGet(t, o, e, r) {
var p = _get(_getPrototypeOf(t.prototype ), o, e);
return 2 & r && "function" == typeof p ? function (t) {
return p.apply(e, t);
} : p;
}
function _superPropSet(t, e, o, r, p, f) {
return _set(_getPrototypeOf(t.prototype ), e, o, r, p);
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
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);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var REL_API_URL = 'https://speed.cloudflare.com';
var defaultConfig = {
// Engine
autoStart: true,
// APIs
downloadApiUrl: "".concat(REL_API_URL, "/__down"),
uploadApiUrl: "".concat(REL_API_URL, "/__up"),
logMeasurementApiUrl: null,
logAimApiUrl: 'https://aim.cloudflare.com/__log',
turnServerUri: 'turn.speed.cloudflare.com:50000',
turnServerCredsApiUrl: "".concat(REL_API_URL, "/turn-creds"),
turnServerUser: null,
turnServerPass: null,
rpkiInvalidHost: 'invalid.rpki.cloudflare.com',
cfTraceUrl: "".concat(REL_API_URL, "/cdn-cgi/trace"),
includeCredentials: false,
sessionId: undefined,
// Measurements
measurements: [{
type: 'latency',
numPackets: 1
},
// initial ttfb estimation
{
type: 'download',
bytes: 1e5,
count: 1,
bypassMinDuration: true
},
// initial download estimation
{
type: 'latency',
numPackets: 20
}, {
type: 'download',
bytes: 1e5,
count: 9
}, {
type: 'download',
bytes: 1e6,
count: 8
}, {
type: 'upload',
bytes: 1e5,
count: 8
}, {
type: 'packetLoss',
numPackets: 1e3,
batchSize: 10,
batchWaitTime: 10,
// ms (in between batches)
responsesWaitTime: 3000 // ms (silent time after last sent msg)
}, {
type: 'upload',
bytes: 1e6,
count: 6
}, {
type: 'download',
bytes: 1e7,
count: 6
}, {
type: 'upload',
bytes: 1e7,
count: 4
}, {
type: 'download',
bytes: 2.5e7,
count: 4
}, {
type: 'upload',
bytes: 2.5e7,
count: 4
}, {
type: 'download',
bytes: 1e8,
count: 3
}, {
type: 'upload',
bytes: 5e7,
count: 3
}, {
type: 'download',
bytes: 2.5e8,
count: 2
}],
measureDownloadLoadedLatency: true,
measureUploadLoadedLatency: true,
loadedLatencyThrottle: 400,
// ms in between loaded latency requests
bandwidthFinishRequestDuration: 1000,
// download/upload duration (ms) to reach for stopping further measurements
estimatedServerTime: 10,
// ms to discount from latency calculation (if not present in response headers)
// Result interpretation
latencyPercentile: 0.5,
// Percentile used to calculate latency from a set of measurements
bandwidthPercentile: 0.9,
// Percentile used to calculate bandwidth from a set of measurements
bandwidthMinRequestDuration: 10,
// minimum duration (ms) to consider a measurement good enough to use in bandwidth calculation
loadedRequestMinDuration: 250,
// minimum duration (ms) of a request to consider it to be loading the connection
loadedLatencyMaxPoints: 20 // number of data points to keep for loaded latency
};
var internalConfig = {
// AIM
aimMeasurementScoring: {
packetLoss: scaleThreshold([0.01, 0.05, 0.25, 0.5], [10, 5, 0, -10, -20]),
latency: scaleThreshold([10, 20, 50, 100, 500], [20, 10, 5, 0, -10, -20]),
loadedLatencyIncrease: scaleThreshold([10, 20, 50, 100, 500], [20, 10, 5, 0, -10, -20]),
jitter: scaleThreshold([10, 20, 100, 500], [10, 5, 0, -10, -20]),
download: scaleThreshold([1e6, 10e6, 50e6, 100e6], [0, 5, 10, 20, 30]),
upload: scaleThreshold([1e6, 10e6, 50e6, 100e6], [0, 5, 10, 20, 30])
},
aimExperiencesDefs: {
streaming: {
input: ['latency', 'packetLoss', 'download', 'loadedLatencyIncrease'],
pointThresholds: [15, 20, 40, 60]
},
gaming: {
input: ['latency', 'packetLoss', 'loadedLatencyIncrease'],
pointThresholds: [5, 15, 25, 30]
},
rtc: {
input: ['latency', 'jitter', 'packetLoss', 'loadedLatencyIncrease'],
pointThresholds: [5, 15, 25, 40]
}
}
};
var MAX_RETRIES = 20;
var ESTIMATED_HEADER_FRACTION = 0.005; // ~.5% of packet header / payload size. used when transferSize is not available.
var cfGetServerTime = function cfGetServerTime(r) {
// extract server-timing from headers: server-timing: cfRequestDuration;dur=15.999794
var serverTiming = r.headers.get("server-timing");
if (serverTiming) {
var re = serverTiming.match(/dur=([0-9.]+)/);
if (re) return +re[1];
}
};
var getTtfb = function getTtfb(perf) {
return perf.responseStart - perf.requestStart;
};
var gePayloadDownload = function gePayloadDownload(perf) {
return perf.responseEnd - perf.responseStart;
}; // min 1ms
var calcDownloadDuration = function calcDownloadDuration(_ref) {
var ping = _ref.ping,
payloadDownloadTime = _ref.payloadDownloadTime;
return ping + payloadDownloadTime;
}; // request duration excluding server time
var calcUploadDuration = function calcUploadDuration(_ref2) {
var ttfb = _ref2.ttfb;
return ttfb;
};
var calcDownloadSpeed = function calcDownloadSpeed(_ref3, numBytes) {
var duration = _ref3.duration,
transferSize = _ref3.transferSize;
// use transferSize if available. if estimating from numBytes, add ~0.5% of headers.
var bits = 8 * (transferSize || +numBytes * (1 + ESTIMATED_HEADER_FRACTION));
var secs = duration / 1000;
return !secs ? undefined : bits / secs;
};
var calcUploadSpeed = function calcUploadSpeed(_ref4, numBytes) {
var duration = _ref4.duration;
var bits = 8 * numBytes * (1 + ESTIMATED_HEADER_FRACTION); // take into account estimated packet headers
var secs = duration / 1000; // subtract estimated server time
return !secs ? undefined : bits / secs;
};
var genContent = memoize(function (numBytes) {
return '0'.repeat(numBytes);
});
//
var _qsParams = /*#__PURE__*/new WeakMap();
var _fetchOptions = /*#__PURE__*/new WeakMap();
var _responseHook = /*#__PURE__*/new WeakMap();
var _onRunningChange = /*#__PURE__*/new WeakMap();
var _onNewMeasurementStarted = /*#__PURE__*/new WeakMap();
var _onMeasurementResult = /*#__PURE__*/new WeakMap();
var _onFinished$1 = /*#__PURE__*/new WeakMap();
var _onConnectionError$1 = /*#__PURE__*/new WeakMap();
var _measurements = /*#__PURE__*/new WeakMap();
var _downloadApi = /*#__PURE__*/new WeakMap();
var _uploadApi = /*#__PURE__*/new WeakMap();
var _running$2 = /*#__PURE__*/new WeakMap();
var _finished$1 = /*#__PURE__*/new WeakMap();
var _results$1 = /*#__PURE__*/new WeakMap();
var _measIdx = /*#__PURE__*/new WeakMap();
var _counter = /*#__PURE__*/new WeakMap();
var _retries = /*#__PURE__*/new WeakMap();
var _minDuration = /*#__PURE__*/new WeakMap();
var _throttleMs = /*#__PURE__*/new WeakMap();
var _estimatedServerTime = /*#__PURE__*/new WeakMap();
var _currentFetchPromise = /*#__PURE__*/new WeakMap();
var _currentNextMsmTimeoutId = /*#__PURE__*/new WeakMap();
var _BandwidthMeasurementEngine_brand = /*#__PURE__*/new WeakSet();
var BandwidthMeasurementEngine = /*#__PURE__*/function () {
function BandwidthMeasurementEngine(_measurements2) {
var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
downloadApiUrl = _ref5.downloadApiUrl,
uploadApiUrl = _ref5.uploadApiUrl,
_ref5$throttleMs = _ref5.throttleMs,
throttleMs = _ref5$throttleMs === void 0 ? 0 : _ref5$throttleMs,
_ref5$estimatedServer = _ref5.estimatedServerTime,
estimatedServerTime = _ref5$estimatedServer === void 0 ? 0 : _ref5$estimatedServer;
_classCallCheck(this, BandwidthMeasurementEngine);
// Internal methods
_classPrivateMethodInitSpec(this, _BandwidthMeasurementEngine_brand);
_classPrivateFieldInitSpec(this, _qsParams, {});
_classPrivateFieldInitSpec(this, _fetchOptions, {});
_defineProperty(this, "finishRequestDuration", 1000);
// download/upload duration (ms) to reach for stopping further measurements
_defineProperty(this, "getServerTime", cfGetServerTime);
// method to extract server time from response
_classPrivateFieldInitSpec(this, _responseHook, function (r) {
return r;
});
_classPrivateFieldInitSpec(this, _onRunningChange, function () {});
_classPrivateFieldInitSpec(this, _onNewMeasurementStarted, function () {});
_classPrivateFieldInitSpec(this, _onMeasurementResult, function () {});
_classPrivateFieldInitSpec(this, _onFinished$1, function () {});
_classPrivateFieldInitSpec(this, _onConnectionError$1, function () {});
// Internal state
_classPrivateFieldInitSpec(this, _measurements, void 0);
_classPrivateFieldInitSpec(this, _downloadApi, void 0);
_classPrivateFieldInitSpec(this, _uploadApi, void 0);
_classPrivateFieldInitSpec(this, _running$2, false);
_classPrivateFieldInitSpec(this, _finished$1, {
down: false,
up: false
});
_classPrivateFieldInitSpec(this, _results$1, {
down: {},
up: {}
});
_classPrivateFieldInitSpec(this, _measIdx, 0);
_classPrivateFieldInitSpec(this, _counter, 0);
_classPrivateFieldInitSpec(this, _retries, 0);
_classPrivateFieldInitSpec(this, _minDuration, -Infinity);
// of current measurement
_classPrivateFieldInitSpec(this, _throttleMs, 0);
_classPrivateFieldInitSpec(this, _estimatedServerTime, 0);
_classPrivateFieldInitSpec(this, _currentFetchPromise, undefined);
_classPrivateFieldInitSpec(this, _currentNextMsmTimeoutId, undefined);
if (!_measurements2) throw new Error('Missing measurements argument');
if (!downloadApiUrl) throw new Error('Missing downloadApiUrl argument');
if (!uploadApiUrl) throw new Error('Missing uploadApiUrl argument');
_classPrivateFieldSet2(_measurements, this, _measurements2);
_classPrivateFieldSet2(_downloadApi, this, downloadApiUrl);
_classPrivateFieldSet2(_uploadApi, this, uploadApiUrl);
_classPrivateFieldSet2(_throttleMs, this, throttleMs);
_classPrivateFieldSet2(_estimatedServerTime, this, Math.max(0, estimatedServerTime));
}
// Public attributes
return _createClass(BandwidthMeasurementEngine, [{
key: "results",
get: function get() {
// read access to results
return _classPrivateFieldGet2(_results$1, this);
}
}, {
key: "qsParams",
get:
// additional query string params to include in the requests
function get() {
return _classPrivateFieldGet2(_qsParams, this);
},
set: function set(v) {
_classPrivateFieldSet2(_qsParams, this, v);
}
}, {
key: "fetchOptions",
get:
// additional options included in the requests
function get() {
return _classPrivateFieldGet2(_fetchOptions, this);
},
set: function set(v) {
_classPrivateFieldSet2(_fetchOptions, this, v);
}
}, {
key: "responseHook",
set:
// pipe-through of response objects
function set(f) {
_classPrivateFieldSet2(_responseHook, this, f);
}
}, {
key: "onRunningChange",
set:
// callback invoked when engine starts/stops
function set(f) {
_classPrivateFieldSet2(_onRunningChange, this, f);
}
}, {
key: "onNewMeasurementStarted",
set:
// callback invoked when a new item in the measurement list is started
function set(f) {
_classPrivateFieldSet2(_onNewMeasurementStarted, this, f);
}
}, {
key: "onMeasurementResult",
set:
// callback invoked when a new measurement result arrives
function set(f) {
_classPrivateFieldSet2(_onMeasurementResult, this, f);
}
}, {
key: "onFinished",
set:
// callback invoked when all the measurements are finished
function set(f) {
_classPrivateFieldSet2(_onFinished$1, this, f);
}
}, {
key: "onConnectionError",
set:
// Invoked when unable to get a response from the API
function set(f) {
_classPrivateFieldSet2(_onConnectionError$1, this, f);
}
// Public methods
}, {
key: "pause",
value: function pause() {
clearTimeout(_classPrivateFieldGet2(_currentNextMsmTimeoutId, this));
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _cancelCurrentMeasurement).call(this);
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _setRunning$2).call(this, false);
}
}, {
key: "play",
value: function play() {
if (!_classPrivateFieldGet2(_running$2, this)) {
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _setRunning$2).call(this, true);
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _nextMeasurement).call(this);
}
}
}]);
}();
function _setRunning$2(running) {
var _this = this;
if (running !== _classPrivateFieldGet2(_running$2, this)) {
_classPrivateFieldSet2(_running$2, this, running);
setTimeout(function () {
return _classPrivateFieldGet2(_onRunningChange, _this).call(_this, _classPrivateFieldGet2(_running$2, _this));
});
}
}
function _saveMeasurementResults(measIdx, measTiming) {
var _this2 = this;
var _classPrivateFieldGet2$1 = _classPrivateFieldGet2(_measurements, this)[measIdx],
bytes = _classPrivateFieldGet2$1.bytes,
dir = _classPrivateFieldGet2$1.dir;
var results = _classPrivateFieldGet2(_results$1, this);
var bytesResult = results[dir].hasOwnProperty(bytes) ? results[dir][bytes] : {
timings: [],
// count all measurements with same bytes and direction
numMeasurements: _classPrivateFieldGet2(_measurements, this).filter(function (_ref6) {
var b = _ref6.bytes,
d = _ref6.dir;
return bytes === b && dir === d;
}).map(function (m) {
return m.count;
}).reduce(function (agg, cnt) {
return agg + cnt;
}, 0)
};
!!measTiming && bytesResult.timings.push(measTiming);
bytesResult.timings = bytesResult.timings.slice(-bytesResult.numMeasurements);
results[dir][bytes] = bytesResult;
if (measTiming) {
setTimeout(function () {
_classPrivateFieldGet2(_onMeasurementResult, _this2).call(_this2, _objectSpread2({
type: dir,
bytes: bytes
}, measTiming), results);
});
} else {
_classPrivateFieldGet2(_onNewMeasurementStarted, this).call(this, _classPrivateFieldGet2(_measurements, this)[measIdx], results);
}
}
function _nextMeasurement() {
var _this3 = this;
var measurements = _classPrivateFieldGet2(_measurements, this);
var meas = measurements[_classPrivateFieldGet2(_measIdx, this)];
if (_classPrivateFieldGet2(_counter, this) >= meas.count) {
// Finished current measurement
var finished = _classPrivateFieldGet2(_finished$1, this);
if (_classPrivateFieldGet2(_minDuration, this) > this.finishRequestDuration && !meas.bypassMinDuration) {
// mark direction as finished
var _dir = meas.dir;
_classPrivateFieldGet2(_finished$1, this)[_dir] = true;
Object.values(_classPrivateFieldGet2(_finished$1, this)).every(function (finished) {
return finished;
}) && _classPrivateFieldGet2(_onFinished$1, this).call(this, _classPrivateFieldGet2(_results$1, this));
}
// clear settings
_classPrivateFieldSet2(_counter, this, 0);
_classPrivateFieldSet2(_minDuration, this, -Infinity);
performance.clearResourceTimings();
do {
_classPrivateFieldSet2(_measIdx, this, _classPrivateFieldGet2(_measIdx, this) + 1); // skip through finished measurements
} while (_classPrivateFieldGet2(_measIdx, this) < measurements.length && finished[measurements[_classPrivateFieldGet2(_measIdx, this)].dir]);
if (_classPrivateFieldGet2(_measIdx, this) >= measurements.length) {
// reached the end: halt further measurements
_classPrivateFieldSet2(_finished$1, this, {
down: true,
up: true
});
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _setRunning$2).call(this, false);
_classPrivateFieldGet2(_onFinished$1, this).call(this, _classPrivateFieldGet2(_results$1, this));
return;
}
meas = measurements[_classPrivateFieldGet2(_measIdx, this)];
}
var measIdx = _classPrivateFieldGet2(_measIdx, this);
if (_classPrivateFieldGet2(_counter, this) === 0) {
_assertClassBrand(_BandwidthMeasurementEngine_brand, this, _saveMeasurementResults).call(this, measIdx); // register measurement start
}
var _meas = meas,
numBytes = _meas.bytes,
dir = _meas.dir;
var isDown = dir === 'down';
var apiUrl = isDown ? _classPrivateFieldGet2(_downloadApi, this) : _classPrivateFieldGet2(_uploadApi, this);
var qsParams = Object.assign({}, _classPrivateFieldGet2(_qsParams, this));
isDown && (qsParams.bytes = "".concat(numBytes));
var url = "".concat(apiUrl.startsWith('http') || apiUrl.startsWith('//') ? '' : window.location.origin // use abs to match perf timing urls
).concat(apiUrl, "?").concat(Object.entries(qsParams).map(function (_ref7) {
var _ref8 = _slicedToArray(_ref7, 2),
k = _ref8[0],
v = _ref8[1];
return "".concat(k, "=").concat(v);
}).join('&'));
var fetchOpt = Object.assign({}, isDown ? {} : {
method: 'POST',
body: genContent(numBytes)
}, _classPrivateFieldGet2(_fetchOptions, this));
var serverTime;
var curPromise = _classPrivateFieldSet2(_currentFetchPromise, this, fetch(url, fetchOpt).then(function (r) {
if (r.ok) return r;
throw Error(r.statusText);
}).then(function (r) {
_this3.getServerTime && (serverTime = _this3.getServerTime(r));
return r;
}).then(function (r) {
return r.text().then(function (body) {
_classPrivateFieldGet2(_responseHook, _this3) && _classPrivateFieldGet2(_responseHook, _this3).call(_this3, {
url: url,
headers: r.headers,
body: body
});
return body;
});
}).then(function (_, reject) {
if (curPromise._cancel) {
reject('cancelled');
return;
}
var perf = performance.getEntriesByName(url).slice(-1)[0]; // get latest perf timing
var timing = {
transferSize: perf.transferSize,
ttfb: getTtfb(perf),
payloadDownloadTime: gePayloadDownload(perf),
serverTime: serverTime || -1,
measTime: new Date()
};
timing.ping = Math.max(1e-2, timing.ttfb - (serverTime || _classPrivateFieldGet2(_estimatedServerTime, _this3))); // ttfb = network latency + server time
timing.duration = (isDown ? calcDownloadDuration : calcUploadDuration)(timing);
timing.bps = (isDown ? calcDownloadSpeed : calcUploadSpeed)(timing, numBytes);
if (isDown && numBytes) {
var reqSize = +numBytes;
if (timing.transferSize && (timing.transferSize < reqSize || timing.transferSize / reqSize > 1.05)) {
// log if transferSize is too different from requested size
console.warn("Requested ".concat(reqSize, "B but received ").concat(timing.transferSize, "B (").concat(Math.round(timing.transferSize / reqSize * 1e4) / 1e2, "%)."));
}
}
_assertClassBrand(_BandwidthMeasurementEngine_brand, _this3, _saveMeasurementResults).call(_this3, measIdx, timing);
var requestDuration = timing.duration;
_classPrivateFieldSet2(_minDuration, _this3, _classPrivateFieldGet2(_minDuration, _this3) < 0 ? requestDuration : Math.min(_classPrivateFieldGet2(_minDuration, _this3), requestDuration)); // carry minimum request duration
_classPrivateFieldSet2(_counter, _this3, _classPrivateFieldGet2(_counter, _this3) + 1);
_classPrivateFieldSet2(_retries, _this3, 0);
if (_classPrivateFieldGet2(_throttleMs, _this3)) {
_classPrivateFieldSet2(_currentNextMsmTimeoutId, _this3, setTimeout(function () {
return _assertClassBrand(_BandwidthMeasurementEngine_brand, _this3, _nextMeasurement).call(_this3);
}, _classPrivateFieldGet2(_throttleMs, _this3)));
} else {
_assertClassBrand(_BandwidthMeasurementEngine_brand, _this3, _nextMeasurement).call(_this3);
}
})["catch"](function (error) {
var _this$retries, _this$retries2;
if (curPromise._cancel) return;
console.warn("Error fetching ".concat(url, ": ").concat(error));
if ((_classPrivateFieldSet2(_retries, _this3, (_this$retries = _classPrivateFieldGet2(_retries, _this3), _this$retries2 = _this$retries++, _this$retries)), _this$retries2) < MAX_RETRIES) {
_assertClassBrand(_BandwidthMeasurementEngine_brand, _this3, _nextMeasurement).call(_this3); // keep trying
} else {
_classPrivateFieldSet2(_retries, _this3, 0);
_assertClassBrand(_BandwidthMeasurementEngine_brand, _this3, _setRunning$2).call(_this3, false);
_classPrivateFieldGet2(_onConnectionError$1, _this3).call(_this3, "Connection failed to ".concat(url, ". Gave up after ").concat(MAX_RETRIES, " retries."));
}
}));
}
function _cancelCurrentMeasurement() {
var curPromise = _classPrivateFieldGet2(_currentFetchPromise, this);
curPromise && (curPromise._cancel = true);
}
var _excluded$5 = ["measureParallelLatency", "parallelLatencyThrottleMs", "downloadApiUrl", "uploadApiUrl", "estimatedServerTime"];
var _latencyEngine = /*#__PURE__*/new WeakMap();
var _latencyTimeout = /*#__PURE__*/new WeakMap();
var _BandwidthWithParallelLatencyEngine_brand = /*#__PURE__*/new WeakSet();
var BandwidthWithParallelLatencyEngine = /*#__PURE__*/function (_BandwidthEngine) {
function BandwidthWithParallelLatencyEngine(measurements) {
var _this;
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$measureParallelL = _ref.measureParallelLatency,
measureParallelLatency = _ref$measureParallelL === void 0 ? false : _ref$measureParallelL,
_ref$parallelLatencyT = _ref.parallelLatencyThrottleMs,
parallelLatencyThrottleMs = _ref$parallelLatencyT === void 0 ? 100 : _ref$parallelLatencyT,
downloadApiUrl = _ref.downloadApiUrl,
uploadApiUrl = _ref.uploadApiUrl,
_ref$estimatedServerT = _ref.estimatedServerTime,
estimatedServerTime = _ref$estimatedServerT === void 0 ? 0 : _ref$estimatedServerT,
ptProps = _objectWithoutProperties(_ref, _excluded$5);
_classCallCheck(this, BandwidthWithParallelLatencyEngine);
_this = _callSuper(this, BandwidthWithParallelLatencyEngine, [measurements, _objectSpread2({
downloadApiUrl: downloadApiUrl,
uploadApiUrl: uploadApiUrl,
estimatedServerTime: estimatedServerTime
}, ptProps)]);
// Internal methods
_classPrivateMethodInitSpec(_this, _BandwidthWithParallelLatencyEngine_brand);
// Internal state
_classPrivateFieldInitSpec(_this, _latencyEngine, void 0);
_classPrivateFieldInitSpec(_this, _latencyTimeout, void 0);
if (measureParallelLatency) {
_classPrivateFieldSet2(_latencyEngine, _this, new BandwidthMeasurementEngine([{
dir: 'down',
bytes: 0,
count: Infinity,
bypassMinDuration: true
}], {
downloadApiUrl: downloadApiUrl,
uploadApiUrl: uploadApiUrl,
estimatedServerTime: estimatedServerTime,
throttleMs: parallelLatencyThrottleMs
}));
_classPrivateFieldGet2(_latencyEngine, _this).qsParams = {
during: "".concat(measurements[0].dir, "load")
};
_superPropSet((BandwidthWithParallelLatencyEngine), "onRunningChange", _assertClassBrand(_BandwidthWithParallelLatencyEngine_brand, _this, _setLatencyRunning), _this, 1);
_superPropSet((BandwidthWithParallelLatencyEngine), "onConnectionError", function () {
return _classPrivateFieldGet2(_latencyEngine, _this).pause();
}, _this, 1);
}
return _this;
}
// Public attributes
_inherits(BandwidthWithParallelLatencyEngine, _BandwidthEngine);
return _createClass(BandwidthWithParallelLatencyEngine, [{
key: "latencyResults",
get: function get() {
// read access to latency results
return _classPrivateFieldGet2(_latencyEngine, this) && _classPrivateFieldGet2(_latencyEngine, this).results.down[0].timings;
}
// callback invoked when a new parallel latency result arrives
}, {
key: "onParallelLatencyResult",
set: function set(f) {
_classPrivateFieldGet2(_latencyEngine, this) && (_classPrivateFieldGet2(_latencyEngine, this).onMeasurementResult = function (res) {
return f(res);
});
}
// Overridden attributes
}, {
key: "fetchOptions",
get: function get() {
return _superPropGet(BandwidthWithParallelLatencyEngine, "fetchOptions", this, 1);
},
set: function set(fetchOptions) {
_superPropSet(BandwidthWithParallelLatencyEngine, "fetchOptions", fetchOptions, this, 1);
_classPrivateFieldGet2(_latencyEngine, this) && (_classPrivateFieldGet2(_latencyEngine, this).fetchOptions = fetchOptions);
}
}, {
key: "onRunningChange",
set: function set(onRunningChange) {
var _this2 = this;
_superPropSet(BandwidthWithParallelLatencyEngine, "onRunningChange", function (running) {
_assertClassBrand(_BandwidthWithParallelLatencyEngine_brand, _this2, _setLatencyRunning).call(_this2, running);
onRunningChange(running);
}, this, 1);
}
}, {
key: "onConnectionError",
set: function set(onConnectionError) {
var _this3 = this;
_superPropSet(BandwidthWithParallelLatencyEngine, "onConnectionError", function () {
_classPrivateFieldGet2(_latencyEngine, _this3) && _classPrivateFieldGet2(_latencyEngine, _this3).pause();
onConnectionError.apply(void 0, arguments);
}, this, 1);
}
}]);
}(BandwidthMeasurementEngine);
function _setLatencyRunning(running) {
var _this4 = this;
if (_classPrivateFieldGet2(_latencyEngine, this)) {
if (!running) {
clearTimeout(_classPrivateFieldGet2(_latencyTimeout, this));
_classPrivateFieldGet2(_latencyEngine, this).pause();
} else {
// slight delay in starting latency measurements
_classPrivateFieldSet2(_latencyTimeout, this, setTimeout(function () {
return _classPrivateFieldGet2(_latencyEngine, _this4).play();
}, 20));
}
}
}
var _excluded$4 = ["measurementId", "logApiUrl", "sessionId"];
var _measurementId$1 = /*#__PURE__*/new WeakMap();
var _token = /*#__PURE__*/new WeakMap();
var _requestTime = /*#__PURE__*/new WeakMap();
var _logApiUrl = /*#__PURE__*/new WeakMap();
var _sessionId$1 = /*#__PURE__*/new WeakMap();
var _LoggingBandwidthEngine_brand = /*#__PURE__*/new WeakSet();
var LoggingBandwidthEngine = /*#__PURE__*/function (_BandwidthEngine) {
function LoggingBandwidthEngine(measurements) {
var _this;
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
measurementId = _ref.measurementId,
logApiUrl = _ref.logApiUrl,
sessionId = _ref.sessionId,
ptProps = _objectWithoutProperties(_ref, _excluded$4);
_classCallCheck(this, LoggingBandwidthEngine);
_this = _callSuper(this, LoggingBandwidthEngine, [measurements, ptProps]);
// Internal methods
_classPrivateMethodInitSpec(_this, _LoggingBandwidthEngine_brand);
// Internal state
_classPrivateFieldInitSpec(_this, _measurementId$1, void 0);
_classPrivateFieldInitSpec(_this, _token, void 0);
_classPrivateFieldInitSpec(_this, _requestTime, void 0);
_classPrivateFieldInitSpec(_this, _logApiUrl, void 0);
_classPrivateFieldInitSpec(_this, _sessionId$1, void 0);
_classPrivateFieldSet2(_measurementId$1, _this, measurementId);
_classPrivateFieldSet2(_logApiUrl, _this, logApiUrl);
_classPrivateFieldSet2(_sessionId$1, _this, sessionId);
_superPropSet((LoggingBandwidthEngine), "qsParams", logApiUrl ? {
measId: _classPrivateFieldGet2(_measurementId$1, _this)
} : {}, _this, 1);
_superPropSet((LoggingBandwidthEngine), "responseHook", function (r) {
return _assertClassBrand(_LoggingBandwidthEngine_brand, _this, _loggingResponseHook).call(_this, r);
}, _this, 1);
_superPropSet((LoggingBandwidthEngine), "onMeasurementResult", function (meas) {
return _assertClassBrand(_LoggingBandwidthEngine_brand, _this, _logMeasurement).call(_this, meas);
}, _this, 1);
return _this;
}
// Overridden attributes
_inherits(LoggingBandwidthEngine, _BandwidthEngine);
return _createClass(LoggingBandwidthEngine, [{
key: "qsParams",
set: function set(qsParams) {
_superPropSet(LoggingBandwidthEngine, "qsParams", _classPrivateFieldGet2(_logApiUrl, this) ? _objectSpread2({
measId: _classPrivateFieldGet2(_measurementId$1, this)
}, qsParams) : qsParams, this, 1);
}
}, {
key: "responseHook",
set: function set(responseHook) {
var _this2 = this;
_superPropSet(LoggingBandwidthEngine, "responseHook", function (r) {
responseHook(r);
_assertClassBrand(_LoggingBandwidthEngine_brand, _this2, _loggingResponseHook).call(_this2, r);
}, this, 1);
}
}, {
key: "onMeasurementResult",
set: function set(onMeasurementResult) {
var _this3 = this;
_superPropSet(LoggingBandwidthEngine, "onMeasurementResult", function (meas) {
for (var _len = arguments.length, restArgs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
restArgs[_key - 1] = arguments[_key];
}
onMeasurementResult.apply(void 0, [meas].concat(restArgs));
_assertClassBrand(_LoggingBandwidthEngine_brand, _this3, _logMeasurement).call(_this3, meas);
}, this, 1);
}
}]);
}(BandwidthWithParallelLatencyEngine);
function _loggingResponseHook(r) {
if (!_classPrivateFieldGet2(_logApiUrl, this)) return;
// get request time
_classPrivateFieldSet2(_requestTime, this, +r.headers.get("cf-meta-request-time"));
// get token in payload
_classPrivateFieldSet2(_token, this, r.body.slice(-300).split('___').pop());
}
function _logMeasurement(measData) {
if (!_classPrivateFieldGet2(_logApiUrl, this)) return;
var logData = {
type: measData.type,
bytes: measData.bytes,
ping: Math.round(measData.ping),
// round to ms
ttfb: Math.round(measData.ttfb),
// round to ms
payloadDownloadTime: Math.round(measData.payloadDownloadTime),
duration: Math.round(measData.duration),
transferSize: Math.round(measData.transferSize),
serverTime: Math.round(measData.serverTime),
token: _classPrivateFieldGet2(_token, this),
requestTime: _classPrivateFieldGet2(_requestTime, this),
measId: _classPrivateFieldGet2(_measurementId$1, this),
sessionId: _classPrivateFieldGet2(_sessionId$1, this)
};
_classPrivateFieldSet2(_token, this, null);
_classPrivateFieldSet2(_requestTime, this, null);
fetch(_classPrivateFieldGet2(_logApiUrl, this), _objectSpread2({
method: 'POST',
body: JSON.stringify(logData)
}, this.fetchOptions));
}
var _running$1 = /*#__PURE__*/new WeakMap();
var _currentPromise = /*#__PURE__*/new WeakMap();
var _promiseFn = /*#__PURE__*/new WeakMap();
var _PromiseEngine_brand = /*#__PURE__*/new WeakSet();
var PromiseEngine = /*#__PURE__*/function () {
function PromiseEngine(promiseFn) {
_classCallCheck(this, PromiseEngine);
// Internal methods
_classPrivateMethodInitSpec(this, _PromiseEngine_brand);
// Internal state
_classPrivateFieldInitSpec(this, _running$1, false);
_classPrivateFieldInitSpec(this, _currentPromise, undefined);
_classPrivateFieldInitSpec(this, _promiseFn, void 0);
if (!promiseFn) throw new Error("Missing operation to perform");
_classPrivateFieldSet2(_promiseFn, this, promiseFn);
this.play();
}
// Public methods
return _createClass(PromiseEngine, [{
key: "pause",
value: function pause() {
_assertClassBrand(_PromiseEngine_brand, this, _cancelCurrent).call(this);
_assertClassBrand(_PromiseEngine_brand, this, _setRunning$1).call(this, false);
}
}, {
key: "stop",
value: function stop() {
this.pause();
}
}, {
key: "play",
value: function play() {
if (!_classPrivateFieldGet2(_running$1, this)) {
_assertClassBrand(_PromiseEngine_brand, this, _setRunning$1).call(this, true);
_assertClassBrand(_PromiseEngine_brand, this, _next$1).call(this);
}
}
}]);
}();
function _setRunning$1(running) {
if (running !== _classPrivateFieldGet2(_running$1, this)) {
_classPrivateFieldSet2(_running$1, this, running);
}
}
function _next$1() {
var _this2 = this;
var curPromise = _classPrivateFieldSet2(_currentPromise, this, _classPrivateFieldGet2(_promiseFn, this).call(this).then(function () {
!curPromise._cancel && _assertClassBrand(_PromiseEngine_brand, _this2, _next$1).call(_this2);
}));
}
function _cancelCurrent() {
var curPromise = _classPrivateFieldGet2(_currentPromise, this);
curPromise && (curPromise._cancel = true);
}
var _engines = /*#__PURE__*/new WeakMap();
var LoadNetworkEngine = /*#__PURE__*/function () {
function LoadNetworkEngine() {
var _this = this;
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
download = _ref.download,
upload = _ref.upload;
_classCallCheck(this, LoadNetworkEngine);
// Public attributes
_defineProperty(this, "qsParams", {});
// additional query string params to include in the requests
_defineProperty(this, "fetchOptions", {});
// Internal state
_classPrivateFieldInitSpec(this, _engines, []);
// Expected attrs for each: { apiUrl, chunkSize }
if (!download && !upload) throw new Error('Missing at least one of download/upload config');
[[download, 'download'], [upload, 'upload']].filter(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 1),
cfg = _ref3[0];
return cfg;
}).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
cfg = _ref5[0],
type = _ref5[1];
var apiUrl = cfg.apiUrl,
chunkSize = cfg.chunkSize;
if (!apiUrl) throw new Error("Missing ".concat(type, " apiUrl argument"));
if (!chunkSize) throw new Error("Missing ".concat(type, " chunkSize argument"));
});
var getLoadEngine = function getLoadEngine(_ref6) {
var apiUrl = _ref6.apiUrl,
_ref6$qsParams = _ref6.qsParams,
qsParams = _ref6$qsParams === void 0 ? {} : _ref6$qsParams,
_ref6$fetchOptions = _ref6.fetchOptions,
fetchOptions = _ref6$fetchOptions === void 0 ? {} : _ref6$fetchOptions;
return new PromiseEngine(function () {
var fetchQsParams = Object.assign({}, qsParams, _this.qsParams);
var url = "".concat(apiUrl.startsWith('http') || apiUrl.startsWith('//') ? '' : window.location.origin // use abs to match perf timing urls
).concat(apiUrl, "?").concat(Object.entries(fetchQsParams).map(function (_ref7) {
var _ref8 = _slicedToArray(_ref7, 2),
k = _ref8[0],
v = _ref8[1];
return "".concat(k, "=").concat(v);
}).join('&'));
var fetchOpt = Object.assign({}, fetchOptions, _this.fetchOptions);
return fetch(url, fetchOpt).then(function (r) {
if (r.ok) return r;
throw Error(r.statusText);
}).then(function (r) {
return r.text();
});
});
};
download && _classPrivateFieldGet2(_engines, this).push(getLoadEngine({
apiUrl: download.apiUrl,
qsParams: {
bytes: "".concat(download.chunkSize)
}
}));
upload && _classPrivateFieldGet2(_engines, this).push(getLoadEngine({
apiUrl: upload.apiUrl,
fetchOptions: {
method: 'POST',
body: '0'.repeat(upload.chunkSize)
}
}));
}
return _createClass(LoadNetworkEngine, [{
key: "pause",
value:
// additional options included in the requests
// Public methods
function pause() {
_classPrivateFieldGet2(_engines, this).forEach(function (engine) {
return engine.pause();
});
}
}, {
key: "stop",
value: function stop() {
this.pause();
}
}, {
key: "play",
value: function play() {
_classPrivateFieldGet2(_engines, this).forEach(function (engine) {
return engine.play();
});
}
}]);
}();
var _excluded$3 = ["iceServers", "acceptIceCandidate", "dataChannelCfg"];
var _established = /*#__PURE__*/new WeakMap();
var _sender = /*#__PURE__*/new WeakMap();
var _receiver = /*#__PURE__*/new WeakMap();
var _senderDc = /*#__PURE__*/new WeakMap();
var _receiverDc = /*#__PURE__*/new WeakMap();
var SelfWebRtcDataConnection = /*#__PURE__*/function () {
function SelfWebRtcDataConnection() {
var _this = this;
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$iceServers = _ref.iceServers,
iceServers = _ref$iceServers === void 0 ? [] : _ref$iceServers,
_ref$acceptIceCandida = _ref.acceptIceCandidate,
acceptIceCandidate = _ref$acceptIceCandida === void 0 ? function (candidate) {
var protocol = candidate.protocol || '';
// parsed webRTC candidate properties not extracted in Firefox: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate
if (!protocol && candidate.candidate) {
var sdpAttrs = candidate.candidate.split(' ');
sdpAttrs.length >= 3 && (protocol = sdpAttrs[2]);
}
return protocol.toLowerCase() === 'udp';
} : _ref$acceptIceCandida,
_ref$dataChannelCfg = _ref.dataChannelCfg,
dataChannelCfg = _ref$dataChannelCfg === void 0 ? {
ordered: false,
maxRetransmits: 0
} : _ref$dataChannelCfg,
rtcPeerConnectionCfg = _objectWithoutProperties(_ref, _excluded$3);
_classCallCheck(this, SelfWebRtcDataConnection);
// Public attributes
_defineProperty(this, "onOpen", function () {});
// callback invoked when WebRTC TURN connection is established
_defineProperty(this, "onClose", function () {});
// callback invoked when WebRTC TURN connection is closed
_defineProperty(this, "onMessageReceived", function () {});
// Internal state
_classPrivateFieldInitSpec(this, _established, false);
_classPrivateFieldInitSpec(this, _sender, void 0);
_classPrivateFieldInitSpec(this, _receiver, void 0);
_classPrivateFieldInitSpec(this, _senderDc, void 0);
_classPrivateFieldInitSpec(this, _receiverDc, void 0);
var sender = new RTCPeerConnection(_objectSpread2({
iceServers: iceServers
}, rtcPeerConnectionCfg));
var receiver = new RTCPeerConnection(_objectSpread2({
iceServers: iceServers
}, rtcPeerConnectionCfg));
var senderDc = sender.createDataChannel('channel', dataChannelCfg);
senderDc.onopen = function () {
_classPrivateFieldSet2(_established, _this, true);
_this.onOpen();
};
senderDc.onclose = function () {
return _this.close();
};
// senderDc.onmessage = msg => this.#onMessage(msg.data);
receiver.ondatachannel = function (e) {
var dc = e.channel;
dc.onclose = function () {
return _this.close();
};
dc.onmessage = function (msg) {
return _this.onMessageReceived(msg.data);
};
_classPrivateFieldSet2(_receiverDc, _this, dc);
};
// sender.onconnectionstatechange = e => console.log('connection state change', e);
// sender.oniceconnectionstatechange = e => console.log('ice connection state change', e);
// sender.onicecandidateerror = e => console.log('ice error', e);
sender.onicecandidate = function (e) {
// console.log('sender', e.candidate);
e.candidate && acceptIceCandidate(e.candidate) && receiver.addIceCandidate(e.candidate);
};
receiver.onicecandidate = function (e) {
// console.log('receiver', e.candidate);
e.candidate && acceptIceCandidate(e.candidate) && sender.addIceCandidate(e.candidate);
};
sender.createOffer().then(function (offer) {
return sender.setLocalDescription(offer);
}).then(function () {
return receiver.setRemoteDescription(sender.localDescription);
}).then(function () {
return receiver.createAnswer();
}).then(function (answer) {
return receiver.setLocalDescription(answer);
}).then(function () {
return sender.setRemoteDescription(receiver.localDescription);
});
_classPrivateFieldSet2(_sender, this, sender);
_classPrivateFieldSet2(_receiver, this, receiver);
_classPrivateFieldSet2(_senderDc, this, senderDc);
_classPrivateFieldSet2(_established, this, false);
}
return _createClass(SelfWebRtcDataConnection, [{
key: "send",
value:
// callback invoked when a new message is received from the TURN server
// Public methods
function send(msg) {
return _classPrivateFieldGet2(_senderDc, this).send(msg);
}
}, {
key: "close",
value: function close() {
_classPrivateFieldGet2(_sender, this) && _classPrivateFieldGet2(_sender, this).close();
_classPrivateFieldGet2(_receiver, this) && _classPrivateFieldGet2(_receiver, this).close();
_classPrivateFieldGet2(_senderDc, this) && _classPrivateFieldGet2(_senderDc, this).close();
_classPrivateFieldGet2(_receiverDc, this) && _classPrivateFieldGet2(_receiverDc, this).close();
_classPrivateFieldGet2(_established, this) && this.onClose();
_classPrivateFieldSet2(_established, this, false);
return this;
}
}]);
}();
var _onCredentialsFailure = /*#__PURE__*/new WeakMap();
var _onConnectionError = /*#__PURE__*/new WeakMap();
var _onFinished = /*#__PURE__*/new WeakMap();
var _msgTracker = /*#__PURE__*/new WeakMap();
var _webRtcConnection = /*#__PURE__*/new WeakMap();
var _numMsgs = /*#__PURE__*/new WeakMap();
var PacketLossEngine = /*#__PURE__*/function () {
function PacketLossEngine() {
var _this = this;
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
turnServerUri = _ref.turnServerUri,
turnServerCredsApi = _ref.turnServerCredsApi,
_ref$turnServerCredsA = _ref.turnServerCredsApiParser,
turnServerCredsApiParser = _ref$turnServerCredsA === void 0 ? func