skapi-js 1.0.187-beta.4 → 1.0.188-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.
@@ -1,4 +1,5 @@
1
1
  import { SkapiError } from "../Main";
2
+ import { extractFormData } from "../utils/utils";
2
3
  import validator from "../utils/validator";
3
4
  export const __peerConnection = {};
4
5
  export const __dataChannel = {};
@@ -13,51 +14,62 @@ function setBuffer(buffer, recipient, item) {
13
14
  }
14
15
  buffer[recipient].push(item);
15
16
  }
16
- function processBuffer(buffer, recipient, fn) {
17
+ async function processBuffer(buffer, recipient, fn) {
17
18
  let proceed = [];
18
19
  if (buffer[recipient]) {
19
- buffer[recipient].forEach(v => {
20
- if (v)
21
- proceed.push(fn(v));
22
- });
20
+ for (let v of buffer[recipient]) {
21
+ if (v) {
22
+ let process = fn(v);
23
+ if (process instanceof Promise) {
24
+ process = await process;
25
+ }
26
+ proceed.push(process);
27
+ }
28
+ }
29
+ ;
23
30
  delete buffer[recipient];
24
31
  }
25
32
  return proceed;
26
33
  }
27
34
  export async function answerSdpOffer(offer, recipient) {
28
- this.log('answerSdpOffer', offer);
29
35
  if (!this?.session?.accessToken?.jwtToken) {
30
36
  throw new SkapiError('Access token is required.', { code: 'INVALID_PARAMETER' });
31
37
  }
32
38
  let socket = await this.__socket;
39
+ async function sendAnswer(offer, recipient, socket) {
40
+ this.log('answerSdpOffer from', recipient);
41
+ await __peerConnection[recipient].setRemoteDescription(new RTCSessionDescription(offer));
42
+ const answer = await __peerConnection[recipient].createAnswer();
43
+ await __peerConnection[recipient].setLocalDescription(answer);
44
+ socket.send(JSON.stringify({
45
+ action: 'rtc',
46
+ uid: recipient,
47
+ content: { sdpanswer: answer },
48
+ token: this.session.accessToken.jwtToken
49
+ }));
50
+ }
33
51
  if (__peerConnection?.[recipient]) {
34
52
  if (!offer) {
35
- return processBuffer(__rtcSdpOfferBuffer, recipient, (offer) => answerSdpOffer.bind(this)(offer, recipient));
53
+ await processBuffer(__rtcSdpOfferBuffer, recipient, (offer) => sendAnswer.bind(this)(offer, recipient, socket));
54
+ }
55
+ else {
56
+ await processBuffer(__rtcSdpOfferBuffer, recipient, (offer) => sendAnswer.bind(this)(offer, recipient, socket));
57
+ await sendAnswer.bind(this)(offer, recipient, socket);
36
58
  }
37
59
  }
38
60
  else {
39
61
  if (offer) {
40
- return setBuffer(__rtcSdpOfferBuffer, recipient, offer);
62
+ setBuffer(__rtcSdpOfferBuffer, recipient, offer);
41
63
  }
42
64
  }
43
- await Promise.all(processBuffer(__rtcSdpOfferBuffer, recipient, (offer) => answerSdpOffer.bind(this)(offer, recipient)));
44
- await __peerConnection[recipient].setRemoteDescription(new RTCSessionDescription(offer));
45
- const answer = await __peerConnection[recipient].createAnswer();
46
- await __peerConnection[recipient].setLocalDescription(answer);
47
- socket.send(JSON.stringify({
48
- action: 'rtc',
49
- uid: recipient,
50
- content: { sdpanswer: answer },
51
- token: this.session.accessToken.jwtToken
52
- }));
53
65
  }
54
66
  export async function receiveIceCandidate(candidate, recipient) {
55
67
  this.log('receiveIceCandidate', candidate);
56
68
  if (__peerConnection?.[recipient] && __peerConnection[recipient]?.remoteDescription && __peerConnection[recipient]?.remoteDescription?.type) {
57
69
  if (!candidate) {
58
- return processBuffer(__rtcCandidatesBuffer, recipient, (candidate) => receiveIceCandidate.bind(this)(candidate, recipient));
70
+ return processBuffer(__rtcCandidatesBuffer, recipient, (candidate) => __peerConnection[recipient].addIceCandidate(candidate));
59
71
  }
60
- await Promise.all(processBuffer(__rtcCandidatesBuffer, recipient, (candidate) => receiveIceCandidate.bind(this)(candidate, recipient)));
72
+ await processBuffer(__rtcCandidatesBuffer, recipient, (candidate) => __peerConnection[recipient].addIceCandidate(candidate));
61
73
  await __peerConnection[recipient].addIceCandidate(candidate);
62
74
  }
63
75
  else {
@@ -66,81 +78,93 @@ export async function receiveIceCandidate(candidate, recipient) {
66
78
  }
67
79
  export async function closeRTC(params) {
68
80
  validator.Params(params, {
69
- recipient: v => validator.UserId(v),
81
+ cid: v => {
82
+ if (v && typeof v !== 'string') {
83
+ throw new SkapiError(`"cid" should be type: <string>.`, { code: 'INVALID_PARAMETER' });
84
+ }
85
+ if (v && v.slice(0, 4) !== 'cid:') {
86
+ throw new SkapiError(`"cid" should be a valid connection id.`, { code: 'INVALID_PARAMETER' });
87
+ }
88
+ return v;
89
+ },
70
90
  close: 'boolean'
71
91
  });
72
92
  let socket = await this.__socket;
73
- let { recipient, closeAll = false } = params || {};
74
- if (!closeAll && !recipient) {
75
- throw new SkapiError(`"recipient" is required.`, { code: 'INVALID_PARAMETER' });
93
+ let { cid, close_all = false } = params || {};
94
+ if (!close_all && !cid) {
95
+ throw new SkapiError(`"cid" is required.`, { code: 'INVALID_PARAMETER' });
76
96
  }
77
- function close(recipient) {
78
- if (!recipient) {
79
- throw new SkapiError(`"recipient" is required.`, { code: 'INVALID_PARAMETER' });
97
+ let close = (cid) => {
98
+ if (!cid) {
99
+ throw new SkapiError(`"cid" is required.`, { code: 'INVALID_PARAMETER' });
80
100
  }
81
- delete __rtcSdpOfferBuffer[recipient];
82
- delete __rtcCandidatesBuffer[recipient];
83
- if (__dataChannel[recipient]) {
84
- Object.values(__dataChannel[recipient]).forEach(channel => {
101
+ delete __rtcSdpOfferBuffer[cid];
102
+ delete __rtcCandidatesBuffer[cid];
103
+ if (__dataChannel[cid]) {
104
+ Object.values(__dataChannel[cid]).forEach(channel => {
85
105
  if (channel.readyState !== 'closed') {
86
106
  channel.close();
87
107
  }
88
108
  });
89
- delete __dataChannel[recipient];
90
109
  }
91
- if (__peerConnection?.[recipient]) {
92
- if (__peerConnection[recipient].connectionState !== 'closed') {
93
- __peerConnection[recipient].close();
110
+ delete __dataChannel[cid];
111
+ if (__peerConnection?.[cid]) {
112
+ if (__peerConnection[cid].connectionState !== 'closed') {
113
+ __peerConnection[cid].close();
94
114
  socket.send(JSON.stringify({
95
115
  action: 'rtc',
96
- uid: recipient,
116
+ uid: cid,
97
117
  content: { hungup: this.user.user_id },
98
118
  token: this.session.accessToken.jwtToken
99
119
  }));
100
120
  }
101
121
  let msg = {
102
122
  type: 'connectionstatechange',
103
- target: __peerConnection[recipient],
123
+ target: __peerConnection[cid],
104
124
  timestamp: new Date().toISOString(),
105
- state: __peerConnection[recipient].connectionState,
106
- iceState: __peerConnection[recipient].iceConnectionState,
107
- signalingState: __peerConnection[recipient].signalingState
125
+ state: __peerConnection[cid].connectionState,
126
+ iceState: __peerConnection[cid].iceConnectionState,
127
+ signalingState: __peerConnection[cid].signalingState
108
128
  };
109
- if (__rtcCallbacks[recipient]) {
110
- __rtcCallbacks[recipient](msg);
129
+ if (__rtcCallbacks[cid]) {
130
+ __rtcCallbacks[cid](msg);
111
131
  }
112
- delete __rtcCallbacks[recipient];
113
- delete __receiver_ringing[recipient];
114
- delete __caller_ringing[recipient];
115
132
  this.log('closeRTC', msg);
116
133
  }
117
- delete __peerConnection[recipient];
118
- }
119
- if (closeAll) {
134
+ delete __rtcCallbacks[cid];
135
+ delete __receiver_ringing[cid];
136
+ delete __caller_ringing[cid];
137
+ delete __peerConnection[cid];
138
+ };
139
+ if (close_all) {
120
140
  for (let key in __peerConnection) {
121
- close.bind(this)(key);
141
+ close(key);
122
142
  }
123
143
  }
124
144
  else {
125
- close.bind(this)(recipient);
145
+ close(cid);
126
146
  }
127
147
  }
128
148
  export async function connectRTC(params, callback) {
129
149
  if (typeof callback !== 'function') {
130
150
  throw new SkapiError(`Callback is required.`, { code: 'INVALID_PARAMETER' });
131
151
  }
132
- let socket = this.__socket ? await this.__socket : this.__socket;
133
- if (!socket) {
134
- throw new SkapiError(`No realtime connection. Execute connectRealtime() before this method.`, { code: 'INVALID_REQUEST' });
135
- }
136
152
  if (!this?.session?.accessToken?.jwtToken) {
137
153
  throw new SkapiError('Access token is required.', { code: 'INVALID_PARAMETER' });
138
154
  }
139
155
  params = validator.Params(params, {
140
- recipient: 'string',
156
+ cid: v => {
157
+ if (typeof v !== 'string') {
158
+ throw new SkapiError(`"cid" should be type: <string>.`, { code: 'INVALID_PARAMETER' });
159
+ }
160
+ if (v.slice(0, 4) !== 'cid:') {
161
+ throw new SkapiError(`"cid" should be a valid connection id.`, { code: 'INVALID_PARAMETER' });
162
+ }
163
+ return v;
164
+ },
141
165
  ice: ['string', () => 'stun:stun.skapi.com:3468'],
142
- mediaStream: v => v,
143
- dataChannelSettings: ['text-chat', 'file-transfer', 'video-chat', 'voice-chat', {
166
+ media: v => v,
167
+ channels: ['text-chat', 'file-transfer', 'video-chat', 'voice-chat', 'gaming', {
144
168
  ordered: 'boolean',
145
169
  maxPacketLifeTime: 'number',
146
170
  maxRetransmits: 'number',
@@ -148,142 +172,140 @@ export async function connectRTC(params, callback) {
148
172
  }, () => {
149
173
  return [{ ordered: true, maxPacketLifeTime: 10, protocol: 'default' }];
150
174
  }]
151
- }, ['recipient']);
152
- let { recipient, ice } = params;
153
- if (!(params?.mediaStream instanceof MediaStream)) {
154
- if (params?.mediaStream?.video || params?.mediaStream?.audio) {
175
+ }, ['cid']);
176
+ let { cid, ice } = params;
177
+ if (!(params?.media instanceof MediaStream)) {
178
+ if (params?.media?.video || params?.media?.audio) {
155
179
  if (location.hostname !== 'localhost' && location.protocol !== 'https:') {
156
180
  throw new SkapiError(`Media stream is only supported on either localhost or https.`, { code: 'INVALID_REQUEST' });
157
181
  }
158
182
  }
159
183
  }
160
- if (socket.readyState === 1) {
161
- const configuration = {
162
- iceServers: [
163
- { urls: ice }
164
- ]
165
- };
166
- if (!__peerConnection?.[recipient]) {
167
- __peerConnection[recipient] = new RTCPeerConnection(configuration);
184
+ let socket = this.__socket ? await this.__socket : this.__socket;
185
+ if (!socket) {
186
+ throw new SkapiError(`No realtime connection. Execute connectRealtime() before this method.`, { code: 'INVALID_REQUEST' });
187
+ }
188
+ if (socket.readyState !== 1) {
189
+ throw new SkapiError('Realtime connection is not ready.', { code: 'INVALID_REQUEST' });
190
+ }
191
+ const configuration = {
192
+ iceServers: [
193
+ { urls: ice }
194
+ ]
195
+ };
196
+ if (!__peerConnection?.[cid]) {
197
+ __peerConnection[cid] = new RTCPeerConnection(configuration);
198
+ }
199
+ if (params?.media) {
200
+ if (params?.media instanceof MediaStream || this.__mediaStream) {
201
+ this.__mediaStream = this.__mediaStream || params.media;
168
202
  }
169
- if (params?.mediaStream) {
170
- if (params?.mediaStream instanceof MediaStream) {
171
- this.__mediaStream = params.mediaStream;
172
- }
173
- else {
174
- if (params?.mediaStream?.video || params?.mediaStream?.audio) {
175
- this.__mediaStream = await navigator.mediaDevices.getUserMedia({
176
- video: params?.mediaStream?.video,
177
- audio: params?.mediaStream?.audio
178
- });
179
- }
180
- }
181
- if (this.__mediaStream)
182
- this.__mediaStream.getTracks().forEach(track => {
183
- __peerConnection[recipient].addTrack(track, this.__mediaStream);
203
+ else {
204
+ if (params?.media?.video || params?.media?.audio) {
205
+ this.__mediaStream = await navigator.mediaDevices.getUserMedia({
206
+ video: params?.media?.video,
207
+ audio: params?.media?.audio
184
208
  });
185
- }
186
- __rtcCallbacks[recipient] = callback;
187
- if (!__dataChannel[recipient]) {
188
- __dataChannel[recipient] = {};
189
- }
190
- for (let i = 0; i < params.dataChannelSettings.length; i++) {
191
- let options = params.dataChannelSettings[i];
192
- if (typeof options === 'string') {
193
- switch (options) {
194
- case 'text-chat':
195
- options = { ordered: true, maxRetransmits: 10, protocol: 'text-chat' };
196
- break;
197
- case 'file-transfer':
198
- options = { ordered: false, maxPacketLifeTime: 3000, protocol: 'file-transfer' };
199
- break;
200
- case 'video-chat':
201
- options = { ordered: true, maxPacketLifeTime: 10, protocol: 'video-chat' };
202
- break;
203
- case 'voice-chat':
204
- options = { ordered: true, maxPacketLifeTime: 10, protocol: 'voice-chat' };
205
- break;
206
- default:
207
- options = { ordered: true, maxRetransmits: 10, protocol: 'default' };
208
- break;
209
- }
210
209
  }
211
- let protocol = params.dataChannelSettings[i].protocol || 'default';
212
- if (Object.keys(__dataChannel[recipient]).includes(protocol)) {
213
- throw new SkapiError(`Data channel with the protocol "${protocol}" already exists.`, { code: 'INVALID_REQUEST' });
210
+ }
211
+ if (this.__mediaStream)
212
+ this.__mediaStream.getTracks().forEach(track => {
213
+ __peerConnection[cid].addTrack(track, this.__mediaStream);
214
+ });
215
+ }
216
+ __rtcCallbacks[cid] = callback;
217
+ if (!__dataChannel[cid]) {
218
+ __dataChannel[cid] = {};
219
+ }
220
+ for (let i = 0; i < params.channels.length; i++) {
221
+ let options = params.channels[i];
222
+ if (typeof options === 'string') {
223
+ switch (options) {
224
+ case 'text-chat':
225
+ options = { ordered: true, maxRetransmits: 10, protocol: 'text-chat' };
226
+ break;
227
+ case 'file-transfer':
228
+ options = { ordered: false, maxPacketLifeTime: 3000, protocol: 'file-transfer' };
229
+ break;
230
+ case 'video-chat':
231
+ options = { ordered: true, maxRetransmits: 10, protocol: 'video-chat' };
232
+ break;
233
+ case 'voice-chat':
234
+ options = { ordered: true, maxRetransmits: 10, protocol: 'voice-chat' };
235
+ break;
236
+ case 'gaming':
237
+ options = { ordered: false, maxPacketLifeTime: 100, protocol: 'gaming' };
238
+ break;
239
+ default:
240
+ options = { ordered: true, maxRetransmits: 10, protocol: 'default' };
241
+ break;
214
242
  }
215
- let dataChannel = __peerConnection[recipient].createDataChannel(protocol, options);
216
- __dataChannel[recipient][protocol] = dataChannel;
217
243
  }
218
- for (let key in __dataChannel[recipient]) {
219
- let dataChannel = __dataChannel[recipient][key];
220
- handleDataChannel.bind(this)(recipient, dataChannel);
244
+ let protocol = options.protocol || 'default';
245
+ if (Object.keys(__dataChannel[cid]).includes(protocol)) {
246
+ throw new SkapiError(`Data channel with the protocol "${protocol}" already exists.`, { code: 'INVALID_REQUEST' });
221
247
  }
222
- peerConnectionHandler.bind(this)(recipient, ['onnegotiationneeded']);
223
- await sendOffer.bind(this)(recipient);
224
- return new Promise((resolve, reject) => {
225
- __caller_ringing[recipient] = ((proceed) => {
226
- this.log('receiver picked up the call', recipient);
248
+ let dataChannel = __peerConnection[cid].createDataChannel(protocol, options);
249
+ __dataChannel[cid][protocol] = dataChannel;
250
+ }
251
+ for (let key in __dataChannel[cid]) {
252
+ let dataChannel = __dataChannel[cid][key];
253
+ handleDataChannel.bind(this)(cid, dataChannel);
254
+ }
255
+ peerConnectionHandler.bind(this)(cid, ['onnegotiationneeded']);
256
+ await sendOffer.bind(this)(cid);
257
+ return {
258
+ hangup: () => __caller_ringing[cid] && __caller_ringing[cid](false),
259
+ connection: new Promise(resolve => {
260
+ __caller_ringing[cid] = ((proceed) => {
261
+ this.log('receiver picked up the call', cid);
227
262
  if (!proceed) {
228
- resolve(null);
229
- return;
263
+ closeRTC.bind(this)({ cid: cid });
264
+ return null;
230
265
  }
231
- __peerConnection[recipient].onnegotiationneeded = (() => {
232
- sendOffer.bind(this)(recipient);
233
- if (__rtcCallbacks[recipient])
234
- __rtcCallbacks[recipient]({
266
+ __peerConnection[cid].onnegotiationneeded = () => {
267
+ this.log('onnegotiationneeded', `Sending offer to "${cid}".`);
268
+ sendOffer.bind(this)(cid);
269
+ if (__rtcCallbacks[cid])
270
+ __rtcCallbacks[cid]({
235
271
  type: 'negotiationneeded',
236
- target: __peerConnection[recipient],
272
+ target: __peerConnection[cid],
237
273
  timestamp: new Date().toISOString(),
238
- signalingState: __peerConnection[recipient].signalingState,
239
- connectionState: __peerConnection[recipient].iceConnectionState,
240
- gatheringState: __peerConnection[recipient].iceGatheringState
274
+ signalingState: __peerConnection[cid].signalingState,
275
+ connectionState: __peerConnection[cid].iceConnectionState,
276
+ gatheringState: __peerConnection[cid].iceGatheringState
241
277
  });
242
- }).bind(this);
278
+ };
243
279
  resolve({
244
- target: __peerConnection[recipient],
245
- dataChannel: __dataChannel[recipient],
246
- hangup: (() => {
247
- closeRTC.bind(this)({ recipient });
248
- }).bind(this),
249
- mediaStream: this.__mediaStream
280
+ target: __peerConnection[cid],
281
+ channels: __dataChannel[cid],
282
+ hangup: () => closeRTC.bind(this)({ cid: cid }),
283
+ media: this.__mediaStream
250
284
  });
251
285
  }).bind(this);
252
- ;
253
- });
254
- }
255
- else {
256
- throw new SkapiError('Realtime connection is not ready.', { code: 'INVALID_REQUEST' });
257
- }
286
+ })
287
+ };
258
288
  }
259
289
  export function respondRTC(msg) {
260
290
  return async (params, callback) => {
261
- let rtc = msg.message;
262
- let sender = msg.sender;
291
+ params = params || {};
292
+ params = extractFormData(params).data;
293
+ let sender = msg.sender_cid;
294
+ let socket = await this.__socket;
263
295
  if (!__receiver_ringing[sender]) {
264
296
  return null;
265
297
  }
266
298
  if (typeof callback !== 'function') {
267
299
  throw new SkapiError(`Callback is required.`, { code: 'INVALID_PARAMETER' });
268
300
  }
269
- if (!(params?.mediaStream instanceof MediaStream)) {
270
- if (params?.mediaStream?.video || params?.mediaStream?.audio) {
301
+ if (!(params?.media instanceof MediaStream)) {
302
+ if (params?.media?.video || params?.media?.audio) {
271
303
  if (location.hostname !== 'localhost' && location.protocol !== 'https:') {
272
304
  throw new SkapiError(`Media stream is only supported on either localhost or https.`, { code: 'INVALID_REQUEST' });
273
305
  }
274
306
  }
275
307
  }
276
- let socket = await this.__socket;
277
- if (params?.hangup) {
278
- socket.send(JSON.stringify({
279
- action: 'rtc',
280
- uid: sender,
281
- content: { hungup: this.user.user_id },
282
- token: this.session.accessToken.jwtToken
283
- }));
284
- return null;
285
- }
286
- let { ice = 'stun:stun.skapi.com:3468' } = params || {};
308
+ let { ice = 'stun:stun.skapi.com:3468' } = params;
287
309
  if (!__peerConnection?.[sender]) {
288
310
  __peerConnection[sender] = new RTCPeerConnection({
289
311
  iceServers: [
@@ -291,15 +313,15 @@ export function respondRTC(msg) {
291
313
  ]
292
314
  });
293
315
  }
294
- if (params?.mediaStream) {
295
- if (params?.mediaStream instanceof MediaStream) {
296
- this.__mediaStream = params.mediaStream;
316
+ if (params?.media) {
317
+ if (params?.media instanceof MediaStream || this.__mediaStream) {
318
+ this.__mediaStream = this.__mediaStream || params.media;
297
319
  }
298
320
  else {
299
- if (params?.mediaStream?.video || params?.mediaStream?.audio)
321
+ if (params?.media?.video || params?.media?.audio)
300
322
  this.__mediaStream = await navigator.mediaDevices.getUserMedia({
301
- video: params?.mediaStream?.video,
302
- audio: params?.mediaStream?.audio
323
+ video: params?.media?.video,
324
+ audio: params?.media?.audio
303
325
  });
304
326
  }
305
327
  if (this.__mediaStream)
@@ -319,8 +341,8 @@ export function respondRTC(msg) {
319
341
  handleDataChannel.bind(this)(sender, dataChannel);
320
342
  };
321
343
  peerConnectionHandler.bind(this)(sender, ['onnegotiationneeded']);
322
- await answerSdpOffer.bind(this)(rtc?.sdpoffer, sender);
323
- await receiveIceCandidate.bind(this)(rtc?.candidate, sender);
344
+ await answerSdpOffer.bind(this)(null, sender);
345
+ await receiveIceCandidate.bind(this)(null, sender);
324
346
  socket.send(JSON.stringify({
325
347
  action: 'rtc',
326
348
  uid: sender,
@@ -329,11 +351,9 @@ export function respondRTC(msg) {
329
351
  }));
330
352
  return {
331
353
  target: __peerConnection[sender],
332
- dataChannel: __dataChannel[sender],
333
- hangup: (() => {
334
- closeRTC.bind(this)({ recipient: sender });
335
- }).bind(this),
336
- mediaStream: this.__mediaStream
354
+ channels: __dataChannel[sender],
355
+ hangup: () => closeRTC.bind(this)({ cid: sender }),
356
+ media: this.__mediaStream
337
357
  };
338
358
  };
339
359
  }
@@ -341,12 +361,12 @@ async function sendOffer(recipient) {
341
361
  if (!this?.session?.accessToken?.jwtToken) {
342
362
  throw new SkapiError('Access token is required.', { code: 'INVALID_PARAMETER' });
343
363
  }
364
+ this.log('sendOffer', recipient);
344
365
  let socket = await this.__socket;
345
366
  const offer = await __peerConnection[recipient].createOffer();
346
367
  await __peerConnection[recipient].setLocalDescription(offer);
347
368
  let sdpoffer = __peerConnection[recipient].localDescription;
348
- this.log('rtcSdpOffer', sdpoffer);
349
- validator.UserId(recipient);
369
+ this.log('rtcSdpOffer to:', sdpoffer);
350
370
  socket.send(JSON.stringify({
351
371
  action: 'rtc',
352
372
  uid: recipient,
@@ -355,10 +375,10 @@ async function sendOffer(recipient) {
355
375
  }));
356
376
  }
357
377
  async function sendIceCandidate(event, recipient) {
358
- if (this?.session?.accessToken?.jwtToken) {
378
+ if (!this?.session?.accessToken?.jwtToken) {
359
379
  throw new SkapiError('Access token is required.', { code: 'INVALID_PARAMETER' });
360
380
  }
361
- validator.UserId(recipient);
381
+ this.log('sendIceCandidate to:', recipient);
362
382
  let socket = await this.__socket;
363
383
  if (!event.candidate) {
364
384
  this.log('candidate-end', 'All ICE candidates have been sent');
@@ -485,13 +505,13 @@ function peerConnectionHandler(key, skipKey) {
485
505
  });
486
506
  let state = peer.connectionState;
487
507
  if (state === 'disconnected' || state === 'failed' || state === 'closed') {
488
- closeRTC.bind(this)({ recipient: key });
508
+ closeRTC.bind(this)({ cid: key });
489
509
  }
490
510
  }
491
511
  };
492
512
  for (const [event, handler] of Object.entries(handlers)) {
493
513
  if (!skip.has(event)) {
494
- peer[event] = handler.bind(this);
514
+ peer[event] = handler;
495
515
  }
496
516
  }
497
517
  }
@@ -540,7 +560,7 @@ function handleDataChannel(key, dataChannel, skipKey) {
540
560
  if (__dataChannel[key]) {
541
561
  delete __dataChannel[key][dataChannel.label];
542
562
  if (Object.keys(__dataChannel[key]).length === 0) {
543
- closeRTC.bind(this)({ recipient: key });
563
+ closeRTC.bind(this)({ cid: key });
544
564
  }
545
565
  }
546
566
  },
@@ -573,7 +593,7 @@ function handleDataChannel(key, dataChannel, skipKey) {
573
593
  };
574
594
  for (const [event, handler] of Object.entries(events)) {
575
595
  if (!skip.has(event)) {
576
- dataChannel[event] = handler.bind(this);
596
+ dataChannel[event] = handler;
577
597
  }
578
598
  }
579
599
  }