node-rtc-connection 1.0.4 → 1.0.6
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/dist/index.cjs +2667 -2547
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2667 -2547
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
- package/src/NativePeerConnectionFactory.js +125 -17
- package/src/RTCPeerConnection.js +12 -1
- package/src/index.d.ts +229 -0
- package/src/index.js +1 -0
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-rtc-connection",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "WebRTC DataChannel implementation for Node.js with STUN, TURN, NAT traversal, and encryption. Pure Node.js, no native dependencies.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
9
11
|
"require": "./dist/index.cjs",
|
|
10
12
|
"import": "./dist/index.mjs"
|
|
11
13
|
}
|
|
@@ -100,6 +100,9 @@ class NativePeerConnection extends EventEmitter {
|
|
|
100
100
|
this._secureConnection = null;
|
|
101
101
|
this._udpTransport = null;
|
|
102
102
|
this._iceCandidates = [];
|
|
103
|
+
this._remoteCandidates = [];
|
|
104
|
+
this._selectedLocalCandidate = null;
|
|
105
|
+
this._selectedRemoteCandidate = null;
|
|
103
106
|
|
|
104
107
|
console.log('[NativePeerConnection] Created with STUN/ICE/Encryption support');
|
|
105
108
|
console.log(` - Encryption: ${this._useEncryption ? 'enabled' : 'disabled (requires valid certs)'}`);
|
|
@@ -245,22 +248,106 @@ class NativePeerConnection extends EventEmitter {
|
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
if (!candidate || !candidate.candidate) {
|
|
251
|
+
// null candidate signals end of candidates - try to select best pair
|
|
252
|
+
if (this._remoteCandidates.length > 0 && !this._selectedRemoteCandidate) {
|
|
253
|
+
this._selectBestCandidatePair();
|
|
254
|
+
}
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Parse ICE candidate
|
|
259
|
+
const parsed = this._parseIceCandidate(candidate.candidate);
|
|
260
|
+
if (!parsed) {
|
|
248
261
|
return;
|
|
249
262
|
}
|
|
250
263
|
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
264
|
+
// Store the remote candidate
|
|
265
|
+
this._remoteCandidates.push(parsed);
|
|
266
|
+
console.log(`[NativePeerConnection] Added remote ICE candidate (${parsed.type}): ${parsed.ip}:${parsed.port}`);
|
|
267
|
+
|
|
268
|
+
// For backward compatibility, set remote address immediately if not set
|
|
269
|
+
if (!this._remoteAddress) {
|
|
270
|
+
this._remoteAddress = parsed.ip;
|
|
271
|
+
this._remotePort = parsed.port;
|
|
256
272
|
console.log(`[NativePeerConnection] Remote address: ${this._remoteAddress}:${this._remotePort}`);
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// If we haven't selected a pair yet, try to select now
|
|
276
|
+
if (!this._selectedRemoteCandidate && this._iceCandidates.length > 0) {
|
|
277
|
+
this._selectBestCandidatePair();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// If we selected a pair and are offerer, connect
|
|
281
|
+
if (this._selectedRemoteCandidate && this._isOfferer &&
|
|
282
|
+
this._signalingState === 0 && !this._socket) {
|
|
283
|
+
await this._connectToPeer();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Parse ICE candidate string
|
|
289
|
+
* @private
|
|
290
|
+
*/
|
|
291
|
+
_parseIceCandidate(candidateStr) {
|
|
292
|
+
const parts = candidateStr.split(' ');
|
|
293
|
+
if (parts.length < 6) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
foundation: parts[0].replace('candidate:', ''),
|
|
299
|
+
component: parts[1],
|
|
300
|
+
protocol: parts[2],
|
|
301
|
+
priority: parseInt(parts[3], 10),
|
|
302
|
+
ip: parts[4],
|
|
303
|
+
port: parseInt(parts[5], 10),
|
|
304
|
+
type: parts[7], // typ host/srflx/relay
|
|
305
|
+
relatedAddress: parts[9] || null,
|
|
306
|
+
relatedPort: parts[11] ? parseInt(parts[11], 10) : null
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Select best candidate pair for connection
|
|
312
|
+
* Prioritizes: relay > srflx > host
|
|
313
|
+
* @private
|
|
314
|
+
*/
|
|
315
|
+
_selectBestCandidatePair() {
|
|
316
|
+
if (this._remoteCandidates.length === 0 || this._iceCandidates.length === 0) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Priority order: relay > srflx > host
|
|
321
|
+
const typePriority = { 'relay': 3, 'srflx': 2, 'host': 1 };
|
|
322
|
+
|
|
323
|
+
// Find best local candidate
|
|
324
|
+
let bestLocal = this._iceCandidates[0];
|
|
325
|
+
for (const candidate of this._iceCandidates) {
|
|
326
|
+
if (typePriority[candidate.type] > typePriority[bestLocal.type]) {
|
|
327
|
+
bestLocal = candidate;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Find best remote candidate
|
|
332
|
+
let bestRemote = this._remoteCandidates[0];
|
|
333
|
+
for (const candidate of this._remoteCandidates) {
|
|
334
|
+
if (typePriority[candidate.type] > typePriority[bestRemote.type]) {
|
|
335
|
+
bestRemote = candidate;
|
|
262
336
|
}
|
|
263
337
|
}
|
|
338
|
+
|
|
339
|
+
this._selectedLocalCandidate = bestLocal;
|
|
340
|
+
this._selectedRemoteCandidate = bestRemote;
|
|
341
|
+
|
|
342
|
+
// Update addresses for connection
|
|
343
|
+
this._localAddress = bestLocal.ip;
|
|
344
|
+
this._localPort = bestLocal.port;
|
|
345
|
+
this._remoteAddress = bestRemote.ip;
|
|
346
|
+
this._remotePort = bestRemote.port;
|
|
347
|
+
|
|
348
|
+
console.log(`[NativePeerConnection] Selected candidate pair:`);
|
|
349
|
+
console.log(` Local: ${bestLocal.type} ${this._localAddress}:${this._localPort}`);
|
|
350
|
+
console.log(` Remote: ${bestRemote.type} ${this._remoteAddress}:${this._remotePort}`);
|
|
264
351
|
}
|
|
265
352
|
|
|
266
353
|
/**
|
|
@@ -396,14 +483,24 @@ class NativePeerConnection extends EventEmitter {
|
|
|
396
483
|
return;
|
|
397
484
|
}
|
|
398
485
|
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
486
|
+
// Check if we're using relay candidates - if so, skip tie-breaking
|
|
487
|
+
const usingRelay = this._selectedLocalCandidate?.type === 'relay' ||
|
|
488
|
+
this._selectedRemoteCandidate?.type === 'relay';
|
|
489
|
+
|
|
490
|
+
if (!usingRelay) {
|
|
491
|
+
// Tie-breaking: only connect if our port is higher than remote port
|
|
492
|
+
// This ensures only one peer connects, avoiding the race condition
|
|
493
|
+
// Note: This only works for direct connections (host/srflx)
|
|
494
|
+
if (this._localPort < this._remotePort) {
|
|
495
|
+
console.log(`[NativePeerConnection] Not connecting (local port ${this._localPort} < remote port ${this._remotePort}), waiting for incoming`);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
404
498
|
}
|
|
405
499
|
|
|
406
500
|
console.log(`[NativePeerConnection] Connecting to ${this._remoteAddress}:${this._remotePort}`);
|
|
501
|
+
if (usingRelay) {
|
|
502
|
+
console.log(`[NativePeerConnection] Using TURN relay connection`);
|
|
503
|
+
}
|
|
407
504
|
|
|
408
505
|
this._socket = new net.Socket();
|
|
409
506
|
|
|
@@ -696,7 +793,12 @@ a=max-message-size:262144
|
|
|
696
793
|
|
|
697
794
|
// Emit each candidate
|
|
698
795
|
for (const candidate of candidates) {
|
|
699
|
-
|
|
796
|
+
// Parse and store the candidate
|
|
797
|
+
const parsed = this._parseIceCandidate(candidate.candidate);
|
|
798
|
+
if (parsed) {
|
|
799
|
+
this._iceCandidates.push(parsed);
|
|
800
|
+
}
|
|
801
|
+
|
|
700
802
|
this.emit('icecandidate', {
|
|
701
803
|
candidate: candidate.candidate,
|
|
702
804
|
sdpMid: candidate.sdpMid,
|
|
@@ -710,8 +812,14 @@ a=max-message-size:262144
|
|
|
710
812
|
|
|
711
813
|
// Fallback: emit only local host candidate
|
|
712
814
|
if (this._localAddress && this._localPort) {
|
|
815
|
+
const candidateStr = `candidate:1 1 tcp 2130706431 ${this._localAddress} ${this._localPort} typ host`;
|
|
816
|
+
const parsed = this._parseIceCandidate(candidateStr);
|
|
817
|
+
if (parsed) {
|
|
818
|
+
this._iceCandidates.push(parsed);
|
|
819
|
+
}
|
|
820
|
+
|
|
713
821
|
const candidate = {
|
|
714
|
-
candidate:
|
|
822
|
+
candidate: candidateStr,
|
|
715
823
|
sdpMid: 'data',
|
|
716
824
|
sdpMLineIndex: 0
|
|
717
825
|
};
|
package/src/RTCPeerConnection.js
CHANGED
|
@@ -3,6 +3,16 @@ const RTCDataChannel = require('./RTCDataChannel');
|
|
|
3
3
|
const RTCSessionDescription = require('./RTCSessionDescription');
|
|
4
4
|
const RTCIceCandidate = require('./RTCIceCandidate');
|
|
5
5
|
|
|
6
|
+
// Lazy-load factory to avoid circular dependency
|
|
7
|
+
let _defaultFactory = null;
|
|
8
|
+
function getDefaultFactory() {
|
|
9
|
+
if (!_defaultFactory) {
|
|
10
|
+
const NativePeerConnectionFactory = require('./NativePeerConnectionFactory');
|
|
11
|
+
_defaultFactory = new NativePeerConnectionFactory();
|
|
12
|
+
}
|
|
13
|
+
return _defaultFactory;
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
/**
|
|
7
17
|
* RTCPeerConnection represents a WebRTC connection between the local computer and a remote peer.
|
|
8
18
|
* This is a DataChannel-only implementation ported from Chromium.
|
|
@@ -25,7 +35,8 @@ class RTCPeerConnection extends EventEmitter {
|
|
|
25
35
|
|
|
26
36
|
// Native peer connection (would be native WebRTC binding)
|
|
27
37
|
this._nativePeerConnection = null;
|
|
28
|
-
|
|
38
|
+
// Use provided factory or default factory
|
|
39
|
+
this._nativePeerConnectionFactory = nativePeerConnectionFactory || getDefaultFactory();
|
|
29
40
|
|
|
30
41
|
// Initialize native peer connection
|
|
31
42
|
this._initializeNativePeerConnection();
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// Type definitions for node-rtc-connection
|
|
2
|
+
// Project: https://github.com/nmhung1210/nodertc
|
|
3
|
+
// Definitions by: nmhung1210
|
|
4
|
+
|
|
5
|
+
/// <reference types="node" />
|
|
6
|
+
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
|
|
9
|
+
// RTCConfiguration
|
|
10
|
+
export interface RTCIceServer {
|
|
11
|
+
urls: string | string[];
|
|
12
|
+
username?: string;
|
|
13
|
+
credential?: string;
|
|
14
|
+
credentialType?: 'password' | 'oauth';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RTCConfiguration {
|
|
18
|
+
iceServers?: RTCIceServer[];
|
|
19
|
+
iceTransportPolicy?: 'all' | 'relay';
|
|
20
|
+
bundlePolicy?: 'balanced' | 'max-compat' | 'max-bundle';
|
|
21
|
+
rtcpMuxPolicy?: 'negotiate' | 'require';
|
|
22
|
+
iceCandidatePoolSize?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// RTCSessionDescription
|
|
26
|
+
export type RTCSdpType = 'offer' | 'answer' | 'pranswer' | 'rollback';
|
|
27
|
+
|
|
28
|
+
export interface RTCSessionDescriptionInit {
|
|
29
|
+
type: RTCSdpType;
|
|
30
|
+
sdp?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class RTCSessionDescription {
|
|
34
|
+
constructor(descriptionInitDict?: RTCSessionDescriptionInit);
|
|
35
|
+
readonly type: RTCSdpType;
|
|
36
|
+
readonly sdp: string;
|
|
37
|
+
toJSON(): RTCSessionDescriptionInit;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// RTCIceCandidate
|
|
41
|
+
export type RTCIceCandidateType = 'host' | 'srflx' | 'prflx' | 'relay';
|
|
42
|
+
export type RTCIceProtocol = 'udp' | 'tcp';
|
|
43
|
+
export type RTCIceTcpCandidateType = 'active' | 'passive' | 'so';
|
|
44
|
+
|
|
45
|
+
export interface RTCIceCandidateInit {
|
|
46
|
+
candidate?: string;
|
|
47
|
+
sdpMid?: string | null;
|
|
48
|
+
sdpMLineIndex?: number | null;
|
|
49
|
+
usernameFragment?: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class RTCIceCandidate {
|
|
53
|
+
constructor(candidateInitDict?: RTCIceCandidateInit);
|
|
54
|
+
readonly candidate: string;
|
|
55
|
+
readonly sdpMid: string | null;
|
|
56
|
+
readonly sdpMLineIndex: number | null;
|
|
57
|
+
readonly foundation: string | null;
|
|
58
|
+
readonly component: 'rtp' | 'rtcp' | null;
|
|
59
|
+
readonly priority: number | null;
|
|
60
|
+
readonly address: string | null;
|
|
61
|
+
readonly protocol: RTCIceProtocol | null;
|
|
62
|
+
readonly port: number | null;
|
|
63
|
+
readonly type: RTCIceCandidateType | null;
|
|
64
|
+
readonly tcpType: RTCIceTcpCandidateType | null;
|
|
65
|
+
readonly relatedAddress: string | null;
|
|
66
|
+
readonly relatedPort: number | null;
|
|
67
|
+
readonly usernameFragment: string | null;
|
|
68
|
+
toJSON(): RTCIceCandidateInit;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// RTCDataChannel
|
|
72
|
+
export type RTCDataChannelState = 'connecting' | 'open' | 'closing' | 'closed';
|
|
73
|
+
export type RTCBinaryType = 'blob' | 'arraybuffer';
|
|
74
|
+
|
|
75
|
+
export interface RTCDataChannelInit {
|
|
76
|
+
ordered?: boolean;
|
|
77
|
+
maxPacketLifeTime?: number;
|
|
78
|
+
maxRetransmits?: number;
|
|
79
|
+
protocol?: string;
|
|
80
|
+
negotiated?: boolean;
|
|
81
|
+
id?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface RTCDataChannelEventMap {
|
|
85
|
+
open: Event;
|
|
86
|
+
message: MessageEvent;
|
|
87
|
+
error: RTCErrorEvent;
|
|
88
|
+
close: Event;
|
|
89
|
+
bufferedamountlow: Event;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class RTCDataChannel extends EventEmitter {
|
|
93
|
+
readonly label: string;
|
|
94
|
+
readonly ordered: boolean;
|
|
95
|
+
readonly maxPacketLifeTime: number | null;
|
|
96
|
+
readonly maxRetransmits: number | null;
|
|
97
|
+
readonly protocol: string;
|
|
98
|
+
readonly negotiated: boolean;
|
|
99
|
+
readonly id: number | null;
|
|
100
|
+
readonly readyState: RTCDataChannelState;
|
|
101
|
+
readonly bufferedAmount: number;
|
|
102
|
+
bufferedAmountLowThreshold: number;
|
|
103
|
+
binaryType: RTCBinaryType;
|
|
104
|
+
|
|
105
|
+
close(): void;
|
|
106
|
+
send(data: string | ArrayBuffer | ArrayBufferView): void;
|
|
107
|
+
|
|
108
|
+
on<K extends keyof RTCDataChannelEventMap>(event: K, listener: (ev: RTCDataChannelEventMap[K]) => void): this;
|
|
109
|
+
once<K extends keyof RTCDataChannelEventMap>(event: K, listener: (ev: RTCDataChannelEventMap[K]) => void): this;
|
|
110
|
+
off<K extends keyof RTCDataChannelEventMap>(event: K, listener: (ev: RTCDataChannelEventMap[K]) => void): this;
|
|
111
|
+
emit<K extends keyof RTCDataChannelEventMap>(event: K, ...args: any[]): boolean;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// RTCPeerConnection
|
|
115
|
+
export type RTCSignalingState = 'stable' | 'have-local-offer' | 'have-remote-offer' |
|
|
116
|
+
'have-local-pranswer' | 'have-remote-pranswer' | 'closed';
|
|
117
|
+
|
|
118
|
+
export type RTCIceGatheringState = 'new' | 'gathering' | 'complete';
|
|
119
|
+
|
|
120
|
+
export type RTCIceConnectionState = 'new' | 'checking' | 'connected' | 'completed' |
|
|
121
|
+
'failed' | 'disconnected' | 'closed';
|
|
122
|
+
|
|
123
|
+
export type RTCPeerConnectionState = 'new' | 'connecting' | 'connected' |
|
|
124
|
+
'disconnected' | 'failed' | 'closed';
|
|
125
|
+
|
|
126
|
+
export interface RTCOfferOptions {
|
|
127
|
+
iceRestart?: boolean;
|
|
128
|
+
offerToReceiveAudio?: boolean;
|
|
129
|
+
offerToReceiveVideo?: boolean;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface RTCAnswerOptions {
|
|
133
|
+
iceRestart?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface RTCDataChannelEventInit {
|
|
137
|
+
channel: RTCDataChannel;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export class RTCDataChannelEvent extends Event {
|
|
141
|
+
constructor(type: string, eventInitDict: RTCDataChannelEventInit);
|
|
142
|
+
readonly channel: RTCDataChannel;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface RTCPeerConnectionIceEventInit {
|
|
146
|
+
candidate?: RTCIceCandidate | null;
|
|
147
|
+
url?: string | null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export class RTCPeerConnectionIceEvent extends Event {
|
|
151
|
+
constructor(type: string, eventInitDict?: RTCPeerConnectionIceEventInit);
|
|
152
|
+
readonly candidate: RTCIceCandidate | null;
|
|
153
|
+
readonly url: string | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface RTCPeerConnectionEventMap {
|
|
157
|
+
connectionstatechange: Event;
|
|
158
|
+
datachannel: RTCDataChannelEvent;
|
|
159
|
+
icecandidate: RTCPeerConnectionIceEvent;
|
|
160
|
+
icecandidateerror: Event;
|
|
161
|
+
iceconnectionstatechange: Event;
|
|
162
|
+
icegatheringstatechange: Event;
|
|
163
|
+
negotiationneeded: Event;
|
|
164
|
+
signalingstatechange: Event;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export class RTCPeerConnection extends EventEmitter {
|
|
168
|
+
constructor(configuration?: RTCConfiguration, factory?: NativePeerConnectionFactory);
|
|
169
|
+
|
|
170
|
+
readonly signalingState: RTCSignalingState;
|
|
171
|
+
readonly iceGatheringState: RTCIceGatheringState;
|
|
172
|
+
readonly iceConnectionState: RTCIceConnectionState;
|
|
173
|
+
readonly connectionState: RTCPeerConnectionState;
|
|
174
|
+
readonly localDescription: RTCSessionDescription | null;
|
|
175
|
+
readonly remoteDescription: RTCSessionDescription | null;
|
|
176
|
+
readonly pendingLocalDescription: RTCSessionDescription | null;
|
|
177
|
+
readonly pendingRemoteDescription: RTCSessionDescription | null;
|
|
178
|
+
readonly currentLocalDescription: RTCSessionDescription | null;
|
|
179
|
+
readonly currentRemoteDescription: RTCSessionDescription | null;
|
|
180
|
+
|
|
181
|
+
createOffer(options?: RTCOfferOptions): Promise<RTCSessionDescription>;
|
|
182
|
+
createAnswer(options?: RTCAnswerOptions): Promise<RTCSessionDescription>;
|
|
183
|
+
setLocalDescription(description: RTCSessionDescriptionInit): Promise<void>;
|
|
184
|
+
setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void>;
|
|
185
|
+
addIceCandidate(candidate?: RTCIceCandidateInit | null): Promise<void>;
|
|
186
|
+
createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): RTCDataChannel;
|
|
187
|
+
getConfiguration(): RTCConfiguration;
|
|
188
|
+
setConfiguration(configuration: RTCConfiguration): void;
|
|
189
|
+
close(): void;
|
|
190
|
+
getStats(): Promise<any>;
|
|
191
|
+
|
|
192
|
+
on<K extends keyof RTCPeerConnectionEventMap>(event: K, listener: (ev: RTCPeerConnectionEventMap[K]) => void): this;
|
|
193
|
+
once<K extends keyof RTCPeerConnectionEventMap>(event: K, listener: (ev: RTCPeerConnectionEventMap[K]) => void): this;
|
|
194
|
+
off<K extends keyof RTCPeerConnectionEventMap>(event: K, listener: (ev: RTCPeerConnectionEventMap[K]) => void): this;
|
|
195
|
+
emit<K extends keyof RTCPeerConnectionEventMap>(event: K, ...args: any[]): boolean;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// RTCError
|
|
199
|
+
export class RTCError extends Error {
|
|
200
|
+
constructor(message: string, errorDetail?: string);
|
|
201
|
+
readonly errorDetail: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface RTCErrorEventInit {
|
|
205
|
+
error: RTCError;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export class RTCErrorEvent extends Event {
|
|
209
|
+
constructor(type: string, eventInitDict: RTCErrorEventInit);
|
|
210
|
+
readonly error: RTCError;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// NativePeerConnectionFactory
|
|
214
|
+
export class NativePeerConnectionFactory {
|
|
215
|
+
constructor();
|
|
216
|
+
initialize(): void;
|
|
217
|
+
createPeerConnection(configuration: RTCConfiguration): any;
|
|
218
|
+
dispose(): void;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Factory functions
|
|
222
|
+
export function createPeerConnection(configuration?: RTCConfiguration): RTCPeerConnection;
|
|
223
|
+
export function createPeerConnectionWithFactory(configuration: RTCConfiguration, factory: NativePeerConnectionFactory): RTCPeerConnection;
|
|
224
|
+
|
|
225
|
+
// Alias
|
|
226
|
+
export { RTCPeerConnection as RTCConnection };
|
|
227
|
+
|
|
228
|
+
// Default factory instance
|
|
229
|
+
export const defaultFactory: NativePeerConnectionFactory;
|
package/src/index.js
CHANGED