@observertc/observer-js
Version:
Server Side NodeJS Library for processing ObserveRTC Samples
637 lines (636 loc) • 31.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObservedClient = void 0;
const events_1 = require("events");
const ObservedPeerConnection_1 = require("./ObservedPeerConnection");
const logger_1 = require("./common/logger");
const ClientEventTypes_1 = require("./schema/ClientEventTypes");
const ClientMetaTypes_1 = require("./schema/ClientMetaTypes");
const utils_1 = require("./common/utils");
const Detectors_1 = require("./detectors/Detectors");
const logger = (0, logger_1.createLogger)('ObservedClient');
class ObservedClient extends events_1.EventEmitter {
call;
detectors;
clientId;
observedPeerConnections = new Map();
calculatedScore = {
weight: 1,
value: undefined,
};
appData;
attachments;
updated = Date.now();
acceptedSamples = 0;
closed = false;
joinedAt;
leftAt;
closedAt;
lastSampleTimestamp;
// the timestamp of the CLIENT_JOINED event
operationSystem;
engine;
platform;
browser;
mediaConstraints = [];
usingTURN = false;
usingTCP = false;
availableOutgoingBitrate = 0;
availableIncomingBitrate = 0;
totalInboundPacketsLost = 0;
totalInboundPacketsReceived = 0;
totalOutboundPacketsSent = 0;
totalDataChannelBytesSent = 0;
totalDataChannelBytesReceived = 0;
totalDataChannelMessagesSent = 0;
totalDataChannelMessagesReceived = 0;
totalReceivedAudioBytes = 0;
totalReceivedVideoBytes = 0;
totalSentAudioBytes = 0;
totalSentVideoBytes = 0;
totalSentBytes = 0;
totalReceivedBytes = 0;
deltaReceivedAudioBytes = 0;
deltaReceivedVideoBytes = 0;
deltaSentAudioBytes = 0;
deltaSentVideoBytes = 0;
deltaDataChannelBytesSent = 0;
deltaDataChannelBytesReceived = 0;
deltaDataChannelMessagesSent = 0;
deltaDataChannelMessagesReceived = 0;
deltaInboundPacketsLost = 0;
deltaInboundPacketsReceived = 0;
deltaOutboundPacketsSent = 0;
deltaTransportSentBytes = 0;
deltaTransportReceivedBytes = 0;
deltaRttLt50Measurements = 0;
deltaRttLt150Measurements = 0;
deltaRttLt300Measurements = 0;
deltaRttGtOrEq300Measurements = 0;
currentMaxRttInMs;
currentMinRttInMs;
currentAvgRttInMs;
sendingAudioBitrate = 0;
sendingVideoBitrate = 0;
receivingAudioBitrate = 0;
receivingVideoBitrate = 0;
numberOfInboundRtpStreams = 0;
numberOfInbundTracks = 0;
numberOfOutboundRtpStreams = 0;
numberOfOutboundTracks = 0;
numberOfDataChannels = 0;
totalRttLt50Measurements = 0;
totalRttLt150Measurements = 0;
totalRttLt300Measurements = 0;
totalRttGtOrEq300Measurements = 0;
deltaNumberOfIssues = 0;
totalScoreSum = 0;
numberOfScoreMeasurements = 0;
totalNumberOfIssues = 0;
mediaDevices = [];
issues = [];
_injections = {};
constructor(settings, call) {
super();
this.call = call;
this.setMaxListeners(Infinity);
this.clientId = settings.clientId;
this.appData = settings.appData ?? {};
this.detectors = new Detectors_1.Detectors();
}
get numberOfPeerConnections() {
return this.observedPeerConnections.size;
}
get score() {
return this.calculatedScore.value;
}
close() {
if (this.closed)
return;
this.closed = true;
this._injections.clientEvents?.forEach((clientEvent) => this._processClientEvent(clientEvent));
this._injections.clientIssues?.forEach((clientIssue) => this.addIssue(clientIssue));
this._injections.extensionStats?.forEach((extensionStat) => this.addExtensionStats(extensionStat));
this._injections.clientMetaItems?.forEach((clientMetaItem) => this.addMetadata(clientMetaItem));
Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
if (!this.leftAt) {
this.leftAt = this.lastSampleTimestamp;
if (this.leftAt) {
this.emit('left');
}
}
this.closedAt = Date.now();
this.emit('close');
}
accept(sample) {
if (this.closed)
throw new Error(`Client ${this.clientId} is closed`);
const now = Date.now();
const elapsedInMs = now - this.updated;
const elapsedInSeconds = elapsedInMs / 1000;
let sumOfRtts = 0;
let numberOfRttMeasurements = 0;
++this.acceptedSamples;
this.availableIncomingBitrate = 0;
this.availableOutgoingBitrate = 0;
this.deltaDataChannelBytesReceived = 0;
this.deltaDataChannelBytesSent = 0;
this.deltaDataChannelMessagesReceived = 0;
this.deltaDataChannelMessagesSent = 0;
this.deltaInboundPacketsLost = 0;
this.deltaInboundPacketsReceived = 0;
this.deltaOutboundPacketsSent = 0;
this.deltaReceivedAudioBytes = 0;
this.deltaReceivedVideoBytes = 0;
this.deltaSentAudioBytes = 0;
this.deltaSentVideoBytes = 0;
this.deltaTransportReceivedBytes = 0;
this.deltaTransportSentBytes = 0;
this.deltaRttLt50Measurements = 0;
this.deltaRttLt150Measurements = 0;
this.deltaRttLt300Measurements = 0;
this.deltaRttGtOrEq300Measurements = 0;
this.deltaNumberOfIssues = 0;
this.numberOfDataChannels = 0;
this.numberOfInboundRtpStreams = 0;
this.numberOfInbundTracks = 0;
this.numberOfOutboundRtpStreams = 0;
this.numberOfOutboundTracks = 0;
this.usingTURN = false;
this.usingTCP = false;
this.currentMinRttInMs = undefined;
this.currentMaxRttInMs = undefined;
this._mergeInjections(sample);
const clientEventsPostBuffer = [];
for (const clientEvent of sample.clientEvents ?? []) {
this._processClientEvent(clientEvent, clientEventsPostBuffer);
this.call.observer.emit('client-event', this, clientEvent);
}
for (const metaData of sample.clientMetaItems ?? []) {
this.addMetadata(metaData);
}
for (const issue of sample.clientIssues ?? []) {
this.addIssue(issue);
++this.deltaNumberOfIssues;
}
for (const extensionStat of sample.extensionStats ?? []) {
this.addExtensionStats(extensionStat);
}
for (const pcSample of sample.peerConnections ?? []) {
const observedPeerConnection = this._updatePeerConnection(pcSample);
if (!observedPeerConnection)
continue;
this.deltaDataChannelBytesReceived += observedPeerConnection.deltaDataChannelBytesReceived;
this.deltaDataChannelBytesSent += observedPeerConnection.deltaDataChannelBytesSent;
this.deltaDataChannelMessagesReceived += observedPeerConnection.deltaDataChannelMessagesReceived;
this.deltaDataChannelMessagesSent += observedPeerConnection.deltaDataChannelMessagesSent;
this.deltaInboundPacketsLost += observedPeerConnection.deltaInboundPacketsLost;
this.deltaInboundPacketsReceived += observedPeerConnection.deltaInboundPacketsReceived;
this.deltaOutboundPacketsSent += observedPeerConnection.deltaOutboundPacketsSent;
this.deltaReceivedAudioBytes += observedPeerConnection.deltaReceivedAudioBytes;
this.deltaReceivedVideoBytes += observedPeerConnection.deltaReceivedVideoBytes;
this.deltaSentAudioBytes += observedPeerConnection.deltaSentAudioBytes;
this.deltaSentVideoBytes += observedPeerConnection.deltaSentVideoBytes;
this.deltaTransportReceivedBytes += observedPeerConnection.deltaTransportReceivedBytes;
this.deltaTransportSentBytes += observedPeerConnection.deltaTransportSentBytes;
this.availableIncomingBitrate += observedPeerConnection.availableIncomingBitrate;
this.availableOutgoingBitrate += observedPeerConnection.availableOutgoingBitrate;
this.numberOfDataChannels += observedPeerConnection.observedDataChannels.size;
this.numberOfInbundTracks += observedPeerConnection.observedInboundTracks.size;
this.numberOfOutboundRtpStreams += observedPeerConnection.observedOutboundRtps.size;
this.numberOfOutboundTracks += observedPeerConnection.observedOutboundTracks.size;
this.numberOfInboundRtpStreams += observedPeerConnection.observedInboundRtps.size;
if (observedPeerConnection.usingTURN) {
this.usingTURN = true;
}
if (observedPeerConnection.usingTCP) {
this.usingTCP = true;
}
if (observedPeerConnection.currentRttInMs) {
if (this.currentMinRttInMs === undefined || observedPeerConnection.currentRttInMs < this.currentMinRttInMs) {
this.currentMinRttInMs = observedPeerConnection.currentRttInMs;
}
if (this.currentMaxRttInMs === undefined || observedPeerConnection.currentRttInMs > this.currentMaxRttInMs) {
this.currentMaxRttInMs = observedPeerConnection.currentRttInMs;
}
if (observedPeerConnection.currentRttInMs < 50) {
this.deltaRttLt50Measurements += 1;
}
else if (observedPeerConnection.currentRttInMs < 150) {
this.deltaRttLt150Measurements += 1;
}
else if (observedPeerConnection.currentRttInMs < 300) {
this.deltaRttLt300Measurements += 1;
}
else if (300 <= observedPeerConnection.currentRttInMs) {
this.deltaRttGtOrEq300Measurements += 1;
}
sumOfRtts += observedPeerConnection.currentRttInMs;
++numberOfRttMeasurements;
}
}
for (const clientEvent of clientEventsPostBuffer) {
this._processClientEvent(clientEvent);
}
// emit new attachments?
this.attachments = sample.attachments;
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
this.totalInboundPacketsLost += this.deltaInboundPacketsLost;
this.totalInboundPacketsReceived += this.deltaInboundPacketsReceived;
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
this.totalSentAudioBytes += this.deltaSentAudioBytes;
this.totalSentVideoBytes += this.deltaSentVideoBytes;
this.totalReceivedBytes += this.deltaTransportReceivedBytes;
this.totalSentBytes += this.deltaTransportSentBytes;
this.totalRttLt50Measurements += this.deltaRttLt50Measurements;
this.totalRttLt150Measurements += this.deltaRttLt150Measurements;
this.totalRttLt300Measurements += this.deltaRttLt300Measurements;
this.totalRttGtOrEq300Measurements += this.deltaRttGtOrEq300Measurements;
this.totalNumberOfIssues += this.deltaNumberOfIssues;
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / (elapsedInSeconds);
this.receivingVideoBitrate = (this.totalReceivedVideoBytes * 8) / (elapsedInSeconds);
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / (elapsedInSeconds);
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / (elapsedInSeconds);
this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : undefined;
this.calculatedScore.value = sample.score;
this.detectors.update();
this.lastSampleTimestamp = sample.timestamp;
// emit update
this.emit('update', sample, now - this.updated);
this.updated = now;
// if result changed after update
if (this.calculatedScore.value) {
this.totalScoreSum += this.calculatedScore.value;
++this.numberOfScoreMeasurements;
}
}
_processClientEvent(event, postBuffer) {
// eslint-disable-next-line no-console
// console.warn('ClientEvent', event);
switch (event.type) {
case ClientEventTypes_1.ClientEventTypes.CLIENT_JOINED: {
if (event.timestamp) {
if (!this.joinedAt) {
this.joinedAt = event.timestamp;
this.emit('joined');
}
else if (this.joinedAt < event.timestamp) {
this.emit('rejoined', event.timestamp);
}
else {
this.joinedAt = event.timestamp;
logger.warn(`Client ${this.clientId} joinedAt timestamp was updated to ${event.timestamp}. the joined event will not be emitted.`);
}
}
logger.debug('Client %s joined at %o', this.clientId, event);
break;
}
case ClientEventTypes_1.ClientEventTypes.CLIENT_LEFT: {
if (event.timestamp) {
if (!this.leftAt) {
this.leftAt = event.timestamp;
this.emit('left');
}
else {
logger.warn(`Client ${this.clientId} leftAt timestamp was already set`);
}
}
logger.debug('Client %s left at %o', this.clientId, event);
break;
}
case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_OPENED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
if (observedPeerConnection) {
observedPeerConnection.openedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received PEER_CONNECTION_OPENED event without a corresponding observedPeerConnection: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_CLOSED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
if (observedPeerConnection) {
observedPeerConnection.closedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received PEER_CONNECTION_CLOSED event without a corresponding observedPeerConnection: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_ADDED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
if (observedTrack) {
observedTrack.addedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received MEDIA_TRACK_ADDED event without a corresponding observedPeerConnection or observedTrack: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_REMOVED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
if (observedTrack) {
observedTrack.removedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received MEDIA_TRACK_REMOVED event without a corresponding observedPeerConnection or observedTrack: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_OPEN: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
if (observedDataChannel) {
observedDataChannel.addedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received DATA_CHANNEL_OPENED event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.DATA_CHANNEL_CLOSED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.dataChannelId && typeof payload.dataChannelId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
if (observedDataChannel) {
observedDataChannel.removedAt = event.timestamp;
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received DATA_CHANNEL_CLOSE event without a corresponding observedPeerConnection or observedDataChannel: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_MUTED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
if (observedPeerConnection) {
if (observedInboundTrack) {
observedInboundTrack.muted = true;
observedPeerConnection?.emit('muted-inbound-track', observedInboundTrack);
}
else if (observedOutboundTrack) {
observedOutboundTrack.muted = true;
observedPeerConnection?.emit('muted-outbound-track', observedOutboundTrack);
}
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received MEDIA_TRACK_MUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.MEDIA_TRACK_UNMUTED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.trackId && typeof payload.trackId === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
if (observedPeerConnection) {
if (observedInboundTrack) {
observedInboundTrack.muted = false;
observedPeerConnection?.emit('unmuted-inbound-track', observedInboundTrack);
}
else if (observedOutboundTrack) {
observedOutboundTrack.muted = false;
observedPeerConnection?.emit('unmuted-outbound-track', observedOutboundTrack);
}
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received MEDIA_TRACK_UNMUTED event without a corresponding observedPeerConnection or observedTrack: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.ICE_CONNECTION_STATE_CHANGED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceConnectionState && typeof payload.iceConnectionState === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
if (observedPeerConnection) {
observedPeerConnection.iceConnectionState = payload.iceConnectionState;
observedPeerConnection.emit('iceconnectionstatechange', {
state: payload.iceConnectionState,
});
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received ICE_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.ICE_GATHERING_STATE_CHANGED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.iceGatheringState && typeof payload.iceGatheringState === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
if (observedPeerConnection) {
observedPeerConnection.iceGatheringState = payload.iceGatheringState;
observedPeerConnection.emit('icegatheringstatechange', {
state: payload.iceGatheringState,
});
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received ICE_GATHERING_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
}
}
break;
}
case ClientEventTypes_1.ClientEventTypes.PEER_CONNECTION_STATE_CHANGED: {
const payload = (0, utils_1.parseJsonAs)(event.payload);
if (payload?.peerConnectionId && typeof payload.peerConnectionId === 'string' && payload?.peerConnectionState && typeof payload.peerConnectionState === 'string') {
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
if (observedPeerConnection) {
observedPeerConnection.connectionState = payload.peerConnectionState;
observedPeerConnection.emit('connectionstatechange', {
state: payload.peerConnectionState,
});
}
else if (postBuffer) {
postBuffer.push(event);
}
else {
logger.warn('Received PEER_CONNECTION_STATE_CHANGED event without a corresponding observedPeerConnection: %o', event);
}
}
break;
}
}
this.emit('clientEvent', event);
}
injectMetaData(metaData) {
if (this.closed)
return;
if (!this._injections.clientMetaItems)
this._injections.clientMetaItems = [];
this._injections.clientMetaItems.push(metaData);
}
injectEvent(event) {
if (this.closed)
return;
if (!this._injections.clientEvents)
this._injections.clientEvents = [];
this._injections.clientEvents.push(event);
}
injectIssue(issue) {
if (this.closed)
return;
if (!this._injections.clientIssues)
this._injections.clientIssues = [];
this._injections.clientIssues.push(issue);
}
injectExtensionStat(stat) {
if (this.closed)
return;
if (!this._injections.extensionStats)
this._injections.extensionStats = [];
this._injections.extensionStats.push(stat);
}
injectAttachment(key, value) {
if (this.closed)
return;
if (!this._injections.attachments)
this._injections.attachments = {};
this._injections.attachments[key] = value;
}
addMetadata(metadata) {
if (this.closed)
return;
switch (metadata.type) {
case ClientMetaTypes_1.ClientMetaTypes.BROWSER: {
this.browser = (0, utils_1.parseJsonAs)(metadata.payload);
break;
}
case ClientMetaTypes_1.ClientMetaTypes.ENGINE: {
this.engine = (0, utils_1.parseJsonAs)(metadata.payload);
break;
}
case ClientMetaTypes_1.ClientMetaTypes.PLATFORM: {
this.platform = (0, utils_1.parseJsonAs)(metadata.payload);
break;
}
case ClientMetaTypes_1.ClientMetaTypes.OPERATION_SYSTEM: {
this.operationSystem = (0, utils_1.parseJsonAs)(metadata.payload);
break;
}
}
this.call.observer.emit('client-metadata', this, metadata);
}
addIssue(issue) {
if (this.closed)
return;
this.emit('issue', issue);
this.call.observer.emit('client-issue', this, issue);
}
addExtensionStats(stats) {
this.call.observer.emit('client-extension-stats', this, stats);
this.emit('extensionStats', stats);
}
_updatePeerConnection(sample) {
let observedPeerConnection = this.observedPeerConnections.get(sample.peerConnectionId);
if (!observedPeerConnection) {
if (!sample.peerConnectionId) {
return (logger.warn(`ObservedClient received an invalid PeerConnectionSample (missing peerConnectionId field). ClientId: ${this.clientId}, CallId: ${this.call.callId}`, sample), void 0);
}
observedPeerConnection = new ObservedPeerConnection_1.ObservedPeerConnection(sample.peerConnectionId, this);
observedPeerConnection.once('close', () => {
this.observedPeerConnections.delete(sample.peerConnectionId);
});
this.observedPeerConnections.set(sample.peerConnectionId, observedPeerConnection);
this.emit('newpeerconnection', observedPeerConnection);
}
observedPeerConnection.accept(sample);
return observedPeerConnection;
}
_mergeInjections(sample) {
if (this.closed)
return sample;
if (this._injections.clientEvents) {
if (!sample.clientEvents)
sample.clientEvents = [];
sample.clientEvents.push(...this._injections.clientEvents);
this._injections.clientEvents = undefined;
}
if (this._injections.clientIssues) {
if (!sample.clientIssues)
sample.clientIssues = [];
sample.clientIssues.push(...this._injections.clientIssues);
this._injections.clientIssues = undefined;
}
if (this._injections.extensionStats) {
if (!sample.extensionStats)
sample.extensionStats = [];
sample.extensionStats.push(...this._injections.extensionStats);
this._injections.extensionStats = undefined;
}
if (this._injections.attachments) {
if (!sample.attachments)
sample.attachments = {};
Object.assign(sample.attachments, this._injections.attachments);
this._injections.attachments = undefined;
}
if (this._injections.clientMetaItems) {
if (!sample.clientMetaItems)
sample.clientMetaItems = [];
sample.clientMetaItems.push(...this._injections.clientMetaItems);
this._injections.clientMetaItems = undefined;
}
return sample;
}
}
exports.ObservedClient = ObservedClient;