node-datachannel 0.5.5 → 0.7.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.
@@ -76,8 +76,8 @@ jobs:
76
76
  sudo apt update
77
77
  sudo apt install -y g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
78
78
  mkdir sysroot && cd sysroot
79
- wget https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/953c2471bc7e71a788309f6c2d2003e8b703305d/debian_sid_arm64_sysroot.tar.xz
80
- tar xf debian_sid_arm64_sysroot.tar.xz
79
+ wget https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/41a6c8dec4c4304d6509e30cbaf9218dffb4438e/debian_bullseye_arm64_sysroot.tar.xz
80
+ tar xf debian_bullseye_arm64_sysroot.tar.xz
81
81
  echo "ARM64_SYSROOT=$(pwd)" >> $GITHUB_ENV
82
82
  ls -l
83
83
  - name: Use Node.js ${{ matrix.node-version }}
package/CMakeLists.txt CHANGED
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15)
2
2
  cmake_policy(SET CMP0091 NEW)
3
3
  cmake_policy(SET CMP0042 NEW)
4
4
 
5
- project(node_datachannel VERSION 0.5.5)
5
+ project(node_datachannel VERSION 0.7.0)
6
6
 
7
7
  # -Dnapi_build_version=8
8
8
  add_definitions(-DNAPI_VERSION=8)
@@ -20,14 +20,8 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Android")
20
20
  set(CMAKE_C_FLAGS "-Wno-error=unused-but-set-variable -Wno-error=strict-prototypes")
21
21
  endif()
22
22
 
23
- # Got linker error for arm64
24
- # /usr/lib/gcc-cross/aarch64-linux-gnu/9/../../../../aarch64-linux-gnu/bin/ld: ../sysroot/usr/lib/aarch64-linux-gnu/libcrypto.a(sha1-armv8.o): relocation R_AARCH64_PREL64 against symbol `OPENSSL_armcap_P' which may bind externally can not be used when making a shared object; recompile with -fPIC
25
- # ../sysroot/usr/lib/aarch64-linux-gnu/libcrypto.a(sha1-armv8.o): in function `sha1_block_armv8':
26
- # (.text+0x1240): dangerous relocation: unsupported relocation
27
- if(NOT ${NODE_ARCH} STREQUAL "arm64")
28
- set(OPENSSL_USE_STATIC_LIBS TRUE)
29
- find_package(OpenSSL REQUIRED)
30
- endif()
23
+ set(OPENSSL_USE_STATIC_LIBS TRUE)
24
+ find_package(OpenSSL REQUIRED)
31
25
 
32
26
  include(FetchContent)
33
27
 
@@ -39,7 +33,7 @@ FetchContent_Declare(
39
33
  )
40
34
 
41
35
  option(NO_MEDIA "Disable media transport support in libdatachannel" OFF)
42
- option(NO_WEBSOCKET "Disable WebSocket support in libdatachannel" ON)
36
+ option(NO_WEBSOCKET "Disable WebSocket support in libdatachannel" OFF)
43
37
 
44
38
  FetchContent_GetProperties(libdatachannel)
45
39
 
@@ -58,6 +52,8 @@ add_library(${PROJECT_NAME} SHARED
58
52
  src/data-channel-wrapper.cpp
59
53
  src/peer-connection-wrapper.cpp
60
54
  src/thread-safe-callback.cpp
55
+ src/web-socket-wrapper.cpp
56
+ src/web-socket-server-wrapper.cpp
61
57
  src/main.cpp
62
58
  ${CMAKE_JS_SRC}
63
59
  )
@@ -3832,9 +3832,9 @@
3832
3832
  }
3833
3833
  },
3834
3834
  "node_modules/follow-redirects": {
3835
- "version": "1.15.4",
3836
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
3837
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
3835
+ "version": "1.15.6",
3836
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
3837
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
3838
3838
  "dev": true,
3839
3839
  "funding": [
3840
3840
  {
@@ -11877,9 +11877,9 @@
11877
11877
  }
11878
11878
  },
11879
11879
  "follow-redirects": {
11880
- "version": "1.15.4",
11881
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
11882
- "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
11880
+ "version": "1.15.6",
11881
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
11882
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
11883
11883
  "dev": true
11884
11884
  },
11885
11885
  "foreground-child": {
@@ -20,3 +20,15 @@ Use the following gstreamer demo pipeline to display the traffic
20
20
  ```
21
21
  $ gst-launch-1.0 udpsrc address=127.0.0.1 port=5000 caps="application/x-rtp" ! queue ! rtph264depay ! video/x-h264,stream-format=byte-stream ! queue ! avdec_h264 ! queue ! autovideosink
22
22
  ```
23
+
24
+ For saving the stream to a file, use the following pipeline (mp4):
25
+
26
+ ```
27
+ gst-launch-1.0 -e udpsrc address=127.0.0.1 port=5000 caps="application/x-rtp" ! queue ! rtph264depay ! h264parse ! mp4mux ! filesink location=out.mp4
28
+ ```
29
+
30
+ ## Requirements
31
+
32
+ - GStreamer 1.0
33
+ - gstreamer1.0-libav (sudo apt-get install gstreamer1.0-libav)
34
+ - h264enc (sudo apt-get install h264enc)
@@ -0,0 +1,7 @@
1
+ /** @type {import('jest').Config} */
2
+ const config = {
3
+ verbose: true,
4
+ testPathIgnorePatterns: ['<rootDir>/node_modules/', 'multiple-run.test'],
5
+ };
6
+
7
+ module.exports = config;
package/lib/index.cjs ADDED
@@ -0,0 +1,142 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var module$1 = require('module');
6
+ var stream = require('stream');
7
+
8
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
+ /**
10
+ * Turns a node-datachannel DataChannel into a real Node.js stream, complete with buffering,
11
+ * backpressure (up to a point - if the buffer fills up, messages are dropped), and
12
+ * support for piping data elsewhere.
13
+ *
14
+ * Read & written data may be either UTF-8 strings or Buffers - this difference exists at
15
+ * the protocol level, and is preserved here throughout.
16
+ */
17
+ class DataChannelStream extends stream.Duplex {
18
+ constructor(rawChannel, streamOptions) {
19
+ super({
20
+ allowHalfOpen: false, // Default to autoclose on end().
21
+ ...streamOptions,
22
+ objectMode: true, // Preserve the string/buffer distinction (WebRTC treats them differently)
23
+ });
24
+
25
+ this._rawChannel = rawChannel;
26
+ this._readActive = true;
27
+
28
+ rawChannel.onMessage((msg) => {
29
+ if (!this._readActive) return; // If the buffer is full, drop messages.
30
+
31
+ // If the push is rejected, we pause reading until the next call to _read().
32
+ this._readActive = this.push(msg);
33
+ });
34
+
35
+ // When the DataChannel closes, the readable & writable ends close
36
+ rawChannel.onClosed(() => {
37
+ this.push(null);
38
+ this.destroy();
39
+ });
40
+
41
+ rawChannel.onError((errMsg) => {
42
+ this.destroy(new Error(`DataChannel error: ${errMsg}`));
43
+ });
44
+
45
+ // Buffer all writes until the DataChannel opens
46
+ if (!rawChannel.isOpen()) {
47
+ this.cork();
48
+ rawChannel.onOpen(() => this.uncork());
49
+ }
50
+ }
51
+
52
+ _read() {
53
+ // Stop dropping messages, if the buffer filling up meant we were doing so before.
54
+ this._readActive = true;
55
+ }
56
+
57
+ _write(chunk, encoding, callback) {
58
+ let sentOk;
59
+
60
+ try {
61
+ if (Buffer.isBuffer(chunk)) {
62
+ sentOk = this._rawChannel.sendMessageBinary(chunk);
63
+ } else if (typeof chunk === 'string') {
64
+ sentOk = this._rawChannel.sendMessage(chunk);
65
+ } else {
66
+ const typeName = chunk.constructor.name || typeof chunk;
67
+ throw new Error(`Cannot write ${typeName} to DataChannel stream`);
68
+ }
69
+ } catch (err) {
70
+ return callback(err);
71
+ }
72
+
73
+ if (sentOk) {
74
+ callback(null);
75
+ } else {
76
+ callback(new Error('Failed to write to DataChannel'));
77
+ }
78
+ }
79
+
80
+ _final(callback) {
81
+ if (!this.allowHalfOpen) this.destroy();
82
+ callback(null);
83
+ }
84
+
85
+ _destroy(maybeErr, callback) {
86
+ // When the stream is destroyed, we close the DataChannel.
87
+ this._rawChannel.close();
88
+ callback(maybeErr);
89
+ }
90
+
91
+ get label() {
92
+ return this._rawChannel.getLabel();
93
+ }
94
+
95
+ get id() {
96
+ return this._rawChannel.getId();
97
+ }
98
+
99
+ get protocol() {
100
+ return this._rawChannel.getProtocol();
101
+ }
102
+ }
103
+
104
+ // createRequire is native in node version >= 12
105
+ 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)));
106
+
107
+ const nodeDataChannel = require$1('../build/Release/node_datachannel.node');
108
+
109
+ const {
110
+ initLogger,
111
+ cleanup,
112
+ preload,
113
+ setSctpSettings,
114
+ RtcpReceivingSession,
115
+ Track,
116
+ Video,
117
+ Audio,
118
+ DataChannel,
119
+ PeerConnection,
120
+ WebSocket,
121
+ WebSocketServer,
122
+ } = nodeDataChannel;
123
+
124
+ var index = {
125
+ ...nodeDataChannel,
126
+ DataChannelStream,
127
+ };
128
+
129
+ exports.Audio = Audio;
130
+ exports.DataChannel = DataChannel;
131
+ exports.DataChannelStream = DataChannelStream;
132
+ exports.PeerConnection = PeerConnection;
133
+ exports.RtcpReceivingSession = RtcpReceivingSession;
134
+ exports.Track = Track;
135
+ exports.Video = Video;
136
+ exports.WebSocket = WebSocket;
137
+ exports.WebSocketServer = WebSocketServer;
138
+ exports.cleanup = cleanup;
139
+ exports.default = index;
140
+ exports.initLogger = initLogger;
141
+ exports.preload = preload;
142
+ exports.setSctpSettings = setSctpSettings;
package/lib/index.d.ts CHANGED
@@ -189,11 +189,58 @@ export class Track {
189
189
  onMessage(cb: (msg: Buffer) => void): void;
190
190
  }
191
191
 
192
- export class DataChannel {
192
+ export interface Channel {
193
193
  close(): void;
194
+ sendMessage(msg: string): boolean;
195
+ sendMessageBinary(buffer: Uint8Array): boolean;
196
+ isOpen(): boolean;
197
+ bufferedAmount(): number;
198
+ maxMessageSize(): number;
199
+ setBufferedAmountLowThreshold(newSize: number): void;
200
+ onOpen(cb: () => void): void;
201
+ onClosed(cb: () => void): void;
202
+ onError(cb: (err: string) => void): void;
203
+ onBufferedAmountLow(cb: () => void): void;
204
+ onMessage(cb: (msg: string | Buffer) => void): void;
205
+ }
206
+ export class DataChannel implements Channel {
194
207
  getLabel(): string;
195
208
  getId(): number;
196
209
  getProtocol(): string;
210
+
211
+ // Channel implementation
212
+ close(): void;
213
+ sendMessage(msg: string): boolean;
214
+ sendMessageBinary(buffer: Uint8Array): boolean;
215
+ isOpen(): boolean;
216
+ bufferedAmount(): number;
217
+ maxMessageSize(): number;
218
+ setBufferedAmountLowThreshold(newSize: number): void;
219
+ onOpen(cb: () => void): void;
220
+ onClosed(cb: () => void): void;
221
+ onError(cb: (err: string) => void): void;
222
+ onBufferedAmountLow(cb: () => void): void;
223
+ onMessage(cb: (msg: string | Buffer) => void): void;
224
+ }
225
+
226
+ export interface WebSocketConfiguration {
227
+ disableTlsVerification?: boolean; // default = false, if true, don't verify the TLS certificate
228
+ proxyServer?: ProxyServer; // only non-authenticated http supported for now
229
+ protocols?: string[];
230
+ connectionTimeout?: number; // miliseconds, zero to disable
231
+ pingInterval?: number; // millisecondrs, zero to disable
232
+ maxOutstandingPings?: number;
233
+ caCertificatePemFile?: string;
234
+ certificatePemFile?: string;
235
+ keyPemFile?: string;
236
+ keyPemPass?: string;
237
+ maxMessageSize: number;
238
+ }
239
+ export class WebSocket implements Channel {
240
+ constructor(config?: WebSocketConfiguration);
241
+
242
+ // Channel implementation
243
+ close(): void;
197
244
  sendMessage(msg: string): boolean;
198
245
  sendMessageBinary(buffer: Uint8Array): boolean;
199
246
  isOpen(): boolean;
@@ -207,10 +254,27 @@ export class DataChannel {
207
254
  onMessage(cb: (msg: string | Buffer) => void): void;
208
255
  }
209
256
 
257
+ export interface WebSocketServerConfiguration {
258
+ port?: number; // default 8080
259
+ enableTls?: boolean; // default = false;
260
+ certificatePemFile?: string;
261
+ keyPemFile?: string;
262
+ keyPemPass?: string;
263
+ bindAddress?: string;
264
+ connectionTimeout?: number; // milliseconds
265
+ maxMessageSize?: number;
266
+ }
267
+
268
+ export class WebSocketServer {
269
+ constructor(config?: WebSocketServerConfiguration);
270
+ port(): number;
271
+ stop(): void;
272
+ onClient(cb: (ws: WebSocket) => void): void;
273
+ }
274
+
210
275
  export class PeerConnection {
211
276
  constructor(peerName: string, config: RtcConfig);
212
277
  close(): void;
213
- destroy(): void;
214
278
  setLocalDescription(type?: DescriptionType): void;
215
279
  setRemoteDescription(sdp: string, type: DescriptionType): void;
216
280
  localDescription(): { type: string; sdp: string } | null;
package/lib/index.js CHANGED
@@ -16,6 +16,8 @@ const {
16
16
  Audio,
17
17
  DataChannel,
18
18
  PeerConnection,
19
+ WebSocket,
20
+ WebSocketServer,
19
21
  } = nodeDataChannel;
20
22
 
21
23
  export {
@@ -29,6 +31,8 @@ export {
29
31
  Audio,
30
32
  DataChannel,
31
33
  PeerConnection,
34
+ WebSocket,
35
+ WebSocketServer,
32
36
  // Extra exports
33
37
  DataChannelStream,
34
38
  };
package/package.json CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "node-datachannel",
3
- "version": "0.5.5",
3
+ "version": "0.7.0",
4
4
  "description": "libdatachannel node bindings",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./lib/index.js",
8
- "./polyfill": "./polyfill/index.js"
7
+ ".": {
8
+ "import": "./lib/index.js",
9
+ "require": "./lib/index.cjs"
10
+ },
11
+ "./polyfill": {
12
+ "import": "./polyfill/index.js",
13
+ "require": "./polyfill/polyfill.cjs"
14
+ }
9
15
  },
10
16
  "typings": "lib/index.d.ts",
11
17
  "engines": {
@@ -27,7 +33,8 @@
27
33
  "lint": "eslint lib/**/* test/**/*",
28
34
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
29
35
  "wpt-test": "node test/wpt.js",
30
- "test-types": "tsc"
36
+ "test-types": "tsc",
37
+ "prepublishOnly": "rollup lib/index.js --file lib/index.cjs --format cjs && rollup polyfill/index.js --file polyfill/polyfill.cjs --format cjs"
31
38
  },
32
39
  "binary": {
33
40
  "napi_versions": [
@@ -44,7 +51,8 @@
44
51
  "p2p",
45
52
  "peer-to-peer",
46
53
  "datachannel",
47
- "data channel"
54
+ "data channel",
55
+ "websocket"
48
56
  ],
49
57
  "contributors": [
50
58
  {
@@ -77,6 +85,7 @@
77
85
  },
78
86
  "dependencies": {
79
87
  "node-domexception": "^2.0.1",
80
- "prebuild-install": "^7.0.1"
88
+ "prebuild-install": "^7.0.1",
89
+ "rollup": "^4.14.1"
81
90
  }
82
91
  }
@@ -222,7 +222,6 @@ export default class _RTCPeerConnection extends EventTarget {
222
222
  });
223
223
 
224
224
  this.#peerConnection.close();
225
- this.#peerConnection.destroy();
226
225
  }
227
226
 
228
227
  createAnswer() {