node-datachannel 0.10.1 → 0.12.0
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/.github/workflows/build-linux.yml +7 -2
- package/.github/workflows/build-win.yml +3 -3
- package/.gitmodules +3 -0
- package/CMakeLists.txt +1 -1
- package/README.md +18 -4
- package/cmake/toolchain/ci.cmake +1 -1
- package/examples/client-server/client-benchmark.js +7 -9
- package/examples/client-server/client-periodic.js +7 -9
- package/examples/client-server/client.js +7 -9
- package/examples/client-server/package-lock.json +0 -27
- package/examples/client-server/package.json +0 -1
- package/examples/client-server/signaling-server.js +21 -10
- package/examples/electron-demo/README.md +1 -1
- package/examples/electron-demo/package-lock.json +316 -372
- package/examples/electron-demo/package.json +2 -1
- package/examples/electron-demo/webpack.main.config.js +10 -0
- package/examples/websocket/websocket-client.js +20 -0
- package/examples/websocket/websocket-server.js +22 -0
- package/jest.config.cjs +1 -1
- package/lib/index.cjs +52 -9
- package/lib/index.js +22 -15
- package/lib/node-datachannel.js +7 -0
- package/lib/websocket-server.js +34 -0
- package/package.json +3 -3
- package/polyfill/Events.js +5 -3
- package/polyfill/Exception.js +23 -0
- package/polyfill/README.md +4 -0
- package/polyfill/RTCDataChannel.js +19 -11
- package/polyfill/RTCError.d.ts +11 -0
- package/polyfill/RTCError.js +65 -0
- package/polyfill/RTCIceCandidate.js +22 -23
- package/polyfill/RTCPeerConnection.js +157 -42
- package/polyfill/index.cjs +350 -82
- package/polyfill/index.js +3 -0
- package/src/peer-connection-wrapper.cpp +11 -3
- package/src/web-socket-server-wrapper.cpp +23 -23
- package/src/web-socket-server-wrapper.h +8 -6
- package/src/web-socket-wrapper.cpp +7 -1
- package/test/connectivity.js +1 -23
- package/test/wpt-tests/README.md +46 -0
- package/test/wpt-tests/chrome-failed-tests.js +42 -0
- package/test/wpt-tests/index.js +96 -0
- package/test/wpt-tests/last-test-results.md +301 -0
- package/test/wpt-tests/package-lock.json +1712 -0
- package/test/wpt-tests/package.json +19 -0
- package/test/wpt-tests/wpt-test-list.js +139 -0
- package/test/wpt-tests/wpt.js +131 -0
- package/test/wpt.js +0 -50
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"@electron-forge/plugin-webpack": "^6.4.2",
|
|
28
28
|
"@electron/rebuild": "^3.3.0",
|
|
29
29
|
"@vercel/webpack-asset-relocator-loader": "^1.7.3",
|
|
30
|
+
"copy-webpack-plugin": "^12.0.2",
|
|
30
31
|
"css-loader": "^6.8.1",
|
|
31
32
|
"electron": "26.2.4",
|
|
32
33
|
"node-loader": "^2.0.0",
|
|
@@ -40,4 +41,4 @@
|
|
|
40
41
|
"runtime": "electron",
|
|
41
42
|
"runtimeVersion": "26.2.0"
|
|
42
43
|
}
|
|
43
|
-
}
|
|
44
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const CopyPlugin = require('copy-webpack-plugin');
|
|
2
|
+
|
|
1
3
|
module.exports = {
|
|
2
4
|
/**
|
|
3
5
|
* This is the main entry point for your application, it's the first file
|
|
@@ -8,4 +10,12 @@ module.exports = {
|
|
|
8
10
|
module: {
|
|
9
11
|
rules: require('./webpack.rules'),
|
|
10
12
|
},
|
|
13
|
+
externals: {
|
|
14
|
+
'node-datachannel': 'node-datachannel',
|
|
15
|
+
},
|
|
16
|
+
plugins: [
|
|
17
|
+
new CopyPlugin({
|
|
18
|
+
patterns: [{ from: 'node_modules/node-datachannel', to: 'node_modules/node-datachannel' }],
|
|
19
|
+
}),
|
|
20
|
+
],
|
|
11
21
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as nodeDataChannel from '../../lib/index.js';
|
|
2
|
+
|
|
3
|
+
const clientSocket = new nodeDataChannel.WebSocket();
|
|
4
|
+
|
|
5
|
+
clientSocket.open('ws://127.0.0.1:3000');
|
|
6
|
+
|
|
7
|
+
clientSocket.onOpen(() => {
|
|
8
|
+
console.log('Client socket opened');
|
|
9
|
+
clientSocket.sendMessage('Echo this!');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
clientSocket.onMessage((message) => {
|
|
13
|
+
console.log('Message from server: ' + message);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
clientSocket.onClosed(() => {
|
|
17
|
+
console.log('Client socket closed');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// clientSocket.close();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as nodeDataChannel from '../../lib/index.js';
|
|
2
|
+
|
|
3
|
+
const ws = new nodeDataChannel.WebSocketServer({ bindAddress: '127.0.0.1', port: 3000 });
|
|
4
|
+
|
|
5
|
+
ws.onClient((clientSocket) => {
|
|
6
|
+
clientSocket.onOpen(() => {
|
|
7
|
+
console.log('Client socket opened');
|
|
8
|
+
clientSocket.sendMessage('Hello from server');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
clientSocket.onMessage((message) => {
|
|
12
|
+
console.log('Message from client: ' + message);
|
|
13
|
+
clientSocket.sendMessage(message);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
clientSocket.onClosed(() => {
|
|
17
|
+
console.log('Client socket closed');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// When done, close the server
|
|
22
|
+
// ws.stop();
|
package/jest.config.cjs
CHANGED
package/lib/index.cjs
CHANGED
|
@@ -4,8 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var module$1 = require('module');
|
|
6
6
|
var stream = require('stream');
|
|
7
|
+
var events = require('events');
|
|
7
8
|
|
|
8
9
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
10
|
+
// createRequire is native in node version >= 12
|
|
11
|
+
const require$1 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
12
|
+
|
|
13
|
+
const nodeDataChannel = require$1('../build/Release/node_datachannel.node');
|
|
14
|
+
|
|
9
15
|
/**
|
|
10
16
|
* Turns a node-datachannel DataChannel into a real Node.js stream, complete with buffering,
|
|
11
17
|
* backpressure (up to a point - if the buffer fills up, messages are dropped), and
|
|
@@ -101,10 +107,37 @@ class DataChannelStream extends stream.Duplex {
|
|
|
101
107
|
}
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
|
|
110
|
+
class WebSocketServer extends events.EventEmitter {
|
|
111
|
+
#server;
|
|
112
|
+
#clients = [];
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
constructor(options) {
|
|
115
|
+
super();
|
|
116
|
+
this.#server = new nodeDataChannel.WebSocketServer(options);
|
|
117
|
+
|
|
118
|
+
this.#server.onClient((client) => {
|
|
119
|
+
this.emit('client', client);
|
|
120
|
+
this.#clients.push(client);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
port() {
|
|
125
|
+
return this.#server?.port() || 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
stop() {
|
|
129
|
+
this.#clients.forEach((client) => {
|
|
130
|
+
client?.close();
|
|
131
|
+
});
|
|
132
|
+
this.#server?.stop();
|
|
133
|
+
this.#server = null;
|
|
134
|
+
this.removeAllListeners();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
onClient(cb) {
|
|
138
|
+
if (this.#server) this.on('client', cb);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
108
141
|
|
|
109
142
|
const {
|
|
110
143
|
initLogger,
|
|
@@ -118,14 +151,8 @@ const {
|
|
|
118
151
|
DataChannel,
|
|
119
152
|
PeerConnection,
|
|
120
153
|
WebSocket,
|
|
121
|
-
WebSocketServer,
|
|
122
154
|
} = nodeDataChannel;
|
|
123
155
|
|
|
124
|
-
var index = {
|
|
125
|
-
...nodeDataChannel,
|
|
126
|
-
DataChannelStream,
|
|
127
|
-
};
|
|
128
|
-
|
|
129
156
|
const DescriptionType = {
|
|
130
157
|
Unspec: 'unspec',
|
|
131
158
|
Offer: 'offer',
|
|
@@ -134,6 +161,22 @@ const DescriptionType = {
|
|
|
134
161
|
Rollback: 'rollback',
|
|
135
162
|
};
|
|
136
163
|
|
|
164
|
+
var index = {
|
|
165
|
+
initLogger,
|
|
166
|
+
cleanup,
|
|
167
|
+
preload,
|
|
168
|
+
setSctpSettings,
|
|
169
|
+
RtcpReceivingSession,
|
|
170
|
+
Track,
|
|
171
|
+
Video,
|
|
172
|
+
Audio,
|
|
173
|
+
DataChannel,
|
|
174
|
+
PeerConnection,
|
|
175
|
+
WebSocket,
|
|
176
|
+
WebSocketServer,
|
|
177
|
+
DataChannelStream,
|
|
178
|
+
};
|
|
179
|
+
|
|
137
180
|
exports.Audio = Audio;
|
|
138
181
|
exports.DataChannel = DataChannel;
|
|
139
182
|
exports.DataChannelStream = DataChannelStream;
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { createRequire } from 'module';
|
|
3
|
-
const require = createRequire(import.meta.url);
|
|
4
|
-
|
|
5
|
-
const nodeDataChannel = require('../build/Release/node_datachannel.node');
|
|
1
|
+
import nodeDataChannel from './node-datachannel.js';
|
|
6
2
|
import DataChannelStream from './datachannel-stream.js';
|
|
3
|
+
import WebSocketServer from './websocket-server.js';
|
|
7
4
|
|
|
8
5
|
const {
|
|
9
6
|
initLogger,
|
|
@@ -17,9 +14,16 @@ const {
|
|
|
17
14
|
DataChannel,
|
|
18
15
|
PeerConnection,
|
|
19
16
|
WebSocket,
|
|
20
|
-
WebSocketServer,
|
|
21
17
|
} = nodeDataChannel;
|
|
22
18
|
|
|
19
|
+
export const DescriptionType = {
|
|
20
|
+
Unspec: 'unspec',
|
|
21
|
+
Offer: 'offer',
|
|
22
|
+
Answer: 'answer',
|
|
23
|
+
Pranswer: 'pranswer',
|
|
24
|
+
Rollback: 'rollback',
|
|
25
|
+
};
|
|
26
|
+
|
|
23
27
|
export {
|
|
24
28
|
initLogger,
|
|
25
29
|
cleanup,
|
|
@@ -38,14 +42,17 @@ export {
|
|
|
38
42
|
};
|
|
39
43
|
|
|
40
44
|
export default {
|
|
41
|
-
|
|
45
|
+
initLogger,
|
|
46
|
+
cleanup,
|
|
47
|
+
preload,
|
|
48
|
+
setSctpSettings,
|
|
49
|
+
RtcpReceivingSession,
|
|
50
|
+
Track,
|
|
51
|
+
Video,
|
|
52
|
+
Audio,
|
|
53
|
+
DataChannel,
|
|
54
|
+
PeerConnection,
|
|
55
|
+
WebSocket,
|
|
56
|
+
WebSocketServer,
|
|
42
57
|
DataChannelStream,
|
|
43
58
|
};
|
|
44
|
-
|
|
45
|
-
export const DescriptionType = {
|
|
46
|
-
Unspec: 'unspec',
|
|
47
|
-
Offer: 'offer',
|
|
48
|
-
Answer: 'answer',
|
|
49
|
-
Pranswer: 'pranswer',
|
|
50
|
-
Rollback: 'rollback',
|
|
51
|
-
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import nodeDataChannel from './node-datachannel.js';
|
|
3
|
+
|
|
4
|
+
export default class WebSocketServer extends EventEmitter {
|
|
5
|
+
#server;
|
|
6
|
+
#clients = [];
|
|
7
|
+
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super();
|
|
10
|
+
this.#server = new nodeDataChannel.WebSocketServer(options);
|
|
11
|
+
|
|
12
|
+
this.#server.onClient((client) => {
|
|
13
|
+
this.emit('client', client);
|
|
14
|
+
this.#clients.push(client);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
port() {
|
|
19
|
+
return this.#server?.port() || 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
stop() {
|
|
23
|
+
this.#clients.forEach((client) => {
|
|
24
|
+
client?.close();
|
|
25
|
+
});
|
|
26
|
+
this.#server?.stop();
|
|
27
|
+
this.#server = null;
|
|
28
|
+
this.removeAllListeners();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onClient(cb) {
|
|
32
|
+
if (this.#server) this.on('client', cb);
|
|
33
|
+
}
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-datachannel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "libdatachannel node bindings",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
"node-addon-api": "^7.0.0",
|
|
94
94
|
"prebuild": "^12.0.0",
|
|
95
95
|
"prettier": "^2.8.8",
|
|
96
|
-
"
|
|
97
|
-
"
|
|
96
|
+
"rollup": "^4.14.1",
|
|
97
|
+
"typescript": "^5.3.2"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
100
|
"node-domexception": "^2.0.1",
|
package/polyfill/Events.js
CHANGED
|
@@ -15,10 +15,12 @@ export class RTCPeerConnectionIceEvent extends Event {
|
|
|
15
15
|
export class RTCDataChannelEvent extends Event {
|
|
16
16
|
#channel;
|
|
17
17
|
|
|
18
|
-
constructor(
|
|
19
|
-
super(
|
|
18
|
+
constructor(type, eventInitDict) {
|
|
19
|
+
super(type);
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
if (type && !eventInitDict.channel) throw new TypeError('channel member is required');
|
|
22
|
+
|
|
23
|
+
this.#channel = eventInitDict?.channel;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
get channel() {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const InvalidStateError = (msg) => {
|
|
2
|
+
return new DOMException(msg, 'InvalidStateError');
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export const InvalidAccessError = (msg) => {
|
|
6
|
+
return new DOMException(msg, 'InvalidAccessError');
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const NotFoundError = (msg) => {
|
|
10
|
+
return new DOMException(msg, 'NotFoundError');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const OperationError = (msg) => {
|
|
14
|
+
return new DOMException(msg, 'OperationError');
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const TypeError = (msg) => {
|
|
18
|
+
return new DOMException(msg, 'TypeError');
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const SyntaxError = (msg) => {
|
|
22
|
+
return new DOMException(msg, 'SyntaxError');
|
|
23
|
+
};
|
package/polyfill/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import 'node-domexception';
|
|
2
|
+
import * as exceptions from './Exception.js';
|
|
2
3
|
|
|
3
4
|
export default class _RTCDataChannel extends EventTarget {
|
|
4
5
|
#dataChannel;
|
|
@@ -10,6 +11,8 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
10
11
|
#negotiated;
|
|
11
12
|
#ordered;
|
|
12
13
|
|
|
14
|
+
#closeRequested = false;
|
|
15
|
+
|
|
13
16
|
onbufferedamountlow;
|
|
14
17
|
onclose;
|
|
15
18
|
onclosing;
|
|
@@ -32,12 +35,20 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
32
35
|
// forward dataChannel events
|
|
33
36
|
this.#dataChannel.onOpen(() => {
|
|
34
37
|
this.#readyState = 'open';
|
|
35
|
-
this.dispatchEvent(new Event('open'));
|
|
38
|
+
this.dispatchEvent(new Event('open', { channel: this }));
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
this.#dataChannel.onClosed(() => {
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// Simulate closing event
|
|
43
|
+
if (!this.#closeRequested) {
|
|
44
|
+
this.#readyState = 'closing';
|
|
45
|
+
this.dispatchEvent(new Event('closing', { channel: this }));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setImmediate(() => {
|
|
49
|
+
this.#readyState = 'closed';
|
|
50
|
+
this.dispatchEvent(new Event('close', { channel: this }));
|
|
51
|
+
});
|
|
41
52
|
});
|
|
42
53
|
|
|
43
54
|
this.#dataChannel.onError((msg) => {
|
|
@@ -54,7 +65,7 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
54
65
|
});
|
|
55
66
|
|
|
56
67
|
this.#dataChannel.onBufferedAmountLow(() => {
|
|
57
|
-
this.dispatchEvent(new Event('bufferedamountlow'));
|
|
68
|
+
this.dispatchEvent(new Event('bufferedamountlow', { channel: this }));
|
|
58
69
|
});
|
|
59
70
|
|
|
60
71
|
this.#dataChannel.onMessage((data) => {
|
|
@@ -62,7 +73,7 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
62
73
|
data = data.buffer;
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
this.dispatchEvent(new MessageEvent('message', { data }));
|
|
76
|
+
this.dispatchEvent(new MessageEvent('message', { data, channel: this }));
|
|
66
77
|
});
|
|
67
78
|
|
|
68
79
|
// forward events to properties
|
|
@@ -148,9 +159,8 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
148
159
|
|
|
149
160
|
send(data) {
|
|
150
161
|
if (this.#readyState !== 'open') {
|
|
151
|
-
throw
|
|
162
|
+
throw exceptions.InvalidStateError(
|
|
152
163
|
"Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'",
|
|
153
|
-
'InvalidStateError',
|
|
154
164
|
);
|
|
155
165
|
}
|
|
156
166
|
|
|
@@ -167,9 +177,7 @@ export default class _RTCDataChannel extends EventTarget {
|
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
close() {
|
|
170
|
-
this.#
|
|
171
|
-
this.dispatchEvent(new Event('closing'));
|
|
172
|
-
|
|
180
|
+
this.#closeRequested = true;
|
|
173
181
|
this.#dataChannel.close();
|
|
174
182
|
}
|
|
175
183
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
|
|
3
|
+
export class _RTCError extends DOMException implements RTCError {
|
|
4
|
+
constructor(init: RTCErrorInit, message?: string);
|
|
5
|
+
// type RTCErrorDetailType = "data-channel-failure" | "dtls-failure" | "fingerprint-failure" | "hardware-encoder-error" | "hardware-encoder-not-available" | "sctp-failure" | "sdp-syntax-error";
|
|
6
|
+
readonly errorDetail: RTCErrorDetailType;
|
|
7
|
+
readonly receivedAlert: number | null;
|
|
8
|
+
readonly sctpCauseCode: number | null;
|
|
9
|
+
readonly sdpLineNumber: number | null;
|
|
10
|
+
readonly sentAlert: number | null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export default class RTCError extends DOMException {
|
|
2
|
+
constructor(init, message = '') {
|
|
3
|
+
super(message, 'OperationError');
|
|
4
|
+
|
|
5
|
+
if (!init || !init.errorDetail) throw new TypeError('Cannot construct RTCError, errorDetail is required');
|
|
6
|
+
if (
|
|
7
|
+
[
|
|
8
|
+
'data-channel-failure',
|
|
9
|
+
'dtls-failure',
|
|
10
|
+
'fingerprint-failure',
|
|
11
|
+
'hardware-encoder-error',
|
|
12
|
+
'hardware-encoder-not-available',
|
|
13
|
+
'sctp-failure',
|
|
14
|
+
'sdp-syntax-error',
|
|
15
|
+
].indexOf(init.errorDetail) === -1
|
|
16
|
+
)
|
|
17
|
+
throw new TypeError('Cannot construct RTCError, errorDetail is invalid');
|
|
18
|
+
|
|
19
|
+
this._errorDetail = init.errorDetail;
|
|
20
|
+
this._receivedAlert = init.receivedAlert ?? null;
|
|
21
|
+
this._sctpCauseCode = init.sctpCauseCode ?? null;
|
|
22
|
+
this._sdpLineNumber = init.sdpLineNumber ?? null;
|
|
23
|
+
this._sentAlert = init.sentAlert ?? null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get errorDetail() {
|
|
27
|
+
return this._errorDetail;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set errorDetail(value) {
|
|
31
|
+
throw new TypeError('Cannot set errorDetail, it is read-only');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get receivedAlert() {
|
|
35
|
+
return this._receivedAlert;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set receivedAlert(value) {
|
|
39
|
+
throw new TypeError('Cannot set receivedAlert, it is read-only');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get sctpCauseCode() {
|
|
43
|
+
return this._sctpCauseCode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
set sctpCauseCode(value) {
|
|
47
|
+
throw new TypeError('Cannot set sctpCauseCode, it is read-only');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get sdpLineNumber() {
|
|
51
|
+
return this._sdpLineNumber;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
set sdpLineNumber(value) {
|
|
55
|
+
throw new TypeError('Cannot set sdpLineNumber, it is read-only');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get sentAlert() {
|
|
59
|
+
return this._sentAlert;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
set sentAlert(value) {
|
|
63
|
+
throw new TypeError('Cannot set sentAlert, it is read-only');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Example: candidate:123456 1 UDP 123456 192.168.1.1 12345 typ host raddr=10.0.0.1 rport=54321 generation 0
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import 'node-domexception';
|
|
6
6
|
|
|
7
7
|
export default class _RTCIceCandidate {
|
|
8
8
|
#address;
|
|
@@ -19,41 +19,40 @@ export default class _RTCIceCandidate {
|
|
|
19
19
|
#tcpType;
|
|
20
20
|
#type;
|
|
21
21
|
#usernameFragment;
|
|
22
|
-
#ip;
|
|
23
22
|
|
|
24
23
|
constructor({ candidate, sdpMLineIndex, sdpMid, usernameFragment }) {
|
|
25
|
-
if (
|
|
26
|
-
throw new
|
|
27
|
-
}
|
|
24
|
+
if (sdpMLineIndex == null && sdpMid == null)
|
|
25
|
+
throw new TypeError('At least one of sdpMLineIndex or sdpMid must be specified');
|
|
28
26
|
|
|
29
|
-
this.#candidate = candidate;
|
|
30
|
-
this.#sdpMLineIndex = sdpMLineIndex
|
|
31
|
-
this.#sdpMid = sdpMid
|
|
32
|
-
this.#usernameFragment = usernameFragment
|
|
27
|
+
this.#candidate = candidate === null ? 'null' : candidate ?? '';
|
|
28
|
+
this.#sdpMLineIndex = sdpMLineIndex ?? null;
|
|
29
|
+
this.#sdpMid = sdpMid ?? null;
|
|
30
|
+
this.#usernameFragment = usernameFragment ?? null;
|
|
33
31
|
|
|
34
32
|
if (candidate) {
|
|
35
33
|
const fields = candidate.split(' ');
|
|
36
|
-
this.#foundation = fields[0];
|
|
34
|
+
this.#foundation = fields[0].replace('candidate:', ''); // remove text candidate:
|
|
37
35
|
this.#component = fields[1] == '1' ? 'rtp' : 'rtcp';
|
|
38
36
|
this.#protocol = fields[2];
|
|
39
37
|
this.#priority = parseInt(fields[3], 10);
|
|
40
|
-
this.#
|
|
38
|
+
this.#address = fields[4];
|
|
41
39
|
this.#port = parseInt(fields[5], 10);
|
|
42
40
|
this.#type = fields[7];
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.#tcpType = fields[7];
|
|
47
|
-
this.#type = fields[8];
|
|
48
|
-
}
|
|
41
|
+
this.#tcpType = null;
|
|
42
|
+
this.#relatedAddress = null;
|
|
43
|
+
this.#relatedPort = null;
|
|
49
44
|
|
|
50
45
|
// Parse the candidate string to extract relatedPort and relatedAddress
|
|
51
|
-
for (let i =
|
|
46
|
+
for (let i = 8; i < fields.length; i++) {
|
|
52
47
|
const field = fields[i];
|
|
53
|
-
if (field
|
|
54
|
-
this.#relatedAddress =
|
|
55
|
-
} else if (field
|
|
56
|
-
this.#relatedPort = parseInt(
|
|
48
|
+
if (field === 'raddr') {
|
|
49
|
+
this.#relatedAddress = fields[i + 1];
|
|
50
|
+
} else if (field === 'rport') {
|
|
51
|
+
this.#relatedPort = parseInt(fields[i + 1], 10);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (this.#protocol === 'tcp' && field === 'tcptype') {
|
|
55
|
+
this.#tcpType = fields[i + 1];
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -64,7 +63,7 @@ export default class _RTCIceCandidate {
|
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
get candidate() {
|
|
67
|
-
return this.#candidate
|
|
66
|
+
return this.#candidate;
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
get component() {
|