@wazo/sdk 0.37.23 → 0.37.27

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 (118) hide show
  1. package/README.md +95 -57
  2. package/dist/wazo-sdk.js +3 -3
  3. package/esm/__tests__/api-client.test.js +12 -7
  4. package/esm/__tests__/web-rtc-client.test.js +47 -20
  5. package/esm/api/agentd.js +1 -1
  6. package/esm/api/amid.js +1 -1
  7. package/esm/api/application.js +1 -1
  8. package/esm/api/auth.js +1 -1
  9. package/esm/api/call-logd.js +1 -1
  10. package/esm/api/calld.js +1 -1
  11. package/esm/api/chatd.js +1 -1
  12. package/esm/api/confd.js +11 -6
  13. package/esm/api/ctid-ng.js +1 -1
  14. package/esm/api/dird.js +2 -2
  15. package/esm/api/webhookd.js +1 -1
  16. package/esm/api-client.js +12 -7
  17. package/esm/checker/Checker.js +47 -20
  18. package/esm/checker/checks/aor.js +12 -7
  19. package/esm/checker/checks/api.js +12 -7
  20. package/esm/checker/checks/index.js +47 -20
  21. package/esm/checker/checks/wazo-websocket.js +1 -1
  22. package/esm/checker/checks/webrtc-transport.js +47 -20
  23. package/esm/checker/checks/webrtc.js +47 -20
  24. package/esm/domain/AdHocAPIConference.js +12 -7
  25. package/esm/domain/Contact.js +1 -1
  26. package/esm/domain/Features.js +12 -7
  27. package/esm/domain/Meeting.js +12 -5
  28. package/esm/domain/Phone/CTIPhone.js +12 -7
  29. package/esm/domain/Phone/WebRTCPhone.js +34 -6
  30. package/esm/domain/__tests__/Contact.test.js +1 -1
  31. package/esm/domain/__tests__/Meeting.test.js +144 -0
  32. package/esm/index.js +80 -25
  33. package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
  34. package/esm/service/CallApi.js +12 -7
  35. package/esm/service/IssueReporter.js +1 -1
  36. package/esm/service/__tests__/IssueReporter.test.js +1 -1
  37. package/esm/service/getApiClient.js +12 -7
  38. package/esm/simple/Auth.js +80 -25
  39. package/esm/simple/Configuration.js +80 -25
  40. package/esm/simple/Directory.js +12 -7
  41. package/esm/simple/Phone.js +80 -25
  42. package/esm/simple/Websocket.js +1 -1
  43. package/esm/simple/index.js +80 -25
  44. package/esm/simple/room/LocalParticipant.js +80 -25
  45. package/esm/simple/room/Participant.js +80 -25
  46. package/esm/simple/room/RemoteParticipant.js +80 -25
  47. package/esm/simple/room/Room.js +80 -25
  48. package/esm/simple/room/SipRoom.js +80 -25
  49. package/esm/simple/room/Stream.js +80 -25
  50. package/esm/simple/room/__tests__/RemoteParticipant.test.js +80 -25
  51. package/esm/simple/utils.js +80 -25
  52. package/esm/types/WebSocketMessage.js +1 -1
  53. package/esm/utils/__tests__/api-requester.test.js +1 -1
  54. package/esm/utils/api-requester.js +1 -1
  55. package/esm/web-rtc-client.js +47 -20
  56. package/esm/websocket-client.js +1 -1
  57. package/lib/__tests__/api-client.test.js +12 -7
  58. package/lib/__tests__/web-rtc-client.test.js +47 -20
  59. package/lib/api/agentd.js +1 -1
  60. package/lib/api/amid.js +1 -1
  61. package/lib/api/application.js +1 -1
  62. package/lib/api/auth.js +1 -1
  63. package/lib/api/call-logd.js +1 -1
  64. package/lib/api/calld.js +1 -1
  65. package/lib/api/chatd.js +1 -1
  66. package/lib/api/confd.js +11 -6
  67. package/lib/api/ctid-ng.js +1 -1
  68. package/lib/api/dird.js +2 -2
  69. package/lib/api/webhookd.js +1 -1
  70. package/lib/api-client.js +12 -7
  71. package/lib/checker/Checker.js +47 -20
  72. package/lib/checker/checks/aor.js +12 -7
  73. package/lib/checker/checks/api.js +12 -7
  74. package/lib/checker/checks/index.js +47 -20
  75. package/lib/checker/checks/wazo-websocket.js +1 -1
  76. package/lib/checker/checks/webrtc-transport.js +47 -20
  77. package/lib/checker/checks/webrtc.js +47 -20
  78. package/lib/domain/AdHocAPIConference.js +12 -7
  79. package/lib/domain/Contact.js +1 -1
  80. package/lib/domain/Features.js +12 -7
  81. package/lib/domain/Meeting.js +16 -5
  82. package/lib/domain/Phone/CTIPhone.js +12 -7
  83. package/lib/domain/Phone/WebRTCPhone.js +34 -6
  84. package/lib/domain/__tests__/Contact.test.js +1 -1
  85. package/lib/domain/__tests__/Meeting.test.js +150 -0
  86. package/lib/index.js +80 -25
  87. package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
  88. package/lib/service/CallApi.js +12 -7
  89. package/lib/service/IssueReporter.js +1 -1
  90. package/lib/service/__tests__/IssueReporter.test.js +1 -1
  91. package/lib/service/getApiClient.js +12 -7
  92. package/lib/simple/Auth.js +80 -25
  93. package/lib/simple/Configuration.js +80 -25
  94. package/lib/simple/Directory.js +12 -7
  95. package/lib/simple/Phone.js +80 -25
  96. package/lib/simple/Websocket.js +1 -1
  97. package/lib/simple/index.js +80 -25
  98. package/lib/simple/room/LocalParticipant.js +80 -25
  99. package/lib/simple/room/Participant.js +80 -25
  100. package/lib/simple/room/RemoteParticipant.js +80 -25
  101. package/lib/simple/room/Room.js +80 -25
  102. package/lib/simple/room/SipRoom.js +80 -25
  103. package/lib/simple/room/Stream.js +80 -25
  104. package/lib/simple/room/__tests__/RemoteParticipant.test.js +80 -25
  105. package/lib/simple/utils.js +80 -25
  106. package/lib/types/WebSocketMessage.js +2 -0
  107. package/lib/utils/__tests__/api-requester.test.js +1 -1
  108. package/lib/utils/api-requester.js +1 -1
  109. package/lib/web-rtc-client.js +47 -20
  110. package/lib/websocket-client.js +1 -1
  111. package/package.json +1 -1
  112. package/src/domain/Contact.js +1 -1
  113. package/src/domain/Meeting.js +12 -5
  114. package/src/domain/Phone/WebRTCPhone.js +33 -5
  115. package/src/domain/__tests__/Meeting.test.js +50 -0
  116. package/src/lib/WazoSessionDescriptionHandler.js +8 -3
  117. package/src/utils/api-requester.js +1 -1
  118. package/src/web-rtc-client.js +27 -10
@@ -115,7 +115,7 @@ const logger$2 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
115
115
 
116
116
  // Use a function here to be able to mock it in tests
117
117
  const realFetch = () => {
118
- if (typeof document !== 'undefined') {
118
+ if (typeof document !== 'undefined' && window.fetch) {
119
119
  // Browser
120
120
  return window.fetch;
121
121
  }
@@ -834,11 +834,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
834
834
 
835
835
  // $FlowFixMe
836
836
  setRemoteSessionDescription(sessionDescription ) {
837
- const result = super.setRemoteSessionDescription(sessionDescription);
837
+ try {
838
+ const result = super.setRemoteSessionDescription(sessionDescription);
838
839
 
839
- this.eventEmitter.emit('setDescription', sessionDescription);
840
+ this.eventEmitter.emit('setDescription', sessionDescription);
840
841
 
841
- return result;
842
+ return result;
843
+ } catch (error) {
844
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
845
+ throw error;
846
+ }
842
847
  }
843
848
 
844
849
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -2458,7 +2463,7 @@ class Contact {
2458
2463
  this[key] = old[key] || this[key];
2459
2464
  });
2460
2465
 
2461
- if (old.lineState && !this.lineState) {
2466
+ if (old.lineState) {
2462
2467
  this.lineState = old.lineState;
2463
2468
  }
2464
2469
 
@@ -3165,8 +3170,9 @@ class ExternalApp {
3165
3170
 
3166
3171
 
3167
3172
 
3168
-
3173
+
3169
3174
 
3175
+
3170
3176
 
3171
3177
 
3172
3178
  class Meeting {
@@ -3177,9 +3183,10 @@ class Meeting {
3177
3183
 
3178
3184
 
3179
3185
 
3180
-
3186
+
3181
3187
 
3182
3188
 
3189
+
3183
3190
 
3184
3191
  static parse(plain ) {
3185
3192
  return new Meeting({
@@ -3189,8 +3196,9 @@ class Meeting {
3189
3196
  ownerUuids: plain.owner_uuids,
3190
3197
  port: plain.port,
3191
3198
  uuid: plain.uuid,
3192
- number: plain.number,
3199
+ extension: plain.exten,
3193
3200
  persistent: plain.persistent,
3201
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
3194
3202
  });
3195
3203
  }
3196
3204
 
@@ -3212,8 +3220,9 @@ class Meeting {
3212
3220
  ownerUuids,
3213
3221
  port,
3214
3222
  uri,
3215
- number,
3223
+ extension,
3216
3224
  persistent,
3225
+ creationTime,
3217
3226
  } = {}) {
3218
3227
  this.guestSipAuthorization = guestSipAuthorization;
3219
3228
  this.uri = uri;
@@ -3221,8 +3230,9 @@ class Meeting {
3221
3230
  this.ownerUuids = ownerUuids;
3222
3231
  this.port = port;
3223
3232
  this.uuid = uuid;
3224
- this.number = number;
3233
+ this.extension = extension;
3225
3234
  this.persistent = persistent;
3235
+ this.creationTime = creationTime;
3226
3236
 
3227
3237
  // Useful to compare instead of instanceof with minified code
3228
3238
  this.type = 'Meeting';
@@ -5714,7 +5724,7 @@ class WebRTCClient extends Emitter {
5714
5724
  }
5715
5725
 
5716
5726
  call(number , enableVideo , audioOnly = false, conference = false) {
5717
- logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
5727
+ logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
5718
5728
  const inviterOptions = {
5719
5729
  sessionDescriptionHandlerOptionsReInvite: {
5720
5730
  conference,
@@ -6790,6 +6800,7 @@ class WebRTCClient extends Emitter {
6790
6800
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
6791
6801
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
6792
6802
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
6803
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
6793
6804
 
6794
6805
  logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
6795
6806
 
@@ -6797,7 +6808,8 @@ class WebRTCClient extends Emitter {
6797
6808
  constraints: {
6798
6809
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
6799
6810
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
6800
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
6811
+ video: screenSharing ? (isDesktop
6812
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
6801
6813
  : this._getVideoConstraints(enableVideo),
6802
6814
  screen: screenSharing,
6803
6815
  desktop: isDesktop,
@@ -7132,12 +7144,14 @@ class WebRTCClient extends Emitter {
7132
7144
 
7133
7145
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7134
7146
 
7135
- pc.oniceconnectionstatechange = () => {
7136
- logger.info('on ice connection state changed', { state: pc.iceConnectionState });
7137
- if (pc.iceConnectionState === 'disconnected') {
7138
- this.eventEmitter.emit(ON_DISCONNECTED);
7139
- }
7140
- };
7147
+ if (pc) {
7148
+ pc.oniceconnectionstatechange = () => {
7149
+ logger.info('on ice connection state changed', { state: pc.iceConnectionState });
7150
+ if (pc.iceConnectionState === 'disconnected') {
7151
+ this.eventEmitter.emit(ON_DISCONNECTED);
7152
+ }
7153
+ };
7154
+ }
7141
7155
 
7142
7156
  if (withEvent) {
7143
7157
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -7347,13 +7361,17 @@ class WebRTCClient extends Emitter {
7347
7361
  const nbStats = this.sessionNetworkStats[sessionId].length;
7348
7362
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
7349
7363
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
7364
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
7350
7365
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
7351
7366
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
7367
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
7352
7368
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
7353
7369
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
7354
7370
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
7355
- let audioBytesSent = 0;
7356
- let audioBytesReceived = 0;
7371
+ let audioBytesSent = 0; // content + header
7372
+ let audioBytesReceived = 0; // content + header
7373
+ let audioContentSent = 0; // useful to detect blank call
7374
+ let audioContentReceived = 0;
7357
7375
  let videoBytesSent = 0;
7358
7376
  let videoBytesReceived = 0;
7359
7377
  let transportSent = 0;
@@ -7363,6 +7381,7 @@ class WebRTCClient extends Emitter {
7363
7381
  stats.forEach(report => {
7364
7382
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
7365
7383
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
7384
+ audioContentSent += Number(report.bytesSent);
7366
7385
  }
7367
7386
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
7368
7387
  audioBytesSent += Number(report.bytesSent);
@@ -7374,6 +7393,7 @@ class WebRTCClient extends Emitter {
7374
7393
  packetsLost += Number(report.packetsLost);
7375
7394
  networkStats.packetsReceived = Number(report.packetsReceived);
7376
7395
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
7396
+ audioContentReceived += Number(report.bytesReceived);
7377
7397
  }
7378
7398
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
7379
7399
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -7402,10 +7422,17 @@ class WebRTCClient extends Emitter {
7402
7422
  });
7403
7423
 
7404
7424
  networkStats.packetsLost = packetsLost;
7425
+
7405
7426
  networkStats.totalAudioBytesSent = audioBytesSent;
7406
7427
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
7407
7428
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
7408
7429
  networkStats.audioBytesReceived = audioBytesReceived;
7430
+
7431
+ networkStats.totalAudioContentSent = audioContentSent;
7432
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
7433
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
7434
+ networkStats.audioContentReceived = audioContentReceived;
7435
+
7409
7436
  networkStats.totalVideoBytesSent = videoBytesSent;
7410
7437
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
7411
7438
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -49,7 +49,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
49
49
 
50
50
  // Use a function here to be able to mock it in tests
51
51
  const realFetch = () => {
52
- if (typeof document !== 'undefined') {
52
+ if (typeof document !== 'undefined' && window.fetch) {
53
53
  // Browser
54
54
  return window.fetch;
55
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "0.37.23",
3
+ "version": "0.37.27",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "dist/wazo-sdk.js",
6
6
  "author": "Wazo (http://wazo.io)",
@@ -654,7 +654,7 @@ export default class Contact {
654
654
  this[key] = old[key] || this[key];
655
655
  });
656
656
 
657
- if (old.lineState && !this.lineState) {
657
+ if (old.lineState) {
658
658
  this.lineState = old.lineState;
659
659
  }
660
660
 
@@ -1,4 +1,6 @@
1
1
  // @flow
2
+ import moment from 'moment';
3
+
2
4
  import newFrom from '../utils/new-from';
3
5
 
4
6
  export type MeetingCreationResponse = {
@@ -8,8 +10,9 @@ export type MeetingCreationResponse = {
8
10
  owner_uuids: Array<string>,
9
11
  port: string,
10
12
  uuid: string,
11
- number: string,
13
+ exten: string,
12
14
  persistent: boolean,
15
+ creation_time: string,
13
16
  }
14
17
 
15
18
  export default class Meeting {
@@ -20,9 +23,10 @@ export default class Meeting {
20
23
  uuid: string;
21
24
  name: string;
22
25
  port: string;
23
- number: string;
26
+ extension: string;
24
27
  persistent: boolean;
25
28
  ownerUuids: Array<string>;
29
+ creationTime: Date;
26
30
 
27
31
  static parse(plain: MeetingCreationResponse): Meeting {
28
32
  return new Meeting({
@@ -32,8 +36,9 @@ export default class Meeting {
32
36
  ownerUuids: plain.owner_uuids,
33
37
  port: plain.port,
34
38
  uuid: plain.uuid,
35
- number: plain.number,
39
+ extension: plain.exten,
36
40
  persistent: plain.persistent,
41
+ creationTime: moment(plain.creation_time).toDate(),
37
42
  });
38
43
  }
39
44
 
@@ -55,8 +60,9 @@ export default class Meeting {
55
60
  ownerUuids,
56
61
  port,
57
62
  uri,
58
- number,
63
+ extension,
59
64
  persistent,
65
+ creationTime,
60
66
  }: Object = {}) {
61
67
  this.guestSipAuthorization = guestSipAuthorization;
62
68
  this.uri = uri;
@@ -64,8 +70,9 @@ export default class Meeting {
64
70
  this.ownerUuids = ownerUuids;
65
71
  this.port = port;
66
72
  this.uuid = uuid;
67
- this.number = number;
73
+ this.extension = extension;
68
74
  this.persistent = persistent;
75
+ this.creationTime = creationTime;
69
76
 
70
77
  // Useful to compare instead of instanceof with minified code
71
78
  this.type = 'Meeting';
@@ -203,6 +203,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
203
203
  constraints,
204
204
  audioOnly,
205
205
  conference,
206
+ iceRestart,
206
207
  });
207
208
 
208
209
  if (!sipSession) {
@@ -306,6 +307,11 @@ export default class WebRTCPhone extends Emitter implements Phone {
306
307
 
307
308
  this.client.downgradeToAudio(sipSession);
308
309
 
310
+ if (callSession) {
311
+ callSession.cameraEnabled = false;
312
+ this._updateCallSession(callSession);
313
+ }
314
+
309
315
  if (withMessage) {
310
316
  this._sendReinviteMessage(callSession, false);
311
317
  }
@@ -333,6 +339,11 @@ export default class WebRTCPhone extends Emitter implements Phone {
333
339
 
334
340
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
335
341
 
342
+ if (callSession) {
343
+ callSession.cameraEnabled = true;
344
+ this._updateCallSession(callSession);
345
+ }
346
+
336
347
  // If no stream is returned, it means we have to reinvite
337
348
  if (!newStream) {
338
349
  return true;
@@ -604,7 +615,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
604
615
  }
605
616
 
606
617
  _onCallAccepted(sipSession: Session, cameraEnabled: boolean): CallSession {
607
- logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
618
+ logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
608
619
 
609
620
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
610
621
  this.currentSipSession = sipSession;
@@ -673,6 +684,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
673
684
  _onCallTerminated(sipSession: Session) {
674
685
  logger.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
675
686
 
687
+ const sipSessionId = this.getSipSessionId(sipSession);
676
688
  const callSession = this._createCallSession(sipSession);
677
689
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
678
690
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -690,7 +702,6 @@ export default class WebRTCPhone extends Emitter implements Phone {
690
702
  }, 5);
691
703
  }
692
704
 
693
- const sipSessionId = this.getSipSessionId(sipSession);
694
705
  if (sipSessionId) {
695
706
  this.removeIncomingSessions(sipSessionId);
696
707
  }
@@ -1116,7 +1127,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
1116
1127
  // @TODO: line is not used here
1117
1128
  async makeCall(number: string, line: any, cameraEnabled?: boolean,
1118
1129
  audioOnly: boolean = false, conference: boolean = false): Promise<?CallSession> {
1119
- logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
1130
+ logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
1120
1131
  if (!number) {
1121
1132
  return Promise.resolve(null);
1122
1133
  }
@@ -1335,8 +1346,12 @@ export default class WebRTCPhone extends Emitter implements Phone {
1335
1346
  }
1336
1347
 
1337
1348
  const sessionId = this.incomingSessions[0];
1349
+ const sipSession = this.client.getSipSession(sessionId);
1350
+ if (!sipSession) {
1351
+ return null;
1352
+ }
1338
1353
 
1339
- return this._createCallSession(this.client.getSipSession(sessionId));
1354
+ return this._createCallSession(sipSession);
1340
1355
  }
1341
1356
 
1342
1357
  sendMessage(sipSession: Session = null, body: string, contentType: string = 'text/plain') {
@@ -1477,9 +1492,13 @@ export default class WebRTCPhone extends Emitter implements Phone {
1477
1492
  if (this.shouldSendReinvite && this.currentSipSession
1478
1493
  && this.currentSipSession.state === SessionState.Established) {
1479
1494
  this.shouldSendReinvite = false;
1495
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
1496
+ const isConference = pc ? pc.sfu : false;
1497
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
1498
+
1480
1499
  try {
1481
1500
  // Send reinvite with iceRestart
1482
- this.sendReinvite(this.currentCallSession, null, false, false, true);
1501
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
1483
1502
  } catch (e) {
1484
1503
  logger.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
1485
1504
  }
@@ -1563,6 +1582,15 @@ export default class WebRTCPhone extends Emitter implements Phone {
1563
1582
  return this.client.getSipSessionId(sipSession);
1564
1583
  }
1565
1584
 
1585
+ _updateCallSession(callSession: CallSession) {
1586
+ const sipSession = this.findSipSession(callSession);
1587
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
1588
+
1589
+ if (sipSessionId) {
1590
+ this.callSessions[sipSessionId] = callSession;
1591
+ }
1592
+ }
1593
+
1566
1594
  _onMessage(message: Message) {
1567
1595
  if (!message || message.method !== 'MESSAGE') {
1568
1596
  return;
@@ -0,0 +1,50 @@
1
+ // @flow
2
+ /* global btoa */
3
+
4
+ import Meeting from '../Meeting';
5
+
6
+ describe('Meeting domain', () => {
7
+ it('can return username and secret from an base64 encrypted string', () => {
8
+ const USERNAME = 'username';
9
+ const SECRET = 'secret';
10
+
11
+ const args = {
12
+ guest_sip_authorization: btoa(`${USERNAME}:${SECRET}`),
13
+ creation_time: '',
14
+ ingress_http_uri: '',
15
+ name: '',
16
+ owner_uuids: [],
17
+ port: '',
18
+ uuid: '',
19
+ exten: '',
20
+ persistent: false,
21
+ };
22
+
23
+ const meeting = Meeting.parse(args);
24
+
25
+ const { username, secret } = meeting.getGuestSipCredentials();
26
+
27
+ expect(username).toEqual(USERNAME);
28
+ expect(secret).toEqual(SECRET);
29
+ });
30
+
31
+ it('should return a date from a string', () => {
32
+ const args = {
33
+ creation_time: '2021-12-21T15:56:42.880Z',
34
+ guest_sip_authorization: '',
35
+ ingress_http_uri: '',
36
+ name: '',
37
+ owner_uuids: [],
38
+ port: '',
39
+ uuid: '',
40
+ exten: '',
41
+ persistent: false,
42
+ };
43
+
44
+ const { creationTime } = Meeting.parse(args);
45
+
46
+ expect(creationTime.getDate()).toEqual(21);
47
+ expect(creationTime.getFullYear()).toEqual(2021);
48
+ expect(creationTime.getMonth()).toEqual(11);
49
+ });
50
+ });
@@ -62,11 +62,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
62
62
 
63
63
  // $FlowFixMe
64
64
  setRemoteSessionDescription(sessionDescription: RTCSessionDescriptionInit): Promise<void> {
65
- const result = super.setRemoteSessionDescription(sessionDescription);
65
+ try {
66
+ const result = super.setRemoteSessionDescription(sessionDescription);
66
67
 
67
- this.eventEmitter.emit('setDescription', sessionDescription);
68
+ this.eventEmitter.emit('setDescription', sessionDescription);
68
69
 
69
- return result;
70
+ return result;
71
+ } catch (error) {
72
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
73
+ throw error;
74
+ }
70
75
  }
71
76
 
72
77
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -25,7 +25,7 @@ const logger = IssueReporter ? IssueReporter.loggerFor('api') : console;
25
25
 
26
26
  // Use a function here to be able to mock it in tests
27
27
  export const realFetch = () => {
28
- if (typeof document !== 'undefined') {
28
+ if (typeof document !== 'undefined' && window.fetch) {
29
29
  // Browser
30
30
  return window.fetch;
31
31
  }
@@ -453,7 +453,7 @@ export default class WebRTCClient extends Emitter {
453
453
  }
454
454
 
455
455
  call(number: string, enableVideo?: boolean, audioOnly: boolean = false, conference: boolean = false): Session {
456
- logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
456
+ logger.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
457
457
  const inviterOptions: Object = {
458
458
  sessionDescriptionHandlerOptionsReInvite: {
459
459
  conference,
@@ -1529,6 +1529,7 @@ export default class WebRTCClient extends Emitter {
1529
1529
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
1530
1530
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
1531
1531
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
1532
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
1532
1533
 
1533
1534
  logger.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
1534
1535
 
@@ -1536,7 +1537,8 @@ export default class WebRTCClient extends Emitter {
1536
1537
  constraints: {
1537
1538
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
1538
1539
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
1539
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
1540
+ video: screenSharing ? (isDesktop
1541
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
1540
1542
  : this._getVideoConstraints(enableVideo),
1541
1543
  screen: screenSharing,
1542
1544
  desktop: isDesktop,
@@ -1871,12 +1873,14 @@ export default class WebRTCClient extends Emitter {
1871
1873
 
1872
1874
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
1873
1875
 
1874
- pc.oniceconnectionstatechange = () => {
1875
- logger.info('on ice connection state changed', { state: pc.iceConnectionState });
1876
- if (pc.iceConnectionState === 'disconnected') {
1877
- this.eventEmitter.emit(ON_DISCONNECTED);
1878
- }
1879
- };
1876
+ if (pc) {
1877
+ pc.oniceconnectionstatechange = () => {
1878
+ logger.info('on ice connection state changed', { state: pc.iceConnectionState });
1879
+ if (pc.iceConnectionState === 'disconnected') {
1880
+ this.eventEmitter.emit(ON_DISCONNECTED);
1881
+ }
1882
+ };
1883
+ }
1880
1884
 
1881
1885
  if (withEvent) {
1882
1886
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -2086,13 +2090,17 @@ export default class WebRTCClient extends Emitter {
2086
2090
  const nbStats = this.sessionNetworkStats[sessionId].length;
2087
2091
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
2088
2092
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
2093
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
2089
2094
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
2090
2095
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
2096
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
2091
2097
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
2092
2098
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
2093
2099
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
2094
- let audioBytesSent = 0;
2095
- let audioBytesReceived = 0;
2100
+ let audioBytesSent = 0; // content + header
2101
+ let audioBytesReceived = 0; // content + header
2102
+ let audioContentSent = 0; // useful to detect blank call
2103
+ let audioContentReceived = 0;
2096
2104
  let videoBytesSent = 0;
2097
2105
  let videoBytesReceived = 0;
2098
2106
  let transportSent = 0;
@@ -2102,6 +2110,7 @@ export default class WebRTCClient extends Emitter {
2102
2110
  stats.forEach(report => {
2103
2111
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
2104
2112
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
2113
+ audioContentSent += Number(report.bytesSent);
2105
2114
  }
2106
2115
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
2107
2116
  audioBytesSent += Number(report.bytesSent);
@@ -2113,6 +2122,7 @@ export default class WebRTCClient extends Emitter {
2113
2122
  packetsLost += Number(report.packetsLost);
2114
2123
  networkStats.packetsReceived = Number(report.packetsReceived);
2115
2124
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
2125
+ audioContentReceived += Number(report.bytesReceived);
2116
2126
  }
2117
2127
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
2118
2128
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -2141,10 +2151,17 @@ export default class WebRTCClient extends Emitter {
2141
2151
  });
2142
2152
 
2143
2153
  networkStats.packetsLost = packetsLost;
2154
+
2144
2155
  networkStats.totalAudioBytesSent = audioBytesSent;
2145
2156
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
2146
2157
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
2147
2158
  networkStats.audioBytesReceived = audioBytesReceived;
2159
+
2160
+ networkStats.totalAudioContentSent = audioContentSent;
2161
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
2162
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
2163
+ networkStats.audioContentReceived = audioContentReceived;
2164
+
2148
2165
  networkStats.totalVideoBytesSent = videoBytesSent;
2149
2166
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
2150
2167
  networkStats.totalVideoBytesReceived = videoBytesReceived;