@flashphoner/sfusdk 1.0.41 → 1.0.43

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.
package/src/sdk/room.js CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  const { v4: uuidv4 } = require("uuid");
7
7
  const constants = require("./constants");
8
+ const promises = require("./promise");
9
+ const logger = require("./logger");
8
10
 
9
11
  const room = function(options) {
10
12
  if (!options) {
@@ -25,16 +27,16 @@ const room = function(options) {
25
27
  //data channel
26
28
  const dChannel = options.pc.createDataChannel("control");
27
29
  dChannel.onopen = function() {
28
- console.log("DataChannel opened");
30
+ logger.log("DataChannel opened");
29
31
  };
30
32
  dChannel.onclose = function() {
31
- console.log("DataChannel closed");
33
+ logger.log("DataChannel closed");
32
34
  };
33
35
  dChannel.onerror = function(e) {
34
36
  //console.error("Got error in data channel ", e);
35
37
  };
36
38
  dChannel.onmessage = function(msg) {
37
- console.log("received message: " + msg.data);
39
+ logger.log("dchannel ", "<==", msg);
38
40
  const message = JSON.parse(msg.data);
39
41
  if (message.type === constants.SFU_ROOM_EVENT.MESSAGE && message.message.message.indexOf("\"payload\":") !== -1) {
40
42
  try {
@@ -56,35 +58,67 @@ const room = function(options) {
56
58
  window.log.info("Failed to process inner message: " + message.message);
57
59
  notify(message.type, message.message);
58
60
  }
61
+ } else if (message.type === constants.SFU_EVENT.ACK && promises.promised(message.internalMessageId)) {
62
+ promises.resolve(message.internalMessageId);
59
63
  } else {
60
64
  notify(message.type, message.message);
61
65
  }
62
66
  };
63
67
 
68
+ const dChannelSend = (msg) => {
69
+ logger.log("dchannel ", "==>", msg);
70
+ dChannel.send(msg);
71
+ };
72
+
64
73
  const processEvent = function(e) {
74
+ logger.log("<==", e);
65
75
  if (e.type === constants.SFU_ROOM_EVENT.REMOTE_SDP) {
66
- switch (e.info.type) {
67
- case "offer":
68
- pc.setRemoteDescription(e.info).then(() => pc.createAnswer())
69
- .then(answer => pc.setLocalDescription(answer))
70
- .then(() => {
71
- connection.send(constants.SFU_INTERNAL_API.UPDATE_ROOM_STATE, {
72
- name: name,
73
- pin: pin,
74
- sdp: pc.localDescription.sdp
76
+ if (state !== constants.SFU_ROOM_STATE.FAILED && state !== constants.SFU_ROOM_STATE.DISPOSED) {
77
+ switch (e.info.type) {
78
+ case "offer":
79
+ pc.setRemoteDescription(e.info).then(() => pc.createAnswer())
80
+ .then(answer => pc.setLocalDescription(answer))
81
+ .then(() => {
82
+ connection.send(constants.SFU_INTERNAL_API.UPDATE_ROOM_STATE, {
83
+ name: name,
84
+ pin: pin,
85
+ sdp: pc.localDescription.sdp
86
+ });
75
87
  });
76
- });
77
- break;
78
- case "answer":
79
- pc.setRemoteDescription(e.info);
80
- break;
88
+ break;
89
+ case "answer":
90
+ pc.setRemoteDescription(e.info);
91
+ break;
92
+ }
81
93
  }
82
94
  } else if (e.type === constants.SFU_ROOM_EVENT.ROLE_ASSIGNED) {
83
95
  role = e.role;
84
96
  notify(e.type, e);
85
97
  } else if (e.type === constants.SFU_ROOM_EVENT.CREATED) {
86
98
  inviteId = e.inviteId;
87
- notify(e.type, e);
99
+ if (!promises.resolve(e.internalMessageId, e)) {
100
+ notify(e.type, e);
101
+ }
102
+ } else if (e.type === constants.SFU_ROOM_EVENT.OPERATION_FAILED && promises.promised(e.internalMessageId)) {
103
+ promises.reject(e.internalMessageId, e);
104
+ } else if (e.type === constants.SFU_ROOM_EVENT.JOINED) {
105
+ if (!promises.resolve(e.internalMessageId, e)) {
106
+ notify(e.type, e);
107
+ }
108
+ } else if (e.type === constants.SFU_ROOM_EVENT.LEFT) {
109
+ if (!promises.resolve(e.internalMessageId, e)) {
110
+ notify(e.type, e);
111
+ }
112
+ } else if (e.type === constants.SFU_ROOM_EVENT.ADD_TRACKS) {
113
+ if (!promises.resolve(e.internalMessageId, e.info)) {
114
+ notify(e.type, e);
115
+ }
116
+ } else if (e.type === constants.SFU_ROOM_EVENT.REMOVE_TRACKS) {
117
+ if (!promises.resolve(e.internalMessageId, e)) {
118
+ notify(e.type, e);
119
+ }
120
+ } else if (e.type === constants.SFU_EVENT.ACK && promises.promised(e.internalMessageId)) {
121
+ promises.resolve(e.internalMessageId);
88
122
  } else {
89
123
  notify(e.type, e);
90
124
  }
@@ -94,9 +128,14 @@ const room = function(options) {
94
128
  * Create room at server side.
95
129
  */
96
130
  const createRoom = function() {
97
- connection.send(constants.SFU_INTERNAL_API.CREATE_ROOM, {
98
- name: name,
99
- pin: pin
131
+ return new Promise((resolve, reject) => {
132
+ const id = uuidv4();
133
+ promises.add(id, resolve, reject);
134
+ connection.send(constants.SFU_INTERNAL_API.CREATE_ROOM, {
135
+ name: name,
136
+ pin: pin,
137
+ internalMessageId: id
138
+ });
100
139
  });
101
140
  };
102
141
 
@@ -107,21 +146,28 @@ const room = function(options) {
107
146
  * @memberOf FlashphonerSFU.Room
108
147
  */
109
148
  const join = function(config) {
110
- if (state === constants.SFU_ROOM_STATE.NEW) {
111
- state = constants.SFU_ROOM_STATE.JOINED;
112
- pc.createOffer().then(function(offer) {
113
- if (config) {
114
- offer.sdp = applyContentTypeConfig(offer.sdp, config);
115
- }
116
- pc.setLocalDescription(offer).then(function() {
117
- connection.send(constants.SFU_INTERNAL_API.JOIN_ROOM, {
118
- name: name,
119
- pin: pin,
120
- sdp: offer.sdp
121
- });
122
- });
123
- });
124
- }
149
+ return new Promise((resolve, reject) => {
150
+ if (state === constants.SFU_ROOM_STATE.NEW) {
151
+ state = constants.SFU_ROOM_STATE.JOINED;
152
+ pc.createOffer().then(function (offer) {
153
+ if (config) {
154
+ offer.sdp = applyContentTypeConfig(offer.sdp, config);
155
+ }
156
+ pc.setLocalDescription(offer).then(function () {
157
+ const id = uuidv4();
158
+ promises.add(id, resolve, reject);
159
+ connection.send(constants.SFU_INTERNAL_API.JOIN_ROOM, {
160
+ name: name,
161
+ pin: pin,
162
+ sdp: offer.sdp,
163
+ internalMessageId: id
164
+ });
165
+ }, reject);
166
+ }, reject);
167
+ } else {
168
+ reject("Can't joined room with state " + state);
169
+ }
170
+ });
125
171
  };
126
172
 
127
173
  /**
@@ -133,21 +179,27 @@ const room = function(options) {
133
179
  * @memberOf FlashphonerSFU.Room
134
180
  */
135
181
  const updateState = function(config) {
136
- if (pc.signalingState !== "stable") {
137
- throw new Error("Peer connection signaling state is " + pc.signalingState + ". Can't update room while negotiation is in progress");
138
- }
139
- pc.createOffer().then(function(offer) {
140
- pc.setLocalDescription(offer).then(function() {
141
- if (config) {
142
- offer.sdp = applyContentTypeConfig(offer.sdp, config);
143
- }
144
- connection.send(constants.SFU_INTERNAL_API.UPDATE_ROOM_STATE, {
145
- name: name,
146
- pin: pin,
147
- sdp: offer.sdp
148
- });
149
- });
150
- });
182
+ return new Promise((resolve, reject) => {
183
+ if (pc.signalingState !== "stable") {
184
+ reject("Peer connection signaling state is " + pc.signalingState + ". Can't update room while negotiation is in progress");
185
+ }
186
+ pc.createOffer().then(function(offer) {
187
+ pc.setLocalDescription(offer).then(function() {
188
+ if (config) {
189
+ offer.sdp = applyContentTypeConfig(offer.sdp, config);
190
+ }
191
+ const id = uuidv4();
192
+ promises.add(id, resolve, reject);
193
+ connection.send(constants.SFU_INTERNAL_API.UPDATE_ROOM_STATE, {
194
+ name: name,
195
+ pin: pin,
196
+ sdp: offer.sdp,
197
+ internalMessageId: id
198
+ });
199
+ }, reject);
200
+ }, reject);
201
+ })
202
+
151
203
  };
152
204
 
153
205
  const applyContentTypeConfig = function(sdp, config) {
@@ -171,9 +223,15 @@ const room = function(options) {
171
223
  * @memberOf FlashphonerSFU.Room
172
224
  */
173
225
  const destroyRoom = function() {
174
- connection.send(constants.SFU_INTERNAL_API.DESTROY_ROOM, {
175
- name: name,
176
- pin: pin
226
+ return new Promise((resolve, reject) => {
227
+ state = constants.SFU_ROOM_STATE.DISPOSED;
228
+ const id = uuidv4();
229
+ promises.add(id, resolve, reject);
230
+ connection.send(constants.SFU_INTERNAL_API.DESTROY_ROOM, {
231
+ name: name,
232
+ pin: pin,
233
+ internalMessageId: id
234
+ });
177
235
  });
178
236
  };
179
237
 
@@ -182,12 +240,19 @@ const room = function(options) {
182
240
  * @memberOf FlashphonerSFU.Room
183
241
  */
184
242
  const leaveRoom = function() {
185
- connection.send(constants.SFU_INTERNAL_API.LEAVE_ROOM, {
186
- name: name,
187
- pin: pin
188
- });
189
- pc.close();
190
- pc.dispatchEvent(new Event("connectionstatechange"));
243
+ return new Promise((resolve, reject) => {
244
+ state = constants.SFU_ROOM_STATE.DISPOSED;
245
+ const id = uuidv4();
246
+ promises.add(id, resolve, reject);
247
+ connection.send(constants.SFU_INTERNAL_API.LEAVE_ROOM, {
248
+ name: name,
249
+ pin: pin,
250
+ internalMessageId: id
251
+ });
252
+ pc.close();
253
+ pc.dispatchEvent(new Event("connectionstatechange"));
254
+ })
255
+
191
256
  };
192
257
 
193
258
  /**
@@ -197,21 +262,31 @@ const room = function(options) {
197
262
  * @memberOf FlashphonerSFU.Room
198
263
  */
199
264
  const sendMessage = function(msg) {
200
- //throttle messages
201
- const chuckSize = 16384;
202
- if (msg.length > chuckSize) {
265
+ return new Promise((resolve, reject) => {
266
+ //throttle messages
203
267
  const id = uuidv4();
204
- const chunks = msg.match(new RegExp("(.|[\r\n]){1,"+chuckSize+"}", "g"));
205
- for (let i = 0; i < chunks.length; i++) {
206
- dChannel.send(JSON.stringify({
268
+ /**
269
+ * Note that in case of chunked message promise will be resolved only after sending last message (last: true)
270
+ */
271
+ promises.add(id, resolve, reject);
272
+ const chunkSize = 16384;
273
+ if (msg.length > chunkSize) {
274
+ const chunks = msg.match(new RegExp("(.|[\r\n]){1,"+chunkSize+"}", "g"));
275
+ for (let i = 0; i < chunks.length; i++) {
276
+ dChannelSend(JSON.stringify({
277
+ id: id,
278
+ last: i === chunks.length - 1,
279
+ payload: chunks[i]
280
+ }));
281
+ }
282
+ } else {
283
+ dChannelSend(JSON.stringify({
207
284
  id: id,
208
- last: i === chunks.length - 1,
209
- payload: chunks[i]
285
+ payload: msg
210
286
  }));
211
287
  }
212
- } else {
213
- dChannel.send(msg);
214
- }
288
+ })
289
+
215
290
  };
216
291
 
217
292
  /**
@@ -222,12 +297,17 @@ const room = function(options) {
222
297
  * @param {Boolean} broadcast ignore 'to' and broadcast the message (send it to all participants)
223
298
  */
224
299
  const sendControlMessage = function(to, msg, broadcast) {
225
- connection.send(constants.SFU_INTERNAL_API.SEND_CONTROL_MESSAGE, {
226
- broadcast: broadcast,
227
- from: "",
228
- to: to,
229
- body: msg
230
- });
300
+ return new Promise((resolve, reject) => {
301
+ const id = uuidv4();
302
+ promises.add(id, resolve, reject);
303
+ connection.send(constants.SFU_INTERNAL_API.SEND_CONTROL_MESSAGE, {
304
+ broadcast: broadcast,
305
+ from: "",
306
+ to: to,
307
+ body: msg,
308
+ internalMessageId: id
309
+ });
310
+ })
231
311
  };
232
312
 
233
313
  /**
@@ -239,12 +319,17 @@ const room = function(options) {
239
319
  * @memberOf FlashphonerSFU.Room
240
320
  */
241
321
  const changeQuality = function(trackId, quality, tid) {
242
- connection.send("changeQuality", {
243
- roomName: name,
244
- id: trackId,
245
- quality: quality,
246
- tid: tid
247
- });
322
+ return new Promise((resolve, reject) => {
323
+ const id = uuidv4();
324
+ promises.add(id, resolve, reject);
325
+ connection.send("changeQuality", {
326
+ roomName: name,
327
+ id: trackId,
328
+ quality: quality,
329
+ tid: tid,
330
+ internalMessageId: id
331
+ });
332
+ })
248
333
  };
249
334
 
250
335
  /**
@@ -254,11 +339,17 @@ const room = function(options) {
254
339
  * @memberOf FlashphonerSFU.Room
255
340
  */
256
341
  const authorizeWaitingList = function(userId, authorized) {
257
- connection.send(constants.SFU_INTERNAL_API.AUTHORIZE_WAITING_LIST, {
258
- name: name,
259
- userId: userId,
260
- authorized: authorized
261
- });
342
+ return new Promise((resolve, reject) => {
343
+ const id = uuidv4();
344
+ promises.add(id, resolve, reject);
345
+ connection.send(constants.SFU_INTERNAL_API.AUTHORIZE_WAITING_LIST, {
346
+ name: name,
347
+ userId: userId,
348
+ authorized: authorized,
349
+ internalMessageId: id
350
+ });
351
+ })
352
+
262
353
  };
263
354
 
264
355
  /**
@@ -267,9 +358,14 @@ const room = function(options) {
267
358
  * @memberOf FlashphonerSFU.Room
268
359
  */
269
360
  const moveToWaitingRoom = function(nickname) {
270
- connection.send(constants.SFU_INTERNAL_API.MOVE_TO_WAITING_ROOM, {
271
- roomName: name,
272
- nickname: nickname
361
+ return new Promise((resolve, reject) => {
362
+ const id = uuidv4();
363
+ promises.add(id, resolve, reject);
364
+ connection.send(constants.SFU_INTERNAL_API.MOVE_TO_WAITING_ROOM, {
365
+ roomName: name,
366
+ nickname: nickname,
367
+ internalMessageId: id
368
+ });
273
369
  });
274
370
  };
275
371
 
@@ -279,9 +375,14 @@ const room = function(options) {
279
375
  * @memberOf FlashphonerSFU.Room
280
376
  */
281
377
  const configureWaitingRoom = function(enabled) {
282
- connection.send(constants.SFU_INTERNAL_API.CONFIGURE_WAITING_ROOM, {
283
- name: name,
284
- enabled: enabled
378
+ return new Promise((resolve, reject) => {
379
+ const id = uuidv4();
380
+ promises.add(id, resolve, reject);
381
+ connection.send(constants.SFU_INTERNAL_API.CONFIGURE_WAITING_ROOM, {
382
+ name: name,
383
+ enabled: enabled,
384
+ internalMessageId: id
385
+ });
285
386
  });
286
387
  };
287
388
 
@@ -292,11 +393,15 @@ const room = function(options) {
292
393
  * @memberOf FlashphonerSFU.Room
293
394
  */
294
395
  const muteTrack = function(trackId, mute) {
295
- connection.send(constants.SFU_INTERNAL_API.MUTE_TRACK, {
296
- roomName: name,
297
- id: trackId,
298
- mute: mute
299
- });
396
+ return new Promise((resolve, reject) => {
397
+ const id = uuidv4();
398
+ promises.add(id, resolve, reject);
399
+ connection.send(constants.SFU_INTERNAL_API.MUTE_TRACK, {
400
+ roomName: name,
401
+ id: trackId,
402
+ mute: mute
403
+ });
404
+ })
300
405
  };
301
406
 
302
407
  /**
@@ -306,11 +411,16 @@ const room = function(options) {
306
411
  * @memberOf FlashphonerSFU.Room
307
412
  */
308
413
  const assignRole = function(nickname, role) {
309
- connection.send(constants.SFU_INTERNAL_API.ASSIGN_ROLE, {
310
- roomName: name,
311
- nickname: nickname,
312
- role: role
313
- });
414
+ return new Promise((resolve, reject) => {
415
+ const id = uuidv4();
416
+ promises.add(id, resolve, reject);
417
+ connection.send(constants.SFU_INTERNAL_API.ASSIGN_ROLE, {
418
+ roomName: name,
419
+ nickname: nickname,
420
+ role: role,
421
+ internalMessageId: id
422
+ });
423
+ })
314
424
  };
315
425
 
316
426
  /**
@@ -321,10 +431,15 @@ const room = function(options) {
321
431
  * @memberOf FlashphonerSFU.Room
322
432
  */
323
433
  const subscribeToWaitingParticipant = function(nickname) {
324
- connection.send(constants.SFU_INTERNAL_API.SUBSCRIBE_TO_WAITING_PARTICIPANT, {
325
- roomName: name,
326
- nickname: nickname
327
- });
434
+ return new Promise((resolve, reject) => {
435
+ const id = uuidv4();
436
+ promises.add(id, resolve, reject);
437
+ connection.send(constants.SFU_INTERNAL_API.SUBSCRIBE_TO_WAITING_PARTICIPANT, {
438
+ roomName: name,
439
+ nickname: nickname,
440
+ internalMessageId: id
441
+ });
442
+ })
328
443
  };
329
444
 
330
445
  /**
@@ -334,10 +449,16 @@ const room = function(options) {
334
449
  * @memberOf FlashphonerSFU.Room
335
450
  */
336
451
  const unsubscribeFromWaitingParticipant = function(nickname) {
337
- connection.send(constants.SFU_INTERNAL_API.UNSUBSCRIBE_FROM_WAITING_PARTICIPANT, {
338
- roomName: name,
339
- nickname: nickname
340
- });
452
+ return new Promise((resolve, reject) => {
453
+ const id = uuidv4();
454
+ promises.add(id, resolve, reject);
455
+ connection.send(constants.SFU_INTERNAL_API.UNSUBSCRIBE_FROM_WAITING_PARTICIPANT, {
456
+ roomName: name,
457
+ nickname: nickname,
458
+ internalMessageId: id
459
+ });
460
+ })
461
+
341
462
  };
342
463
 
343
464
  /**
@@ -348,7 +469,7 @@ const room = function(options) {
348
469
  */
349
470
 
350
471
  /**
351
- * Add session event callback.
472
+ * Add room event callback.
352
473
  *
353
474
  * @param {String} event One of {@link FlashphonerSFU.SFU_ROOM_EVENT} events
354
475
  * @param {FlashphonerSFU.Room~eventCallback} callback Callback function
@@ -371,6 +492,34 @@ const room = function(options) {
371
492
  return room;
372
493
  };
373
494
 
495
+ /**
496
+ * Remove room event callback.
497
+ *
498
+ * @param {String} event One of {@link FlashphonerSFU.SFU_ROOM_EVENT} events
499
+ * @param {FlashphonerSFU.Room~eventCallback} callback Callback function
500
+ * @returns {FlashphonerSFU.Room} SDK instance callback was removed from
501
+ * @throws {TypeError} Error if event is not specified
502
+ * @throws {Error} Error if callback is not a valid function
503
+ * @memberOf FlashphonerSFU.Room
504
+ */
505
+ const off = function (event, callback) {
506
+ if (!event) {
507
+ throw new TypeError("Event can't be null");
508
+ }
509
+ if (!callback || typeof callback !== "function") {
510
+ throw new Error("Callback needs to be a valid function");
511
+ }
512
+ if (!callbacks[event]) {
513
+ callbacks[event] = [];
514
+ }
515
+ let index = callbacks[event].findIndex(element => element === callback);
516
+ if (index !== -1) {
517
+ console.log("off ", event);
518
+ callbacks[event] = callbacks[event].slice(index, 1);
519
+ }
520
+ return room;
521
+ };
522
+
374
523
  const notify = function(event, msg) {
375
524
  if (callbacks[event]) {
376
525
  for (const callback of callbacks[event]) {
@@ -380,21 +529,21 @@ const room = function(options) {
380
529
  };
381
530
 
382
531
  room.processEvent = processEvent;
383
- room.createRoom = createRoom;
384
- room.join = join;
385
- room.updateState = updateState;
386
- room.destroyRoom = destroyRoom;
387
- room.leaveRoom = leaveRoom;
388
- room.sendMessage = sendMessage;
389
- room.sendControlMessage = sendControlMessage;
390
- room.changeQuality = changeQuality;
391
- room.authorizeWaitingList = authorizeWaitingList;
392
- room.muteTrack = muteTrack;
393
- room.assignRole = assignRole;
394
- room.subscribeToWaitingParticipant = subscribeToWaitingParticipant;
395
- room.unsubscribeFromWaitingParticipant = unsubscribeFromWaitingParticipant;
396
- room.moveToWaitingRoom = moveToWaitingRoom;
397
- room.configureWaitingRoom = configureWaitingRoom;
532
+ room.createRoom = createRoom;//done
533
+ room.join = join;//done
534
+ room.updateState = updateState;//done
535
+ room.destroyRoom = destroyRoom;//done
536
+ room.leaveRoom = leaveRoom;//done
537
+ room.sendMessage = sendMessage;//done
538
+ room.sendControlMessage = sendControlMessage;//done
539
+ room.changeQuality = changeQuality;//done
540
+ room.authorizeWaitingList = authorizeWaitingList;//done
541
+ room.muteTrack = muteTrack;//done
542
+ room.assignRole = assignRole;//done
543
+ room.subscribeToWaitingParticipant = subscribeToWaitingParticipant;//done
544
+ room.unsubscribeFromWaitingParticipant = unsubscribeFromWaitingParticipant;//done
545
+ room.moveToWaitingRoom = moveToWaitingRoom;//done
546
+ room.configureWaitingRoom = configureWaitingRoom;//done
398
547
  /**
399
548
  * Room name
400
549
  * @returns {String} room name
@@ -432,6 +581,7 @@ const room = function(options) {
432
581
  return inviteId;
433
582
  };
434
583
  room.on = on;
584
+ room.off = off;
435
585
 
436
586
  return room;
437
587
  };