node-datachannel 0.29.0 → 0.31.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.
Files changed (61) hide show
  1. package/.clang-format +17 -0
  2. package/CMakeLists.txt +16 -2
  3. package/dist/cjs/lib/index.cjs +21 -0
  4. package/dist/cjs/lib/index.cjs.map +1 -1
  5. package/dist/cjs/polyfill/RTCPeerConnection.cjs +6 -1
  6. package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
  7. package/dist/esm/lib/index.mjs +15 -1
  8. package/dist/esm/lib/index.mjs.map +1 -1
  9. package/dist/esm/polyfill/RTCPeerConnection.mjs +6 -1
  10. package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
  11. package/dist/types/lib/index.d.ts +58 -4
  12. package/dist/types/lib/types.d.ts +3 -1
  13. package/package.json +3 -2
  14. package/rollup.config.mjs +1 -1
  15. package/src/cpp/data-channel-wrapper.cpp +432 -411
  16. package/src/cpp/data-channel-wrapper.h +0 -2
  17. package/src/cpp/ice-udp-mux-listener-wrapper.cpp +104 -97
  18. package/src/cpp/main.cpp +25 -11
  19. package/src/cpp/media-audio-wrapper.cpp +291 -294
  20. package/src/cpp/media-audio-wrapper.h +1 -3
  21. package/src/cpp/media-av1packetization.cpp +24 -0
  22. package/src/cpp/media-av1packetization.h +11 -0
  23. package/src/cpp/media-av1rtppacketizer-wrapper.cpp +126 -0
  24. package/src/cpp/media-av1rtppacketizer-wrapper.h +29 -0
  25. package/src/cpp/media-direction.cpp +32 -32
  26. package/src/cpp/media-direction.h +1 -1
  27. package/src/cpp/media-h264rtppacketizer-wrapper.cpp +126 -0
  28. package/src/cpp/media-h264rtppacketizer-wrapper.h +30 -0
  29. package/src/cpp/media-h265rtppacketizer-wrapper.cpp +126 -0
  30. package/src/cpp/media-h265rtppacketizer-wrapper.h +30 -0
  31. package/src/cpp/media-h26xseparator.cpp +32 -0
  32. package/src/cpp/media-h26xseparator.h +11 -0
  33. package/src/cpp/media-mediahandler-helper.cpp +28 -0
  34. package/src/cpp/media-mediahandler-helper.h +11 -0
  35. package/src/cpp/media-rtcpnackresponder-wrapper.cpp +68 -0
  36. package/src/cpp/media-rtcpnackresponder-wrapper.h +28 -0
  37. package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +38 -25
  38. package/src/cpp/media-rtcpreceivingsession-wrapper.h +1 -6
  39. package/src/cpp/media-rtcpsrreporter-wrapper.cpp +93 -0
  40. package/src/cpp/media-rtcpsrreporter-wrapper.h +30 -0
  41. package/src/cpp/media-rtppacketizationconfig-wrapper.cpp +167 -0
  42. package/src/cpp/media-rtppacketizationconfig-wrapper.h +35 -0
  43. package/src/cpp/media-rtppacketizer-wrapper.cpp +95 -0
  44. package/src/cpp/media-rtppacketizer-wrapper.h +30 -0
  45. package/src/cpp/media-track-wrapper.cpp +356 -340
  46. package/src/cpp/media-track-wrapper.h +0 -3
  47. package/src/cpp/media-video-wrapper.cpp +347 -313
  48. package/src/cpp/media-video-wrapper.h +3 -3
  49. package/src/cpp/peer-connection-wrapper.cpp +1094 -1047
  50. package/src/cpp/peer-connection-wrapper.h +0 -2
  51. package/src/cpp/rtc-wrapper.cpp +142 -138
  52. package/src/cpp/rtc-wrapper.h +8 -10
  53. package/src/cpp/thread-safe-callback.cpp +39 -50
  54. package/src/cpp/thread-safe-callback.h +26 -28
  55. package/src/cpp/web-socket-server-wrapper.cpp +205 -199
  56. package/src/cpp/web-socket-server-wrapper.h +0 -4
  57. package/src/cpp/web-socket-wrapper.cpp +625 -598
  58. package/src/cpp/web-socket-wrapper.h +0 -3
  59. package/src/lib/index.ts +69 -2
  60. package/src/lib/types.ts +6 -0
  61. package/src/polyfill/RTCPeerConnection.ts +8 -2
@@ -1,4 +1,5 @@
1
1
  #include "web-socket-server-wrapper.h"
2
+ #include "web-socket-wrapper.h"
2
3
 
3
4
  #include "plog/Log.h"
4
5
 
@@ -7,263 +8,268 @@ std::unordered_set<WebSocketServerWrapper *> WebSocketServerWrapper::instances;
7
8
 
8
9
  void WebSocketServerWrapper::StopAll()
9
10
  {
10
- PLOG_DEBUG << "StopAll() called";
11
- auto copy(instances);
12
- for (auto inst : copy)
13
- inst->doStop();
11
+ PLOG_DEBUG << "StopAll() called";
12
+ auto copy(instances);
13
+ for (auto inst : copy)
14
+ inst->doStop();
14
15
  }
15
16
 
16
17
  Napi::Object WebSocketServerWrapper::Init(Napi::Env env, Napi::Object exports)
17
18
  {
18
- Napi::HandleScope scope(env);
19
-
20
- Napi::Function func = DefineClass(
21
- env,
22
- "WebSocketServer",
23
- {
24
- InstanceMethod("stop", &WebSocketServerWrapper::stop),
25
- InstanceMethod("port", &WebSocketServerWrapper::port),
26
- InstanceMethod("onClient", &WebSocketServerWrapper::onClient)
27
- });
28
-
29
- // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
30
- if(constructor.IsEmpty())
31
- {
32
- constructor = Napi::Persistent(func);
33
- constructor.SuppressDestruct();
34
- }
35
-
36
- exports.Set("WebSocketServer", func);
37
- return exports;
19
+ Napi::HandleScope scope(env);
20
+
21
+ Napi::Function func = DefineClass(env, "WebSocketServer",
22
+ {InstanceMethod("stop", &WebSocketServerWrapper::stop),
23
+ InstanceMethod("port", &WebSocketServerWrapper::port),
24
+ InstanceMethod("onClient", &WebSocketServerWrapper::onClient)});
25
+
26
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
27
+ if (constructor.IsEmpty())
28
+ {
29
+ constructor = Napi::Persistent(func);
30
+ constructor.SuppressDestruct();
31
+ }
32
+
33
+ exports.Set("WebSocketServer", func);
34
+ return exports;
38
35
  }
39
36
 
40
- WebSocketServerWrapper::WebSocketServerWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<WebSocketServerWrapper>(info)
37
+ WebSocketServerWrapper::WebSocketServerWrapper(const Napi::CallbackInfo &info)
38
+ : Napi::ObjectWrap<WebSocketServerWrapper>(info)
41
39
  {
42
- PLOG_DEBUG << "Constructor called";
43
- Napi::Env env = info.Env();
40
+ PLOG_DEBUG << "Constructor called";
41
+ Napi::Env env = info.Env();
44
42
 
45
- // Create WebSocketServer without config
46
- if (info.Length() == 0)
43
+ // Create WebSocketServer without config
44
+ if (info.Length() == 0)
45
+ {
46
+ try
47
+ {
48
+ PLOG_DEBUG << "Creating a new WebSocketServer without config";
49
+ mWebSocketServerPtr = std::make_unique<rtc::WebSocketServer>();
50
+ }
51
+ catch (std::exception &ex)
47
52
  {
48
- try
49
- {
50
- PLOG_DEBUG << "Creating a new WebSocketServer without config";
51
- mWebSocketServerPtr = std::make_unique<rtc::WebSocketServer>();
52
- }
53
- catch (std::exception &ex)
54
- {
55
- Napi::Error::New(env, std::string("libdatachannel error while creating WebSocketServer without config: ") + ex.what()).ThrowAsJavaScriptException();
56
- return;
57
- }
58
-
59
- PLOG_DEBUG << "WebSocketServer created without config";
60
-
61
- instances.insert(this);
62
- return;
53
+ Napi::Error::New(env,
54
+ std::string("libdatachannel error while creating WebSocketServer without config: ") + ex.what())
55
+ .ThrowAsJavaScriptException();
56
+ return;
63
57
  }
64
58
 
65
- // Create WebSocketServer with config
59
+ PLOG_DEBUG << "WebSocketServer created without config";
66
60
 
67
- Napi::Object config = info[0].As<Napi::Object>();
68
- rtc::WebSocketServerConfiguration webSocketServerConfig;
61
+ instances.insert(this);
62
+ return;
63
+ }
69
64
 
70
- // Port
71
- if (config.Has("port"))
72
- {
73
- if (!config.Get("port").IsNumber())
74
- {
75
- Napi::TypeError::New(info.Env(), "port must be a number").ThrowAsJavaScriptException();
76
- return;
77
- }
78
- webSocketServerConfig.port = config.Get("port").ToNumber().Uint32Value();
79
- }
65
+ // Create WebSocketServer with config
80
66
 
81
- // Enable TLS
82
- if (config.Has("enableTls"))
83
- {
84
- if (!config.Get("enableTls").IsBoolean())
85
- {
86
- Napi::TypeError::New(info.Env(), "enableTls must be boolean").ThrowAsJavaScriptException();
87
- return;
88
- }
89
- webSocketServerConfig.enableTls = config.Get("enableTls").ToBoolean();
90
- }
67
+ Napi::Object config = info[0].As<Napi::Object>();
68
+ rtc::WebSocketServerConfiguration webSocketServerConfig;
91
69
 
92
- // Certificate PEM File
93
- if (config.Has("certificatePemFile"))
70
+ // Port
71
+ if (config.Has("port"))
72
+ {
73
+ if (!config.Get("port").IsNumber())
94
74
  {
95
- if (!config.Get("certificatePemFile").IsString())
96
- {
97
- Napi::TypeError::New(info.Env(), "certificatePemFile must be a string").ThrowAsJavaScriptException();
98
- return;
99
- }
100
- webSocketServerConfig.certificatePemFile = config.Get("certificatePemFile").ToString();
75
+ Napi::TypeError::New(info.Env(), "port must be a number").ThrowAsJavaScriptException();
76
+ return;
101
77
  }
78
+ webSocketServerConfig.port = config.Get("port").ToNumber().Uint32Value();
79
+ }
102
80
 
103
- // Key PEM File
104
- if (config.Has("keyPemFile"))
81
+ // Enable TLS
82
+ if (config.Has("enableTls"))
83
+ {
84
+ if (!config.Get("enableTls").IsBoolean())
105
85
  {
106
- if (!config.Get("keyPemFile").IsString())
107
- {
108
- Napi::TypeError::New(info.Env(), "keyPemFile must be a string").ThrowAsJavaScriptException();
109
- return;
110
- }
111
- webSocketServerConfig.keyPemFile = config.Get("keyPemFile").ToString();
86
+ Napi::TypeError::New(info.Env(), "enableTls must be boolean").ThrowAsJavaScriptException();
87
+ return;
112
88
  }
89
+ webSocketServerConfig.enableTls = config.Get("enableTls").ToBoolean();
90
+ }
113
91
 
114
- // Key PEM Pass
115
- if (config.Has("keyPemPass"))
92
+ // Certificate PEM File
93
+ if (config.Has("certificatePemFile"))
94
+ {
95
+ if (!config.Get("certificatePemFile").IsString())
116
96
  {
117
- if (!config.Get("keyPemPass").IsString())
118
- {
119
- Napi::TypeError::New(info.Env(), "keyPemPass must be a string").ThrowAsJavaScriptException();
120
- return;
121
- }
122
- webSocketServerConfig.keyPemPass = config.Get("keyPemPass").ToString();
97
+ Napi::TypeError::New(info.Env(), "certificatePemFile must be a string").ThrowAsJavaScriptException();
98
+ return;
123
99
  }
100
+ webSocketServerConfig.certificatePemFile = config.Get("certificatePemFile").ToString();
101
+ }
124
102
 
125
- // Bind Address
126
- if (config.Has("bindAddress"))
103
+ // Key PEM File
104
+ if (config.Has("keyPemFile"))
105
+ {
106
+ if (!config.Get("keyPemFile").IsString())
127
107
  {
128
- if (!config.Get("bindAddress").IsString())
129
- {
130
- Napi::TypeError::New(info.Env(), "bindAddress must be a string").ThrowAsJavaScriptException();
131
- return;
132
- }
133
- webSocketServerConfig.bindAddress = config.Get("bindAddress").ToString();
108
+ Napi::TypeError::New(info.Env(), "keyPemFile must be a string").ThrowAsJavaScriptException();
109
+ return;
134
110
  }
111
+ webSocketServerConfig.keyPemFile = config.Get("keyPemFile").ToString();
112
+ }
135
113
 
136
- // Connection Timeout
137
- if (config.Has("connectionTimeout"))
114
+ // Key PEM Pass
115
+ if (config.Has("keyPemPass"))
116
+ {
117
+ if (!config.Get("keyPemPass").IsString())
138
118
  {
139
- if (!config.Get("connectionTimeout").IsNumber())
140
- {
141
- Napi::TypeError::New(info.Env(), "connectionTimeout must be a number").ThrowAsJavaScriptException();
142
- return;
143
- }
144
- webSocketServerConfig.connectionTimeout = std::chrono::milliseconds(config.Get("connectionTimeout").ToNumber().Int64Value());
119
+ Napi::TypeError::New(info.Env(), "keyPemPass must be a string").ThrowAsJavaScriptException();
120
+ return;
145
121
  }
122
+ webSocketServerConfig.keyPemPass = config.Get("keyPemPass").ToString();
123
+ }
146
124
 
147
- // Max Message Size
148
- if (config.Has("maxMessageSize"))
125
+ // Bind Address
126
+ if (config.Has("bindAddress"))
127
+ {
128
+ if (!config.Get("bindAddress").IsString())
149
129
  {
150
- if (!config.Get("maxMessageSize").IsNumber())
151
- {
152
- Napi::TypeError::New(info.Env(), "maxMessageSize must be a number").ThrowAsJavaScriptException();
153
- return;
154
- }
155
- webSocketServerConfig.maxMessageSize = config.Get("maxMessageSize").ToNumber().Int32Value();
130
+ Napi::TypeError::New(info.Env(), "bindAddress must be a string").ThrowAsJavaScriptException();
131
+ return;
156
132
  }
133
+ webSocketServerConfig.bindAddress = config.Get("bindAddress").ToString();
134
+ }
157
135
 
158
- // Create WebSocketServer with config
159
- try
136
+ // Connection Timeout
137
+ if (config.Has("connectionTimeout"))
138
+ {
139
+ if (!config.Get("connectionTimeout").IsNumber())
160
140
  {
161
- PLOG_DEBUG << "Creating a new WebSocketServer";
162
- mWebSocketServerPtr = std::make_unique<rtc::WebSocketServer>(webSocketServerConfig);
141
+ Napi::TypeError::New(info.Env(), "connectionTimeout must be a number").ThrowAsJavaScriptException();
142
+ return;
163
143
  }
164
- catch (std::exception &ex)
144
+ webSocketServerConfig.connectionTimeout =
145
+ std::chrono::milliseconds(config.Get("connectionTimeout").ToNumber().Int64Value());
146
+ }
147
+
148
+ // Max Message Size
149
+ if (config.Has("maxMessageSize"))
150
+ {
151
+ if (!config.Get("maxMessageSize").IsNumber())
165
152
  {
166
- Napi::Error::New(env, std::string("libdatachannel error while creating WebSocketServer: ") + ex.what()).ThrowAsJavaScriptException();
167
- return;
153
+ Napi::TypeError::New(info.Env(), "maxMessageSize must be a number").ThrowAsJavaScriptException();
154
+ return;
168
155
  }
169
-
170
- PLOG_DEBUG << "WebSocketServer created";
171
- instances.insert(this);
156
+ webSocketServerConfig.maxMessageSize = config.Get("maxMessageSize").ToNumber().Int32Value();
157
+ }
158
+
159
+ // Create WebSocketServer with config
160
+ try
161
+ {
162
+ PLOG_DEBUG << "Creating a new WebSocketServer";
163
+ mWebSocketServerPtr = std::make_unique<rtc::WebSocketServer>(webSocketServerConfig);
164
+ }
165
+ catch (std::exception &ex)
166
+ {
167
+ Napi::Error::New(env, std::string("libdatachannel error while creating WebSocketServer: ") + ex.what())
168
+ .ThrowAsJavaScriptException();
169
+ return;
170
+ }
171
+
172
+ PLOG_DEBUG << "WebSocketServer created";
173
+ instances.insert(this);
172
174
  }
173
175
 
174
176
  WebSocketServerWrapper::~WebSocketServerWrapper()
175
177
  {
176
- PLOG_DEBUG << "Destructor called";
177
- doStop();
178
+ PLOG_DEBUG << "Destructor called";
179
+ doStop();
178
180
  }
179
181
 
180
182
  void WebSocketServerWrapper::doStop()
181
183
  {
182
- PLOG_DEBUG << "doStop() called";
183
- if (mWebSocketServerPtr)
184
+ PLOG_DEBUG << "doStop() called";
185
+ if (mWebSocketServerPtr)
186
+ {
187
+ PLOG_DEBUG << "Stopping...";
188
+ try
184
189
  {
185
- PLOG_DEBUG << "Stopping...";
186
- try
187
- {
188
- mWebSocketServerPtr->stop();
189
- mWebSocketServerPtr.reset();
190
- }
191
- catch (std::exception &ex)
192
- {
193
- std::cerr << std::string("libdatachannel error while closing WebSocketServer: ") + ex.what() << std::endl;
194
- return;
195
- }
190
+ mWebSocketServerPtr->stop();
191
+ mWebSocketServerPtr.reset();
196
192
  }
193
+ catch (std::exception &ex)
194
+ {
195
+ std::cerr << std::string("libdatachannel error while closing WebSocketServer: ") + ex.what() << std::endl;
196
+ return;
197
+ }
198
+ }
197
199
 
198
- mOnClientCallback.reset();
199
- instances.erase(this);
200
+ mOnClientCallback.reset();
201
+ instances.erase(this);
200
202
  }
201
203
 
202
204
  void WebSocketServerWrapper::stop(const Napi::CallbackInfo &info)
203
205
  {
204
- PLOG_DEBUG << "stop() called";
205
- doStop();
206
+ PLOG_DEBUG << "stop() called";
207
+ doStop();
206
208
  }
207
209
 
208
210
  Napi::Value WebSocketServerWrapper::port(const Napi::CallbackInfo &info)
209
211
  {
210
- PLOG_DEBUG << "port() called";
211
- Napi::Env env = info.Env();
212
-
213
- if (!mWebSocketServerPtr)
214
- {
215
- return Napi::Number::New(info.Env(), 0);
216
- }
217
-
218
- try
219
- {
220
- return Napi::Number::New(info.Env(), mWebSocketServerPtr->port());
221
- }
222
- catch (std::exception &ex)
223
- {
224
- Napi::Error::New(env, std::string("WebSocketServer error: ") + ex.what()).ThrowAsJavaScriptException();
225
- return Napi::Number::New(info.Env(), 0);
226
- }
212
+ PLOG_DEBUG << "port() called";
213
+ Napi::Env env = info.Env();
214
+
215
+ if (!mWebSocketServerPtr)
216
+ {
217
+ return Napi::Number::New(info.Env(), 0);
218
+ }
219
+
220
+ try
221
+ {
222
+ return Napi::Number::New(info.Env(), mWebSocketServerPtr->port());
223
+ }
224
+ catch (std::exception &ex)
225
+ {
226
+ Napi::Error::New(env, std::string("WebSocketServer error: ") + ex.what()).ThrowAsJavaScriptException();
227
+ return Napi::Number::New(info.Env(), 0);
228
+ }
227
229
  }
228
230
 
229
231
  void WebSocketServerWrapper::onClient(const Napi::CallbackInfo &info)
230
232
  {
231
- PLOG_DEBUG << "onClient() called";
232
- Napi::Env env = info.Env();
233
- int length = info.Length();
234
-
235
- if (!mWebSocketServerPtr)
236
- {
237
- Napi::Error::New(env, "onClient() called on destroyed WebSocketServer").ThrowAsJavaScriptException();
238
- return;
239
- }
240
-
241
- if (length < 1 || !info[0].IsFunction())
242
- {
243
- Napi::TypeError::New(env, "Function expected as onClient callback").ThrowAsJavaScriptException();
244
- return;
245
- }
246
-
247
- // Callback
248
- mOnClientCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
249
-
250
- mWebSocketServerPtr->onClient([&](std::shared_ptr<rtc::WebSocket> ws)
251
- {
252
- PLOG_DEBUG << "onClient ws received from WebSocketServer";
253
- if (mOnClientCallback)
254
- mOnClientCallback->call([this, ws](Napi::Env env, std::vector<napi_value> &args) {
255
- PLOG_DEBUG << "mOnClientCallback call(1)";
256
- // Check the WebSocketServer is not stopped
257
- if(instances.find(this) == instances.end())
258
- throw ThreadSafeCallback::CancelException();
259
-
260
- // This will run in main thread and needs to construct the
261
- // arguments for the call
262
- std::shared_ptr<rtc::WebSocket> webSocket = ws;
263
- // First argument is just a placeholder
264
- auto instance = WebSocketWrapper::constructor.New({Napi::Boolean::New(env, false), Napi::External<std::shared_ptr<rtc::WebSocket>>::New(env, &webSocket)});
265
- args = {instance};
266
- PLOG_DEBUG << "mOnClientCallback call(2)";
267
- });
268
- });
233
+ PLOG_DEBUG << "onClient() called";
234
+ Napi::Env env = info.Env();
235
+ int length = info.Length();
236
+
237
+ if (!mWebSocketServerPtr)
238
+ {
239
+ Napi::Error::New(env, "onClient() called on destroyed WebSocketServer").ThrowAsJavaScriptException();
240
+ return;
241
+ }
242
+
243
+ if (length < 1 || !info[0].IsFunction())
244
+ {
245
+ Napi::TypeError::New(env, "Function expected as onClient callback").ThrowAsJavaScriptException();
246
+ return;
247
+ }
248
+
249
+ // Callback
250
+ mOnClientCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
251
+
252
+ mWebSocketServerPtr->onClient(
253
+ [&](std::shared_ptr<rtc::WebSocket> ws)
254
+ {
255
+ PLOG_DEBUG << "onClient ws received from WebSocketServer";
256
+ if (mOnClientCallback)
257
+ mOnClientCallback->call(
258
+ [this, ws](Napi::Env env, std::vector<napi_value> &args)
259
+ {
260
+ PLOG_DEBUG << "mOnClientCallback call(1)";
261
+ // Check the WebSocketServer is not stopped
262
+ if (instances.find(this) == instances.end())
263
+ throw ThreadSafeCallback::CancelException();
264
+
265
+ // This will run in main thread and needs to construct the
266
+ // arguments for the call
267
+ std::shared_ptr<rtc::WebSocket> webSocket = ws;
268
+ // First argument is just a placeholder
269
+ auto instance = WebSocketWrapper::constructor.New(
270
+ {Napi::Boolean::New(env, false), Napi::External<std::shared_ptr<rtc::WebSocket>>::New(env, &webSocket)});
271
+ args = {instance};
272
+ PLOG_DEBUG << "mOnClientCallback call(2)";
273
+ });
274
+ });
269
275
  }
@@ -1,16 +1,12 @@
1
1
  #ifndef WEB_SOCKET_SERVER_WRAPPER_H
2
2
  #define WEB_SOCKET_SERVER_WRAPPER_H
3
3
 
4
- #include <iostream>
5
- #include <string>
6
- #include <variant>
7
4
  #include <memory>
8
5
  #include <unordered_set>
9
6
 
10
7
  #include <napi.h>
11
8
  #include <rtc/rtc.hpp>
12
9
 
13
- #include "web-socket-wrapper.h"
14
10
  #include "thread-safe-callback.h"
15
11
 
16
12
  class WebSocketServerWrapper : public Napi::ObjectWrap<WebSocketServerWrapper>