mediasoup-client 3.6.59 → 3.6.60

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 (86) hide show
  1. package/README.md +17 -3
  2. package/lib/Consumer.d.ts +3 -3
  3. package/lib/Consumer.d.ts.map +1 -1
  4. package/lib/DataConsumer.d.ts +3 -3
  5. package/lib/DataConsumer.d.ts.map +1 -1
  6. package/lib/DataProducer.d.ts +3 -3
  7. package/lib/DataProducer.d.ts.map +1 -1
  8. package/lib/Device.d.ts +3 -3
  9. package/lib/Device.d.ts.map +1 -1
  10. package/lib/EnhancedEventEmitter.d.ts +1 -1
  11. package/lib/EnhancedEventEmitter.d.ts.map +1 -1
  12. package/lib/Producer.d.ts +4 -4
  13. package/lib/Producer.d.ts.map +1 -1
  14. package/lib/RtpParameters.d.ts +11 -11
  15. package/lib/RtpParameters.d.ts.map +1 -1
  16. package/lib/SctpParameters.d.ts +4 -4
  17. package/lib/SctpParameters.d.ts.map +1 -1
  18. package/lib/Transport.d.ts +11 -11
  19. package/lib/Transport.d.ts.map +1 -1
  20. package/lib/handlers/Chrome55.js +6 -6
  21. package/lib/handlers/Chrome67.js +6 -6
  22. package/lib/handlers/Chrome70.d.ts.map +1 -1
  23. package/lib/handlers/Chrome70.js +10 -7
  24. package/lib/handlers/Chrome74.d.ts.map +1 -1
  25. package/lib/handlers/Chrome74.js +10 -7
  26. package/lib/handlers/Edge11.js +6 -6
  27. package/lib/handlers/FakeHandler.d.ts +1 -1
  28. package/lib/handlers/FakeHandler.d.ts.map +1 -1
  29. package/lib/handlers/FakeHandler.js +6 -6
  30. package/lib/handlers/Firefox60.d.ts.map +1 -1
  31. package/lib/handlers/Firefox60.js +10 -7
  32. package/lib/handlers/HandlerInterface.d.ts +11 -11
  33. package/lib/handlers/HandlerInterface.d.ts.map +1 -1
  34. package/lib/handlers/ReactNative.js +6 -6
  35. package/lib/handlers/Safari11.js +6 -6
  36. package/lib/handlers/Safari12.d.ts.map +1 -1
  37. package/lib/handlers/Safari12.js +10 -7
  38. package/lib/index.d.ts +1 -1
  39. package/lib/index.js +1 -1
  40. package/lib/scalabilityModes.d.ts +1 -1
  41. package/lib/scalabilityModes.d.ts.map +1 -1
  42. package/npm-scripts.js +124 -28
  43. package/package.json +17 -5
  44. package/.eslintrc.js +0 -243
  45. package/.github/FUNDING.yml +0 -12
  46. package/.github/ISSUE_TEMPLATE/Bug_Report.md +0 -24
  47. package/.github/ISSUE_TEMPLATE/Feature_Request.md +0 -7
  48. package/.github/ISSUE_TEMPLATE/Support_Question.md +0 -12
  49. package/.travis.yml +0 -26
  50. package/src/Consumer.ts +0 -334
  51. package/src/DataConsumer.ts +0 -271
  52. package/src/DataProducer.ts +0 -291
  53. package/src/Device.ts +0 -584
  54. package/src/EnhancedEventEmitter.ts +0 -133
  55. package/src/Logger.ts +0 -47
  56. package/src/Producer.ts +0 -534
  57. package/src/RtpParameters.ts +0 -326
  58. package/src/SctpParameters.ts +0 -74
  59. package/src/Transport.ts +0 -1275
  60. package/src/errors.ts +0 -45
  61. package/src/handlers/Chrome55.ts +0 -866
  62. package/src/handlers/Chrome67.ts +0 -951
  63. package/src/handlers/Chrome70.ts +0 -964
  64. package/src/handlers/Chrome74.ts +0 -1058
  65. package/src/handlers/Edge11.ts +0 -667
  66. package/src/handlers/FakeHandler.ts +0 -448
  67. package/src/handlers/Firefox60.ts +0 -1040
  68. package/src/handlers/HandlerInterface.ts +0 -162
  69. package/src/handlers/ReactNative.ts +0 -886
  70. package/src/handlers/Safari11.ts +0 -944
  71. package/src/handlers/Safari12.ts +0 -1009
  72. package/src/handlers/ortc/edgeUtils.ts +0 -77
  73. package/src/handlers/sdp/MediaSection.ts +0 -836
  74. package/src/handlers/sdp/RemoteSdp.ts +0 -474
  75. package/src/handlers/sdp/commonUtils.ts +0 -259
  76. package/src/handlers/sdp/plainRtpUtils.ts +0 -58
  77. package/src/handlers/sdp/planBUtils.ts +0 -227
  78. package/src/handlers/sdp/unifiedPlanUtils.ts +0 -188
  79. package/src/index.ts +0 -28
  80. package/src/ortc.ts +0 -1169
  81. package/src/scalabilityModes.ts +0 -27
  82. package/src/types.ts +0 -11
  83. package/src/utils.ts +0 -18
  84. package/test/fakeParameters.js +0 -701
  85. package/test/test.js +0 -1672
  86. package/tsconfig.json +0 -17
package/src/Transport.ts DELETED
@@ -1,1275 +0,0 @@
1
- import { AwaitQueue } from 'awaitqueue';
2
- import { Logger } from './Logger';
3
- import { EnhancedEventEmitter } from './EnhancedEventEmitter';
4
- import { UnsupportedError, InvalidStateError } from './errors';
5
- import * as utils from './utils';
6
- import * as ortc from './ortc';
7
- import { HandlerFactory, HandlerInterface, HandlerReceiveOptions } from './handlers/HandlerInterface';
8
- import { Producer, ProducerOptions } from './Producer';
9
- import { Consumer, ConsumerOptions } from './Consumer';
10
- import { DataProducer, DataProducerOptions } from './DataProducer';
11
- import { DataConsumer, DataConsumerOptions } from './DataConsumer';
12
- import { RtpParameters, MediaKind } from './RtpParameters';
13
- import { SctpParameters, SctpStreamParameters } from './SctpParameters';
14
-
15
- const logger = new Logger('Transport');
16
-
17
- interface InternalTransportOptions extends TransportOptions
18
- {
19
- direction: 'send' | 'recv';
20
- handlerFactory: HandlerFactory;
21
- extendedRtpCapabilities: any;
22
- canProduceByKind: CanProduceByKind;
23
- }
24
-
25
- class ConsumerCreationTask
26
- {
27
- consumerOptions: ConsumerOptions;
28
- promise: Promise<Consumer>;
29
- resolve?: (consumer: Consumer) => void;
30
- reject?: (error: Error) => void;
31
-
32
- constructor(consumerOptions: ConsumerOptions)
33
- {
34
- this.consumerOptions = consumerOptions;
35
- this.promise = new Promise<Consumer>((resolve, reject) =>
36
- {
37
- this.resolve = resolve;
38
- this.reject = reject;
39
- });
40
- }
41
- }
42
-
43
- export type TransportOptions =
44
- {
45
- id: string;
46
- iceParameters: IceParameters;
47
- iceCandidates: IceCandidate[];
48
- dtlsParameters: DtlsParameters;
49
- sctpParameters?: SctpParameters;
50
- iceServers?: RTCIceServer[];
51
- iceTransportPolicy?: RTCIceTransportPolicy;
52
- additionalSettings?: any;
53
- proprietaryConstraints?: any;
54
- appData?: Record<string, unknown>;
55
- }
56
-
57
- export type CanProduceByKind =
58
- {
59
- audio: boolean;
60
- video: boolean;
61
- [key: string]: boolean;
62
- }
63
-
64
- export type IceParameters =
65
- {
66
- /**
67
- * ICE username fragment.
68
- * */
69
- usernameFragment: string;
70
- /**
71
- * ICE password.
72
- */
73
- password: string;
74
- /**
75
- * ICE Lite.
76
- */
77
- iceLite?: boolean;
78
- }
79
-
80
- export type IceCandidate =
81
- {
82
- /**
83
- * Unique identifier that allows ICE to correlate candidates that appear on
84
- * multiple transports.
85
- */
86
- foundation: string;
87
- /**
88
- * The assigned priority of the candidate.
89
- */
90
- priority: number;
91
- /**
92
- * The IP address of the candidate.
93
- */
94
- ip: string;
95
- /**
96
- * The protocol of the candidate.
97
- */
98
- protocol: 'udp' | 'tcp';
99
- /**
100
- * The port for the candidate.
101
- */
102
- port: number;
103
- /**
104
- * The type of candidate.
105
- */
106
- type: 'host' | 'srflx' | 'prflx' | 'relay';
107
- /**
108
- * The type of TCP candidate.
109
- */
110
- tcpType: 'active' | 'passive' | 'so';
111
- }
112
-
113
- export type DtlsParameters =
114
- {
115
- /**
116
- * Server DTLS role. Default 'auto'.
117
- */
118
- role?: DtlsRole;
119
- /**
120
- * Server DTLS fingerprints.
121
- */
122
- fingerprints: DtlsFingerprint[];
123
- }
124
-
125
- /**
126
- * The hash function algorithm (as defined in the "Hash function Textual Names"
127
- * registry initially specified in RFC 4572 Section 8) and its corresponding
128
- * certificate fingerprint value (in lowercase hex string as expressed utilizing
129
- * the syntax of "fingerprint" in RFC 4572 Section 5).
130
- */
131
- export type DtlsFingerprint =
132
- {
133
- algorithm: string;
134
- value: string;
135
- }
136
-
137
- export type DtlsRole = 'auto' | 'client' | 'server';
138
-
139
- export type ConnectionState =
140
- | 'new'
141
- | 'connecting'
142
- | 'connected'
143
- | 'failed'
144
- | 'disconnected'
145
- | 'closed';
146
-
147
- export type PlainRtpParameters =
148
- {
149
- ip: string;
150
- ipVersion: 4 | 6;
151
- port: number;
152
- };
153
-
154
- export type TransportEvents =
155
- {
156
- connect: [{ dtlsParameters: DtlsParameters }, () => void, (error: Error) => void];
157
- connectionstatechange: [ConnectionState];
158
- produce:
159
- [
160
- {
161
- kind: MediaKind;
162
- rtpParameters: RtpParameters;
163
- appData: Record<string, unknown>;
164
- },
165
- ({ id }: { id: string }) => void,
166
- (error: Error) => void
167
- ];
168
- producedata:
169
- [
170
- {
171
- sctpStreamParameters: SctpStreamParameters;
172
- label?: string;
173
- protocol?: string;
174
- appData: Record<string, unknown>;
175
- },
176
- ({ id }: { id: string }) => void,
177
- (error: Error) => void
178
- ];
179
- };
180
-
181
- export type TransportObserverEvents =
182
- {
183
- close: [];
184
- newproducer: [Producer];
185
- newconsumer: [Consumer];
186
- newdataproducer: [DataProducer];
187
- newdataconsumer: [DataConsumer];
188
- };
189
-
190
- export class Transport extends EnhancedEventEmitter<TransportEvents>
191
- {
192
- // Id.
193
- private readonly _id: string;
194
- // Closed flag.
195
- private _closed = false;
196
- // Direction.
197
- private readonly _direction: 'send' | 'recv';
198
- // Extended RTP capabilities.
199
- private readonly _extendedRtpCapabilities: any;
200
- // Whether we can produce audio/video based on computed extended RTP
201
- // capabilities.
202
- private readonly _canProduceByKind: CanProduceByKind;
203
- // SCTP max message size if enabled, null otherwise.
204
- private readonly _maxSctpMessageSize?: number | null;
205
- // RTC handler isntance.
206
- private readonly _handler: HandlerInterface;
207
- // Transport connection state.
208
- private _connectionState: ConnectionState = 'new';
209
- // App custom data.
210
- private readonly _appData: Record<string, unknown>;
211
- // Map of Producers indexed by id.
212
- private readonly _producers: Map<string, Producer> = new Map();
213
- // Map of Consumers indexed by id.
214
- private readonly _consumers: Map<string, Consumer> = new Map();
215
- // Map of DataProducers indexed by id.
216
- private readonly _dataProducers: Map<string, DataProducer> = new Map();
217
- // Map of DataConsumers indexed by id.
218
- private readonly _dataConsumers: Map<string, DataConsumer> = new Map();
219
- // Whether the Consumer for RTP probation has been created.
220
- private _probatorConsumerCreated = false;
221
- // AwaitQueue instance to make async tasks happen sequentially.
222
- private readonly _awaitQueue = new AwaitQueue({ ClosedErrorClass: InvalidStateError });
223
- // Consumer creation tasks awaiting to be processed.
224
- private _pendingConsumerTasks: ConsumerCreationTask[] = [];
225
- // Consumer creation in progress flag.
226
- private _consumerCreationInProgress = false;
227
- // Consumers pending to be paused.
228
- private _pendingPauseConsumers: Map<string, Consumer> = new Map();
229
- // Consumer pause in progress flag.
230
- private _consumerPauseInProgress = false;
231
- // Consumers pending to be resumed.
232
- private _pendingResumeConsumers: Map<string, Consumer> = new Map();
233
- // Consumer resume in progress flag.
234
- private _consumerResumeInProgress = false;
235
- // Consumers pending to be closed.
236
- private _pendingCloseConsumers: Map<string, Consumer> = new Map();
237
- // Consumer close in progress flag.
238
- private _consumerCloseInProgress = false;
239
- // Observer instance.
240
- protected readonly _observer = new EnhancedEventEmitter<TransportObserverEvents>();
241
-
242
- constructor(
243
- {
244
- direction,
245
- id,
246
- iceParameters,
247
- iceCandidates,
248
- dtlsParameters,
249
- sctpParameters,
250
- iceServers,
251
- iceTransportPolicy,
252
- additionalSettings,
253
- proprietaryConstraints,
254
- appData,
255
- handlerFactory,
256
- extendedRtpCapabilities,
257
- canProduceByKind
258
- }: InternalTransportOptions
259
- )
260
- {
261
- super();
262
-
263
- logger.debug('constructor() [id:%s, direction:%s]', id, direction);
264
-
265
- this._id = id;
266
- this._direction = direction;
267
- this._extendedRtpCapabilities = extendedRtpCapabilities;
268
- this._canProduceByKind = canProduceByKind;
269
- this._maxSctpMessageSize =
270
- sctpParameters ? sctpParameters.maxMessageSize : null;
271
-
272
- // Clone and sanitize additionalSettings.
273
- additionalSettings = utils.clone(additionalSettings, {});
274
-
275
- delete additionalSettings.iceServers;
276
- delete additionalSettings.iceTransportPolicy;
277
- delete additionalSettings.bundlePolicy;
278
- delete additionalSettings.rtcpMuxPolicy;
279
- delete additionalSettings.sdpSemantics;
280
-
281
- this._handler = handlerFactory();
282
-
283
- this._handler.run(
284
- {
285
- direction,
286
- iceParameters,
287
- iceCandidates,
288
- dtlsParameters,
289
- sctpParameters,
290
- iceServers,
291
- iceTransportPolicy,
292
- additionalSettings,
293
- proprietaryConstraints,
294
- extendedRtpCapabilities
295
- });
296
-
297
- this._appData = appData || {};
298
-
299
- this._handleHandler();
300
- }
301
-
302
- /**
303
- * Transport id.
304
- */
305
- get id(): string
306
- {
307
- return this._id;
308
- }
309
-
310
- /**
311
- * Whether the Transport is closed.
312
- */
313
- get closed(): boolean
314
- {
315
- return this._closed;
316
- }
317
-
318
- /**
319
- * Transport direction.
320
- */
321
- get direction(): 'send' | 'recv'
322
- {
323
- return this._direction;
324
- }
325
-
326
- /**
327
- * RTC handler instance.
328
- */
329
- get handler(): HandlerInterface
330
- {
331
- return this._handler;
332
- }
333
-
334
- /**
335
- * Connection state.
336
- */
337
- get connectionState(): ConnectionState
338
- {
339
- return this._connectionState;
340
- }
341
-
342
- /**
343
- * App custom data.
344
- */
345
- get appData(): Record<string, unknown>
346
- {
347
- return this._appData;
348
- }
349
-
350
- /**
351
- * Invalid setter.
352
- */
353
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
354
- set appData(appData: Record<string, unknown>)
355
- {
356
- throw new Error('cannot override appData object');
357
- }
358
-
359
- get observer(): EnhancedEventEmitter
360
- {
361
- return this._observer;
362
- }
363
-
364
- /**
365
- * Close the Transport.
366
- */
367
- close(): void
368
- {
369
- if (this._closed)
370
- return;
371
-
372
- logger.debug('close()');
373
-
374
- this._closed = true;
375
-
376
- // Close the AwaitQueue.
377
- this._awaitQueue.close();
378
-
379
- // Close the handler.
380
- this._handler.close();
381
-
382
- // Close all Producers.
383
- for (const producer of this._producers.values())
384
- {
385
- producer.transportClosed();
386
- }
387
- this._producers.clear();
388
-
389
- // Close all Consumers.
390
- for (const consumer of this._consumers.values())
391
- {
392
- consumer.transportClosed();
393
- }
394
- this._consumers.clear();
395
-
396
- // Close all DataProducers.
397
- for (const dataProducer of this._dataProducers.values())
398
- {
399
- dataProducer.transportClosed();
400
- }
401
- this._dataProducers.clear();
402
-
403
- // Close all DataConsumers.
404
- for (const dataConsumer of this._dataConsumers.values())
405
- {
406
- dataConsumer.transportClosed();
407
- }
408
- this._dataConsumers.clear();
409
-
410
- // Emit observer event.
411
- this._observer.safeEmit('close');
412
- }
413
-
414
- /**
415
- * Get associated Transport (RTCPeerConnection) stats.
416
- *
417
- * @returns {RTCStatsReport}
418
- */
419
- async getStats(): Promise<RTCStatsReport>
420
- {
421
- if (this._closed)
422
- throw new InvalidStateError('closed');
423
-
424
- return this._handler.getTransportStats();
425
- }
426
-
427
- /**
428
- * Restart ICE connection.
429
- */
430
- async restartIce(
431
- { iceParameters }:
432
- { iceParameters: IceParameters }
433
- ): Promise<void>
434
- {
435
- logger.debug('restartIce()');
436
-
437
- if (this._closed)
438
- throw new InvalidStateError('closed');
439
- else if (!iceParameters)
440
- throw new TypeError('missing iceParameters');
441
-
442
- // Enqueue command.
443
- return this._awaitQueue.push(
444
- async () => this._handler.restartIce(iceParameters),
445
- 'transport.restartIce()');
446
- }
447
-
448
- /**
449
- * Update ICE servers.
450
- */
451
- async updateIceServers(
452
- { iceServers }:
453
- { iceServers?: RTCIceServer[] } = {}
454
- ): Promise<void>
455
- {
456
- logger.debug('updateIceServers()');
457
-
458
- if (this._closed)
459
- throw new InvalidStateError('closed');
460
- else if (!Array.isArray(iceServers))
461
- throw new TypeError('missing iceServers');
462
-
463
- // Enqueue command.
464
- return this._awaitQueue.push(
465
- async () => this._handler.updateIceServers(iceServers),
466
- 'transport.updateIceServers()');
467
- }
468
-
469
- /**
470
- * Create a Producer.
471
- */
472
- async produce(
473
- {
474
- track,
475
- encodings,
476
- codecOptions,
477
- codec,
478
- stopTracks = true,
479
- disableTrackOnPause = true,
480
- zeroRtpOnPause = false,
481
- appData = {}
482
- }: ProducerOptions = {}
483
- ): Promise<Producer>
484
- {
485
- logger.debug('produce() [track:%o]', track);
486
-
487
- if (!track)
488
- throw new TypeError('missing track');
489
- else if (this._direction !== 'send')
490
- throw new UnsupportedError('not a sending Transport');
491
- else if (!this._canProduceByKind[track.kind])
492
- throw new UnsupportedError(`cannot produce ${track.kind}`);
493
- else if (track.readyState === 'ended')
494
- throw new InvalidStateError('track ended');
495
- else if (this.listenerCount('connect') === 0 && this._connectionState === 'new')
496
- throw new TypeError('no "connect" listener set into this transport');
497
- else if (this.listenerCount('produce') === 0)
498
- throw new TypeError('no "produce" listener set into this transport');
499
- else if (appData && typeof appData !== 'object')
500
- throw new TypeError('if given, appData must be an object');
501
-
502
- // Enqueue command.
503
- return this._awaitQueue.push(
504
- async () =>
505
- {
506
- let normalizedEncodings;
507
-
508
- if (encodings && !Array.isArray(encodings))
509
- {
510
- throw TypeError('encodings must be an array');
511
- }
512
- else if (encodings && encodings.length === 0)
513
- {
514
- normalizedEncodings = undefined;
515
- }
516
- else if (encodings)
517
- {
518
- normalizedEncodings = encodings
519
- .map((encoding: any) =>
520
- {
521
- const normalizedEncoding: any = { active: true };
522
-
523
- if (encoding.active === false)
524
- normalizedEncoding.active = false;
525
- if (typeof encoding.dtx === 'boolean')
526
- normalizedEncoding.dtx = encoding.dtx;
527
- if (typeof encoding.scalabilityMode === 'string')
528
- normalizedEncoding.scalabilityMode = encoding.scalabilityMode;
529
- if (typeof encoding.scaleResolutionDownBy === 'number')
530
- normalizedEncoding.scaleResolutionDownBy = encoding.scaleResolutionDownBy;
531
- if (typeof encoding.maxBitrate === 'number')
532
- normalizedEncoding.maxBitrate = encoding.maxBitrate;
533
- if (typeof encoding.maxFramerate === 'number')
534
- normalizedEncoding.maxFramerate = encoding.maxFramerate;
535
- if (typeof encoding.adaptivePtime === 'boolean')
536
- normalizedEncoding.adaptivePtime = encoding.adaptivePtime;
537
- if (typeof encoding.priority === 'string')
538
- normalizedEncoding.priority = encoding.priority;
539
- if (typeof encoding.networkPriority === 'string')
540
- normalizedEncoding.networkPriority = encoding.networkPriority;
541
-
542
- return normalizedEncoding;
543
- });
544
- }
545
-
546
- const { localId, rtpParameters, rtpSender } = await this._handler.send(
547
- {
548
- track,
549
- encodings : normalizedEncodings,
550
- codecOptions,
551
- codec
552
- });
553
-
554
- try
555
- {
556
- // This will fill rtpParameters's missing fields with default values.
557
- ortc.validateRtpParameters(rtpParameters);
558
-
559
- const { id } = await new Promise<{ id: string }>((resolve, reject) =>
560
- {
561
- this.safeEmit(
562
- 'produce',
563
- {
564
- kind : track.kind as MediaKind,
565
- rtpParameters,
566
- appData
567
- },
568
- resolve,
569
- reject
570
- );
571
- });
572
-
573
- const producer = new Producer(
574
- {
575
- id,
576
- localId,
577
- rtpSender,
578
- track,
579
- rtpParameters,
580
- stopTracks,
581
- disableTrackOnPause,
582
- zeroRtpOnPause,
583
- appData
584
- });
585
-
586
- this._producers.set(producer.id, producer);
587
- this._handleProducer(producer);
588
-
589
- // Emit observer event.
590
- this._observer.safeEmit('newproducer', producer);
591
-
592
- return producer;
593
- }
594
- catch (error)
595
- {
596
- this._handler.stopSending(localId)
597
- .catch(() => {});
598
-
599
- throw error;
600
- }
601
- },
602
- 'transport.produce()')
603
- // This catch is needed to stop the given track if the command above
604
- // failed due to closed Transport.
605
- .catch((error: Error) =>
606
- {
607
- if (stopTracks)
608
- {
609
- try { track.stop(); }
610
- catch (error2) {}
611
- }
612
-
613
- throw error;
614
- });
615
- }
616
-
617
- /**
618
- * Create a Consumer to consume a remote Producer.
619
- */
620
- async consume(
621
- {
622
- id,
623
- producerId,
624
- kind,
625
- rtpParameters,
626
- appData = {}
627
- }: ConsumerOptions
628
- ): Promise<Consumer>
629
- {
630
- logger.debug('consume()');
631
-
632
- rtpParameters = utils.clone(rtpParameters, undefined);
633
-
634
- if (this._closed)
635
- throw new InvalidStateError('closed');
636
- else if (this._direction !== 'recv')
637
- throw new UnsupportedError('not a receiving Transport');
638
- else if (typeof id !== 'string')
639
- throw new TypeError('missing id');
640
- else if (typeof producerId !== 'string')
641
- throw new TypeError('missing producerId');
642
- else if (kind !== 'audio' && kind !== 'video')
643
- throw new TypeError(`invalid kind '${kind}'`);
644
- else if (this.listenerCount('connect') === 0 && this._connectionState === 'new')
645
- throw new TypeError('no "connect" listener set into this transport');
646
- else if (appData && typeof appData !== 'object')
647
- throw new TypeError('if given, appData must be an object');
648
-
649
- // Ensure the device can consume it.
650
- const canConsume = ortc.canReceive(
651
- rtpParameters, this._extendedRtpCapabilities);
652
-
653
- if (!canConsume)
654
- throw new UnsupportedError('cannot consume this Producer');
655
-
656
- const consumerCreationTask = new ConsumerCreationTask(
657
- {
658
- id,
659
- producerId,
660
- kind,
661
- rtpParameters,
662
- appData
663
- }
664
- );
665
-
666
- // Store the Consumer creation task.
667
- this._pendingConsumerTasks.push(consumerCreationTask);
668
-
669
- // There is no Consumer creation in progress, create it now.
670
- if (this._consumerCreationInProgress === false)
671
- {
672
- this._createPendingConsumers();
673
- }
674
-
675
- return consumerCreationTask.promise;
676
- }
677
-
678
- /**
679
- * Create a DataProducer
680
- */
681
- async produceData(
682
- {
683
- ordered = true,
684
- maxPacketLifeTime,
685
- maxRetransmits,
686
- label = '',
687
- protocol = '',
688
- appData = {}
689
- }: DataProducerOptions = {}
690
- ): Promise<DataProducer>
691
- {
692
- logger.debug('produceData()');
693
-
694
- if (this._direction !== 'send')
695
- throw new UnsupportedError('not a sending Transport');
696
- else if (!this._maxSctpMessageSize)
697
- throw new UnsupportedError('SCTP not enabled by remote Transport');
698
- else if (this.listenerCount('connect') === 0 && this._connectionState === 'new')
699
- throw new TypeError('no "connect" listener set into this transport');
700
- else if (this.listenerCount('producedata') === 0)
701
- throw new TypeError('no "producedata" listener set into this transport');
702
- else if (appData && typeof appData !== 'object')
703
- throw new TypeError('if given, appData must be an object');
704
-
705
- if (maxPacketLifeTime || maxRetransmits)
706
- ordered = false;
707
-
708
- // Enqueue command.
709
- return this._awaitQueue.push(
710
- async () =>
711
- {
712
- const {
713
- dataChannel,
714
- sctpStreamParameters
715
- } = await this._handler.sendDataChannel(
716
- {
717
- ordered,
718
- maxPacketLifeTime,
719
- maxRetransmits,
720
- label,
721
- protocol
722
- });
723
-
724
- // This will fill sctpStreamParameters's missing fields with default values.
725
- ortc.validateSctpStreamParameters(sctpStreamParameters);
726
-
727
- const { id } = await new Promise<{ id: string }>((resolve, reject) =>
728
- {
729
- this.safeEmit(
730
- 'producedata',
731
- {
732
- sctpStreamParameters,
733
- label,
734
- protocol,
735
- appData
736
- },
737
- resolve,
738
- reject
739
- );
740
- });
741
-
742
- const dataProducer =
743
- new DataProducer({ id, dataChannel, sctpStreamParameters, appData });
744
-
745
- this._dataProducers.set(dataProducer.id, dataProducer);
746
- this._handleDataProducer(dataProducer);
747
-
748
- // Emit observer event.
749
- this._observer.safeEmit('newdataproducer', dataProducer);
750
-
751
- return dataProducer;
752
- },
753
- 'transport.produceData()');
754
- }
755
-
756
- /**
757
- * Create a DataConsumer
758
- */
759
- async consumeData(
760
- {
761
- id,
762
- dataProducerId,
763
- sctpStreamParameters,
764
- label = '',
765
- protocol = '',
766
- appData = {}
767
- }: DataConsumerOptions
768
- ): Promise<DataConsumer>
769
- {
770
- logger.debug('consumeData()');
771
-
772
- sctpStreamParameters = utils.clone(sctpStreamParameters, undefined);
773
-
774
- if (this._closed)
775
- throw new InvalidStateError('closed');
776
- else if (this._direction !== 'recv')
777
- throw new UnsupportedError('not a receiving Transport');
778
- else if (!this._maxSctpMessageSize)
779
- throw new UnsupportedError('SCTP not enabled by remote Transport');
780
- else if (typeof id !== 'string')
781
- throw new TypeError('missing id');
782
- else if (typeof dataProducerId !== 'string')
783
- throw new TypeError('missing dataProducerId');
784
- else if (this.listenerCount('connect') === 0 && this._connectionState === 'new')
785
- throw new TypeError('no "connect" listener set into this transport');
786
- else if (appData && typeof appData !== 'object')
787
- throw new TypeError('if given, appData must be an object');
788
-
789
- // This may throw.
790
- ortc.validateSctpStreamParameters(sctpStreamParameters);
791
-
792
- // Enqueue command.
793
- return this._awaitQueue.push(
794
- async () =>
795
- {
796
- const {
797
- dataChannel
798
- } = await this._handler.receiveDataChannel(
799
- {
800
- sctpStreamParameters,
801
- label,
802
- protocol
803
- });
804
-
805
- const dataConsumer = new DataConsumer(
806
- {
807
- id,
808
- dataProducerId,
809
- dataChannel,
810
- sctpStreamParameters,
811
- appData
812
- });
813
-
814
- this._dataConsumers.set(dataConsumer.id, dataConsumer);
815
- this._handleDataConsumer(dataConsumer);
816
-
817
- // Emit observer event.
818
- this._observer.safeEmit('newdataconsumer', dataConsumer);
819
-
820
- return dataConsumer;
821
- },
822
- 'transport.consumeData()');
823
- }
824
-
825
- // This method is guaranteed to never throw.
826
- async _createPendingConsumers(): Promise<void>
827
- {
828
- this._consumerCreationInProgress = true;
829
-
830
- this._awaitQueue.push(
831
- async () =>
832
- {
833
- if (this._pendingConsumerTasks.length === 0)
834
- {
835
- logger.debug('_createPendingConsumers() | there is no Consumer to be created');
836
-
837
- return;
838
- }
839
-
840
- const pendingConsumerTasks = [ ...this._pendingConsumerTasks ];
841
-
842
- // Clear pending Consumer tasks.
843
- this._pendingConsumerTasks = [];
844
-
845
- // Video Consumer in order to create the probator.
846
- let videoConsumerForProbator: Consumer | undefined = undefined;
847
-
848
- // Fill options list.
849
- const optionsList: HandlerReceiveOptions[] = [];
850
-
851
- for (const task of pendingConsumerTasks)
852
- {
853
- const { id, kind, rtpParameters } = task.consumerOptions;
854
-
855
- optionsList.push({
856
- trackId : id!,
857
- kind : kind as 'audio' | 'video',
858
- rtpParameters
859
- });
860
- }
861
-
862
- try
863
- {
864
- const results = await this._handler.receive(optionsList);
865
-
866
- for (let idx=0; idx < results.length; idx++)
867
- {
868
- const task = pendingConsumerTasks[idx];
869
- const result = results[idx];
870
- const { id, producerId, kind, rtpParameters, appData } = task.consumerOptions;
871
- const { localId, rtpReceiver, track } = result;
872
- const consumer = new Consumer(
873
- {
874
- id : id!,
875
- localId,
876
- producerId : producerId!,
877
- rtpReceiver,
878
- track,
879
- rtpParameters,
880
- appData
881
- });
882
-
883
- this._consumers.set(consumer.id, consumer);
884
- this._handleConsumer(consumer);
885
-
886
- // If this is the first video Consumer and the Consumer for RTP probation
887
- // has not yet been created, it's time to create it.
888
- if (!this._probatorConsumerCreated && !videoConsumerForProbator && kind === 'video')
889
- {
890
- videoConsumerForProbator = consumer;
891
- }
892
-
893
- // Emit observer event.
894
- this._observer.safeEmit('newconsumer', consumer);
895
-
896
- task.resolve!(consumer);
897
- }
898
- }
899
- catch (error)
900
- {
901
- for (const task of pendingConsumerTasks)
902
- {
903
- task.reject!(error as Error);
904
- }
905
- }
906
-
907
- // If RTP probation must be handled, do it now.
908
- if (videoConsumerForProbator)
909
- {
910
- try
911
- {
912
- const probatorRtpParameters =
913
- ortc.generateProbatorRtpParameters(videoConsumerForProbator!.rtpParameters);
914
-
915
- await this._handler.receive(
916
- [ {
917
- trackId : 'probator',
918
- kind : 'video',
919
- rtpParameters : probatorRtpParameters
920
- } ]);
921
-
922
- logger.debug('_createPendingConsumers() | Consumer for RTP probation created');
923
-
924
- this._probatorConsumerCreated = true;
925
- }
926
- catch (error)
927
- {
928
- logger.error(
929
- '_createPendingConsumers() | failed to create Consumer for RTP probation:%o',
930
- error);
931
- }
932
- }
933
- },
934
- 'transport._createPendingConsumers()')
935
- .then(() =>
936
- {
937
- this._consumerCreationInProgress = false;
938
-
939
- // There are pending Consumer tasks, enqueue their creation.
940
- if (this._pendingConsumerTasks.length > 0)
941
- {
942
- this._createPendingConsumers();
943
- }
944
- })
945
- // NOTE: We only get here when the await queue is closed.
946
- .catch(() => {});
947
- }
948
-
949
- _pausePendingConsumers()
950
- {
951
- this._consumerPauseInProgress = true;
952
-
953
- this._awaitQueue.push(
954
- async () =>
955
- {
956
- if (this._pendingPauseConsumers.size === 0)
957
- {
958
- logger.debug('_pausePendingConsumers() | there is no Consumer to be paused');
959
-
960
- return;
961
- }
962
-
963
- const pendingPauseConsumers = Array.from(this._pendingPauseConsumers.values());
964
-
965
- // Clear pending pause Consumer map.
966
- this._pendingPauseConsumers.clear();
967
-
968
- try
969
- {
970
- const localIds = pendingPauseConsumers
971
- .map((consumer) => consumer.localId);
972
-
973
- await this._handler.pauseReceiving(localIds);
974
- }
975
- catch (error)
976
- {
977
- logger.error('_pausePendingConsumers() | failed to pause Consumers:', error);
978
- }
979
- },
980
- 'transport._pausePendingConsumers')
981
- .then(() =>
982
- {
983
- this._consumerPauseInProgress = false;
984
-
985
- // There are pending Consumers to be paused, do it.
986
- if (this._pendingPauseConsumers.size > 0)
987
- {
988
- this._pausePendingConsumers();
989
- }
990
- })
991
- // NOTE: We only get here when the await queue is closed.
992
- .catch(() => { });
993
- }
994
-
995
- _resumePendingConsumers()
996
- {
997
- this._consumerResumeInProgress = true;
998
-
999
- this._awaitQueue.push(
1000
- async () =>
1001
- {
1002
- if (this._pendingResumeConsumers.size === 0)
1003
- {
1004
- logger.debug('_resumePendingConsumers() | there is no Consumer to be resumed');
1005
-
1006
- return;
1007
- }
1008
-
1009
- const pendingResumeConsumers = Array.from(this._pendingResumeConsumers.values());
1010
-
1011
- // Clear pending resume Consumer map.
1012
- this._pendingResumeConsumers.clear();
1013
-
1014
- try
1015
- {
1016
- const localIds = pendingResumeConsumers
1017
- .map((consumer) => consumer.localId);
1018
-
1019
- await this._handler.resumeReceiving(localIds);
1020
- }
1021
- catch (error)
1022
- {
1023
- logger.error('_resumePendingConsumers() | failed to resume Consumers:', error);
1024
- }
1025
- },
1026
- 'transport._resumePendingConsumers')
1027
- .then(() =>
1028
- {
1029
- this._consumerResumeInProgress = false;
1030
-
1031
- // There are pending Consumer to be resumed, do it.
1032
- if (this._pendingResumeConsumers.size > 0)
1033
- {
1034
- this._resumePendingConsumers();
1035
- }
1036
- })
1037
- // NOTE: We only get here when the await queue is closed.
1038
- .catch(() => { });
1039
- }
1040
-
1041
- _closePendingConsumers()
1042
- {
1043
- this._consumerCloseInProgress = true;
1044
-
1045
- this._awaitQueue.push(
1046
- async () =>
1047
- {
1048
- if (this._pendingCloseConsumers.size === 0)
1049
- {
1050
- logger.debug('_closePendingConsumers() | there is no Consumer to be closed');
1051
-
1052
- return;
1053
- }
1054
-
1055
- const pendingCloseConsumers = Array.from(this._pendingCloseConsumers.values());
1056
-
1057
- // Clear pending close Consumer map.
1058
- this._pendingCloseConsumers.clear();
1059
-
1060
- try
1061
- {
1062
- await this._handler.stopReceiving(
1063
- pendingCloseConsumers.map((consumer) => consumer.localId)
1064
- );
1065
- }
1066
- catch (error)
1067
- {
1068
- logger.error('_closePendingConsumers() | failed to close Consumers:', error);
1069
- }
1070
- },
1071
- 'transport._closePendingConsumers')
1072
- .then(() =>
1073
- {
1074
- this._consumerCloseInProgress = false;
1075
-
1076
- // There are pending Consumer to be resumed, do it.
1077
- if (this._pendingCloseConsumers.size > 0)
1078
- {
1079
- this._closePendingConsumers();
1080
- }
1081
- })
1082
- // NOTE: We only get here when the await queue is closed.
1083
- .catch(() => { });
1084
- }
1085
- _handleHandler(): void
1086
- {
1087
- const handler = this._handler;
1088
-
1089
- handler.on('@connect', (
1090
- { dtlsParameters }: { dtlsParameters: DtlsParameters },
1091
- callback: () => void,
1092
- errback: (error: Error) => void
1093
- ) =>
1094
- {
1095
- if (this._closed)
1096
- {
1097
- errback(new InvalidStateError('closed'));
1098
-
1099
- return;
1100
- }
1101
-
1102
- this.safeEmit('connect', { dtlsParameters }, callback, errback);
1103
- });
1104
-
1105
- handler.on('@connectionstatechange', (connectionState: ConnectionState) =>
1106
- {
1107
- if (connectionState === this._connectionState)
1108
- return;
1109
-
1110
- logger.debug('connection state changed to %s', connectionState);
1111
-
1112
- this._connectionState = connectionState;
1113
-
1114
- if (!this._closed)
1115
- this.safeEmit('connectionstatechange', connectionState);
1116
- });
1117
- }
1118
-
1119
- _handleProducer(producer: Producer): void
1120
- {
1121
- producer.on('@close', () =>
1122
- {
1123
- this._producers.delete(producer.id);
1124
-
1125
- if (this._closed)
1126
- return;
1127
-
1128
- this._awaitQueue.push(
1129
- async () => this._handler.stopSending(producer.localId),
1130
- 'producer @close event')
1131
- .catch((error: Error) => logger.warn('producer.close() failed:%o', error));
1132
- });
1133
-
1134
- producer.on('@pause', (callback, errback) =>
1135
- {
1136
- this._awaitQueue.push(
1137
- async () => this._handler.pauseSending(producer.localId),
1138
- 'producer @pause event')
1139
- .then(callback)
1140
- .catch(errback);
1141
- });
1142
-
1143
- producer.on('@resume', (callback, errback) =>
1144
- {
1145
- this._awaitQueue.push(
1146
- async () => this._handler.resumeSending(producer.localId),
1147
- 'producer @resume event')
1148
- .then(callback)
1149
- .catch(errback);
1150
- });
1151
-
1152
- producer.on('@replacetrack', (track, callback, errback) =>
1153
- {
1154
- this._awaitQueue.push(
1155
- async () => this._handler.replaceTrack(producer.localId, track),
1156
- 'producer @replacetrack event')
1157
- .then(callback)
1158
- .catch(errback);
1159
- });
1160
-
1161
- producer.on('@setmaxspatiallayer', (spatialLayer, callback, errback) =>
1162
- {
1163
- this._awaitQueue.push(
1164
- async () => (
1165
- this._handler.setMaxSpatialLayer(producer.localId, spatialLayer)
1166
- ), 'producer @setmaxspatiallayer event')
1167
- .then(callback)
1168
- .catch(errback);
1169
- });
1170
-
1171
- producer.on('@setrtpencodingparameters', (params, callback, errback) =>
1172
- {
1173
- this._awaitQueue.push(
1174
- async () => (
1175
- this._handler.setRtpEncodingParameters(producer.localId, params)
1176
- ), 'producer @setrtpencodingparameters event')
1177
- .then(callback)
1178
- .catch(errback);
1179
- });
1180
-
1181
- producer.on('@getstats', (callback, errback) =>
1182
- {
1183
- if (this._closed)
1184
- return errback!(new InvalidStateError('closed'));
1185
-
1186
- this._handler.getSenderStats(producer.localId)
1187
- .then(callback)
1188
- .catch(errback);
1189
- });
1190
- }
1191
-
1192
- _handleConsumer(consumer: Consumer): void
1193
- {
1194
- consumer.on('@close', () =>
1195
- {
1196
- this._consumers.delete(consumer.id);
1197
- this._pendingPauseConsumers.delete(consumer.id);
1198
- this._pendingResumeConsumers.delete(consumer.id);
1199
-
1200
- if (this._closed)
1201
- return;
1202
-
1203
- // Store the Consumer into the close list.
1204
- this._pendingCloseConsumers.set(consumer.id, consumer);
1205
-
1206
- // There is no Consumer close in progress, do it now.
1207
- if (this._consumerCloseInProgress === false)
1208
- {
1209
- this._closePendingConsumers();
1210
- }
1211
- });
1212
-
1213
- consumer.on('@pause', () =>
1214
- {
1215
- // If Consumer is pending to be resumed, remove from pending resume list.
1216
- if (this._pendingResumeConsumers.has(consumer.id))
1217
- {
1218
- this._pendingResumeConsumers.delete(consumer.id);
1219
- }
1220
-
1221
- // Store the Consumer into the pending list.
1222
- this._pendingPauseConsumers.set(consumer.id, consumer);
1223
-
1224
- // There is no Consumer pause in progress, do it now.
1225
- if (this._consumerPauseInProgress === false)
1226
- {
1227
- this._pausePendingConsumers();
1228
- }
1229
- });
1230
-
1231
- consumer.on('@resume', () =>
1232
- {
1233
- // If Consumer is pending to be paused, remove from pending pause list.
1234
- if (this._pendingPauseConsumers.has(consumer.id))
1235
- {
1236
- this._pendingPauseConsumers.delete(consumer.id);
1237
- }
1238
-
1239
- // Store the Consumer into the pending list.
1240
- this._pendingResumeConsumers.set(consumer.id, consumer);
1241
-
1242
- // There is no Consumer resume in progress, do it now.
1243
- if (this._consumerResumeInProgress === false)
1244
- {
1245
- this._resumePendingConsumers();
1246
- }
1247
- });
1248
-
1249
- consumer.on('@getstats', (callback, errback) =>
1250
- {
1251
- if (this._closed)
1252
- return errback!(new InvalidStateError('closed'));
1253
-
1254
- this._handler.getReceiverStats(consumer.localId)
1255
- .then(callback)
1256
- .catch(errback);
1257
- });
1258
- }
1259
-
1260
- _handleDataProducer(dataProducer: DataProducer): void
1261
- {
1262
- dataProducer.on('@close', () =>
1263
- {
1264
- this._dataProducers.delete(dataProducer.id);
1265
- });
1266
- }
1267
-
1268
- _handleDataConsumer(dataConsumer: DataConsumer): void
1269
- {
1270
- dataConsumer.on('@close', () =>
1271
- {
1272
- this._dataConsumers.delete(dataConsumer.id);
1273
- });
1274
- }
1275
- }