@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
@@ -414,7 +414,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
414
414
 
415
415
  // Use a function here to be able to mock it in tests
416
416
  const realFetch = () => {
417
- if (typeof document !== 'undefined') {
417
+ if (typeof document !== 'undefined' && window.fetch) {
418
418
  // Browser
419
419
  return window.fetch;
420
420
  }
@@ -1060,6 +1060,7 @@ class WebRTCPhone extends Emitter {
1060
1060
  constraints,
1061
1061
  audioOnly,
1062
1062
  conference,
1063
+ iceRestart,
1063
1064
  });
1064
1065
 
1065
1066
  if (!sipSession) {
@@ -1163,6 +1164,11 @@ class WebRTCPhone extends Emitter {
1163
1164
 
1164
1165
  this.client.downgradeToAudio(sipSession);
1165
1166
 
1167
+ if (callSession) {
1168
+ callSession.cameraEnabled = false;
1169
+ this._updateCallSession(callSession);
1170
+ }
1171
+
1166
1172
  if (withMessage) {
1167
1173
  this._sendReinviteMessage(callSession, false);
1168
1174
  }
@@ -1190,6 +1196,11 @@ class WebRTCPhone extends Emitter {
1190
1196
 
1191
1197
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
1192
1198
 
1199
+ if (callSession) {
1200
+ callSession.cameraEnabled = true;
1201
+ this._updateCallSession(callSession);
1202
+ }
1203
+
1193
1204
  // If no stream is returned, it means we have to reinvite
1194
1205
  if (!newStream) {
1195
1206
  return true;
@@ -1459,7 +1470,7 @@ class WebRTCPhone extends Emitter {
1459
1470
  }
1460
1471
 
1461
1472
  _onCallAccepted(sipSession , cameraEnabled ) {
1462
- logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
1473
+ logger.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
1463
1474
 
1464
1475
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
1465
1476
  this.currentSipSession = sipSession;
@@ -1528,6 +1539,7 @@ class WebRTCPhone extends Emitter {
1528
1539
  _onCallTerminated(sipSession ) {
1529
1540
  logger.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
1530
1541
 
1542
+ const sipSessionId = this.getSipSessionId(sipSession);
1531
1543
  const callSession = this._createCallSession(sipSession);
1532
1544
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
1533
1545
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -1545,7 +1557,6 @@ class WebRTCPhone extends Emitter {
1545
1557
  }, 5);
1546
1558
  }
1547
1559
 
1548
- const sipSessionId = this.getSipSessionId(sipSession);
1549
1560
  if (sipSessionId) {
1550
1561
  this.removeIncomingSessions(sipSessionId);
1551
1562
  }
@@ -1971,7 +1982,7 @@ class WebRTCPhone extends Emitter {
1971
1982
  // @TODO: line is not used here
1972
1983
  async makeCall(number , line , cameraEnabled ,
1973
1984
  audioOnly = false, conference = false) {
1974
- logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
1985
+ logger.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
1975
1986
  if (!number) {
1976
1987
  return Promise.resolve(null);
1977
1988
  }
@@ -2190,8 +2201,12 @@ class WebRTCPhone extends Emitter {
2190
2201
  }
2191
2202
 
2192
2203
  const sessionId = this.incomingSessions[0];
2204
+ const sipSession = this.client.getSipSession(sessionId);
2205
+ if (!sipSession) {
2206
+ return null;
2207
+ }
2193
2208
 
2194
- return this._createCallSession(this.client.getSipSession(sessionId));
2209
+ return this._createCallSession(sipSession);
2195
2210
  }
2196
2211
 
2197
2212
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -2332,9 +2347,13 @@ class WebRTCPhone extends Emitter {
2332
2347
  if (this.shouldSendReinvite && this.currentSipSession
2333
2348
  && this.currentSipSession.state === sessionState.SessionState.Established) {
2334
2349
  this.shouldSendReinvite = false;
2350
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
2351
+ const isConference = pc ? pc.sfu : false;
2352
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
2353
+
2335
2354
  try {
2336
2355
  // Send reinvite with iceRestart
2337
- this.sendReinvite(this.currentCallSession, null, false, false, true);
2356
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
2338
2357
  } catch (e) {
2339
2358
  logger.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
2340
2359
  }
@@ -2418,6 +2437,15 @@ class WebRTCPhone extends Emitter {
2418
2437
  return this.client.getSipSessionId(sipSession);
2419
2438
  }
2420
2439
 
2440
+ _updateCallSession(callSession ) {
2441
+ const sipSession = this.findSipSession(callSession);
2442
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
2443
+
2444
+ if (sipSessionId) {
2445
+ this.callSessions[sipSessionId] = callSession;
2446
+ }
2447
+ }
2448
+
2421
2449
  _onMessage(message ) {
2422
2450
  if (!message || message.method !== 'MESSAGE') {
2423
2451
  return;
@@ -700,7 +700,7 @@ class Contact {
700
700
  this[key] = old[key] || this[key];
701
701
  });
702
702
 
703
- if (old.lineState && !this.lineState) {
703
+ if (old.lineState) {
704
704
  this.lineState = old.lineState;
705
705
  }
706
706
 
@@ -0,0 +1,150 @@
1
+ 'use strict';
2
+
3
+ var moment = require('moment');
4
+
5
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
6
+
7
+ var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
8
+
9
+ //
10
+
11
+ var newFrom = (instance , ToClass ) => {
12
+ const args = {};
13
+ Object.getOwnPropertyNames(instance).forEach(prop => {
14
+ args[prop] = instance[prop];
15
+ });
16
+
17
+ return new ToClass(args);
18
+ };
19
+
20
+ //
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+ class Meeting {
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+ static parse(plain ) {
48
+ return new Meeting({
49
+ guestSipAuthorization: plain.guest_sip_authorization,
50
+ uri: plain.ingress_http_uri,
51
+ name: plain.name,
52
+ ownerUuids: plain.owner_uuids,
53
+ port: plain.port,
54
+ uuid: plain.uuid,
55
+ extension: plain.exten,
56
+ persistent: plain.persistent,
57
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
58
+ });
59
+ }
60
+
61
+ static parseMany(items ) {
62
+ if (!items) {
63
+ return [];
64
+ }
65
+ return items.map(plain => Meeting.parse(plain));
66
+ }
67
+
68
+ static newFrom(meeting ) {
69
+ return newFrom(meeting, Meeting);
70
+ }
71
+
72
+ constructor({
73
+ uuid,
74
+ name,
75
+ guestSipAuthorization,
76
+ ownerUuids,
77
+ port,
78
+ uri,
79
+ extension,
80
+ persistent,
81
+ creationTime,
82
+ } = {}) {
83
+ this.guestSipAuthorization = guestSipAuthorization;
84
+ this.uri = uri;
85
+ this.name = name;
86
+ this.ownerUuids = ownerUuids;
87
+ this.port = port;
88
+ this.uuid = uuid;
89
+ this.extension = extension;
90
+ this.persistent = persistent;
91
+ this.creationTime = creationTime;
92
+
93
+ // Useful to compare instead of instanceof with minified code
94
+ this.type = 'Meeting';
95
+ }
96
+
97
+ getGuestSipCredentials() {
98
+ // eslint-disable-next-line no-undef
99
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
100
+ return { username, secret };
101
+ }
102
+ }
103
+
104
+ //
105
+
106
+ describe('Meeting domain', () => {
107
+ it('can return username and secret from an base64 encrypted string', () => {
108
+ const USERNAME = 'username';
109
+ const SECRET = 'secret';
110
+
111
+ const args = {
112
+ guest_sip_authorization: btoa(`${USERNAME}:${SECRET}`),
113
+ creation_time: '',
114
+ ingress_http_uri: '',
115
+ name: '',
116
+ owner_uuids: [],
117
+ port: '',
118
+ uuid: '',
119
+ exten: '',
120
+ persistent: false,
121
+ };
122
+
123
+ const meeting = Meeting.parse(args);
124
+
125
+ const { username, secret } = meeting.getGuestSipCredentials();
126
+
127
+ expect(username).toEqual(USERNAME);
128
+ expect(secret).toEqual(SECRET);
129
+ });
130
+
131
+ it('should return a date from a string', () => {
132
+ const args = {
133
+ creation_time: '2021-12-21T15:56:42.880Z',
134
+ guest_sip_authorization: '',
135
+ ingress_http_uri: '',
136
+ name: '',
137
+ owner_uuids: [],
138
+ port: '',
139
+ uuid: '',
140
+ exten: '',
141
+ persistent: false,
142
+ };
143
+
144
+ const { creationTime } = Meeting.parse(args);
145
+
146
+ expect(creationTime.getDate()).toEqual(21);
147
+ expect(creationTime.getFullYear()).toEqual(2021);
148
+ expect(creationTime.getMonth()).toEqual(11);
149
+ });
150
+ });
package/lib/index.js CHANGED
@@ -475,7 +475,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
475
475
 
476
476
  // Use a function here to be able to mock it in tests
477
477
  const realFetch = () => {
478
- if (typeof document !== 'undefined') {
478
+ if (typeof document !== 'undefined' && window.fetch) {
479
479
  // Browser
480
480
  return window.fetch;
481
481
  }
@@ -1935,7 +1935,7 @@ class Contact {
1935
1935
  this[key] = old[key] || this[key];
1936
1936
  });
1937
1937
 
1938
- if (old.lineState && !this.lineState) {
1938
+ if (old.lineState) {
1939
1939
  this.lineState = old.lineState;
1940
1940
  }
1941
1941
 
@@ -2642,8 +2642,9 @@ class ExternalApp {
2642
2642
 
2643
2643
 
2644
2644
 
2645
-
2645
+
2646
2646
 
2647
+
2647
2648
 
2648
2649
 
2649
2650
  class Meeting {
@@ -2654,9 +2655,10 @@ class Meeting {
2654
2655
 
2655
2656
 
2656
2657
 
2657
-
2658
+
2658
2659
 
2659
2660
 
2661
+
2660
2662
 
2661
2663
  static parse(plain ) {
2662
2664
  return new Meeting({
@@ -2666,8 +2668,9 @@ class Meeting {
2666
2668
  ownerUuids: plain.owner_uuids,
2667
2669
  port: plain.port,
2668
2670
  uuid: plain.uuid,
2669
- number: plain.number,
2671
+ extension: plain.exten,
2670
2672
  persistent: plain.persistent,
2673
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
2671
2674
  });
2672
2675
  }
2673
2676
 
@@ -2689,8 +2692,9 @@ class Meeting {
2689
2692
  ownerUuids,
2690
2693
  port,
2691
2694
  uri,
2692
- number,
2695
+ extension,
2693
2696
  persistent,
2697
+ creationTime,
2694
2698
  } = {}) {
2695
2699
  this.guestSipAuthorization = guestSipAuthorization;
2696
2700
  this.uri = uri;
@@ -2698,8 +2702,9 @@ class Meeting {
2698
2702
  this.ownerUuids = ownerUuids;
2699
2703
  this.port = port;
2700
2704
  this.uuid = uuid;
2701
- this.number = number;
2705
+ this.extension = extension;
2702
2706
  this.persistent = persistent;
2707
+ this.creationTime = creationTime;
2703
2708
 
2704
2709
  // Useful to compare instead of instanceof with minified code
2705
2710
  this.type = 'Meeting';
@@ -5630,11 +5635,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5630
5635
 
5631
5636
  // $FlowFixMe
5632
5637
  setRemoteSessionDescription(sessionDescription ) {
5633
- const result = super.setRemoteSessionDescription(sessionDescription);
5638
+ try {
5639
+ const result = super.setRemoteSessionDescription(sessionDescription);
5634
5640
 
5635
- this.eventEmitter.emit('setDescription', sessionDescription);
5641
+ this.eventEmitter.emit('setDescription', sessionDescription);
5636
5642
 
5637
- return result;
5643
+ return result;
5644
+ } catch (error) {
5645
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
5646
+ throw error;
5647
+ }
5638
5648
  }
5639
5649
 
5640
5650
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -6539,7 +6549,7 @@ class WebRTCClient extends Emitter {
6539
6549
  }
6540
6550
 
6541
6551
  call(number , enableVideo , audioOnly = false, conference = false) {
6542
- logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
6552
+ logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
6543
6553
  const inviterOptions = {
6544
6554
  sessionDescriptionHandlerOptionsReInvite: {
6545
6555
  conference,
@@ -7615,6 +7625,7 @@ class WebRTCClient extends Emitter {
7615
7625
  const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
7616
7626
  const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
7617
7627
  const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
7628
+ const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
7618
7629
 
7619
7630
  logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
7620
7631
 
@@ -7622,7 +7633,8 @@ class WebRTCClient extends Emitter {
7622
7633
  constraints: {
7623
7634
  // Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
7624
7635
  audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
7625
- video: screenSharing ? (isDesktop ? ({ mandatory: { chromeMediaSource: 'desktop' } }) : { cursor: 'always' })
7636
+ video: screenSharing ? (isDesktop
7637
+ ? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
7626
7638
  : this._getVideoConstraints(enableVideo),
7627
7639
  screen: screenSharing,
7628
7640
  desktop: isDesktop,
@@ -7957,12 +7969,14 @@ class WebRTCClient extends Emitter {
7957
7969
 
7958
7970
  session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
7959
7971
 
7960
- pc.oniceconnectionstatechange = () => {
7961
- logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
7962
- if (pc.iceConnectionState === 'disconnected') {
7963
- this.eventEmitter.emit(ON_DISCONNECTED$1);
7964
- }
7965
- };
7972
+ if (pc) {
7973
+ pc.oniceconnectionstatechange = () => {
7974
+ logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
7975
+ if (pc.iceConnectionState === 'disconnected') {
7976
+ this.eventEmitter.emit(ON_DISCONNECTED$1);
7977
+ }
7978
+ };
7979
+ }
7966
7980
 
7967
7981
  if (withEvent) {
7968
7982
  this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
@@ -8172,13 +8186,17 @@ class WebRTCClient extends Emitter {
8172
8186
  const nbStats = this.sessionNetworkStats[sessionId].length;
8173
8187
  const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
8174
8188
  const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
8189
+ const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
8175
8190
  const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
8176
8191
  const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
8192
+ const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
8177
8193
  const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
8178
8194
  const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
8179
8195
  const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
8180
- let audioBytesSent = 0;
8181
- let audioBytesReceived = 0;
8196
+ let audioBytesSent = 0; // content + header
8197
+ let audioBytesReceived = 0; // content + header
8198
+ let audioContentSent = 0; // useful to detect blank call
8199
+ let audioContentReceived = 0;
8182
8200
  let videoBytesSent = 0;
8183
8201
  let videoBytesReceived = 0;
8184
8202
  let transportSent = 0;
@@ -8188,6 +8206,7 @@ class WebRTCClient extends Emitter {
8188
8206
  stats.forEach(report => {
8189
8207
  if (report.type === 'outbound-rtp' && report.kind === 'audio') {
8190
8208
  audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
8209
+ audioContentSent += Number(report.bytesSent);
8191
8210
  }
8192
8211
  if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
8193
8212
  audioBytesSent += Number(report.bytesSent);
@@ -8199,6 +8218,7 @@ class WebRTCClient extends Emitter {
8199
8218
  packetsLost += Number(report.packetsLost);
8200
8219
  networkStats.packetsReceived = Number(report.packetsReceived);
8201
8220
  audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
8221
+ audioContentReceived += Number(report.bytesReceived);
8202
8222
  }
8203
8223
  if (report.type === 'inbound-rtp' && report.kind === 'video') {
8204
8224
  videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
@@ -8227,10 +8247,17 @@ class WebRTCClient extends Emitter {
8227
8247
  });
8228
8248
 
8229
8249
  networkStats.packetsLost = packetsLost;
8250
+
8230
8251
  networkStats.totalAudioBytesSent = audioBytesSent;
8231
8252
  networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
8232
8253
  networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
8233
8254
  networkStats.audioBytesReceived = audioBytesReceived;
8255
+
8256
+ networkStats.totalAudioContentSent = audioContentSent;
8257
+ networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
8258
+ networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
8259
+ networkStats.audioContentReceived = audioContentReceived;
8260
+
8234
8261
  networkStats.totalVideoBytesSent = videoBytesSent;
8235
8262
  networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
8236
8263
  networkStats.totalVideoBytesReceived = videoBytesReceived;
@@ -9335,6 +9362,7 @@ class WebRTCPhone extends Emitter {
9335
9362
  constraints,
9336
9363
  audioOnly,
9337
9364
  conference,
9365
+ iceRestart,
9338
9366
  });
9339
9367
 
9340
9368
  if (!sipSession) {
@@ -9438,6 +9466,11 @@ class WebRTCPhone extends Emitter {
9438
9466
 
9439
9467
  this.client.downgradeToAudio(sipSession);
9440
9468
 
9469
+ if (callSession) {
9470
+ callSession.cameraEnabled = false;
9471
+ this._updateCallSession(callSession);
9472
+ }
9473
+
9441
9474
  if (withMessage) {
9442
9475
  this._sendReinviteMessage(callSession, false);
9443
9476
  }
@@ -9465,6 +9498,11 @@ class WebRTCPhone extends Emitter {
9465
9498
 
9466
9499
  const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
9467
9500
 
9501
+ if (callSession) {
9502
+ callSession.cameraEnabled = true;
9503
+ this._updateCallSession(callSession);
9504
+ }
9505
+
9468
9506
  // If no stream is returned, it means we have to reinvite
9469
9507
  if (!newStream) {
9470
9508
  return true;
@@ -9734,7 +9772,7 @@ class WebRTCPhone extends Emitter {
9734
9772
  }
9735
9773
 
9736
9774
  _onCallAccepted(sipSession , cameraEnabled ) {
9737
- logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9775
+ logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
9738
9776
 
9739
9777
  const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
9740
9778
  this.currentSipSession = sipSession;
@@ -9803,6 +9841,7 @@ class WebRTCPhone extends Emitter {
9803
9841
  _onCallTerminated(sipSession ) {
9804
9842
  logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
9805
9843
 
9844
+ const sipSessionId = this.getSipSessionId(sipSession);
9806
9845
  const callSession = this._createCallSession(sipSession);
9807
9846
  const isCurrentSession = this.isCurrentCallSipSession(callSession);
9808
9847
  const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
@@ -9820,7 +9859,6 @@ class WebRTCPhone extends Emitter {
9820
9859
  }, 5);
9821
9860
  }
9822
9861
 
9823
- const sipSessionId = this.getSipSessionId(sipSession);
9824
9862
  if (sipSessionId) {
9825
9863
  this.removeIncomingSessions(sipSessionId);
9826
9864
  }
@@ -10246,7 +10284,7 @@ class WebRTCPhone extends Emitter {
10246
10284
  // @TODO: line is not used here
10247
10285
  async makeCall(number , line , cameraEnabled ,
10248
10286
  audioOnly = false, conference = false) {
10249
- logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
10287
+ logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
10250
10288
  if (!number) {
10251
10289
  return Promise.resolve(null);
10252
10290
  }
@@ -10465,8 +10503,12 @@ class WebRTCPhone extends Emitter {
10465
10503
  }
10466
10504
 
10467
10505
  const sessionId = this.incomingSessions[0];
10506
+ const sipSession = this.client.getSipSession(sessionId);
10507
+ if (!sipSession) {
10508
+ return null;
10509
+ }
10468
10510
 
10469
- return this._createCallSession(this.client.getSipSession(sessionId));
10511
+ return this._createCallSession(sipSession);
10470
10512
  }
10471
10513
 
10472
10514
  sendMessage(sipSession = null, body , contentType = 'text/plain') {
@@ -10607,9 +10649,13 @@ class WebRTCPhone extends Emitter {
10607
10649
  if (this.shouldSendReinvite && this.currentSipSession
10608
10650
  && this.currentSipSession.state === sessionState.SessionState.Established) {
10609
10651
  this.shouldSendReinvite = false;
10652
+ const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
10653
+ const isConference = pc ? pc.sfu : false;
10654
+ const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
10655
+
10610
10656
  try {
10611
10657
  // Send reinvite with iceRestart
10612
- this.sendReinvite(this.currentCallSession, null, false, false, true);
10658
+ this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
10613
10659
  } catch (e) {
10614
10660
  logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
10615
10661
  }
@@ -10693,6 +10739,15 @@ class WebRTCPhone extends Emitter {
10693
10739
  return this.client.getSipSessionId(sipSession);
10694
10740
  }
10695
10741
 
10742
+ _updateCallSession(callSession ) {
10743
+ const sipSession = this.findSipSession(callSession);
10744
+ const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
10745
+
10746
+ if (sipSessionId) {
10747
+ this.callSessions[sipSessionId] = callSession;
10748
+ }
10749
+ }
10750
+
10696
10751
  _onMessage(message ) {
10697
10752
  if (!message || message.method !== 'MESSAGE') {
10698
10753
  return;
@@ -25,7 +25,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
25
25
 
26
26
  // Use a function here to be able to mock it in tests
27
27
  const realFetch = () => {
28
- if (typeof document !== 'undefined') {
28
+ if (typeof document !== 'undefined' && window.fetch) {
29
29
  // Browser
30
30
  return window.fetch;
31
31
  }
@@ -497,11 +497,16 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
497
497
 
498
498
  // $FlowFixMe
499
499
  setRemoteSessionDescription(sessionDescription ) {
500
- const result = super.setRemoteSessionDescription(sessionDescription);
500
+ try {
501
+ const result = super.setRemoteSessionDescription(sessionDescription);
501
502
 
502
- this.eventEmitter.emit('setDescription', sessionDescription);
503
+ this.eventEmitter.emit('setDescription', sessionDescription);
503
504
 
504
- return result;
505
+ return result;
506
+ } catch (error) {
507
+ this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
508
+ throw error;
509
+ }
505
510
  }
506
511
 
507
512
  // Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
@@ -1416,7 +1416,7 @@ class Contact {
1416
1416
  this[key] = old[key] || this[key];
1417
1417
  });
1418
1418
 
1419
- if (old.lineState && !this.lineState) {
1419
+ if (old.lineState) {
1420
1420
  this.lineState = old.lineState;
1421
1421
  }
1422
1422
 
@@ -2472,7 +2472,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
2472
2472
 
2473
2473
  // Use a function here to be able to mock it in tests
2474
2474
  const realFetch = () => {
2475
- if (typeof document !== 'undefined') {
2475
+ if (typeof document !== 'undefined' && window.fetch) {
2476
2476
  // Browser
2477
2477
  return window.fetch;
2478
2478
  }
@@ -3151,8 +3151,9 @@ class ExternalApp {
3151
3151
 
3152
3152
 
3153
3153
 
3154
-
3154
+
3155
3155
 
3156
+
3156
3157
 
3157
3158
 
3158
3159
  class Meeting {
@@ -3163,9 +3164,10 @@ class Meeting {
3163
3164
 
3164
3165
 
3165
3166
 
3166
-
3167
+
3167
3168
 
3168
3169
 
3170
+
3169
3171
 
3170
3172
  static parse(plain ) {
3171
3173
  return new Meeting({
@@ -3175,8 +3177,9 @@ class Meeting {
3175
3177
  ownerUuids: plain.owner_uuids,
3176
3178
  port: plain.port,
3177
3179
  uuid: plain.uuid,
3178
- number: plain.number,
3180
+ extension: plain.exten,
3179
3181
  persistent: plain.persistent,
3182
+ creationTime: moment__default['default'](plain.creation_time).toDate(),
3180
3183
  });
3181
3184
  }
3182
3185
 
@@ -3198,8 +3201,9 @@ class Meeting {
3198
3201
  ownerUuids,
3199
3202
  port,
3200
3203
  uri,
3201
- number,
3204
+ extension,
3202
3205
  persistent,
3206
+ creationTime,
3203
3207
  } = {}) {
3204
3208
  this.guestSipAuthorization = guestSipAuthorization;
3205
3209
  this.uri = uri;
@@ -3207,8 +3211,9 @@ class Meeting {
3207
3211
  this.ownerUuids = ownerUuids;
3208
3212
  this.port = port;
3209
3213
  this.uuid = uuid;
3210
- this.number = number;
3214
+ this.extension = extension;
3211
3215
  this.persistent = persistent;
3216
+ this.creationTime = creationTime;
3212
3217
 
3213
3218
  // Useful to compare instead of instanceof with minified code
3214
3219
  this.type = 'Meeting';
@@ -17,7 +17,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
17
17
 
18
18
  // Use a function here to be able to mock it in tests
19
19
  const realFetch = () => {
20
- if (typeof document !== 'undefined') {
20
+ if (typeof document !== 'undefined' && window.fetch) {
21
21
  // Browser
22
22
  return window.fetch;
23
23
  }