node-datachannel 0.29.0 → 0.30.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 (33) hide show
  1. package/.clang-format +17 -0
  2. package/CMakeLists.txt +5 -1
  3. package/dist/cjs/polyfill/RTCPeerConnection.cjs +6 -1
  4. package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
  5. package/dist/esm/polyfill/RTCPeerConnection.mjs +6 -1
  6. package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
  7. package/dist/types/polyfill/RTCPeerConnection.d.ts +1 -2
  8. package/package.json +3 -2
  9. package/src/cpp/data-channel-wrapper.cpp +432 -411
  10. package/src/cpp/data-channel-wrapper.h +0 -2
  11. package/src/cpp/ice-udp-mux-listener-wrapper.cpp +104 -97
  12. package/src/cpp/main.cpp +11 -11
  13. package/src/cpp/media-audio-wrapper.cpp +291 -294
  14. package/src/cpp/media-audio-wrapper.h +1 -3
  15. package/src/cpp/media-direction.cpp +32 -32
  16. package/src/cpp/media-direction.h +1 -1
  17. package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +24 -28
  18. package/src/cpp/media-rtcpreceivingsession-wrapper.h +0 -5
  19. package/src/cpp/media-track-wrapper.cpp +350 -339
  20. package/src/cpp/media-track-wrapper.h +0 -3
  21. package/src/cpp/media-video-wrapper.cpp +312 -313
  22. package/src/cpp/media-video-wrapper.h +1 -3
  23. package/src/cpp/peer-connection-wrapper.cpp +1094 -1047
  24. package/src/cpp/peer-connection-wrapper.h +0 -2
  25. package/src/cpp/rtc-wrapper.cpp +142 -138
  26. package/src/cpp/rtc-wrapper.h +8 -10
  27. package/src/cpp/thread-safe-callback.cpp +39 -50
  28. package/src/cpp/thread-safe-callback.h +26 -28
  29. package/src/cpp/web-socket-server-wrapper.cpp +205 -199
  30. package/src/cpp/web-socket-server-wrapper.h +0 -4
  31. package/src/cpp/web-socket-wrapper.cpp +625 -598
  32. package/src/cpp/web-socket-wrapper.h +0 -3
  33. package/src/polyfill/RTCPeerConnection.ts +9 -3
@@ -9,434 +9,445 @@ std::unordered_set<TrackWrapper *> TrackWrapper::instances;
9
9
 
10
10
  void TrackWrapper::CloseAll()
11
11
  {
12
- auto copy(instances);
13
- for (auto inst : copy)
14
- inst->doClose();
12
+ auto copy(instances);
13
+ for (auto inst : copy)
14
+ inst->doClose();
15
15
  }
16
16
 
17
17
  void TrackWrapper::CleanupAll()
18
18
  {
19
- PLOG_DEBUG << "CleanupAll() called";
20
- auto copy(instances);
21
- for (auto inst : copy)
22
- inst->doCleanup();
19
+ PLOG_DEBUG << "CleanupAll() called";
20
+ auto copy(instances);
21
+ for (auto inst : copy)
22
+ inst->doCleanup();
23
23
  }
24
24
 
25
25
  Napi::Object TrackWrapper::Init(Napi::Env env, Napi::Object exports)
26
26
  {
27
- Napi::HandleScope scope(env);
28
-
29
- Napi::Function func = DefineClass(
30
- env,
31
- "Track",
32
- {
33
- InstanceMethod("direction", &TrackWrapper::direction),
34
- InstanceMethod("mid", &TrackWrapper::mid),
35
- InstanceMethod("type", &TrackWrapper::type),
36
- InstanceMethod("close", &TrackWrapper::close),
37
- InstanceMethod("sendMessage", &TrackWrapper::sendMessage),
38
- InstanceMethod("sendMessageBinary", &TrackWrapper::sendMessageBinary),
39
- InstanceMethod("isOpen", &TrackWrapper::isOpen),
40
- InstanceMethod("isClosed", &TrackWrapper::isClosed),
41
- InstanceMethod("maxMessageSize", &TrackWrapper::maxMessageSize),
42
- InstanceMethod("requestBitrate", &TrackWrapper::requestBitrate),
43
- InstanceMethod("requestKeyframe", &TrackWrapper::requestKeyframe),
44
- InstanceMethod("setMediaHandler", &TrackWrapper::setMediaHandler),
45
- InstanceMethod("onOpen", &TrackWrapper::onOpen),
46
- InstanceMethod("onClosed", &TrackWrapper::onClosed),
47
- InstanceMethod("onError", &TrackWrapper::onError),
48
- InstanceMethod("onMessage", &TrackWrapper::onMessage),
49
- });
50
-
51
- // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
52
- if(constructor.IsEmpty())
53
- {
54
- constructor = Napi::Persistent(func);
55
- constructor.SuppressDestruct();
56
- }
57
-
58
- exports.Set("Track", func);
59
- return exports;
27
+ Napi::HandleScope scope(env);
28
+
29
+ Napi::Function func = DefineClass(env, "Track",
30
+ {
31
+ InstanceMethod("direction", &TrackWrapper::direction),
32
+ InstanceMethod("mid", &TrackWrapper::mid),
33
+ InstanceMethod("type", &TrackWrapper::type),
34
+ InstanceMethod("close", &TrackWrapper::close),
35
+ InstanceMethod("sendMessage", &TrackWrapper::sendMessage),
36
+ InstanceMethod("sendMessageBinary", &TrackWrapper::sendMessageBinary),
37
+ InstanceMethod("isOpen", &TrackWrapper::isOpen),
38
+ InstanceMethod("isClosed", &TrackWrapper::isClosed),
39
+ InstanceMethod("maxMessageSize", &TrackWrapper::maxMessageSize),
40
+ InstanceMethod("requestBitrate", &TrackWrapper::requestBitrate),
41
+ InstanceMethod("requestKeyframe", &TrackWrapper::requestKeyframe),
42
+ InstanceMethod("setMediaHandler", &TrackWrapper::setMediaHandler),
43
+ InstanceMethod("onOpen", &TrackWrapper::onOpen),
44
+ InstanceMethod("onClosed", &TrackWrapper::onClosed),
45
+ InstanceMethod("onError", &TrackWrapper::onError),
46
+ InstanceMethod("onMessage", &TrackWrapper::onMessage),
47
+ });
48
+
49
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
50
+ if (constructor.IsEmpty())
51
+ {
52
+ constructor = Napi::Persistent(func);
53
+ constructor.SuppressDestruct();
54
+ }
55
+
56
+ exports.Set("Track", func);
57
+ return exports;
60
58
  }
61
59
 
62
60
  TrackWrapper::TrackWrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<TrackWrapper>(info)
63
61
  {
64
- PLOG_DEBUG << "Constructor called";
65
- mTrackPtr = *(info[0].As<Napi::External<std::shared_ptr<rtc::Track>>>().Data());
66
- PLOG_DEBUG << "Track created";
62
+ PLOG_DEBUG << "Constructor called";
63
+ mTrackPtr = *(info[0].As<Napi::External<std::shared_ptr<rtc::Track>>>().Data());
64
+ PLOG_DEBUG << "Track created";
67
65
 
68
- // Closed callback must be set to trigger cleanup
69
- mOnClosedCallback = std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo&){}));
66
+ // Closed callback must be set to trigger cleanup
67
+ mOnClosedCallback =
68
+ std::make_unique<ThreadSafeCallback>(Napi::Function::New(info.Env(), [](const Napi::CallbackInfo &) {}));
70
69
 
71
- instances.insert(this);
70
+ instances.insert(this);
72
71
  }
73
72
 
74
- TrackWrapper::~TrackWrapper()
75
- {
76
- doClose();
77
- }
73
+ TrackWrapper::~TrackWrapper() { doClose(); }
78
74
 
79
75
  void TrackWrapper::doClose()
80
76
  {
81
- if (mTrackPtr)
77
+ if (mTrackPtr)
78
+ {
79
+ try
82
80
  {
83
- try
84
- {
85
- mTrackPtr->close();
86
- mTrackPtr.reset();
87
- }
88
- catch (std::exception &ex)
89
- {
90
- std::cerr << std::string("libdatachannel error while closing track: ") + ex.what() << std::endl;
91
- return;
92
- }
81
+ mTrackPtr->close();
82
+ mTrackPtr.reset();
83
+ }
84
+ catch (std::exception &ex)
85
+ {
86
+ std::cerr << std::string("libdatachannel error while closing track: ") + ex.what() << std::endl;
87
+ return;
93
88
  }
89
+ }
94
90
 
95
- mOnOpenCallback.reset();
96
- mOnErrorCallback.reset();
97
- mOnMessageCallback.reset();
91
+ mOnOpenCallback.reset();
92
+ mOnErrorCallback.reset();
93
+ mOnMessageCallback.reset();
98
94
  }
99
95
 
100
96
  void TrackWrapper::doCleanup()
101
97
  {
102
- PLOG_DEBUG << "doCleanup() called";
103
- mOnClosedCallback.reset();
104
- instances.erase(this);
98
+ PLOG_DEBUG << "doCleanup() called";
99
+ mOnClosedCallback.reset();
100
+ instances.erase(this);
105
101
  }
106
102
 
107
- void TrackWrapper::close(const Napi::CallbackInfo &info)
108
- {
109
- doClose();
110
- }
103
+ void TrackWrapper::close(const Napi::CallbackInfo &info) { doClose(); }
111
104
 
112
105
  Napi::Value TrackWrapper::direction(const Napi::CallbackInfo &info)
113
106
  {
114
- if (!mTrackPtr)
115
- {
116
- Napi::Error::New(info.Env(), "direction() called on destroyed track").ThrowAsJavaScriptException();
117
- return info.Env().Null();
118
- }
119
-
120
- Napi::Env env = info.Env();
121
- return Napi::String::New(env, directionToStr(mTrackPtr->direction()));
107
+ if (!mTrackPtr)
108
+ {
109
+ Napi::Error::New(info.Env(), "direction() called on destroyed track").ThrowAsJavaScriptException();
110
+ return info.Env().Null();
111
+ }
112
+
113
+ Napi::Env env = info.Env();
114
+ return Napi::String::New(env, directionToStr(mTrackPtr->direction()));
122
115
  }
123
116
 
124
117
  Napi::Value TrackWrapper::mid(const Napi::CallbackInfo &info)
125
118
  {
126
- if (!mTrackPtr)
127
- {
128
- Napi::Error::New(info.Env(), "mid() called on destroyed track").ThrowAsJavaScriptException();
129
- return info.Env().Null();
130
- }
131
-
132
- Napi::Env env = info.Env();
133
- return Napi::String::New(env, mTrackPtr->mid());
119
+ if (!mTrackPtr)
120
+ {
121
+ Napi::Error::New(info.Env(), "mid() called on destroyed track").ThrowAsJavaScriptException();
122
+ return info.Env().Null();
123
+ }
124
+
125
+ Napi::Env env = info.Env();
126
+ return Napi::String::New(env, mTrackPtr->mid());
134
127
  }
135
128
 
136
129
  Napi::Value TrackWrapper::type(const Napi::CallbackInfo &info)
137
130
  {
138
- if (!mTrackPtr)
139
- {
140
- Napi::Error::New(info.Env(), "type() called on destroyed track").ThrowAsJavaScriptException();
141
- return info.Env().Null();
142
- }
143
-
144
- Napi::Env env = info.Env();
145
- return Napi::String::New(env, mTrackPtr->description().type());
131
+ if (!mTrackPtr)
132
+ {
133
+ Napi::Error::New(info.Env(), "type() called on destroyed track").ThrowAsJavaScriptException();
134
+ return info.Env().Null();
135
+ }
136
+
137
+ Napi::Env env = info.Env();
138
+ return Napi::String::New(env, mTrackPtr->description().type());
146
139
  }
147
140
 
148
141
  Napi::Value TrackWrapper::sendMessage(const Napi::CallbackInfo &info)
149
142
  {
150
- if (!mTrackPtr)
151
- {
152
- Napi::Error::New(info.Env(), "sendMessage() called on destroyed track").ThrowAsJavaScriptException();
153
- return info.Env().Null();
154
- }
155
-
156
- Napi::Env env = info.Env();
157
- int length = info.Length();
158
-
159
- // Allow call with NULL
160
- if (length < 1 || (!info[0].IsString() && !info[0].IsNull()))
161
- {
162
- Napi::TypeError::New(env, "String or Null expected").ThrowAsJavaScriptException();
163
- return info.Env().Null();
164
- }
165
-
166
- try
167
- {
168
- return Napi::Boolean::New(info.Env(), mTrackPtr->send(info[0].As<Napi::String>().ToString()));
169
- }
170
- catch (std::exception &ex)
171
- {
172
- Napi::Error::New(env, std::string("libdatachannel error while sending track message: ") + ex.what()).ThrowAsJavaScriptException();
173
- return Napi::Boolean::New(info.Env(), false);
174
- }
143
+ if (!mTrackPtr)
144
+ {
145
+ Napi::Error::New(info.Env(), "sendMessage() called on destroyed track").ThrowAsJavaScriptException();
146
+ return info.Env().Null();
147
+ }
148
+
149
+ Napi::Env env = info.Env();
150
+ int length = info.Length();
151
+
152
+ // Allow call with NULL
153
+ if (length < 1 || (!info[0].IsString() && !info[0].IsNull()))
154
+ {
155
+ Napi::TypeError::New(env, "String or Null expected").ThrowAsJavaScriptException();
156
+ return info.Env().Null();
157
+ }
158
+
159
+ try
160
+ {
161
+ return Napi::Boolean::New(info.Env(), mTrackPtr->send(info[0].As<Napi::String>().ToString()));
162
+ }
163
+ catch (std::exception &ex)
164
+ {
165
+ Napi::Error::New(env, std::string("libdatachannel error while sending track message: ") + ex.what())
166
+ .ThrowAsJavaScriptException();
167
+ return Napi::Boolean::New(info.Env(), false);
168
+ }
175
169
  }
176
170
 
177
171
  Napi::Value TrackWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
178
172
  {
179
- if (!mTrackPtr)
180
- {
181
- Napi::Error::New(info.Env(), "sendMessageBinary() called on destroyed track").ThrowAsJavaScriptException();
182
- return info.Env().Null();
183
- }
184
-
185
- Napi::Env env = info.Env();
186
- int length = info.Length();
187
-
188
- if (length < 1 || !info[0].IsBuffer())
189
- {
190
- Napi::TypeError::New(env, "Buffer expected").ThrowAsJavaScriptException();
191
- return info.Env().Null();
192
- }
193
-
194
- try
195
- {
196
- Napi::Uint8Array buffer = info[0].As<Napi::Uint8Array>();
197
- return Napi::Boolean::New(info.Env(), mTrackPtr->send((std::byte *)buffer.Data(), buffer.ByteLength()));
198
- }
199
- catch (std::exception &ex)
200
- {
201
- Napi::Error::New(env, std::string("libdatachannel error while sending track message: ") + ex.what()).ThrowAsJavaScriptException();
202
- return Napi::Boolean::New(info.Env(), false);
203
- }
173
+ if (!mTrackPtr)
174
+ {
175
+ Napi::Error::New(info.Env(), "sendMessageBinary() called on destroyed track").ThrowAsJavaScriptException();
176
+ return info.Env().Null();
177
+ }
178
+
179
+ Napi::Env env = info.Env();
180
+ int length = info.Length();
181
+
182
+ if (length < 1 || !info[0].IsBuffer())
183
+ {
184
+ Napi::TypeError::New(env, "Buffer expected").ThrowAsJavaScriptException();
185
+ return info.Env().Null();
186
+ }
187
+
188
+ try
189
+ {
190
+ Napi::Uint8Array buffer = info[0].As<Napi::Uint8Array>();
191
+ return Napi::Boolean::New(info.Env(), mTrackPtr->send((std::byte *)buffer.Data(), buffer.ByteLength()));
192
+ }
193
+ catch (std::exception &ex)
194
+ {
195
+ Napi::Error::New(env, std::string("libdatachannel error while sending track message: ") + ex.what())
196
+ .ThrowAsJavaScriptException();
197
+ return Napi::Boolean::New(info.Env(), false);
198
+ }
204
199
  }
205
200
 
206
201
  Napi::Value TrackWrapper::isOpen(const Napi::CallbackInfo &info)
207
202
  {
208
- Napi::Env env = info.Env();
203
+ Napi::Env env = info.Env();
209
204
 
210
- if (!mTrackPtr)
211
- {
212
- return Napi::Boolean::New(env, false);
213
- }
205
+ if (!mTrackPtr)
206
+ {
207
+ return Napi::Boolean::New(env, false);
208
+ }
214
209
 
215
- return Napi::Boolean::New(env, mTrackPtr->isOpen());
210
+ return Napi::Boolean::New(env, mTrackPtr->isOpen());
216
211
  }
217
212
 
218
213
  Napi::Value TrackWrapper::isClosed(const Napi::CallbackInfo &info)
219
214
  {
220
- Napi::Env env = info.Env();
215
+ Napi::Env env = info.Env();
221
216
 
222
- if (!mTrackPtr)
223
- {
224
- return Napi::Boolean::New(env, true);
225
- }
217
+ if (!mTrackPtr)
218
+ {
219
+ return Napi::Boolean::New(env, true);
220
+ }
226
221
 
227
- return Napi::Boolean::New(env, mTrackPtr->isClosed());
222
+ return Napi::Boolean::New(env, mTrackPtr->isClosed());
228
223
  }
229
224
 
230
225
  Napi::Value TrackWrapper::maxMessageSize(const Napi::CallbackInfo &info)
231
226
  {
232
- Napi::Env env = info.Env();
233
-
234
- if (!mTrackPtr)
235
- {
236
- return Napi::Number::New(info.Env(), 0);
237
- }
238
-
239
- try
240
- {
241
- return Napi::Number::New(info.Env(), mTrackPtr->maxMessageSize());
242
- }
243
- catch (std::exception &ex)
244
- {
245
- Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
246
- return Napi::Number::New(info.Env(), 0);
247
- }
227
+ Napi::Env env = info.Env();
228
+
229
+ if (!mTrackPtr)
230
+ {
231
+ return Napi::Number::New(info.Env(), 0);
232
+ }
233
+
234
+ try
235
+ {
236
+ return Napi::Number::New(info.Env(), mTrackPtr->maxMessageSize());
237
+ }
238
+ catch (std::exception &ex)
239
+ {
240
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
241
+ return Napi::Number::New(info.Env(), 0);
242
+ }
248
243
  }
249
244
 
250
245
  Napi::Value TrackWrapper::requestBitrate(const Napi::CallbackInfo &info)
251
246
  {
252
- if (!mTrackPtr)
253
- {
254
- Napi::Error::New(info.Env(), "requestBitrate() called on destroyed track").ThrowAsJavaScriptException();
255
- return info.Env().Null();
256
- }
257
-
258
- Napi::Env env = info.Env();
259
- int length = info.Length();
260
-
261
- if (length < 1 || !info[0].IsNumber())
262
- {
263
- Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
264
- return info.Env().Null();
265
- }
266
-
267
- unsigned int bitrate = static_cast<uint32_t>(info[0].As<Napi::Number>());
268
- return Napi::Boolean::New(env, mTrackPtr->requestBitrate(bitrate));
247
+ if (!mTrackPtr)
248
+ {
249
+ Napi::Error::New(info.Env(), "requestBitrate() called on destroyed track").ThrowAsJavaScriptException();
250
+ return info.Env().Null();
251
+ }
252
+
253
+ Napi::Env env = info.Env();
254
+ int length = info.Length();
255
+
256
+ if (length < 1 || !info[0].IsNumber())
257
+ {
258
+ Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
259
+ return info.Env().Null();
260
+ }
261
+
262
+ unsigned int bitrate = static_cast<uint32_t>(info[0].As<Napi::Number>());
263
+ return Napi::Boolean::New(env, mTrackPtr->requestBitrate(bitrate));
269
264
  }
270
265
 
271
266
  Napi::Value TrackWrapper::requestKeyframe(const Napi::CallbackInfo &info)
272
267
  {
273
- if (!mTrackPtr)
274
- {
275
- Napi::Error::New(info.Env(), "requestKeyframe() called on destroyed track").ThrowAsJavaScriptException();
276
- return info.Env().Null();
277
- }
278
-
279
- Napi::Env env = info.Env();
280
- return Napi::Boolean::New(env, mTrackPtr->requestKeyframe());
268
+ if (!mTrackPtr)
269
+ {
270
+ Napi::Error::New(info.Env(), "requestKeyframe() called on destroyed track").ThrowAsJavaScriptException();
271
+ return info.Env().Null();
272
+ }
273
+
274
+ Napi::Env env = info.Env();
275
+ return Napi::Boolean::New(env, mTrackPtr->requestKeyframe());
281
276
  }
282
277
 
283
278
  void TrackWrapper::setMediaHandler(const Napi::CallbackInfo &info)
284
279
  {
285
- if (!mTrackPtr)
286
- {
287
- Napi::Error::New(info.Env(), "setMediaHandler() called on destroyed track").ThrowAsJavaScriptException();
288
- return;
289
- }
290
-
291
- Napi::Env env = info.Env();
292
- int length = info.Length();
293
-
294
- if (length < 1 || !info[0].IsObject())
295
- {
296
- Napi::TypeError::New(env, "MediaHandler class instance expected").ThrowAsJavaScriptException();
297
- return;
298
- }
299
-
300
- RtcpReceivingSessionWrapper *handler = Napi::ObjectWrap<RtcpReceivingSessionWrapper>::Unwrap(info[0].As<Napi::Object>());
301
- mTrackPtr->setMediaHandler(handler->getSessionInstance());
280
+ if (!mTrackPtr)
281
+ {
282
+ Napi::Error::New(info.Env(), "setMediaHandler() called on destroyed track").ThrowAsJavaScriptException();
283
+ return;
284
+ }
285
+
286
+ Napi::Env env = info.Env();
287
+ int length = info.Length();
288
+
289
+ if (length < 1 || !info[0].IsObject())
290
+ {
291
+ Napi::TypeError::New(env, "MediaHandler class instance expected").ThrowAsJavaScriptException();
292
+ return;
293
+ }
294
+
295
+ RtcpReceivingSessionWrapper *handler =
296
+ Napi::ObjectWrap<RtcpReceivingSessionWrapper>::Unwrap(info[0].As<Napi::Object>());
297
+ mTrackPtr->setMediaHandler(handler->getSessionInstance());
302
298
  }
303
299
 
304
300
  void TrackWrapper::onOpen(const Napi::CallbackInfo &info)
305
301
  {
306
- if (!mTrackPtr)
307
- {
308
- Napi::Error::New(info.Env(), "onOpen() called on destroyed track").ThrowAsJavaScriptException();
309
- return;
310
- }
311
-
312
- Napi::Env env = info.Env();
313
- int length = info.Length();
314
-
315
- if (length < 1 || !info[0].IsFunction())
316
- {
317
- Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
318
- return;
319
- }
320
-
321
- // Callback
322
- mOnOpenCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
323
-
324
- mTrackPtr->onOpen([&]()
325
- {
326
- if (mOnOpenCallback)
327
- mOnOpenCallback->call([this](Napi::Env env, std::vector<napi_value> &args) {
328
- // Check the track is not closed
329
- if(instances.find(this) == instances.end())
330
- throw ThreadSafeCallback::CancelException();
331
-
332
- // This will run in main thread and needs to construct the
333
- // arguments for the call
334
- args = {};
335
- }); });
302
+ if (!mTrackPtr)
303
+ {
304
+ Napi::Error::New(info.Env(), "onOpen() called on destroyed track").ThrowAsJavaScriptException();
305
+ return;
306
+ }
307
+
308
+ Napi::Env env = info.Env();
309
+ int length = info.Length();
310
+
311
+ if (length < 1 || !info[0].IsFunction())
312
+ {
313
+ Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
314
+ return;
315
+ }
316
+
317
+ // Callback
318
+ mOnOpenCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
319
+
320
+ mTrackPtr->onOpen(
321
+ [&]()
322
+ {
323
+ if (mOnOpenCallback)
324
+ mOnOpenCallback->call(
325
+ [this](Napi::Env env, std::vector<napi_value> &args)
326
+ {
327
+ // Check the track is not closed
328
+ if (instances.find(this) == instances.end())
329
+ throw ThreadSafeCallback::CancelException();
330
+
331
+ // This will run in main thread and needs to construct the
332
+ // arguments for the call
333
+ args = {};
334
+ });
335
+ });
336
336
  }
337
337
 
338
338
  void TrackWrapper::onClosed(const Napi::CallbackInfo &info)
339
339
  {
340
- if (!mTrackPtr)
341
- {
342
- Napi::Error::New(info.Env(), "onClosed() called on destroyed track").ThrowAsJavaScriptException();
343
- return;
344
- }
345
-
346
- Napi::Env env = info.Env();
347
- int length = info.Length();
348
-
349
- if (length < 1 || !info[0].IsFunction())
350
- {
351
- Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
352
- return;
353
- }
354
-
355
- // Callback
356
- mOnClosedCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
357
-
358
- mTrackPtr->onClosed([&]()
359
- {
360
- if (mOnClosedCallback)
361
- mOnClosedCallback->call([this](Napi::Env env, std::vector<napi_value> &args) {
362
- // Do not check if the data channel has been closed here
363
-
364
- // This will run in main thread and needs to construct the
365
- // arguments for the call
366
- args = {};
367
- },[this]{
368
- doCleanup();
369
- }); });
340
+ if (!mTrackPtr)
341
+ {
342
+ Napi::Error::New(info.Env(), "onClosed() called on destroyed track").ThrowAsJavaScriptException();
343
+ return;
344
+ }
345
+
346
+ Napi::Env env = info.Env();
347
+ int length = info.Length();
348
+
349
+ if (length < 1 || !info[0].IsFunction())
350
+ {
351
+ Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
352
+ return;
353
+ }
354
+
355
+ // Callback
356
+ mOnClosedCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
357
+
358
+ mTrackPtr->onClosed(
359
+ [&]()
360
+ {
361
+ if (mOnClosedCallback)
362
+ mOnClosedCallback->call(
363
+ [this](Napi::Env env, std::vector<napi_value> &args)
364
+ {
365
+ // Do not check if the data channel has been closed here
366
+
367
+ // This will run in main thread and needs to construct the
368
+ // arguments for the call
369
+ args = {};
370
+ },
371
+ [this] { doCleanup(); });
372
+ });
370
373
  }
371
374
 
372
375
  void TrackWrapper::onError(const Napi::CallbackInfo &info)
373
376
  {
374
- if (!mTrackPtr)
375
- {
376
- Napi::Error::New(info.Env(), "onError() called on destroyed track").ThrowAsJavaScriptException();
377
- return;
378
- }
379
-
380
- Napi::Env env = info.Env();
381
- int length = info.Length();
382
-
383
- if (length < 1 || !info[0].IsFunction())
384
- {
385
- Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
386
- return;
387
- }
388
-
389
- // Callback
390
- mOnErrorCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
391
-
392
- mTrackPtr->onError([&](const std::string &error)
393
- {
394
- if (mOnErrorCallback)
395
- mOnErrorCallback->call([this, error](Napi::Env env, std::vector<napi_value> &args) {
396
- // Check the track is not closed
397
- if(instances.find(this) == instances.end())
398
- throw ThreadSafeCallback::CancelException();
399
-
400
- // This will run in main thread and needs to construct the
401
- // arguments for the call
402
- args = {Napi::String::New(env, error)};
403
- }); });
377
+ if (!mTrackPtr)
378
+ {
379
+ Napi::Error::New(info.Env(), "onError() called on destroyed track").ThrowAsJavaScriptException();
380
+ return;
381
+ }
382
+
383
+ Napi::Env env = info.Env();
384
+ int length = info.Length();
385
+
386
+ if (length < 1 || !info[0].IsFunction())
387
+ {
388
+ Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
389
+ return;
390
+ }
391
+
392
+ // Callback
393
+ mOnErrorCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
394
+
395
+ mTrackPtr->onError(
396
+ [&](const std::string &error)
397
+ {
398
+ if (mOnErrorCallback)
399
+ mOnErrorCallback->call(
400
+ [this, error](Napi::Env env, std::vector<napi_value> &args)
401
+ {
402
+ // Check the track is not closed
403
+ if (instances.find(this) == instances.end())
404
+ throw ThreadSafeCallback::CancelException();
405
+
406
+ // This will run in main thread and needs to construct the
407
+ // arguments for the call
408
+ args = {Napi::String::New(env, error)};
409
+ });
410
+ });
404
411
  }
405
412
 
406
413
  void TrackWrapper::onMessage(const Napi::CallbackInfo &info)
407
414
  {
408
- if (!mTrackPtr)
409
- {
410
- Napi::Error::New(info.Env(), "onMessage() called on destroyed track").ThrowAsJavaScriptException();
411
- return;
412
- }
413
-
414
- Napi::Env env = info.Env();
415
- int length = info.Length();
416
-
417
- if (length < 1 || !info[0].IsFunction())
418
- {
419
- Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
420
- return;
421
- }
422
-
423
- // Callback
424
- mOnMessageCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
425
-
426
- mTrackPtr->onMessage([&](std::variant<rtc::binary, std::string> message)
427
- {
428
- if (mOnMessageCallback)
429
- mOnMessageCallback->call([this, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args) {
430
- // Check the track is not closed
431
- if(instances.find(this) == instances.end())
432
- throw ThreadSafeCallback::CancelException();
433
-
434
- // This will run in main thread and needs to construct the
435
- // arguments for the call
436
- if (std::holds_alternative<rtc::binary>(message)) // Track will always receive messages as binary
437
- {
438
- auto bin = std::get<rtc::binary>(std::move(message));
439
- args = {Napi::Buffer<std::byte>::Copy(env, bin.data(), bin.size())};
440
- }
441
- }); });
415
+ if (!mTrackPtr)
416
+ {
417
+ Napi::Error::New(info.Env(), "onMessage() called on destroyed track").ThrowAsJavaScriptException();
418
+ return;
419
+ }
420
+
421
+ Napi::Env env = info.Env();
422
+ int length = info.Length();
423
+
424
+ if (length < 1 || !info[0].IsFunction())
425
+ {
426
+ Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
427
+ return;
428
+ }
429
+
430
+ // Callback
431
+ mOnMessageCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
432
+
433
+ mTrackPtr->onMessage(
434
+ [&](std::variant<rtc::binary, std::string> message)
435
+ {
436
+ if (mOnMessageCallback)
437
+ mOnMessageCallback->call(
438
+ [this, message = std::move(message)](Napi::Env env, std::vector<napi_value> &args)
439
+ {
440
+ // Check the track is not closed
441
+ if (instances.find(this) == instances.end())
442
+ throw ThreadSafeCallback::CancelException();
443
+
444
+ // This will run in main thread and needs to construct the
445
+ // arguments for the call
446
+ if (std::holds_alternative<rtc::binary>(message)) // Track will always receive messages as binary
447
+ {
448
+ auto bin = std::get<rtc::binary>(std::move(message));
449
+ args = {Napi::Buffer<std::byte>::Copy(env, bin.data(), bin.size())};
450
+ }
451
+ });
452
+ });
442
453
  }