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.
- package/README.md +17 -3
- package/lib/Consumer.d.ts +3 -3
- package/lib/Consumer.d.ts.map +1 -1
- package/lib/DataConsumer.d.ts +3 -3
- package/lib/DataConsumer.d.ts.map +1 -1
- package/lib/DataProducer.d.ts +3 -3
- package/lib/DataProducer.d.ts.map +1 -1
- package/lib/Device.d.ts +3 -3
- package/lib/Device.d.ts.map +1 -1
- package/lib/EnhancedEventEmitter.d.ts +1 -1
- package/lib/EnhancedEventEmitter.d.ts.map +1 -1
- package/lib/Producer.d.ts +4 -4
- package/lib/Producer.d.ts.map +1 -1
- package/lib/RtpParameters.d.ts +11 -11
- package/lib/RtpParameters.d.ts.map +1 -1
- package/lib/SctpParameters.d.ts +4 -4
- package/lib/SctpParameters.d.ts.map +1 -1
- package/lib/Transport.d.ts +11 -11
- package/lib/Transport.d.ts.map +1 -1
- package/lib/handlers/Chrome55.js +6 -6
- package/lib/handlers/Chrome67.js +6 -6
- package/lib/handlers/Chrome70.d.ts.map +1 -1
- package/lib/handlers/Chrome70.js +10 -7
- package/lib/handlers/Chrome74.d.ts.map +1 -1
- package/lib/handlers/Chrome74.js +10 -7
- package/lib/handlers/Edge11.js +6 -6
- package/lib/handlers/FakeHandler.d.ts +1 -1
- package/lib/handlers/FakeHandler.d.ts.map +1 -1
- package/lib/handlers/FakeHandler.js +6 -6
- package/lib/handlers/Firefox60.d.ts.map +1 -1
- package/lib/handlers/Firefox60.js +10 -7
- package/lib/handlers/HandlerInterface.d.ts +11 -11
- package/lib/handlers/HandlerInterface.d.ts.map +1 -1
- package/lib/handlers/ReactNative.js +6 -6
- package/lib/handlers/Safari11.js +6 -6
- package/lib/handlers/Safari12.d.ts.map +1 -1
- package/lib/handlers/Safari12.js +10 -7
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/scalabilityModes.d.ts +1 -1
- package/lib/scalabilityModes.d.ts.map +1 -1
- package/npm-scripts.js +124 -28
- package/package.json +17 -5
- package/.eslintrc.js +0 -243
- package/.github/FUNDING.yml +0 -12
- package/.github/ISSUE_TEMPLATE/Bug_Report.md +0 -24
- package/.github/ISSUE_TEMPLATE/Feature_Request.md +0 -7
- package/.github/ISSUE_TEMPLATE/Support_Question.md +0 -12
- package/.travis.yml +0 -26
- package/src/Consumer.ts +0 -334
- package/src/DataConsumer.ts +0 -271
- package/src/DataProducer.ts +0 -291
- package/src/Device.ts +0 -584
- package/src/EnhancedEventEmitter.ts +0 -133
- package/src/Logger.ts +0 -47
- package/src/Producer.ts +0 -534
- package/src/RtpParameters.ts +0 -326
- package/src/SctpParameters.ts +0 -74
- package/src/Transport.ts +0 -1275
- package/src/errors.ts +0 -45
- package/src/handlers/Chrome55.ts +0 -866
- package/src/handlers/Chrome67.ts +0 -951
- package/src/handlers/Chrome70.ts +0 -964
- package/src/handlers/Chrome74.ts +0 -1058
- package/src/handlers/Edge11.ts +0 -667
- package/src/handlers/FakeHandler.ts +0 -448
- package/src/handlers/Firefox60.ts +0 -1040
- package/src/handlers/HandlerInterface.ts +0 -162
- package/src/handlers/ReactNative.ts +0 -886
- package/src/handlers/Safari11.ts +0 -944
- package/src/handlers/Safari12.ts +0 -1009
- package/src/handlers/ortc/edgeUtils.ts +0 -77
- package/src/handlers/sdp/MediaSection.ts +0 -836
- package/src/handlers/sdp/RemoteSdp.ts +0 -474
- package/src/handlers/sdp/commonUtils.ts +0 -259
- package/src/handlers/sdp/plainRtpUtils.ts +0 -58
- package/src/handlers/sdp/planBUtils.ts +0 -227
- package/src/handlers/sdp/unifiedPlanUtils.ts +0 -188
- package/src/index.ts +0 -28
- package/src/ortc.ts +0 -1169
- package/src/scalabilityModes.ts +0 -27
- package/src/types.ts +0 -11
- package/src/utils.ts +0 -18
- package/test/fakeParameters.js +0 -701
- package/test/test.js +0 -1672
- 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
|
-
}
|