@wazo/sdk 0.37.15 → 0.37.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/wazo-sdk.js +3 -3
  2. package/esm/__tests__/api-client.test.js +9 -5
  3. package/esm/__tests__/web-rtc-client.test.js +117 -23
  4. package/esm/api/agentd.js +1 -1
  5. package/esm/api/amid.js +1 -1
  6. package/esm/api/application.js +1 -1
  7. package/esm/api/auth.js +1 -1
  8. package/esm/api/call-logd.js +3 -3
  9. package/esm/api/calld.js +1 -1
  10. package/esm/api/chatd.js +1 -1
  11. package/esm/api/confd.js +7 -3
  12. package/esm/api/ctid-ng.js +1 -1
  13. package/esm/api/dird.js +1 -1
  14. package/esm/api/webhookd.js +1 -1
  15. package/esm/api-client.js +9 -5
  16. package/esm/checker/Checker.js +117 -23
  17. package/esm/checker/checks/aor.js +9 -5
  18. package/esm/checker/checks/api.js +9 -5
  19. package/esm/checker/checks/index.js +117 -23
  20. package/esm/checker/checks/wazo-websocket.js +1 -1
  21. package/esm/checker/checks/webrtc-transport.js +117 -23
  22. package/esm/checker/checks/webrtc.js +117 -23
  23. package/esm/domain/AdHocAPIConference.js +9 -5
  24. package/esm/domain/CallLog.js +2 -2
  25. package/esm/domain/Features.js +9 -5
  26. package/esm/domain/Meeting.js +6 -2
  27. package/esm/domain/Phone/CTIPhone.js +9 -5
  28. package/esm/domain/Phone/WebRTCPhone.js +9 -2
  29. package/esm/domain/Recording.js +1 -1
  30. package/esm/domain/__tests__/CallLog.test.js +2 -2
  31. package/esm/index.js +125 -23
  32. package/esm/lib/WazoSessionDescriptionHandler.js +1 -1
  33. package/esm/service/CallApi.js +9 -5
  34. package/esm/service/IssueReporter.js +1 -1
  35. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  36. package/esm/service/getApiClient.js +9 -5
  37. package/esm/simple/Auth.js +125 -23
  38. package/esm/simple/Configuration.js +125 -23
  39. package/esm/simple/Directory.js +9 -5
  40. package/esm/simple/Phone.js +125 -23
  41. package/esm/simple/Websocket.js +1 -1
  42. package/esm/simple/index.js +125 -23
  43. package/esm/simple/room/LocalParticipant.js +125 -23
  44. package/esm/simple/room/Participant.js +125 -23
  45. package/esm/simple/room/RemoteParticipant.js +125 -23
  46. package/esm/simple/room/Room.js +125 -23
  47. package/esm/simple/room/SipRoom.js +125 -23
  48. package/esm/simple/room/Stream.js +125 -23
  49. package/esm/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  50. package/esm/simple/utils.js +125 -23
  51. package/esm/utils/__tests__/api-requester.test.js +1 -1
  52. package/esm/utils/api-requester.js +1 -1
  53. package/esm/web-rtc-client.js +117 -23
  54. package/esm/websocket-client.js +1 -1
  55. package/lib/__tests__/api-client.test.js +9 -5
  56. package/lib/__tests__/web-rtc-client.test.js +117 -23
  57. package/lib/api/agentd.js +1 -1
  58. package/lib/api/amid.js +1 -1
  59. package/lib/api/application.js +1 -1
  60. package/lib/api/auth.js +1 -1
  61. package/lib/api/call-logd.js +3 -3
  62. package/lib/api/calld.js +1 -1
  63. package/lib/api/chatd.js +1 -1
  64. package/lib/api/confd.js +7 -3
  65. package/lib/api/ctid-ng.js +1 -1
  66. package/lib/api/dird.js +1 -1
  67. package/lib/api/webhookd.js +1 -1
  68. package/lib/api-client.js +9 -5
  69. package/lib/checker/Checker.js +117 -23
  70. package/lib/checker/checks/aor.js +9 -5
  71. package/lib/checker/checks/api.js +9 -5
  72. package/lib/checker/checks/index.js +117 -23
  73. package/lib/checker/checks/wazo-websocket.js +1 -1
  74. package/lib/checker/checks/webrtc-transport.js +117 -23
  75. package/lib/checker/checks/webrtc.js +117 -23
  76. package/lib/domain/AdHocAPIConference.js +9 -5
  77. package/lib/domain/CallLog.js +2 -2
  78. package/lib/domain/Features.js +9 -5
  79. package/lib/domain/Meeting.js +6 -2
  80. package/lib/domain/Phone/CTIPhone.js +9 -5
  81. package/lib/domain/Phone/WebRTCPhone.js +9 -1
  82. package/lib/domain/Recording.js +1 -1
  83. package/lib/domain/__tests__/CallLog.test.js +2 -2
  84. package/lib/index.js +125 -23
  85. package/lib/lib/WazoSessionDescriptionHandler.js +1 -1
  86. package/lib/service/CallApi.js +9 -5
  87. package/lib/service/IssueReporter.js +1 -1
  88. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  89. package/lib/service/getApiClient.js +9 -5
  90. package/lib/simple/Auth.js +125 -23
  91. package/lib/simple/Configuration.js +125 -23
  92. package/lib/simple/Directory.js +9 -5
  93. package/lib/simple/Phone.js +125 -23
  94. package/lib/simple/Websocket.js +1 -1
  95. package/lib/simple/index.js +125 -23
  96. package/lib/simple/room/LocalParticipant.js +125 -23
  97. package/lib/simple/room/Participant.js +125 -23
  98. package/lib/simple/room/RemoteParticipant.js +125 -23
  99. package/lib/simple/room/Room.js +125 -23
  100. package/lib/simple/room/SipRoom.js +125 -23
  101. package/lib/simple/room/Stream.js +125 -23
  102. package/lib/simple/room/__tests__/RemoteParticipant.test.js +125 -23
  103. package/lib/simple/utils.js +125 -23
  104. package/lib/utils/__tests__/api-requester.test.js +1 -1
  105. package/lib/utils/api-requester.js +1 -1
  106. package/lib/web-rtc-client.js +117 -23
  107. package/lib/websocket-client.js +1 -1
  108. package/package.json +1 -1
  109. package/src/domain/CallLog.js +1 -1
  110. package/src/domain/Meeting.js +6 -2
  111. package/src/domain/Phone/WebRTCPhone.js +7 -0
  112. package/src/domain/Recording.js +1 -1
  113. package/src/service/IssueReporter.js +1 -1
  114. package/src/web-rtc-client.js +108 -18
@@ -382,7 +382,7 @@ class IssueReporter {
382
382
  payload._retry = retry + 1;
383
383
  }
384
384
 
385
- this._sendDebugToGrafana(body, retry + 1);
385
+ this._sendDebugToGrafana(payload, retry + 1);
386
386
  }, 5000 + retry * 1000);
387
387
  });
388
388
  }
@@ -2585,7 +2585,8 @@ class ExternalApp {
2585
2585
 
2586
2586
 
2587
2587
 
2588
-
2588
+
2589
+
2589
2590
 
2590
2591
 
2591
2592
  class Meeting {
@@ -2597,6 +2598,7 @@ class Meeting {
2597
2598
 
2598
2599
 
2599
2600
 
2601
+
2600
2602
 
2601
2603
 
2602
2604
  static parse(plain ) {
@@ -2608,6 +2610,7 @@ class Meeting {
2608
2610
  port: plain.port,
2609
2611
  uuid: plain.uuid,
2610
2612
  number: plain.number,
2613
+ persistent: plain.persistent,
2611
2614
  });
2612
2615
  }
2613
2616
 
@@ -2615,7 +2618,7 @@ class Meeting {
2615
2618
  return newFrom(meeting, Meeting);
2616
2619
  }
2617
2620
 
2618
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2621
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2619
2622
  this.guestSipAuthorization = guestSipAuthorization;
2620
2623
  this.uri = uri;
2621
2624
  this.name = name;
@@ -2623,6 +2626,7 @@ class Meeting {
2623
2626
  this.port = port;
2624
2627
  this.uuid = uuid;
2625
2628
  this.number = number;
2629
+ this.persistent = persistent;
2626
2630
 
2627
2631
  // Useful to compare instead of instanceof with minified code
2628
2632
  this.type = 'Meeting';
@@ -3186,7 +3190,7 @@ class Recording {
3186
3190
 
3187
3191
 
3188
3192
 
3189
- static parseMany(recordings ) {
3193
+ static parseMany(recordings = []) {
3190
3194
  return recordings.map(item => Recording.parse(item));
3191
3195
  }
3192
3196
 
@@ -3312,7 +3316,7 @@ class CallLog {
3312
3316
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3313
3317
  start: moment(plain.start).toDate(),
3314
3318
  end: plain.end ? moment(plain.end).toDate() : null,
3315
- recordings: Recording.parseMany(plain.recordings),
3319
+ recordings: Recording.parseMany(plain.recordings || []),
3316
3320
  });
3317
3321
  }
3318
3322
 
@@ -1886,7 +1886,7 @@ class IssueReporter {
1886
1886
  payload._retry = retry + 1;
1887
1887
  }
1888
1888
 
1889
- this._sendDebugToGrafana(body, retry + 1);
1889
+ this._sendDebugToGrafana(payload, retry + 1);
1890
1890
  }, 5000 + retry * 1000);
1891
1891
  });
1892
1892
  }
@@ -2604,7 +2604,8 @@ class ExternalApp {
2604
2604
 
2605
2605
 
2606
2606
 
2607
-
2607
+
2608
+
2608
2609
 
2609
2610
 
2610
2611
  class Meeting {
@@ -2616,6 +2617,7 @@ class Meeting {
2616
2617
 
2617
2618
 
2618
2619
 
2620
+
2619
2621
 
2620
2622
 
2621
2623
  static parse(plain ) {
@@ -2627,6 +2629,7 @@ class Meeting {
2627
2629
  port: plain.port,
2628
2630
  uuid: plain.uuid,
2629
2631
  number: plain.number,
2632
+ persistent: plain.persistent,
2630
2633
  });
2631
2634
  }
2632
2635
 
@@ -2634,7 +2637,7 @@ class Meeting {
2634
2637
  return newFrom(meeting, Meeting);
2635
2638
  }
2636
2639
 
2637
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2640
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2638
2641
  this.guestSipAuthorization = guestSipAuthorization;
2639
2642
  this.uri = uri;
2640
2643
  this.name = name;
@@ -2642,6 +2645,7 @@ class Meeting {
2642
2645
  this.port = port;
2643
2646
  this.uuid = uuid;
2644
2647
  this.number = number;
2648
+ this.persistent = persistent;
2645
2649
 
2646
2650
  // Useful to compare instead of instanceof with minified code
2647
2651
  this.type = 'Meeting';
@@ -3576,7 +3580,7 @@ class Recording {
3576
3580
 
3577
3581
 
3578
3582
 
3579
- static parseMany(recordings ) {
3583
+ static parseMany(recordings = []) {
3580
3584
  return recordings.map(item => Recording.parse(item));
3581
3585
  }
3582
3586
 
@@ -3702,7 +3706,7 @@ class CallLog {
3702
3706
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3703
3707
  start: moment(plain.start).toDate(),
3704
3708
  end: plain.end ? moment(plain.end).toDate() : null,
3705
- recordings: Recording.parseMany(plain.recordings),
3709
+ recordings: Recording.parseMany(plain.recordings || []),
3706
3710
  });
3707
3711
  }
3708
3712
 
@@ -6283,6 +6287,7 @@ const ON_REINVITE$1 = 'reinvite';
6283
6287
  const ON_ERROR = 'onError';
6284
6288
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6285
6289
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6290
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6286
6291
 
6287
6292
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6288
6293
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6359,6 +6364,7 @@ class WebRTCClient extends Emitter {
6359
6364
 
6360
6365
 
6361
6366
 
6367
+
6362
6368
 
6363
6369
  static isAPrivateIp(ip ) {
6364
6370
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6424,6 +6430,7 @@ class WebRTCClient extends Emitter {
6424
6430
  this.ON_ERROR = ON_ERROR;
6425
6431
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6426
6432
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6433
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6427
6434
  }
6428
6435
 
6429
6436
  configureMedia(media ) {
@@ -7025,7 +7032,7 @@ class WebRTCClient extends Emitter {
7025
7032
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7026
7033
  const transceivers = pc.getTransceivers();
7027
7034
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7028
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7035
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7029
7036
 
7030
7037
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7031
7038
  } else {
@@ -7271,10 +7278,13 @@ class WebRTCClient extends Emitter {
7271
7278
  return null;
7272
7279
  }
7273
7280
 
7274
- // let's update the local value
7275
- if (this.audio && this.audio.deviceId) {
7276
- // $FlowFixMe
7277
- this.audio.deviceId.exact = id;
7281
+ // let's update the local audio value
7282
+ if (this.audio) {
7283
+ this.audio = {
7284
+ deviceId: {
7285
+ exact: id,
7286
+ },
7287
+ };
7278
7288
  }
7279
7289
 
7280
7290
  if (session) {
@@ -7287,6 +7297,9 @@ class WebRTCClient extends Emitter {
7287
7297
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7288
7298
 
7289
7299
  if (sender) {
7300
+ if (sender.track) {
7301
+ audioTrack.enabled = sender.track.enabled;
7302
+ }
7290
7303
  sender.replaceTrack(audioTrack);
7291
7304
  }
7292
7305
 
@@ -7311,7 +7324,7 @@ class WebRTCClient extends Emitter {
7311
7324
  return null;
7312
7325
  }
7313
7326
 
7314
- // let's update the local value
7327
+ // let's update the local video value
7315
7328
  if (this.video) {
7316
7329
  this.video = {
7317
7330
  deviceId: {
@@ -7346,12 +7359,21 @@ class WebRTCClient extends Emitter {
7346
7359
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7347
7360
  const videoTrack = stream.getVideoTracks()[0];
7348
7361
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7362
+ let wasTrackEnabled = false;
7349
7363
  if (!sender) {
7350
7364
  sender = pc && pc.getSenders().find(s => !s.track);
7351
7365
  }
7352
7366
 
7353
7367
  if (sender) {
7354
- sender.replaceTrack(videoTrack);
7368
+ // No video track means video not enabled
7369
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7370
+ videoTrack.enabled = wasTrackEnabled;
7371
+
7372
+ if (!wasTrackEnabled) {
7373
+ videoTrack.stop();
7374
+ }
7375
+
7376
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7355
7377
  }
7356
7378
 
7357
7379
  // let's update the local stream
@@ -8035,6 +8057,7 @@ class WebRTCClient extends Emitter {
8035
8057
 
8036
8058
  this.updateRemoteStream(this.getSipSessionId(session));
8037
8059
 
8060
+ const pc = session.sessionDescriptionHandler.peerConnection;
8038
8061
  const onTrack = (event ) => {
8039
8062
  const isAudioOnly = this._isAudioOnly(session);
8040
8063
  const { kind, label, readyState, id, muted } = event.track;
@@ -8054,6 +8077,12 @@ class WebRTCClient extends Emitter {
8054
8077
 
8055
8078
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8056
8079
 
8080
+ pc.oniceconnectionstatechange = () => {
8081
+ if (pc.iceConnectionState === 'disconnected') {
8082
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8083
+ }
8084
+ };
8085
+
8057
8086
  if (withEvent) {
8058
8087
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8059
8088
  }
@@ -8249,24 +8278,89 @@ class WebRTCClient extends Emitter {
8249
8278
  const session = this.getSipSession(sessionId);
8250
8279
 
8251
8280
  const stats = session ? await this.getStats(session) : null;
8252
- if (!stats) {
8281
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8253
8282
  return;
8254
8283
  }
8255
8284
 
8256
- stats.forEach(report => {
8257
- if (report.type === 'inbound-rtp') {
8258
- if (report.kind === 'audio') {
8259
- const networkStats = {
8260
- packetsLost: report.packetsLost,
8261
- packetsReceived: report.packetsReceived,
8262
- jitter: report.jitter,
8263
- };
8285
+ const networkStats = {
8286
+ audioBytesSent: 0,
8287
+ videoBytesSent: 0,
8288
+ videoBytesReceived: 0,
8289
+ audioBytesReceived: 0,
8290
+ };
8291
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8292
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8293
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8294
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8295
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8296
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8297
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8298
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8299
+ let audioBytesSent = 0;
8300
+ let audioBytesReceived = 0;
8301
+ let videoBytesSent = 0;
8302
+ let videoBytesReceived = 0;
8303
+ let transportSent = 0;
8304
+ let transportReceived = 0;
8305
+ let packetsLost = 0;
8264
8306
 
8265
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8266
- this.sessionNetworkStats[sessionId].push(networkStats);
8307
+ stats.forEach(report => {
8308
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8309
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8310
+ }
8311
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8312
+ audioBytesSent += report.bytesSent;
8313
+ }
8314
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8315
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8316
+ }
8317
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8318
+ packetsLost += report.packetsLost;
8319
+ networkStats.packetsReceived = report.packetsReceived;
8320
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8321
+ }
8322
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8323
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8324
+ }
8325
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8326
+ if ('framesPerSecond' in report) {
8327
+ networkStats.framesPerSecond = report.framesPerSecond;
8328
+ }
8329
+ if ('framerateMean' in report) {
8330
+ // framerateMean is only available in FF
8331
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8267
8332
  }
8268
8333
  }
8334
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8335
+ packetsLost += report.packetsLost;
8336
+ networkStats.roundTripTime = report.roundTripTime;
8337
+ networkStats.jitter = report.jitter;
8338
+ }
8339
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8340
+ packetsLost += report.packetsLost;
8341
+ }
8342
+ if (report.type === 'transport') {
8343
+ transportSent += report.bytesSent;
8344
+ transportReceived += report.bytesReceived;
8345
+ }
8269
8346
  });
8347
+
8348
+ networkStats.packetsLost = packetsLost;
8349
+ networkStats.audioBytesSent = audioBytesSent;
8350
+ networkStats.audioBytesReceived = audioBytesReceived;
8351
+ networkStats.videoBytesSent = videoBytesSent;
8352
+ networkStats.videoBytesReceived = videoBytesReceived;
8353
+ networkStats.transportSent = transportSent;
8354
+ networkStats.transportReceived = transportReceived;
8355
+
8356
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8357
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8358
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8359
+
8360
+ networkStats.bandwidth = bandwidth;
8361
+
8362
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8363
+ this.sessionNetworkStats[sessionId].push(networkStats);
8270
8364
  }
8271
8365
 
8272
8366
  }
@@ -8312,6 +8406,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8312
8406
  const ON_NETWORK_STATS = 'onNetworkStats';
8313
8407
  const ON_CHAT = 'phone/ON_CHAT';
8314
8408
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8409
+ const ON_DISCONNECTED = 'onDisconnected';
8315
8410
 
8316
8411
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8317
8412
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8351,6 +8446,7 @@ const events = [
8351
8446
  ON_CHAT,
8352
8447
  ON_SIGNAL,
8353
8448
  ON_NETWORK_STATS,
8449
+ ON_DISCONNECTED,
8354
8450
  ];
8355
8451
 
8356
8452
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9703,6 +9799,11 @@ class WebRTCPhone extends Emitter {
9703
9799
  this.eventEmitter.emit(ON_UNREGISTERED);
9704
9800
  });
9705
9801
 
9802
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9803
+ logger$8.info('WebRTC disconnected');
9804
+ this.eventEmitter.emit(ON_DISCONNECTED);
9805
+ });
9806
+
9706
9807
  this.client.on(this.client.REGISTERED, () => {
9707
9808
  logger$8.info('WebRTC registered', {
9708
9809
  shouldSendReinvite: this.shouldSendReinvite,
@@ -9959,6 +10060,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9959
10060
  ON_NETWORK_STATS: ON_NETWORK_STATS,
9960
10061
  ON_CHAT: ON_CHAT,
9961
10062
  ON_SIGNAL: ON_SIGNAL,
10063
+ ON_DISCONNECTED: ON_DISCONNECTED,
9962
10064
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
9963
10065
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
9964
10066
  events: events,
@@ -1886,7 +1886,7 @@ class IssueReporter {
1886
1886
  payload._retry = retry + 1;
1887
1887
  }
1888
1888
 
1889
- this._sendDebugToGrafana(body, retry + 1);
1889
+ this._sendDebugToGrafana(payload, retry + 1);
1890
1890
  }, 5000 + retry * 1000);
1891
1891
  });
1892
1892
  }
@@ -2604,7 +2604,8 @@ class ExternalApp {
2604
2604
 
2605
2605
 
2606
2606
 
2607
-
2607
+
2608
+
2608
2609
 
2609
2610
 
2610
2611
  class Meeting {
@@ -2616,6 +2617,7 @@ class Meeting {
2616
2617
 
2617
2618
 
2618
2619
 
2620
+
2619
2621
 
2620
2622
 
2621
2623
  static parse(plain ) {
@@ -2627,6 +2629,7 @@ class Meeting {
2627
2629
  port: plain.port,
2628
2630
  uuid: plain.uuid,
2629
2631
  number: plain.number,
2632
+ persistent: plain.persistent,
2630
2633
  });
2631
2634
  }
2632
2635
 
@@ -2634,7 +2637,7 @@ class Meeting {
2634
2637
  return newFrom(meeting, Meeting);
2635
2638
  }
2636
2639
 
2637
- constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number } = {}) {
2640
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, uri, number, persistent } = {}) {
2638
2641
  this.guestSipAuthorization = guestSipAuthorization;
2639
2642
  this.uri = uri;
2640
2643
  this.name = name;
@@ -2642,6 +2645,7 @@ class Meeting {
2642
2645
  this.port = port;
2643
2646
  this.uuid = uuid;
2644
2647
  this.number = number;
2648
+ this.persistent = persistent;
2645
2649
 
2646
2650
  // Useful to compare instead of instanceof with minified code
2647
2651
  this.type = 'Meeting';
@@ -3576,7 +3580,7 @@ class Recording {
3576
3580
 
3577
3581
 
3578
3582
 
3579
- static parseMany(recordings ) {
3583
+ static parseMany(recordings = []) {
3580
3584
  return recordings.map(item => Recording.parse(item));
3581
3585
  }
3582
3586
 
@@ -3702,7 +3706,7 @@ class CallLog {
3702
3706
  duration: (plain.duration || 0) * 1000, // duration is in seconds
3703
3707
  start: moment(plain.start).toDate(),
3704
3708
  end: plain.end ? moment(plain.end).toDate() : null,
3705
- recordings: Recording.parseMany(plain.recordings),
3709
+ recordings: Recording.parseMany(plain.recordings || []),
3706
3710
  });
3707
3711
  }
3708
3712
 
@@ -6283,6 +6287,7 @@ const ON_REINVITE$1 = 'reinvite';
6283
6287
  const ON_ERROR = 'onError';
6284
6288
  const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
6285
6289
  const ON_NETWORK_STATS$1 = 'onNetworkStats';
6290
+ const ON_DISCONNECTED$1 = 'onDisconnected';
6286
6291
 
6287
6292
  const events$1 = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
6288
6293
  const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
@@ -6359,6 +6364,7 @@ class WebRTCClient extends Emitter {
6359
6364
 
6360
6365
 
6361
6366
 
6367
+
6362
6368
 
6363
6369
  static isAPrivateIp(ip ) {
6364
6370
  const regex = /^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;
@@ -6424,6 +6430,7 @@ class WebRTCClient extends Emitter {
6424
6430
  this.ON_ERROR = ON_ERROR;
6425
6431
  this.ON_SCREEN_SHARING_REINVITE = ON_SCREEN_SHARING_REINVITE;
6426
6432
  this.ON_NETWORK_STATS = ON_NETWORK_STATS$1;
6433
+ this.ON_DISCONNECTED = ON_DISCONNECTED$1;
6427
6434
  }
6428
6435
 
6429
6436
  configureMedia(media ) {
@@ -7025,7 +7032,7 @@ class WebRTCClient extends Emitter {
7025
7032
  // We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
7026
7033
  const transceivers = pc.getTransceivers();
7027
7034
  const transceiverIdx = lastIndexOf(transceivers, transceiver =>
7028
- transceiver.sender.track === null && transceiver.mid.indexOf('video') === -1);
7035
+ transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
7029
7036
 
7030
7037
  videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
7031
7038
  } else {
@@ -7271,10 +7278,13 @@ class WebRTCClient extends Emitter {
7271
7278
  return null;
7272
7279
  }
7273
7280
 
7274
- // let's update the local value
7275
- if (this.audio && this.audio.deviceId) {
7276
- // $FlowFixMe
7277
- this.audio.deviceId.exact = id;
7281
+ // let's update the local audio value
7282
+ if (this.audio) {
7283
+ this.audio = {
7284
+ deviceId: {
7285
+ exact: id,
7286
+ },
7287
+ };
7278
7288
  }
7279
7289
 
7280
7290
  if (session) {
@@ -7287,6 +7297,9 @@ class WebRTCClient extends Emitter {
7287
7297
  const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
7288
7298
 
7289
7299
  if (sender) {
7300
+ if (sender.track) {
7301
+ audioTrack.enabled = sender.track.enabled;
7302
+ }
7290
7303
  sender.replaceTrack(audioTrack);
7291
7304
  }
7292
7305
 
@@ -7311,7 +7324,7 @@ class WebRTCClient extends Emitter {
7311
7324
  return null;
7312
7325
  }
7313
7326
 
7314
- // let's update the local value
7327
+ // let's update the local video value
7315
7328
  if (this.video) {
7316
7329
  this.video = {
7317
7330
  deviceId: {
@@ -7346,12 +7359,21 @@ class WebRTCClient extends Emitter {
7346
7359
  return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
7347
7360
  const videoTrack = stream.getVideoTracks()[0];
7348
7361
  let sender = pc && pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
7362
+ let wasTrackEnabled = false;
7349
7363
  if (!sender) {
7350
7364
  sender = pc && pc.getSenders().find(s => !s.track);
7351
7365
  }
7352
7366
 
7353
7367
  if (sender) {
7354
- sender.replaceTrack(videoTrack);
7368
+ // No video track means video not enabled
7369
+ wasTrackEnabled = sender.track ? sender.track.enabled : false;
7370
+ videoTrack.enabled = wasTrackEnabled;
7371
+
7372
+ if (!wasTrackEnabled) {
7373
+ videoTrack.stop();
7374
+ }
7375
+
7376
+ sender.replaceTrack(wasTrackEnabled ? videoTrack : null);
7355
7377
  }
7356
7378
 
7357
7379
  // let's update the local stream
@@ -8035,6 +8057,7 @@ class WebRTCClient extends Emitter {
8035
8057
 
8036
8058
  this.updateRemoteStream(this.getSipSessionId(session));
8037
8059
 
8060
+ const pc = session.sessionDescriptionHandler.peerConnection;
8038
8061
  const onTrack = (event ) => {
8039
8062
  const isAudioOnly = this._isAudioOnly(session);
8040
8063
  const { kind, label, readyState, id, muted } = event.track;
@@ -8054,6 +8077,12 @@ class WebRTCClient extends Emitter {
8054
8077
 
8055
8078
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
8056
8079
 
8080
+ pc.oniceconnectionstatechange = () => {
8081
+ if (pc.iceConnectionState === 'disconnected') {
8082
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
8083
+ }
8084
+ };
8085
+
8057
8086
  if (withEvent) {
8058
8087
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
8059
8088
  }
@@ -8249,24 +8278,89 @@ class WebRTCClient extends Emitter {
8249
8278
  const session = this.getSipSession(sessionId);
8250
8279
 
8251
8280
  const stats = session ? await this.getStats(session) : null;
8252
- if (!stats) {
8281
+ if (!stats || !(sessionId in this.sessionNetworkStats)) {
8253
8282
  return;
8254
8283
  }
8255
8284
 
8256
- stats.forEach(report => {
8257
- if (report.type === 'inbound-rtp') {
8258
- if (report.kind === 'audio') {
8259
- const networkStats = {
8260
- packetsLost: report.packetsLost,
8261
- packetsReceived: report.packetsReceived,
8262
- jitter: report.jitter,
8263
- };
8285
+ const networkStats = {
8286
+ audioBytesSent: 0,
8287
+ videoBytesSent: 0,
8288
+ videoBytesReceived: 0,
8289
+ audioBytesReceived: 0,
8290
+ };
8291
+ const nbStats = this.sessionNetworkStats[sessionId].length;
8292
+ const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8293
+ const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8294
+ const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8295
+ const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8296
+ const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8297
+ const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8298
+ const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8299
+ let audioBytesSent = 0;
8300
+ let audioBytesReceived = 0;
8301
+ let videoBytesSent = 0;
8302
+ let videoBytesReceived = 0;
8303
+ let transportSent = 0;
8304
+ let transportReceived = 0;
8305
+ let packetsLost = 0;
8264
8306
 
8265
- this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8266
- this.sessionNetworkStats[sessionId].push(networkStats);
8307
+ stats.forEach(report => {
8308
+ if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8309
+ audioBytesSent += report.bytesSent + report.headerBytesSent;
8310
+ }
8311
+ if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8312
+ audioBytesSent += report.bytesSent;
8313
+ }
8314
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8315
+ videoBytesSent += report.bytesSent + report.headerBytesSent;
8316
+ }
8317
+ if (report.type === 'inbound-rtp' && report.kind === 'audio') {
8318
+ packetsLost += report.packetsLost;
8319
+ networkStats.packetsReceived = report.packetsReceived;
8320
+ audioBytesReceived += report.bytesReceived + report.headerBytesReceived;
8321
+ }
8322
+ if (report.type === 'inbound-rtp' && report.kind === 'video') {
8323
+ videoBytesReceived += report.bytesReceived + report.headerBytesReceived;
8324
+ }
8325
+ if (report.type === 'outbound-rtp' && report.kind === 'video') {
8326
+ if ('framesPerSecond' in report) {
8327
+ networkStats.framesPerSecond = report.framesPerSecond;
8328
+ }
8329
+ if ('framerateMean' in report) {
8330
+ // framerateMean is only available in FF
8331
+ networkStats.framesPerSecond = Math.round(report.framerateMean);
8267
8332
  }
8268
8333
  }
8334
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
8335
+ packetsLost += report.packetsLost;
8336
+ networkStats.roundTripTime = report.roundTripTime;
8337
+ networkStats.jitter = report.jitter;
8338
+ }
8339
+ if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
8340
+ packetsLost += report.packetsLost;
8341
+ }
8342
+ if (report.type === 'transport') {
8343
+ transportSent += report.bytesSent;
8344
+ transportReceived += report.bytesReceived;
8345
+ }
8269
8346
  });
8347
+
8348
+ networkStats.packetsLost = packetsLost;
8349
+ networkStats.audioBytesSent = audioBytesSent;
8350
+ networkStats.audioBytesReceived = audioBytesReceived;
8351
+ networkStats.videoBytesSent = videoBytesSent;
8352
+ networkStats.videoBytesReceived = videoBytesReceived;
8353
+ networkStats.transportSent = transportSent;
8354
+ networkStats.transportReceived = transportReceived;
8355
+
8356
+ const bandwidth = (networkStats.audioBytesSent - lastAudioSent) + (networkStats.videoBytesSent - lastVideoSent)
8357
+ + (networkStats.audioBytesReceived - lastAudioReceived) + (networkStats.videoBytesReceived - lastVideoReceived)
8358
+ + (networkStats.transportReceived - lastTransportReceived) + (networkStats.transportSent - lastTransportSent);
8359
+
8360
+ networkStats.bandwidth = bandwidth;
8361
+
8362
+ this.eventEmitter.emit(ON_NETWORK_STATS$1, session, networkStats, this.sessionNetworkStats[sessionId]);
8363
+ this.sessionNetworkStats[sessionId].push(networkStats);
8270
8364
  }
8271
8365
 
8272
8366
  }
@@ -8312,6 +8406,7 @@ const ON_MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
8312
8406
  const ON_NETWORK_STATS = 'onNetworkStats';
8313
8407
  const ON_CHAT = 'phone/ON_CHAT';
8314
8408
  const ON_SIGNAL = 'phone/ON_SIGNAL';
8409
+ const ON_DISCONNECTED = 'onDisconnected';
8315
8410
 
8316
8411
  const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
8317
8412
  const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
@@ -8351,6 +8446,7 @@ const events = [
8351
8446
  ON_CHAT,
8352
8447
  ON_SIGNAL,
8353
8448
  ON_NETWORK_STATS,
8449
+ ON_DISCONNECTED,
8354
8450
  ];
8355
8451
 
8356
8452
  const logger$8 = IssueReporter$1.loggerFor('webrtc-phone');
@@ -9703,6 +9799,11 @@ class WebRTCPhone extends Emitter {
9703
9799
  this.eventEmitter.emit(ON_UNREGISTERED);
9704
9800
  });
9705
9801
 
9802
+ this.client.on(this.client.ON_DISCONNECTED, () => {
9803
+ logger$8.info('WebRTC disconnected');
9804
+ this.eventEmitter.emit(ON_DISCONNECTED);
9805
+ });
9806
+
9706
9807
  this.client.on(this.client.REGISTERED, () => {
9707
9808
  logger$8.info('WebRTC registered', {
9708
9809
  shouldSendReinvite: this.shouldSendReinvite,
@@ -9959,6 +10060,7 @@ var PHONE_EVENTS = /*#__PURE__*/Object.freeze({
9959
10060
  ON_NETWORK_STATS: ON_NETWORK_STATS,
9960
10061
  ON_CHAT: ON_CHAT,
9961
10062
  ON_SIGNAL: ON_SIGNAL,
10063
+ ON_DISCONNECTED: ON_DISCONNECTED,
9962
10064
  MESSAGE_TYPE_CHAT: MESSAGE_TYPE_CHAT,
9963
10065
  MESSAGE_TYPE_SIGNAL: MESSAGE_TYPE_SIGNAL,
9964
10066
  events: events,