@ohos-ports/genesys-cloud-streaming-client 20.1.0-beta.1

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 (176) hide show
  1. package/README.md +47 -0
  2. package/dist/cjs/alerting-leader.d.ts +29 -0
  3. package/dist/cjs/alerting-leader.js +163 -0
  4. package/dist/cjs/client.d.ts +84 -0
  5. package/dist/cjs/client.js +680 -0
  6. package/dist/cjs/connection-manager.d.ts +18 -0
  7. package/dist/cjs/connection-manager.js +120 -0
  8. package/dist/cjs/connection-transfer.d.ts +7 -0
  9. package/dist/cjs/connection-transfer.js +20 -0
  10. package/dist/cjs/http-client.d.ts +18 -0
  11. package/dist/cjs/http-client.js +230 -0
  12. package/dist/cjs/index.d.ts +10 -0
  13. package/dist/cjs/index.js +31 -0
  14. package/dist/cjs/messenger.d.ts +37 -0
  15. package/dist/cjs/messenger.js +54 -0
  16. package/dist/cjs/notifications.d.ts +94 -0
  17. package/dist/cjs/notifications.js +495 -0
  18. package/dist/cjs/ping.d.ts +21 -0
  19. package/dist/cjs/ping.js +60 -0
  20. package/dist/cjs/polyfills.d.ts +0 -0
  21. package/dist/cjs/polyfills.js +6 -0
  22. package/dist/cjs/server-monitor.d.ts +16 -0
  23. package/dist/cjs/server-monitor.js +44 -0
  24. package/dist/cjs/stanza-definitions/webrtc-signaling.d.ts +29 -0
  25. package/dist/cjs/stanza-definitions/webrtc-signaling.js +113 -0
  26. package/dist/cjs/stanza-definitions/xep0051.d.ts +19 -0
  27. package/dist/cjs/stanza-definitions/xep0051.js +28 -0
  28. package/dist/cjs/stats-formatter.d.ts +6 -0
  29. package/dist/cjs/stats-formatter.js +63 -0
  30. package/dist/cjs/types/genesys-cloud-media-session.d.ts +64 -0
  31. package/dist/cjs/types/genesys-cloud-media-session.js +353 -0
  32. package/dist/cjs/types/interfaces.d.ts +310 -0
  33. package/dist/cjs/types/interfaces.js +22 -0
  34. package/dist/cjs/types/libs.d.ts +32 -0
  35. package/dist/cjs/types/libs.js +1 -0
  36. package/dist/cjs/types/media-session.d.ts +76 -0
  37. package/dist/cjs/types/media-session.js +2 -0
  38. package/dist/cjs/types/named-agent.d.ts +13 -0
  39. package/dist/cjs/types/named-agent.js +2 -0
  40. package/dist/cjs/types/offline-error.d.ts +2 -0
  41. package/dist/cjs/types/offline-error.js +5 -0
  42. package/dist/cjs/types/sasl-error.d.ts +8 -0
  43. package/dist/cjs/types/sasl-error.js +12 -0
  44. package/dist/cjs/types/stanza-media-session.d.ts +56 -0
  45. package/dist/cjs/types/stanza-media-session.js +255 -0
  46. package/dist/cjs/types/streaming-client-extension.d.ts +14 -0
  47. package/dist/cjs/types/streaming-client-extension.js +2 -0
  48. package/dist/cjs/types/timeout-error.d.ts +3 -0
  49. package/dist/cjs/types/timeout-error.js +9 -0
  50. package/dist/cjs/types/user-cancelled-error.d.ts +2 -0
  51. package/dist/cjs/types/user-cancelled-error.js +5 -0
  52. package/dist/cjs/utils.d.ts +34 -0
  53. package/dist/cjs/utils.js +202 -0
  54. package/dist/cjs/webrtc.d.ts +126 -0
  55. package/dist/cjs/webrtc.js +891 -0
  56. package/dist/deploy-info.json +21 -0
  57. package/dist/es/alerting-leader.d.ts +29 -0
  58. package/dist/es/alerting-leader.js +177 -0
  59. package/dist/es/client.d.ts +84 -0
  60. package/dist/es/client.js +699 -0
  61. package/dist/es/connection-manager.d.ts +18 -0
  62. package/dist/es/connection-manager.js +124 -0
  63. package/dist/es/connection-transfer.d.ts +7 -0
  64. package/dist/es/connection-transfer.js +16 -0
  65. package/dist/es/http-client.d.ts +18 -0
  66. package/dist/es/http-client.js +194 -0
  67. package/dist/es/index.bundle.js +39629 -0
  68. package/dist/es/index.d.ts +10 -0
  69. package/dist/es/index.js +10 -0
  70. package/dist/es/messenger.d.ts +37 -0
  71. package/dist/es/messenger.js +62 -0
  72. package/dist/es/notifications.d.ts +94 -0
  73. package/dist/es/notifications.js +507 -0
  74. package/dist/es/ping.d.ts +21 -0
  75. package/dist/es/ping.js +68 -0
  76. package/dist/es/polyfills.d.ts +0 -0
  77. package/dist/es/polyfills.js +6 -0
  78. package/dist/es/server-monitor.d.ts +16 -0
  79. package/dist/es/server-monitor.js +41 -0
  80. package/dist/es/stanza-definitions/webrtc-signaling.d.ts +29 -0
  81. package/dist/es/stanza-definitions/webrtc-signaling.js +110 -0
  82. package/dist/es/stanza-definitions/xep0051.d.ts +19 -0
  83. package/dist/es/stanza-definitions/xep0051.js +25 -0
  84. package/dist/es/stats-formatter.d.ts +6 -0
  85. package/dist/es/stats-formatter.js +54 -0
  86. package/dist/es/types/genesys-cloud-media-session.d.ts +64 -0
  87. package/dist/es/types/genesys-cloud-media-session.js +379 -0
  88. package/dist/es/types/interfaces.d.ts +310 -0
  89. package/dist/es/types/interfaces.js +19 -0
  90. package/dist/es/types/libs.d.ts +32 -0
  91. package/dist/es/types/libs.js +1 -0
  92. package/dist/es/types/media-session.d.ts +76 -0
  93. package/dist/es/types/media-session.js +1 -0
  94. package/dist/es/types/named-agent.d.ts +13 -0
  95. package/dist/es/types/named-agent.js +1 -0
  96. package/dist/es/types/offline-error.d.ts +2 -0
  97. package/dist/es/types/offline-error.js +2 -0
  98. package/dist/es/types/sasl-error.d.ts +8 -0
  99. package/dist/es/types/sasl-error.js +9 -0
  100. package/dist/es/types/stanza-media-session.d.ts +56 -0
  101. package/dist/es/types/stanza-media-session.js +264 -0
  102. package/dist/es/types/streaming-client-extension.d.ts +14 -0
  103. package/dist/es/types/streaming-client-extension.js +1 -0
  104. package/dist/es/types/timeout-error.d.ts +3 -0
  105. package/dist/es/types/timeout-error.js +5 -0
  106. package/dist/es/types/user-cancelled-error.d.ts +2 -0
  107. package/dist/es/types/user-cancelled-error.js +2 -0
  108. package/dist/es/utils.d.ts +34 -0
  109. package/dist/es/utils.js +192 -0
  110. package/dist/es/webrtc.d.ts +126 -0
  111. package/dist/es/webrtc.js +917 -0
  112. package/dist/manifest.json +19 -0
  113. package/dist/npm/CHANGELOG.md +637 -0
  114. package/dist/npm/README.md +47 -0
  115. package/dist/npm/alerting-leader.d.ts +29 -0
  116. package/dist/npm/alerting-leader.js +163 -0
  117. package/dist/npm/client.d.ts +84 -0
  118. package/dist/npm/client.js +680 -0
  119. package/dist/npm/connection-manager.d.ts +18 -0
  120. package/dist/npm/connection-manager.js +120 -0
  121. package/dist/npm/connection-transfer.d.ts +7 -0
  122. package/dist/npm/connection-transfer.js +20 -0
  123. package/dist/npm/http-client.d.ts +18 -0
  124. package/dist/npm/http-client.js +230 -0
  125. package/dist/npm/index.d.ts +10 -0
  126. package/dist/npm/index.js +31 -0
  127. package/dist/npm/messenger.d.ts +37 -0
  128. package/dist/npm/messenger.js +54 -0
  129. package/dist/npm/module.js +10 -0
  130. package/dist/npm/notifications.d.ts +94 -0
  131. package/dist/npm/notifications.js +495 -0
  132. package/dist/npm/ping.d.ts +21 -0
  133. package/dist/npm/ping.js +60 -0
  134. package/dist/npm/polyfills.d.ts +0 -0
  135. package/dist/npm/polyfills.js +6 -0
  136. package/dist/npm/server-monitor.d.ts +16 -0
  137. package/dist/npm/server-monitor.js +44 -0
  138. package/dist/npm/stanza-definitions/webrtc-signaling.d.ts +29 -0
  139. package/dist/npm/stanza-definitions/webrtc-signaling.js +113 -0
  140. package/dist/npm/stanza-definitions/xep0051.d.ts +19 -0
  141. package/dist/npm/stanza-definitions/xep0051.js +28 -0
  142. package/dist/npm/stats-formatter.d.ts +6 -0
  143. package/dist/npm/stats-formatter.js +63 -0
  144. package/dist/npm/types/genesys-cloud-media-session.d.ts +64 -0
  145. package/dist/npm/types/genesys-cloud-media-session.js +353 -0
  146. package/dist/npm/types/interfaces.d.ts +310 -0
  147. package/dist/npm/types/interfaces.js +22 -0
  148. package/dist/npm/types/libs.d.ts +32 -0
  149. package/dist/npm/types/libs.js +1 -0
  150. package/dist/npm/types/media-session.d.ts +76 -0
  151. package/dist/npm/types/media-session.js +2 -0
  152. package/dist/npm/types/named-agent.d.ts +13 -0
  153. package/dist/npm/types/named-agent.js +2 -0
  154. package/dist/npm/types/offline-error.d.ts +2 -0
  155. package/dist/npm/types/offline-error.js +5 -0
  156. package/dist/npm/types/sasl-error.d.ts +8 -0
  157. package/dist/npm/types/sasl-error.js +12 -0
  158. package/dist/npm/types/stanza-media-session.d.ts +56 -0
  159. package/dist/npm/types/stanza-media-session.js +255 -0
  160. package/dist/npm/types/streaming-client-extension.d.ts +14 -0
  161. package/dist/npm/types/streaming-client-extension.js +2 -0
  162. package/dist/npm/types/timeout-error.d.ts +3 -0
  163. package/dist/npm/types/timeout-error.js +9 -0
  164. package/dist/npm/types/user-cancelled-error.d.ts +2 -0
  165. package/dist/npm/types/user-cancelled-error.js +5 -0
  166. package/dist/npm/utils.d.ts +34 -0
  167. package/dist/npm/utils.js +207 -0
  168. package/dist/npm/webrtc.d.ts +126 -0
  169. package/dist/npm/webrtc.js +893 -0
  170. package/dist/streaming-client.browser.js +2 -0
  171. package/dist/streaming-client.browser.js.LICENSE.txt +12 -0
  172. package/dist/v20/streaming-client.browser.js +2 -0
  173. package/dist/v20/streaming-client.browser.js.LICENSE.txt +12 -0
  174. package/dist/v20.1.0/streaming-client.browser.js +2 -0
  175. package/dist/v20.1.0/streaming-client.browser.js.LICENSE.txt +12 -0
  176. package/package.json +132 -0
@@ -0,0 +1,379 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import StatsGatherer from 'webrtc-stats-gatherer';
11
+ import { EventEmitter } from 'events';
12
+ import { timeoutPromise } from '../utils';
13
+ import { SessionTypes } from './interfaces';
14
+ const loggingOverrides = {
15
+ 'Discovered new ICE candidate': { skipMessage: true }
16
+ };
17
+ export class GenesysCloudMediaSession {
18
+ constructor(webrtcExtension, params) {
19
+ this.webrtcExtension = webrtcExtension;
20
+ this.iceCandidatesDiscovered = 0;
21
+ this.iceCandidatesReceivedFromPeer = 0;
22
+ this.state = 'pending';
23
+ this.connectionState = 'starting';
24
+ this.id = params.id;
25
+ this.fromJid = params.fromJid;
26
+ this.peerID = params.peerID;
27
+ this.logger = params.logger;
28
+ this.conversationId = params.conversationId;
29
+ this.fromUserId = params.fromUserId;
30
+ this.pc = this.peerConnection = new RTCPeerConnection({
31
+ iceServers: params.iceServers,
32
+ iceTransportPolicy: params.iceTransportPolicy
33
+ });
34
+ this.originalRoomJid = params.originalRoomJid;
35
+ this.sessionType = SessionTypes[params.sessionType];
36
+ this.ignoreHostCandidatesFromRemote = !!params.ignoreHostCandidatesFromRemote;
37
+ this.allowIPv6 = !!params.allowIPv6;
38
+ this.allowTCP = !!params.allowTCP;
39
+ this.reinvite = !!params.reinvite;
40
+ this.privAnswerMode = params.privAnswerMode;
41
+ this.meetingId = params.meetingId;
42
+ // babel does not like the typescript recipe for multiple extends so we are hacking this one
43
+ // referencing https://github.com/babel/babel/issues/798
44
+ const eventEmitter = new EventEmitter();
45
+ Object.keys(eventEmitter.__proto__).forEach((name) => {
46
+ this[name] = eventEmitter[name];
47
+ });
48
+ if (!params.optOutOfWebrtcStatsTelemetry) {
49
+ this.setupStatsGatherer();
50
+ }
51
+ this.peerConnection.addEventListener('icecandidate', this.onIceCandidate.bind(this));
52
+ this.peerConnection.addEventListener('iceconnectionstatechange', this.onIceStateChange.bind(this));
53
+ this.peerConnection.addEventListener('connectionstatechange', this.onConnectionStateChange.bind(this));
54
+ this.peerConnection.addEventListener('icecandidateerror', this.onIceCandidateError.bind(this));
55
+ // sync the session state after a silent disconnect, like putting the system to sleep.
56
+ }
57
+ keepStateInSyncWithPeerConnection() {
58
+ if (this.stateSyncTimeout) {
59
+ clearTimeout(this.stateSyncTimeout);
60
+ this.stateSyncTimeout = undefined;
61
+ }
62
+ const lastTime = Date.now();
63
+ const checkInterval = 2000;
64
+ const threshold = 2000;
65
+ this.stateSyncTimeout = setTimeout(() => {
66
+ const currentTime = Date.now();
67
+ const timeDiff = currentTime - lastTime;
68
+ if (timeDiff > checkInterval + threshold) {
69
+ this.log('warn', 'MediaSession detected timer anomally. Reasons include taxed resources or system sleep.');
70
+ // if we have a state mismatch
71
+ if (this.state !== 'ended' && ['failed', 'closed'].includes(this.peerConnection.connectionState)) {
72
+ this.log('warn', 'state mismatch between session.state and peerConnection.connectionState, manually terminating the session', { sessionId: this.id, conversationId: this.conversationId, sessionType: this.sessionType });
73
+ this.onSessionTerminate();
74
+ }
75
+ }
76
+ if (this.state !== 'ended') {
77
+ this.keepStateInSyncWithPeerConnection();
78
+ }
79
+ }, checkInterval);
80
+ }
81
+ setRemoteDescription(sdp) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ return this.peerConnection.setRemoteDescription({ sdp, type: 'offer' });
84
+ });
85
+ }
86
+ getLogDetails() {
87
+ return {
88
+ conversationId: this.conversationId,
89
+ sessionId: this.id,
90
+ sessionType: this.sessionType
91
+ };
92
+ }
93
+ log(level, message, details, options) {
94
+ if (!details) {
95
+ details = {};
96
+ }
97
+ const logDetails = Object.assign(Object.assign({}, details), this.getLogDetails());
98
+ this.logger[level](message, logDetails, options);
99
+ }
100
+ sendGenesysWebrtc(info) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ info.id = info.id || globalThis.crypto.randomUUID();
103
+ info.jsonrpc = info.jsonrpc || '2.0';
104
+ const iq = {
105
+ type: 'set',
106
+ genesysWebrtc: info,
107
+ from: this.webrtcExtension.jid,
108
+ to: this.peerID
109
+ };
110
+ return this.webrtcExtension.sendIq(iq);
111
+ });
112
+ }
113
+ end(reason = 'success', silent = false) {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ this.state = 'ended';
116
+ const params = {
117
+ sessionId: this.id,
118
+ reason: reason.condition || reason
119
+ };
120
+ if (!silent) {
121
+ yield timeoutPromise((resolve, reject) => {
122
+ this.log('info', 'sending sdp terminate');
123
+ this.sendGenesysWebrtc({ jsonrpc: '2.0', method: 'terminate', params }).then(resolve, reject);
124
+ }, 2000, 'Timeout waiting for response to termination request', { sessionId: this.id, conversationId: this.conversationId, sessionType: this.sessionType }).catch((e) => this.logger.error(e));
125
+ }
126
+ this.onSessionTerminate(params.reason);
127
+ });
128
+ }
129
+ setupStatsGatherer() {
130
+ this.statsGatherer = new StatsGatherer(this.peerConnection);
131
+ this.statsGatherer.on('stats', this.emit.bind(this, 'stats'));
132
+ }
133
+ onIceStateChange() {
134
+ return __awaiter(this, void 0, void 0, function* () {
135
+ const iceState = this.peerConnection.iceConnectionState;
136
+ const sessionId = this.id;
137
+ const conversationId = this.conversationId;
138
+ const sessionType = this.sessionType;
139
+ this.log('info', 'ICE state changed: ', { iceState, sessionId, conversationId });
140
+ if (iceState === 'disconnected') {
141
+ // this means we actually connected at one point
142
+ if (this.peerConnection.signalingState === 'stable') {
143
+ this.interruptionStart = new Date();
144
+ this.log('info', 'Connection state is interrupted', { sessionId, conversationId, sessionType });
145
+ }
146
+ }
147
+ else if (iceState === 'connected') {
148
+ this.log('info', 'sending session-info: active');
149
+ const params = {
150
+ sessionId: this.id,
151
+ status: 'active'
152
+ };
153
+ yield this.sendGenesysWebrtc({
154
+ jsonrpc: '2.0',
155
+ params,
156
+ method: 'info'
157
+ });
158
+ this._setupDataChannel();
159
+ }
160
+ else if (iceState === 'failed') {
161
+ this.log('info', 'ICE connection failed', {
162
+ candidatesDiscovered: this.iceCandidatesDiscovered,
163
+ candidatesReceivedFromPeer: this.iceCandidatesReceivedFromPeer
164
+ });
165
+ }
166
+ });
167
+ }
168
+ onConnectionStateChange() {
169
+ const connectionState = this.connectionState = this.peerConnection.connectionState;
170
+ const sessionId = this.id;
171
+ const conversationId = this.conversationId;
172
+ const sessionType = this.sessionType;
173
+ if (connectionState === 'connected') {
174
+ this.keepStateInSyncWithPeerConnection();
175
+ }
176
+ this.log('info', 'Connection state changed: ', { connectionState, sessionId, conversationId, sessionType });
177
+ if (this.interruptionStart) {
178
+ if (connectionState === 'connected') {
179
+ const diff = new Date().getTime() - this.interruptionStart.getTime();
180
+ this.log('info', 'Connection was interrupted but was successfully recovered/connected', { sessionId, conversationId, sessionType, timeToRecover: diff });
181
+ this.interruptionStart = undefined;
182
+ }
183
+ else if (connectionState === 'failed') {
184
+ this.log('info', 'Connection was interrupted and failed to recover, cleaning up', { sessionId, conversationId, sessionType });
185
+ this.onSessionTerminate();
186
+ }
187
+ }
188
+ this.emit('connectionState', connectionState);
189
+ }
190
+ onIceCandidateError(ev) {
191
+ const event = ev;
192
+ this.log('error', 'IceCandidateError', {
193
+ errorCode: event.errorCode,
194
+ errorText: event.errorText,
195
+ url: event.url
196
+ });
197
+ }
198
+ /* istanbul ignore next */
199
+ createIceCandidate(sdpMid, candidateStr) {
200
+ return new RTCIceCandidate({
201
+ sdpMid,
202
+ candidate: candidateStr
203
+ });
204
+ }
205
+ addRemoteIceCandidate(sdpFragment) {
206
+ return __awaiter(this, void 0, void 0, function* () {
207
+ // matches the mline type. example: "m=video 9 RTP/AVP 0" should result in "video"
208
+ const sdpMid = sdpFragment.match(/m=([^\s]+)/)[1];
209
+ // matches the entire a= line without the "a="
210
+ const candidate = sdpFragment.match(/a=([^\\\r]+)/)[1];
211
+ const iceCandidate = this.createIceCandidate(sdpMid, candidate);
212
+ yield this.peerConnection.addIceCandidate(iceCandidate);
213
+ });
214
+ }
215
+ // this is for ice candidates we harvest for ourself
216
+ onIceCandidate(e) {
217
+ var _a, _b;
218
+ const candidateString = (_a = e.candidate) === null || _a === void 0 ? void 0 : _a.candidate;
219
+ const sdpMid = (_b = e.candidate) === null || _b === void 0 ? void 0 : _b.sdpMid;
220
+ let sdpStr;
221
+ if (e.candidate) {
222
+ if (!this.allowTCP && e.candidate.protocol === 'tcp') {
223
+ return;
224
+ }
225
+ if (!this.allowIPv6) {
226
+ const addressRegex = /.+udp [^ ]+ ([^ ]+).*typ host/;
227
+ const matches = addressRegex.exec(e.candidate.candidate);
228
+ const ipv4Regex = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
229
+ if (matches && !matches[1].match(ipv4Regex)) {
230
+ this.log('debug', 'Filtering out IPv6 candidate', e.candidate.candidate);
231
+ return;
232
+ }
233
+ }
234
+ // this has too much information and can only be logged locally (debug)
235
+ this.log('debug', 'Processing ice candidate', e.candidate);
236
+ // this one is info level so it can go to the server
237
+ this.log('info', 'Discovered ice candidate to send to peer', { type: e.candidate.type });
238
+ this.iceCandidatesDiscovered++;
239
+ // media team asked us to send the mline and prefix the candidate with "a="
240
+ sdpStr = `m=${sdpMid} 9 RTP/AVP 0\r\na=${candidateString}\r\n`;
241
+ }
242
+ else {
243
+ sdpStr = 'a=end-of-candidates\r\n';
244
+ this.emit('endOfCandidates');
245
+ }
246
+ return this.sendGenesysWebrtc({
247
+ jsonrpc: '2.0',
248
+ method: 'iceCandidate',
249
+ params: {
250
+ sessionId: this.id,
251
+ sdp: sdpStr
252
+ }
253
+ });
254
+ }
255
+ onSessionTerminate(reason) {
256
+ this.state = 'ended';
257
+ if (this.peerConnection) {
258
+ this.peerConnection.close();
259
+ }
260
+ this.logger.info('emitting sdp media-session (terminate)');
261
+ this.emit('terminated', { condition: reason || 'success' });
262
+ }
263
+ addTrack(track, stream) {
264
+ return __awaiter(this, void 0, void 0, function* () {
265
+ const availableTransceiver = this.peerConnection.getTransceivers().find((transceiver) => {
266
+ var _a;
267
+ return !transceiver.sender.track && ((_a = transceiver.receiver.track) === null || _a === void 0 ? void 0 : _a.kind) === track.kind;
268
+ });
269
+ if (availableTransceiver) {
270
+ return availableTransceiver.sender.replaceTrack(track);
271
+ }
272
+ this.peerConnection.addTrack(track, stream);
273
+ });
274
+ }
275
+ _setupDataChannel() {
276
+ var _a;
277
+ // this shouldn't happen, but we shouldn't set the datachannel up more than once
278
+ if (this.dataChannel) {
279
+ return;
280
+ }
281
+ // do nothing if a datachannel wasn't offered
282
+ if ((_a = this.peerConnection.remoteDescription) === null || _a === void 0 ? void 0 : _a.sdp.includes('webrtc-datachannel')) {
283
+ this.log('info', 'creating data channel');
284
+ this.dataChannel = this.peerConnection.createDataChannel('videoConferenceControl');
285
+ this.dataChannel.addEventListener('open', () => {
286
+ this.log('info', 'data channel opened');
287
+ });
288
+ this.dataChannel.addEventListener('message', this._handleDataChannelMessage.bind(this));
289
+ this.dataChannel.addEventListener('close', () => {
290
+ this.log('info', 'closing data channel');
291
+ });
292
+ this.dataChannel.addEventListener('error', (error) => {
293
+ this.log('error', 'Error occurred with the data channel', error);
294
+ });
295
+ }
296
+ }
297
+ _handleDataChannelMessage(event) {
298
+ try {
299
+ const message = JSON.parse(event.data);
300
+ this.emit('dataChannelMessage', message);
301
+ }
302
+ catch (e) {
303
+ this.log('error', 'Failed to parse data channel message', { error: e });
304
+ }
305
+ }
306
+ accept() {
307
+ return __awaiter(this, void 0, void 0, function* () {
308
+ this.state = 'active';
309
+ const answer = yield this.peerConnection.createAnswer();
310
+ yield this.peerConnection.setLocalDescription(answer);
311
+ const params = {
312
+ sdp: answer.sdp,
313
+ sessionId: this.id
314
+ };
315
+ // Do not log the SDP payload to avoid logging sensitive information.
316
+ this.logger.info('sending sdp answer', { sessionId: this.id, conversationId: this.conversationId });
317
+ return this.sendGenesysWebrtc({
318
+ jsonrpc: '2.0',
319
+ method: 'answer',
320
+ params
321
+ });
322
+ });
323
+ }
324
+ mute(userId, type) {
325
+ return __awaiter(this, void 0, void 0, function* () {
326
+ const params = {
327
+ sessionId: this.id,
328
+ type
329
+ };
330
+ return this.sendGenesysWebrtc({
331
+ jsonrpc: '2.0',
332
+ method: 'mute',
333
+ params
334
+ });
335
+ });
336
+ }
337
+ unmute(userId, type) {
338
+ return __awaiter(this, void 0, void 0, function* () {
339
+ const params = {
340
+ sessionId: this.id,
341
+ type
342
+ };
343
+ return this.sendGenesysWebrtc({
344
+ jsonrpc: '2.0',
345
+ method: 'unmute',
346
+ params
347
+ });
348
+ });
349
+ }
350
+ /* istanbul ignore next */
351
+ removeTrack() {
352
+ return __awaiter(this, void 0, void 0, function* () {
353
+ throw new Error('Not Implemented');
354
+ });
355
+ }
356
+ /* istanbul ignore next */
357
+ hold() {
358
+ return __awaiter(this, void 0, void 0, function* () {
359
+ throw new Error('Not Implemented');
360
+ });
361
+ }
362
+ /* istanbul ignore next */
363
+ resume() {
364
+ return __awaiter(this, void 0, void 0, function* () {
365
+ throw new Error('Not Implemented');
366
+ });
367
+ }
368
+ toString() {
369
+ return {
370
+ connectionState: this.connectionState,
371
+ state: this.state,
372
+ sessionType: this.sessionType,
373
+ fromJid: this.fromJid,
374
+ conversationId: this.conversationId,
375
+ id: this.id,
376
+ peerConnection: this.peerConnection
377
+ };
378
+ }
379
+ }
@@ -0,0 +1,310 @@
1
+ import { ILogger, LogFormatterFn, LogLevel } from 'genesys-cloud-client-logger';
2
+ import { AxiosError, ResponseType } from 'axios';
3
+ import { NamedAgent } from './named-agent';
4
+ import { JingleReasonCondition } from 'stanza/Constants';
5
+ export { ILogger, LogLevel };
6
+ export interface IClientOptions {
7
+ host: string;
8
+ apiHost?: string;
9
+ authToken?: string;
10
+ jwt?: string;
11
+ jid?: string;
12
+ userId?: string;
13
+ jidResource?: string;
14
+ reconnectOnNoLongerSubscribed?: boolean;
15
+ optOutOfWebrtcStatsTelemetry?: boolean;
16
+ allowIPv6?: boolean;
17
+ logger?: ILogger;
18
+ logLevel?: LogLevel;
19
+ logFormatters?: LogFormatterFn[];
20
+ signalIceConnected?: boolean;
21
+ useServerSidePings?: boolean;
22
+ appName?: string;
23
+ appVersion?: string;
24
+ appId?: string;
25
+ customHeaders?: ICustomHeader;
26
+ /** When true, creates a unique log uploader instance rather than sharing a singleton per URL. */
27
+ useUniqueLogUploader?: boolean;
28
+ /** Allow bulk topic resubscribe to succeed or fail per-topic rather than all or nothing */
29
+ enablePartialBulkResubscribe?: boolean;
30
+ /** Genesys internal use only - non-Genesys apps that pass in `alertableInteractionTypes` may experience unexpected behavior */
31
+ alertableInteractionTypes?: AlertableInteractionTypes[];
32
+ }
33
+ export interface ICustomHeader {
34
+ [header: string]: string;
35
+ }
36
+ export declare enum AlertableInteractionTypes {
37
+ voice = "voice"
38
+ }
39
+ /** The alerting status for an interaction type */
40
+ export interface IAlertingStatus {
41
+ /**
42
+ * Indicates whether this client should be alerting. This can be because this client is the alerting
43
+ * leader for this interaction type, alerting leader functionality is not configured by an admin,
44
+ * or because setup for alerting leader failed and we fallback to `alerting: true` so interactions
45
+ * don't go unnoticed.
46
+ */
47
+ alerting: boolean;
48
+ /**
49
+ * Indicates if alerting leader functionality is configured by an admin. This will also be `false`
50
+ * if setup for alerting leader failed.
51
+ */
52
+ configured: boolean;
53
+ /** A string representing the client type of the alerting leader, based on OAuth client ID. */
54
+ clientType?: string;
55
+ }
56
+ /** The alerting leader status for this client. Currently only `voice` interactions are supported. */
57
+ export interface ILeaderStatus {
58
+ voice?: IAlertingStatus;
59
+ }
60
+ export interface IClientConfig {
61
+ host: string;
62
+ apiHost: string;
63
+ authToken?: string;
64
+ jwt?: string;
65
+ userId?: string;
66
+ jid?: string;
67
+ jidResource?: string;
68
+ channelId: string;
69
+ appName?: string;
70
+ appVersion?: string;
71
+ appId?: string;
72
+ logLevel?: LogLevel;
73
+ customHeaders?: ICustomHeader;
74
+ }
75
+ export interface IHttpClientOptions {
76
+ customHeaders?: ICustomHeader;
77
+ }
78
+ export interface ExtendedRTCIceServer extends RTCIceServer {
79
+ type: string;
80
+ }
81
+ export declare type RequestApiOptions = {
82
+ method: 'get' | 'post' | 'patch' | 'put' | 'delete';
83
+ host: string;
84
+ data?: any;
85
+ version?: string;
86
+ responseType?: ResponseType;
87
+ contentType?: string;
88
+ authToken?: string;
89
+ logger?: any;
90
+ noAuthHeader?: boolean;
91
+ requestTimeout?: number;
92
+ customHeaders?: ICustomHeader;
93
+ maxAttempts?: number;
94
+ signal?: AbortSignal;
95
+ };
96
+ export interface IAxiosResponseError extends AxiosError {
97
+ text: string;
98
+ }
99
+ export interface ISuperagentNetworkError extends Error {
100
+ status: number | undefined;
101
+ method: string;
102
+ url: string;
103
+ crossDomain: boolean;
104
+ }
105
+ export interface ISuperagentResponseError {
106
+ original?: any;
107
+ status: number;
108
+ response: {
109
+ body: any;
110
+ error: ISuperagentNetworkError;
111
+ header: {
112
+ [key: string]: string;
113
+ };
114
+ headers: {
115
+ [key: string]: string;
116
+ };
117
+ status: number;
118
+ statusCode: number;
119
+ statusText: string;
120
+ text: string;
121
+ req: {
122
+ method: string;
123
+ _data?: string;
124
+ };
125
+ };
126
+ }
127
+ export interface INetworkError extends IError {
128
+ status: number;
129
+ method: string;
130
+ url: string;
131
+ crossDomain: boolean;
132
+ }
133
+ export interface IResponseError extends IError {
134
+ status: number;
135
+ correlationId: string;
136
+ responseBody: string;
137
+ method: string;
138
+ requestBody: string;
139
+ url: string;
140
+ }
141
+ export declare enum StreamingClientErrorTypes {
142
+ generic = "generic",
143
+ invalid_token = "invalid_token",
144
+ userCancelled = "user_cancelled"
145
+ }
146
+ export interface IError {
147
+ message: string;
148
+ name: string;
149
+ stack?: string;
150
+ }
151
+ export declare type SessionTypesAsStrings = 'softphone' | 'screenShare' | 'screenRecording' | 'liveScreenMonitoring' | 'collaborateVideo' | 'unknown';
152
+ export declare enum SessionTypes {
153
+ softphone = "softphone",
154
+ collaborateVideo = "collaborateVideo",
155
+ acdScreenShare = "screenShare",
156
+ screenRecording = "screenRecording",
157
+ liveScreenMonitoring = "liveScreenMonitoring",
158
+ unknown = "unknown"
159
+ }
160
+ export interface ISessionInfo extends IPendingSession {
161
+ }
162
+ export interface IPendingSession {
163
+ sessionId: string;
164
+ id: string;
165
+ autoAnswer: boolean;
166
+ toJid: string;
167
+ fromJid: string;
168
+ conversationId: string;
169
+ originalRoomJid?: string;
170
+ sdpOverXmpp?: boolean;
171
+ privAnswerMode?: 'Auto';
172
+ fromUserId?: string;
173
+ roomJid?: string;
174
+ accepted?: boolean;
175
+ meetingId?: string;
176
+ sessionType: SessionTypes | SessionTypesAsStrings;
177
+ }
178
+ export interface StreamingClientExtension {
179
+ handleIq?: Function;
180
+ handleMessage?: Function;
181
+ handleStanzaInstanceChange: (stanzaInstance: NamedAgent) => void;
182
+ expose: any;
183
+ }
184
+ export interface StreamingClientConnectOptions {
185
+ /**
186
+ * @deprecated since version 15.1.1. Please use maxConnectionAttempts instead
187
+ */
188
+ keepTryingOnFailure?: boolean;
189
+ maxConnectionAttempts?: number;
190
+ maxDelayBetweenConnectionAttempts?: number;
191
+ }
192
+ export interface StreamingSubscriptionErrorDetails {
193
+ missingPermissions?: string[];
194
+ }
195
+ export declare type GenesysWebrtcBaseParams = {
196
+ sessionId: string;
197
+ };
198
+ export declare type GenesysWebrtcSdpParams = GenesysWebrtcBaseParams & {
199
+ sdp: string;
200
+ };
201
+ export declare type GenesysWebrtcOfferParams = GenesysWebrtcSdpParams & {
202
+ conversationId: string;
203
+ reinvite?: boolean;
204
+ };
205
+ export declare type GenesysInfoActiveParams = GenesysWebrtcBaseParams & {
206
+ status: 'active';
207
+ };
208
+ export declare type GenesysSessionTerminateParams = GenesysWebrtcBaseParams & {
209
+ reason?: JingleReasonCondition;
210
+ };
211
+ export declare type GenesysWebrtcMuteParams = GenesysWebrtcBaseParams & {
212
+ type: 'audio' | 'video';
213
+ };
214
+ export declare type TypedJsonRpcMessage<Method extends string, Params> = {
215
+ jsonrpc: string;
216
+ method: Method;
217
+ id?: string;
218
+ params?: Params;
219
+ };
220
+ export declare type JsonRpcMessage = TypedJsonRpcMessage<string, any>;
221
+ export declare type GenesysWebrtcOffer = TypedJsonRpcMessage<'offer', GenesysWebrtcOfferParams>;
222
+ export declare type GenesysWebrtcAnswer = TypedJsonRpcMessage<'answer', GenesysWebrtcSdpParams>;
223
+ export declare type GenesysWebrtcInfo = TypedJsonRpcMessage<'info', GenesysInfoActiveParams>;
224
+ export declare type GenesysWebrtcIceCandidate = TypedJsonRpcMessage<'iceCandidate', GenesysWebrtcSdpParams>;
225
+ export declare type GenesysWebrtcTerminate = TypedJsonRpcMessage<'terminate', GenesysSessionTerminateParams>;
226
+ export declare type GenesysWebrtcMute = TypedJsonRpcMessage<'mute', GenesysWebrtcMuteParams>;
227
+ export declare type GenesysWebrtcUnmute = TypedJsonRpcMessage<'unmute', GenesysWebrtcMuteParams>;
228
+ export declare type GenesysWebrtcJsonRpcMessage = GenesysWebrtcOffer | GenesysWebrtcAnswer | GenesysWebrtcInfo | GenesysWebrtcIceCandidate | GenesysWebrtcTerminate | GenesysWebrtcMute | GenesysWebrtcUnmute;
229
+ export declare type HeadsetControlsRequestType = 'mediaHelper' | 'standard' | 'prioritized';
230
+ export declare type HeadsetControlsRejectionReason = 'activeCall' | 'mediaHelper' | 'priority';
231
+ export declare type HeadsetControlsRejectionParams = {
232
+ requestId: string;
233
+ reason: HeadsetControlsRejectionReason;
234
+ };
235
+ export declare type HeadsetControlsChangedParams = {
236
+ hasControls: boolean;
237
+ };
238
+ export declare type HeadsetControlsRequest = TypedJsonRpcMessage<'headsetControlsRequest', {
239
+ requestType: HeadsetControlsRequestType;
240
+ }>;
241
+ export declare type HeadsetControlsRejection = TypedJsonRpcMessage<'headsetControlsRejection', HeadsetControlsRejectionParams>;
242
+ export declare type HeadsetControlsChanged = TypedJsonRpcMessage<'headsetControlsChanged', HeadsetControlsChangedParams>;
243
+ export declare type GenesysMediaMessage = HeadsetControlsRequest | HeadsetControlsRejection | HeadsetControlsChanged;
244
+ export declare type FlatObject = {
245
+ [key: string]: string | number | boolean | null | Date;
246
+ };
247
+ export declare type GenericAction = {
248
+ _eventType: string;
249
+ };
250
+ export declare type InsightReport = {
251
+ appName: string;
252
+ appVersion: string;
253
+ originAppName?: string;
254
+ originAppVersion?: string;
255
+ actions: InsightAction<any>[];
256
+ };
257
+ export declare type InsightAction<T extends {
258
+ _eventType: string;
259
+ }> = {
260
+ actionName: 'WebrtcStats';
261
+ details: InsightActionDetails<T>;
262
+ };
263
+ export declare type InsightActionDetails<K extends {
264
+ _eventType: string;
265
+ }> = {
266
+ _eventType: K['_eventType'];
267
+ /**
268
+ * This should be ms since epoch, e.g. new Date().getTime()
269
+ */
270
+ _eventTimestamp: number;
271
+ _appId?: string;
272
+ _appName?: string;
273
+ _appVersion?: string;
274
+ } & K;
275
+ export declare type OnlineStatusStat = InsightAction<{
276
+ _eventType: 'onlineStatus';
277
+ online: boolean;
278
+ }>;
279
+ export declare type FirstProposeStat = InsightAction<{
280
+ _eventType: 'firstPropose';
281
+ sdpViaXmppRequested: boolean;
282
+ sessionType: SessionTypesAsStrings;
283
+ originAppId?: string;
284
+ conversationId: string;
285
+ sessionId: string;
286
+ }>;
287
+ export declare type FirstAlertingConversationStat = InsightAction<{
288
+ _eventType: 'firstAlertingConversationUpdate';
289
+ conversationId: string;
290
+ participantId: string;
291
+ }>;
292
+ export declare type MediaStat = InsightAction<{
293
+ _eventType: 'mediaRequested' | 'mediaStarted' | 'mediaError';
294
+ requestId?: string;
295
+ message?: string;
296
+ audioRequested: boolean;
297
+ videoRequested: boolean;
298
+ displayRequested: boolean;
299
+ conversationId?: string;
300
+ sessionType?: SessionTypesAsStrings;
301
+ sessionId?: string;
302
+ elapsedMsFromInitialRequest?: number;
303
+ }>;
304
+ export declare type NRProxyStat = FirstAlertingConversationStat | MediaStat;
305
+ export declare type SCConnectionData = {
306
+ currentDelayMs: number;
307
+ delayMsAfterNextReduction?: number;
308
+ nextDelayReductionTime?: number;
309
+ timeOfTotalReset?: number;
310
+ };