in monitoring-stack-cdk/resources/frontend/connect-rtc.js [10490:11322]
bytesReceived: parseInt(statsReport.stat('bytesReceived')),
packetsLost: (0, _utils.is_defined)(parseInt(statsReport.stat('packetsLost'))) ? Math.max(0, statsReport.stat('packetsLost')) : 0,
frameRateReceived: (0, _utils.when_defined)(parseFloat(statsReport.stat('statsReport.googFrameRateReceived'))),
procMilliseconds: (0, _utils.when_defined)(parseInt(statsReport.stat('googCurrentDelayMs'))),
jbMilliseconds: (0, _utils.when_defined)(parseInt(statsReport.stat('googJitterReceived')))
};
}
// Standardized report for input stream stats
} else if (statsReport.type === 'inbound-rtp' && !statsReport.isRemote && (streamType === 'audio_input' || streamType === 'video_input')) {
reportType = statsReport.type;
extractedStats = {
timestamp: timestamp,
packetsLost: statsReport.packetsLost,
packetsCount: statsReport.packetsReceived,
jbMilliseconds: (0, _utils.when_defined)(statsReport.jitter, 0) * 1000
};
// Standardized report for packets sent
} else if (statsReport.type === 'outbound-rtp' && !statsReport.isRemote && (streamType === 'audio_output' || streamType === 'video_output')) {
// outbound-rtp report can appear either before or after extractedStats object is created
if (extractedStats && !extractedStats.packetsCount) {
extractedStats.packetsCount = statsReport.packetsSent;
} else {
packetsSent = statsReport.packetsSent;
}
// Standardized report for remaining output stream stats
} else if (statsReport.type === 'remote-inbound-rtp' && (streamType === 'audio_output' || streamType === 'video_output')) {
reportType = statsReport.type;
extractedStats = {
timestamp: timestamp,
packetsLost: statsReport.packetsLost,
packetsCount: packetsSent,
rttMilliseconds: Number.isInteger(statsReport.roundTripTime) ? statsReport.roundTripTime : (0, _utils.is_defined)(statsReport.roundTripTime) ? statsReport.roundTripTime * 1000 : null,
jbMilliseconds: (0, _utils.when_defined)(statsReport.jitter, 0) * 1000
};
// Case for Firefox 65 and below for getting remaining output stream stats
} else if (statsReport.type === 'inbound-rtp' && statsReport.isRemote && (streamType === 'audio_output' || streamType === 'video_output')) {
reportType = statsReport.type;
extractedStats = {
timestamp: timestamp,
packetsLost: statsReport.packetsLost,
packetsCount: packetsSent,
rttMilliseconds: Number.isInteger(statsReport.roundTripTime) ? statsReport.roundTripTime : (0, _utils.is_defined)(statsReport.roundTripTime) ? statsReport.roundTripTime * 1000 : null,
jbMilliseconds: (0, _utils.when_defined)(statsReport.jitter, 0) * 1000
};
}
}
});
return extractedStats ? new MediaRtpStats(extractedStats, reportType, streamType) : null;
}
/**
* Basic RTP statistics object, represents statistics of an audio or video stream.
*/
/**
* Extract rtp stats of specified stream from RTCStatsReport
* Chrome reports all stream stats in statsReports whereas firefox reports only single stream stats in report
* StreamType is passed only to pull right stream stats audio_input or audio_output.
*/
var MediaRtpStats = function () {
function MediaRtpStats(paramsIn, statsReportType, streamType) {
(0, _classCallCheck3.default)(this, MediaRtpStats);
var params = paramsIn || {};
this._timestamp = params.timestamp || new Date().getTime();
this._packetsLost = (0, _utils.when_defined)(params.packetsLost);
this._packetsCount = (0, _utils.when_defined)(params.packetsCount);
this._audioLevel = (0, _utils.when_defined)(params.audioLevel);
this._procMilliseconds = (0, _utils.when_defined)(params.procMilliseconds);
this._rttMilliseconds = (0, _utils.when_defined)(params.rttMilliseconds);
this._jbMilliseconds = (0, _utils.when_defined)(params.jbMilliseconds);
this._bytesSent = (0, _utils.when_defined)(params.bytesSent);
this._bytesReceived = (0, _utils.when_defined)(params.bytesReceived);
this._framesEncoded = (0, _utils.when_defined)(params.framesEncoded);
this._framesDecoded = (0, _utils.when_defined)(params.framesDecoded);
this._frameRateSent = (0, _utils.when_defined)(params.frameRateSent);
this._frameRateReceived = (0, _utils.when_defined)(params.frameRateReceived);
this._statsReportType = statsReportType || params._statsReportType || "unknown";
this._streamType = streamType || params.streamType || "unknown";
}
/** {number} number of packets sent to the channel */
(0, _createClass3.default)(MediaRtpStats, [{
key: 'packetsCount',
get: function get() {
return this._packetsCount;
}
/** {number} number of packets lost after travelling through the channel */
}, {
key: 'packetsLost',
get: function get() {
return this._packetsLost;
}
/** {number} number of packets lost after travelling through the channel */
}, {
key: 'packetLossPercentage',
get: function get() {
return this._packetsCount > 0 ? this._packetsLost / this._packetsCount : 0;
}
/** Audio volume level
* Currently firefox doesn't provide audio level in rtp stats.
*/
}, {
key: 'audioLevel',
get: function get() {
return this._audioLevel;
}
/** Timestamp when stats are collected. */
}, {
key: 'timestamp',
get: function get() {
return this._timestamp;
}
/** {number} Processing delay calculated by time to process packet header */
}, {
key: 'procMilliseconds',
get: function get() {
return this._procMilliseconds;
}
/** {number} Round trip time calculated with RTCP reports */
}, {
key: 'rttMilliseconds',
get: function get() {
return this._rttMilliseconds;
}
/** {number} Statistical variance of RTP data packet inter-arrival time */
}, {
key: 'jbMilliseconds',
get: function get() {
return this._jbMilliseconds;
}
/** {number} number of bytes sent to the channel*/
}, {
key: 'bytesSent',
get: function get() {
return this._bytesSent;
}
/** {number} number of bytes received from the channel*/
}, {
key: 'bytesReceived',
get: function get() {
return this._bytesReceived;
}
/** {number} number of video frames encoded*/
}, {
key: 'framesEncoded',
get: function get() {
return this._framesEncoded;
}
/** {number} number of video frames decoded*/
}, {
key: 'framesDecoded',
get: function get() {
return this._framesDecoded;
}
/** {number} frames per second sent to the channel*/
}, {
key: 'frameRateSent',
get: function get() {
return this._frameRateSent;
}
/** {number} frames per second received from the channel*/
}, {
key: 'frameRateReceived',
get: function get() {
return this._frameRateReceived;
}
/** {string} the type of the stats report */
}, {
key: 'statsReportType',
get: function get() {
return this._statsReportType;
}
/** {string} the type of the stream */
}, {
key: 'streamType',
get: function get() {
return this._streamType;
}
}]);
return MediaRtpStats;
}();
},{"./utils":140,"babel-runtime/helpers/classCallCheck":10,"babel-runtime/helpers/createClass":11}],138:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SessionReport = undefined;
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
var SessionReport = exports.SessionReport = function () {
/**
* @class Prototype for tracking various RTC session report
* @constructs
*/
function SessionReport() {
(0, _classCallCheck3.default)(this, SessionReport);
this._sessionStartTime = null;
this._sessionEndTime = null;
this._gumTimeMillis = null;
this._initializationTimeMillis = null;
this._iceCollectionTimeMillis = null;
this._signallingConnectTimeMillis = null;
this._handshakingTimeMillis = null;
this._preTalkingTimeMillis = null;
this._talkingTimeMillis = null;
this._iceConnectionsLost = 0;
this._cleanupTimeMillis = null;
this._iceCollectionFailure = null;
this._signallingConnectionFailure = null;
this._handshakingFailure = null;
this._gumOtherFailure = null;
this._gumTimeoutFailure = null;
this._createOfferFailure = null;
this._setLocalDescriptionFailure = null;
this._userBusyFailure = null;
this._invalidRemoteSDPFailure = null;
this._noRemoteIceCandidateFailure = null;
this._setRemoteDescriptionFailure = null;
this._streamStats = [];
}
/**
*Timestamp when RTCSession started.
*/
(0, _createClass3.default)(SessionReport, [{
key: "sessionStartTime",
get: function get() {
return this._sessionStartTime;
}
/**
* Timestamp when RTCSession ended.
*/
,
set: function set(value) {
this._sessionStartTime = value;
}
}, {
key: "sessionEndTime",
get: function get() {
return this._sessionEndTime;
}
/**
* Time taken for grabbing user microphone at the time of connecting RTCSession.
*/
,
set: function set(value) {
this._sessionEndTime = value;
}
}, {
key: "gumTimeMillis",
get: function get() {
return this._gumTimeMillis;
}
/**
* Time taken for session initialization in millis. Includes time spent in GrabLocalMedia, SetLocalSDP states.
*/
,
set: function set(value) {
this._gumTimeMillis = value;
}
}, {
key: "initializationTimeMillis",
get: function get() {
return this._initializationTimeMillis;
}
/**
* Time spent on ICECollection in millis.
*/
,
set: function set(value) {
this._initializationTimeMillis = value;
}
}, {
key: "iceCollectionTimeMillis",
get: function get() {
return this._iceCollectionTimeMillis;
}
/**
* Time taken for connecting the signalling in millis.
*/
,
set: function set(value) {
this._iceCollectionTimeMillis = value;
}
}, {
key: "signallingConnectTimeMillis",
get: function get() {
return this._signallingConnectTimeMillis;
}
/**
* Times spent from RTCSession connection until entering Talking state in millis.
*/
,
set: function set(value) {
this._signallingConnectTimeMillis = value;
}
}, {
key: "preTalkingTimeMillis",
get: function get() {
return this._preTalkingTimeMillis;
}
/**
* Times spent in completing handshaking process of the RTCSession in millis.
*/
,
set: function set(value) {
this._preTalkingTimeMillis = value;
}
}, {
key: "handshakingTimeMillis",
get: function get() {
return this._handshakingTimeMillis;
}
/**
* Times spent in Talking state in millis.
*/
,
set: function set(value) {
this._handshakingTimeMillis = value;
}
}, {
key: "talkingTimeMillis",
get: function get() {
return this._talkingTimeMillis;
}
/**
* How many times the RTCSession has lost ICE connection in talking state.
*/
,
set: function set(value) {
this._talkingTimeMillis = value;
}
}, {
key: "iceConnectionsLost",
get: function get() {
return this._iceConnectionsLost;
}
/**
* Times spent in Cleanup state in millis
*/
,
set: function set(value) {
this._iceConnectionsLost = value;
}
}, {
key: "cleanupTimeMillis",
get: function get() {
return this._cleanupTimeMillis;
}
/**
* Tells if the RTCSession fails in ICECollection.
*/
,
set: function set(value) {
this._cleanupTimeMillis = value;
}
}, {
key: "iceCollectionFailure",
get: function get() {
return this._iceCollectionFailure;
}
/**
* Tells if the RTCSession failed in signalling connect stage.
*/
,
set: function set(value) {
this._iceCollectionFailure = value;
}
}, {
key: "signallingConnectionFailure",
get: function get() {
return this._signallingConnectionFailure;
}
/**
* Handshaking failure of the RTCSession
*/
,
set: function set(value) {
this._signallingConnectionFailure = value;
}
}, {
key: "handshakingFailure",
get: function get() {
return this._handshakingFailure;
}
/**
* Gum failed due to timeout at the time of new RTCSession connection
*/
,
set: function set(value) {
this._handshakingFailure = value;
}
}, {
key: "gumTimeoutFailure",
get: function get() {
return this._gumTimeoutFailure;
}
/**
* Gum failed due to other reasons (other than Timeout)
*/
,
set: function set(value) {
this._gumTimeoutFailure = value;
}
}, {
key: "gumOtherFailure",
get: function get() {
return this._gumOtherFailure;
}
/**
* RTC Session failed in create Offer state.
*/
,
set: function set(value) {
this._gumOtherFailure = value;
}
}, {
key: "createOfferFailure",
get: function get() {
return this._createOfferFailure;
}
/**
* Tells if setLocalDescription failed for the RTC Session.
*/
,
set: function set(value) {
this._createOfferFailure = value;
}
}, {
key: "setLocalDescriptionFailure",
get: function get() {
return this._setLocalDescriptionFailure;
}
/**
* Tells if handshaking failed due to user busy case,
* happens when multiple softphone calls are initiated at same time.
*/
,
set: function set(value) {
this._setLocalDescriptionFailure = value;
}
}, {
key: "userBusyFailure",
get: function get() {
return this._userBusyFailure;
}
/**
* Tells it remote SDP is invalid.
*/
,
set: function set(value) {
this._userBusyFailure = value;
}
}, {
key: "invalidRemoteSDPFailure",
get: function get() {
return this._invalidRemoteSDPFailure;
}
/**
* Tells if the setRemoteDescription failed for the RTC Session.
*/
,
set: function set(value) {
this._invalidRemoteSDPFailure = value;
}
}, {
key: "setRemoteDescriptionFailure",
get: function get() {
return this._setRemoteDescriptionFailure;
}
/**
* A failure case when there is no RemoteIceCandidate.
*/
,
set: function set(value) {
this._setRemoteDescriptionFailure = value;
}
}, {
key: "noRemoteIceCandidateFailure",
get: function get() {
return this._noRemoteIceCandidateFailure;
}
/**
* Statistics for each stream(audio-in, audio-out, video-in, video-out) of the RTCSession.
*/
,
set: function set(value) {
this._noRemoteIceCandidateFailure = value;
}
}, {
key: "streamStats",
get: function get() {
return this._streamStats;
},
set: function set(value) {
this._streamStats = value;
}
}]);
return SessionReport;
}();
},{"babel-runtime/helpers/classCallCheck":10,"babel-runtime/helpers/createClass":11}],139:[function(require,module,exports){
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FailedState = exports.DisconnectedState = exports.PendingLocalHangupState = exports.PendingRemoteHangupState = exports.PendingReconnectState = exports.TalkingState = exports.PendingAcceptAckState = exports.PendingAcceptState = exports.PendingAnswerState = exports.PendingInviteState = exports.PendingConnectState = exports.FailOnTimeoutState = exports.SignalingState = undefined;
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _utils = require('./utils');
var _rtc_const = require('./rtc_const');
var _exceptions = require('./exceptions');
var _v = require('uuid/v4');
var _v2 = _interopRequireDefault(_v);
var _virtual_wss_connection_manager = require('./virtual_wss_connection_manager');
var _virtual_wss_connection_manager2 = _interopRequireDefault(_virtual_wss_connection_manager);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var CONNECT_MAX_RETRIES = 3;
/**
* Abstract signaling state class.
*/
/**
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
var SignalingState = exports.SignalingState = function () {
/**
* @param {AmznRtcSignaling} signaling Signaling object.
*/
function SignalingState(signaling) {
(0, _classCallCheck3.default)(this, SignalingState);
this._signaling = signaling;
this._createTime = new Date().getTime();
}
(0, _createClass3.default)(SignalingState, [{
key: 'setStateTimeout',
value: function setStateTimeout(timeoutMs) {
setTimeout((0, _utils.hitch)(this, this._onTimeoutChecked), timeoutMs);
}
}, {
key: 'onEnter',
value: function onEnter() {}
}, {
key: '_onTimeoutChecked',
value: function _onTimeoutChecked() {
if (this.isCurrentState) {
this.onTimeout();
}
}
}, {
key: 'onTimeout',
value: function onTimeout() {
throw new _exceptions.UnsupportedOperation();
}
}, {
key: 'transit',
value: function transit(newState) {
this._signaling.transit(newState);
}
}, {
key: 'onExit',
value: function onExit() {}
}, {
key: 'onOpen',
value: function onOpen() {
throw new _exceptions.UnsupportedOperation('onOpen not supported by ' + this.name);
}
}, {
key: 'onError',
value: function onError() {
this.channelDown();
}
}, {
key: 'onClose',
value: function onClose() {
this.channelDown();
}
}, {
key: 'channelDown',
value: function channelDown() {
throw new _exceptions.UnsupportedOperation('channelDown not supported by ' + this.name);
}
}, {
key: 'onRpcMsg',
value: function onRpcMsg(rpcMsg) {
// eslint-disable-line no-unused-vars
throw new _exceptions.UnsupportedOperation('onRpcMsg not supported by ' + this.name);
}
}, {
key: 'invite',
value: function invite(sdp, iceCandidates) {
// eslint-disable-line no-unused-vars
throw new _exceptions.UnsupportedOperation('invite not supported by ' + this.name);
}
}, {
key: 'accept',
value: function accept() {
throw new _exceptions.UnsupportedOperation('accept not supported by ' + this.name);
}
}, {
key: 'hangup',
value: function hangup() {
throw new _exceptions.UnsupportedOperation('hangup not supported by ' + this.name);
}
}, {
key: 'isCurrentState',
get: function get() {
return this === this._signaling.state;
}
}, {
key: 'name',
get: function get() {
return "SignalingState";
}
}, {
key: 'logger',
get: function get() {
return this._signaling._logger;
}
}]);
return SignalingState;
}();
var FailOnTimeoutState = exports.FailOnTimeoutState = function (_SignalingState) {
(0, _inherits3.default)(FailOnTimeoutState, _SignalingState);
function FailOnTimeoutState(signaling, timeoutMs) {
(0, _classCallCheck3.default)(this, FailOnTimeoutState);
var _this = (0, _possibleConstructorReturn3.default)(this, (FailOnTimeoutState.__proto__ || Object.getPrototypeOf(FailOnTimeoutState)).call(this, signaling));
_this._timeoutMs = timeoutMs;
return _this;
}
(0, _createClass3.default)(FailOnTimeoutState, [{
key: 'onEnter',
value: function onEnter() {
this.setStateTimeout(this._timeoutMs);
}
}, {
key: 'onTimeout',
value: function onTimeout() {
this.transit(new FailedState(this._signaling, new _exceptions.Timeout()));
}
}, {
key: 'name',
get: function get() {
return "FailOnTimeoutState";
}
}]);
return FailOnTimeoutState;
}(SignalingState);
var PendingConnectState = exports.PendingConnectState = function (_FailOnTimeoutState) {
(0, _inherits3.default)(PendingConnectState, _FailOnTimeoutState);
function PendingConnectState(signaling, timeoutMs, initialStartTimeIn, retriesIn) {
(0, _classCallCheck3.default)(this, PendingConnectState);
var _this2 = (0, _possibleConstructorReturn3.default)(this, (PendingConnectState.__proto__ || Object.getPrototypeOf(PendingConnectState)).call(this, signaling, timeoutMs));
_this2._initialStartTime = initialStartTimeIn || new Date().getTime();
_this2._retries = retriesIn || 0;
return _this2;
}
(0, _createClass3.default)(PendingConnectState, [{
key: 'onOpen',
value: function onOpen() {
this.transit(new PendingInviteState(this._signaling));
}
}, {
key: 'channelDown',
value: function channelDown() {
var now = new Date().getTime();
var untilTimeoutMs = this._initialStartTime + this._timeoutMs - now;
if (untilTimeoutMs > 0 && ++this._retries < CONNECT_MAX_RETRIES) {
this._signaling._connect();
this.transit(new PendingConnectState(this._signaling, untilTimeoutMs, this._initialStartTime, this._retries));
} else {
this.transit(new FailedState(this._signaling, new Error('channelDown')));
}
}
}, {
key: 'name',
get: function get() {
return "PendingConnectState";
}
}]);
return PendingConnectState;
}(FailOnTimeoutState);
var PendingInviteState = exports.PendingInviteState = function (_SignalingState2) {
(0, _inherits3.default)(PendingInviteState, _SignalingState2);
function PendingInviteState() {
(0, _classCallCheck3.default)(this, PendingInviteState);
return (0, _possibleConstructorReturn3.default)(this, (PendingInviteState.__proto__ || Object.getPrototypeOf(PendingInviteState)).apply(this, arguments));
}
(0, _createClass3.default)(PendingInviteState, [{
key: 'onEnter',
value: function onEnter() {
var self = this;
new Promise(function notifyConnected(resolve) {
self._signaling._connectedHandler();
resolve();
});
}
}, {
key: 'invite',
value: function invite(sdp, iceCandidates) {
var self = this;
var inviteId = (0, _v2.default)();
var inviteParams = {
sdp: sdp,
candidates: iceCandidates,
callContextToken: self._signaling._contactToken
};
self.logger.log('Sending SDP', sdp);
self._signaling._wss.send(JSON.stringify({
jsonrpc: '2.0',
method: _rtc_const.INVITE_METHOD_NAME,
params: inviteParams,
id: inviteId
}));
self.transit(new PendingAnswerState(self._signaling, inviteId));
}
}, {
key: 'channelDown',
value: function channelDown() {
this.transit(new FailedState(this._signaling));
}
}, {
key: 'name',
get: function get() {
return "PendingInviteState";
}
}]);
return PendingInviteState;
}(SignalingState);
var PendingAnswerState = exports.PendingAnswerState = function (_FailOnTimeoutState2) {
(0, _inherits3.default)(PendingAnswerState, _FailOnTimeoutState2);
function PendingAnswerState(signaling, inviteId) {
(0, _classCallCheck3.default)(this, PendingAnswerState);
var _this4 = (0, _possibleConstructorReturn3.default)(this, (PendingAnswerState.__proto__ || Object.getPrototypeOf(PendingAnswerState)).call(this, signaling, _rtc_const.MAX_INVITE_DELAY_MS));
_this4._inviteId = inviteId;
return _this4;
}
(0, _createClass3.default)(PendingAnswerState, [{
key: 'onRpcMsg',
value: function onRpcMsg(msg) {
var self = this;
if (msg.id === this._inviteId) {
if (msg.error || !msg.result) {
this.transit(new FailedState(this._signaling, self.translateInviteError(msg)));
} else {
new Promise(function notifyAnswered(resolve) {