node-datachannel 0.3.1 → 0.3.2
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/lint.yml +22 -0
- package/CMakeLists.txt +2 -2
- package/examples/client-server/client-benchmark.js +43 -32
- package/examples/client-server/client-periodic.js +30 -14
- package/examples/client-server/client.js +6 -5
- package/examples/client-server/package-lock.json +183 -44
- package/examples/client-server/signaling-server.js +3 -5
- package/examples/media/media.js +9 -9
- package/lib/index.d.ts +100 -100
- package/node_modules/lru-cache/package.json +2 -4
- package/node_modules/minimist/package.json +0 -1
- package/node_modules/node-abi/node_modules/semver/README.md +3 -1
- package/node_modules/node-abi/node_modules/semver/bin/semver.js +19 -9
- package/node_modules/node-abi/node_modules/semver/classes/comparator.js +3 -2
- package/node_modules/node-abi/node_modules/semver/classes/index.js +1 -1
- package/node_modules/node-abi/node_modules/semver/classes/range.js +31 -22
- package/node_modules/node-abi/node_modules/semver/classes/semver.js +1 -1
- package/node_modules/node-abi/node_modules/semver/functions/cmp.js +8 -4
- package/node_modules/node-abi/node_modules/semver/functions/coerce.js +3 -2
- package/node_modules/node-abi/node_modules/semver/functions/inc.js +4 -1
- package/node_modules/node-abi/node_modules/semver/functions/parse.js +1 -1
- package/node_modules/node-abi/node_modules/semver/internal/constants.js +2 -2
- package/node_modules/node-abi/node_modules/semver/internal/identifiers.js +1 -1
- package/node_modules/node-abi/node_modules/semver/internal/parse-options.js +3 -3
- package/node_modules/node-abi/node_modules/semver/internal/re.js +3 -3
- package/node_modules/node-abi/node_modules/semver/package.json +51 -18
- package/node_modules/node-abi/node_modules/semver/ranges/min-version.js +2 -1
- package/node_modules/node-abi/node_modules/semver/ranges/outside.js +1 -1
- package/node_modules/node-abi/node_modules/semver/ranges/simplify.js +15 -12
- package/node_modules/node-abi/node_modules/semver/ranges/subset.js +53 -31
- package/node_modules/npmlog/node_modules/are-we-there-yet/package.json +10 -10
- package/node_modules/npmlog/package.json +1 -1
- package/node_modules/tar-stream/node_modules/bl/.travis.yml +4 -3
- package/node_modules/tar-stream/node_modules/bl/BufferList.js +1 -1
- package/node_modules/tar-stream/node_modules/bl/package.json +10 -10
- package/node_modules/tar-stream/node_modules/bl/test/test.js +20 -2
- package/node_modules/wide-align/LICENSE +0 -0
- package/node_modules/wide-align/README.md +0 -0
- package/node_modules/wide-align/align.js +0 -0
- package/node_modules/wide-align/package.json +14 -14
- package/package.json +2 -2
- package/src/data-channel-wrapper.cpp +69 -53
- package/src/data-channel-wrapper.h +0 -1
- package/src/media-track-wrapper.cpp +91 -52
- package/src/media-track-wrapper.h +0 -1
- package/src/peer-connection-wrapper.cpp +106 -70
- package/src/peer-connection-wrapper.h +0 -2
- package/test/connectivity.js +18 -17
- package/test/test.js +22 -30
- package/node_modules/node-abi/node_modules/semver/CHANGELOG.md +0 -111
|
@@ -63,7 +63,7 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
|
|
|
63
63
|
// We expect (String, Object, Function) as param
|
|
64
64
|
if (length < 2 || !info[0].IsString() || !info[1].IsObject())
|
|
65
65
|
{
|
|
66
|
-
Napi::TypeError::New(env, "Peer Name (String)
|
|
66
|
+
Napi::TypeError::New(env, "Peer Name (String) and Configuration (Object) expected").ThrowAsJavaScriptException();
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -211,31 +211,10 @@ PeerConnectionWrapper::PeerConnectionWrapper(const Napi::CallbackInfo &info) : N
|
|
|
211
211
|
}
|
|
212
212
|
catch (std::exception &ex)
|
|
213
213
|
{
|
|
214
|
-
Napi::Error::New(env, std::string("libdatachannel error while creating
|
|
214
|
+
Napi::Error::New(env, std::string("libdatachannel error while creating peer connection: ") + ex.what()).ThrowAsJavaScriptException();
|
|
215
215
|
return;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
mRtcPeerConnPtr->onStateChange([&](rtc::PeerConnection::State state) {
|
|
219
|
-
if (mOnStateChangeCallback)
|
|
220
|
-
mOnStateChangeCallback->call([this, state](Napi::Env env, std::vector<napi_value> &args) {
|
|
221
|
-
// Check the peer connection is not closed
|
|
222
|
-
if(instances.find(this) == instances.end())
|
|
223
|
-
throw ThreadSafeCallback::CancelException();
|
|
224
|
-
|
|
225
|
-
if(mDoCloseFlag && state == rtc::PeerConnection::State::Closed)
|
|
226
|
-
cleanCbsAndEraseInstance();
|
|
227
|
-
|
|
228
|
-
// This will run in main thread and needs to construct the
|
|
229
|
-
// arguments for the call
|
|
230
|
-
std::ostringstream stream;
|
|
231
|
-
stream << state;
|
|
232
|
-
args = {Napi::String::New(env, stream.str())};
|
|
233
|
-
});
|
|
234
|
-
else {
|
|
235
|
-
if(mDoCloseFlag && state == rtc::PeerConnection::State::Closed)
|
|
236
|
-
cleanCbsAndEraseInstance();
|
|
237
|
-
} });
|
|
238
|
-
|
|
239
218
|
instances.insert(this);
|
|
240
219
|
}
|
|
241
220
|
|
|
@@ -246,26 +225,20 @@ PeerConnectionWrapper::~PeerConnectionWrapper()
|
|
|
246
225
|
|
|
247
226
|
void PeerConnectionWrapper::doClose()
|
|
248
227
|
{
|
|
249
|
-
if (mRtcPeerConnPtr
|
|
228
|
+
if (mRtcPeerConnPtr)
|
|
250
229
|
{
|
|
251
230
|
try
|
|
252
231
|
{
|
|
253
|
-
mDoCloseFlag = true;
|
|
254
232
|
mRtcPeerConnPtr->close();
|
|
255
|
-
|
|
256
|
-
// Resetting in cleanCbsAndEraseInstance causes a deadlock
|
|
257
233
|
mRtcPeerConnPtr.reset();
|
|
258
234
|
}
|
|
259
235
|
catch (std::exception &ex)
|
|
260
236
|
{
|
|
261
|
-
std::
|
|
237
|
+
std::cerr << std::string("libdatachannel error while closing peer connection: ") + ex.what() << std::endl;
|
|
262
238
|
return;
|
|
263
239
|
}
|
|
264
240
|
}
|
|
265
|
-
}
|
|
266
241
|
|
|
267
|
-
void PeerConnectionWrapper::cleanCbsAndEraseInstance()
|
|
268
|
-
{
|
|
269
242
|
mOnLocalDescriptionCallback.reset();
|
|
270
243
|
mOnLocalCandidateCallback.reset();
|
|
271
244
|
mOnStateChangeCallback.reset();
|
|
@@ -274,8 +247,6 @@ void PeerConnectionWrapper::cleanCbsAndEraseInstance()
|
|
|
274
247
|
mOnTrackCallback.reset();
|
|
275
248
|
|
|
276
249
|
instances.erase(this);
|
|
277
|
-
|
|
278
|
-
mDoCloseFlag = false;
|
|
279
250
|
}
|
|
280
251
|
|
|
281
252
|
void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
|
|
@@ -286,14 +257,14 @@ void PeerConnectionWrapper::close(const Napi::CallbackInfo &info)
|
|
|
286
257
|
void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
|
|
287
258
|
{
|
|
288
259
|
Napi::Env env = info.Env();
|
|
260
|
+
int length = info.Length();
|
|
261
|
+
|
|
289
262
|
if (!mRtcPeerConnPtr)
|
|
290
263
|
{
|
|
291
|
-
Napi::Error::New(
|
|
264
|
+
Napi::Error::New(env, "setLocalDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
292
265
|
return;
|
|
293
266
|
}
|
|
294
267
|
|
|
295
|
-
int length = info.Length();
|
|
296
|
-
|
|
297
268
|
rtc::Description::Type type = rtc::Description::Type::Unspec;
|
|
298
269
|
|
|
299
270
|
// optional
|
|
@@ -322,13 +293,14 @@ void PeerConnectionWrapper::setLocalDescription(const Napi::CallbackInfo &info)
|
|
|
322
293
|
void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
|
|
323
294
|
{
|
|
324
295
|
Napi::Env env = info.Env();
|
|
296
|
+
int length = info.Length();
|
|
297
|
+
|
|
325
298
|
if (!mRtcPeerConnPtr)
|
|
326
299
|
{
|
|
327
|
-
Napi::Error::New(
|
|
300
|
+
Napi::Error::New(env, "setRemoteDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
328
301
|
return;
|
|
329
302
|
}
|
|
330
303
|
|
|
331
|
-
int length = info.Length();
|
|
332
304
|
if (length < 2 || !info[0].IsString() || !info[1].IsString())
|
|
333
305
|
{
|
|
334
306
|
Napi::TypeError::New(info.Env(), "String,String expected").ThrowAsJavaScriptException();
|
|
@@ -345,7 +317,7 @@ void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
|
|
|
345
317
|
}
|
|
346
318
|
catch (std::exception &ex)
|
|
347
319
|
{
|
|
348
|
-
Napi::Error::New(env, std::string("libdatachannel error while adding remote
|
|
320
|
+
Napi::Error::New(env, std::string("libdatachannel error while adding remote description: ") + ex.what()).ThrowAsJavaScriptException();
|
|
349
321
|
return;
|
|
350
322
|
}
|
|
351
323
|
}
|
|
@@ -353,7 +325,13 @@ void PeerConnectionWrapper::setRemoteDescription(const Napi::CallbackInfo &info)
|
|
|
353
325
|
Napi::Value PeerConnectionWrapper::localDescription(const Napi::CallbackInfo &info)
|
|
354
326
|
{
|
|
355
327
|
Napi::Env env = info.Env();
|
|
356
|
-
|
|
328
|
+
|
|
329
|
+
std::optional<rtc::Description> desc = mRtcPeerConnPtr ? mRtcPeerConnPtr->localDescription() : std::nullopt;
|
|
330
|
+
|
|
331
|
+
// Return JS null if no description
|
|
332
|
+
if (!desc.has_value()) {
|
|
333
|
+
return env.Null();
|
|
334
|
+
}
|
|
357
335
|
|
|
358
336
|
Napi::Object obj = Napi::Object::New(env);
|
|
359
337
|
obj.Set("type", desc->typeString());
|
|
@@ -364,16 +342,17 @@ Napi::Value PeerConnectionWrapper::localDescription(const Napi::CallbackInfo &in
|
|
|
364
342
|
void PeerConnectionWrapper::addRemoteCandidate(const Napi::CallbackInfo &info)
|
|
365
343
|
{
|
|
366
344
|
Napi::Env env = info.Env();
|
|
345
|
+
int length = info.Length();
|
|
346
|
+
|
|
367
347
|
if (!mRtcPeerConnPtr)
|
|
368
348
|
{
|
|
369
|
-
Napi::Error::New(
|
|
349
|
+
Napi::Error::New(env, "addRemoteCandidate() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
370
350
|
return;
|
|
371
351
|
}
|
|
372
352
|
|
|
373
|
-
int length = info.Length();
|
|
374
353
|
if (length < 2 || !info[0].IsString() || !info[1].IsString())
|
|
375
354
|
{
|
|
376
|
-
Napi::TypeError::New(info.Env(), "String,String expected").ThrowAsJavaScriptException();
|
|
355
|
+
Napi::TypeError::New(info.Env(), "String, String expected").ThrowAsJavaScriptException();
|
|
377
356
|
return;
|
|
378
357
|
}
|
|
379
358
|
|
|
@@ -385,22 +364,22 @@ void PeerConnectionWrapper::addRemoteCandidate(const Napi::CallbackInfo &info)
|
|
|
385
364
|
}
|
|
386
365
|
catch (std::exception &ex)
|
|
387
366
|
{
|
|
388
|
-
Napi::Error::New(env, std::string("libdatachannel error while adding remote candidate
|
|
367
|
+
Napi::Error::New(env, std::string("libdatachannel error while adding remote candidate: ") + ex.what()).ThrowAsJavaScriptException();
|
|
389
368
|
return;
|
|
390
369
|
}
|
|
391
370
|
}
|
|
392
371
|
|
|
393
372
|
Napi::Value PeerConnectionWrapper::createDataChannel(const Napi::CallbackInfo &info)
|
|
394
373
|
{
|
|
374
|
+
Napi::Env env = info.Env();
|
|
375
|
+
int length = info.Length();
|
|
376
|
+
|
|
395
377
|
if (!mRtcPeerConnPtr)
|
|
396
378
|
{
|
|
397
|
-
Napi::Error::New(
|
|
379
|
+
Napi::Error::New(env, "createDataChannel() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
398
380
|
return info.Env().Null();
|
|
399
381
|
}
|
|
400
382
|
|
|
401
|
-
Napi::Env env = info.Env();
|
|
402
|
-
int length = info.Length();
|
|
403
|
-
|
|
404
383
|
if (length < 1 || !info[0].IsString())
|
|
405
384
|
{
|
|
406
385
|
Napi::TypeError::New(env, "Data Channel Label expected").ThrowAsJavaScriptException();
|
|
@@ -554,7 +533,7 @@ Napi::Value PeerConnectionWrapper::createDataChannel(const Napi::CallbackInfo &i
|
|
|
554
533
|
}
|
|
555
534
|
catch (std::exception &ex)
|
|
556
535
|
{
|
|
557
|
-
Napi::Error::New(env, std::string("libdatachannel error while creating datachannel
|
|
536
|
+
Napi::Error::New(env, std::string("libdatachannel error while creating datachannel: ") + ex.what()).ThrowAsJavaScriptException();
|
|
558
537
|
return info.Env().Null();
|
|
559
538
|
}
|
|
560
539
|
}
|
|
@@ -564,6 +543,12 @@ void PeerConnectionWrapper::onLocalDescription(const Napi::CallbackInfo &info)
|
|
|
564
543
|
Napi::Env env = info.Env();
|
|
565
544
|
int length = info.Length();
|
|
566
545
|
|
|
546
|
+
if (!mRtcPeerConnPtr)
|
|
547
|
+
{
|
|
548
|
+
Napi::Error::New(env, "onLocalDescription() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
567
552
|
if (length < 1 || !info[0].IsFunction())
|
|
568
553
|
{
|
|
569
554
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -573,9 +558,9 @@ void PeerConnectionWrapper::onLocalDescription(const Napi::CallbackInfo &info)
|
|
|
573
558
|
// Callback
|
|
574
559
|
mOnLocalDescriptionCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
575
560
|
|
|
576
|
-
mRtcPeerConnPtr->onLocalDescription([&](
|
|
561
|
+
mRtcPeerConnPtr->onLocalDescription([&](rtc::Description sdp) {
|
|
577
562
|
if (mOnLocalDescriptionCallback)
|
|
578
|
-
mOnLocalDescriptionCallback->call([this, sdp](Napi::Env env, std::vector<napi_value> &args) {
|
|
563
|
+
mOnLocalDescriptionCallback->call([this, sdp = std::move(sdp)](Napi::Env env, std::vector<napi_value> &args) {
|
|
579
564
|
// Check the peer connection is not closed
|
|
580
565
|
if(instances.find(this) == instances.end())
|
|
581
566
|
throw ThreadSafeCallback::CancelException();
|
|
@@ -593,6 +578,12 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
|
|
|
593
578
|
Napi::Env env = info.Env();
|
|
594
579
|
int length = info.Length();
|
|
595
580
|
|
|
581
|
+
if (!mRtcPeerConnPtr)
|
|
582
|
+
{
|
|
583
|
+
Napi::Error::New(env, "onLocalCandidate() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
|
|
596
587
|
if (length < 1 || !info[0].IsFunction())
|
|
597
588
|
{
|
|
598
589
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -602,9 +593,9 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
|
|
|
602
593
|
// Callback
|
|
603
594
|
mOnLocalCandidateCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
604
595
|
|
|
605
|
-
mRtcPeerConnPtr->onLocalCandidate([&](
|
|
596
|
+
mRtcPeerConnPtr->onLocalCandidate([&](rtc::Candidate cand) {
|
|
606
597
|
if (mOnLocalCandidateCallback)
|
|
607
|
-
mOnLocalCandidateCallback->call([this,
|
|
598
|
+
mOnLocalCandidateCallback->call([this, cand = std::move(cand)](Napi::Env env, std::vector<napi_value> &args) {
|
|
608
599
|
// Check the peer connection is not closed
|
|
609
600
|
if(instances.find(this) == instances.end())
|
|
610
601
|
throw ThreadSafeCallback::CancelException();
|
|
@@ -612,8 +603,8 @@ void PeerConnectionWrapper::onLocalCandidate(const Napi::CallbackInfo &info)
|
|
|
612
603
|
// This will run in main thread and needs to construct the
|
|
613
604
|
// arguments for the call
|
|
614
605
|
args = {
|
|
615
|
-
Napi::String::New(env, std::string(
|
|
616
|
-
Napi::String::New(env,
|
|
606
|
+
Napi::String::New(env, std::string(cand)),
|
|
607
|
+
Napi::String::New(env, cand.mid())};
|
|
617
608
|
}); });
|
|
618
609
|
}
|
|
619
610
|
|
|
@@ -622,6 +613,12 @@ void PeerConnectionWrapper::onStateChange(const Napi::CallbackInfo &info)
|
|
|
622
613
|
Napi::Env env = info.Env();
|
|
623
614
|
int length = info.Length();
|
|
624
615
|
|
|
616
|
+
if (!mRtcPeerConnPtr)
|
|
617
|
+
{
|
|
618
|
+
Napi::Error::New(env, "onStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
625
622
|
if (length < 1 || !info[0].IsFunction())
|
|
626
623
|
{
|
|
627
624
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -631,7 +628,19 @@ void PeerConnectionWrapper::onStateChange(const Napi::CallbackInfo &info)
|
|
|
631
628
|
// Callback
|
|
632
629
|
mOnStateChangeCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
633
630
|
|
|
634
|
-
|
|
631
|
+
mRtcPeerConnPtr->onStateChange([&](rtc::PeerConnection::State state) {
|
|
632
|
+
if (mOnStateChangeCallback)
|
|
633
|
+
mOnStateChangeCallback->call([this, state](Napi::Env env, std::vector<napi_value> &args) {
|
|
634
|
+
// Check the peer connection is not closed but still allow a call for State::Closed
|
|
635
|
+
if(state != rtc::PeerConnection::State::Closed && instances.find(this) == instances.end())
|
|
636
|
+
throw ThreadSafeCallback::CancelException();
|
|
637
|
+
|
|
638
|
+
// This will run in main thread and needs to construct the
|
|
639
|
+
// arguments for the call
|
|
640
|
+
std::ostringstream stream;
|
|
641
|
+
stream << state;
|
|
642
|
+
args = {Napi::String::New(env, stream.str())};
|
|
643
|
+
}); });
|
|
635
644
|
}
|
|
636
645
|
|
|
637
646
|
void PeerConnectionWrapper::onSignalingStateChange(const Napi::CallbackInfo &info)
|
|
@@ -639,6 +648,12 @@ void PeerConnectionWrapper::onSignalingStateChange(const Napi::CallbackInfo &inf
|
|
|
639
648
|
Napi::Env env = info.Env();
|
|
640
649
|
int length = info.Length();
|
|
641
650
|
|
|
651
|
+
if (!mRtcPeerConnPtr)
|
|
652
|
+
{
|
|
653
|
+
Napi::Error::New(env, "onSignalingStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
|
|
642
657
|
if (length < 1 || !info[0].IsFunction())
|
|
643
658
|
{
|
|
644
659
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -668,6 +683,12 @@ void PeerConnectionWrapper::onGatheringStateChange(const Napi::CallbackInfo &inf
|
|
|
668
683
|
Napi::Env env = info.Env();
|
|
669
684
|
int length = info.Length();
|
|
670
685
|
|
|
686
|
+
if (!mRtcPeerConnPtr)
|
|
687
|
+
{
|
|
688
|
+
Napi::Error::New(env, "onGatheringStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
|
|
671
692
|
if (length < 1 || !info[0].IsFunction())
|
|
672
693
|
{
|
|
673
694
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -697,6 +718,12 @@ void PeerConnectionWrapper::onDataChannel(const Napi::CallbackInfo &info)
|
|
|
697
718
|
Napi::Env env = info.Env();
|
|
698
719
|
int length = info.Length();
|
|
699
720
|
|
|
721
|
+
if (!mRtcPeerConnPtr)
|
|
722
|
+
{
|
|
723
|
+
Napi::Error::New(env, "onDataChannel() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
|
|
700
727
|
if (length < 1 || !info[0].IsFunction())
|
|
701
728
|
{
|
|
702
729
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -725,6 +752,7 @@ void PeerConnectionWrapper::onDataChannel(const Napi::CallbackInfo &info)
|
|
|
725
752
|
Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
|
|
726
753
|
{
|
|
727
754
|
Napi::Env env = info.Env();
|
|
755
|
+
|
|
728
756
|
if (!mRtcPeerConnPtr)
|
|
729
757
|
{
|
|
730
758
|
return Napi::Number::New(info.Env(), 0);
|
|
@@ -736,7 +764,7 @@ Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
|
|
|
736
764
|
}
|
|
737
765
|
catch (std::exception &ex)
|
|
738
766
|
{
|
|
739
|
-
Napi::Error::New(env, std::string("libdatachannel error
|
|
767
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
740
768
|
return Napi::Number::New(info.Env(), 0);
|
|
741
769
|
}
|
|
742
770
|
}
|
|
@@ -744,6 +772,7 @@ Napi::Value PeerConnectionWrapper::bytesSent(const Napi::CallbackInfo &info)
|
|
|
744
772
|
Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
|
|
745
773
|
{
|
|
746
774
|
Napi::Env env = info.Env();
|
|
775
|
+
|
|
747
776
|
if (!mRtcPeerConnPtr)
|
|
748
777
|
{
|
|
749
778
|
return Napi::Number::New(info.Env(), 0);
|
|
@@ -755,7 +784,7 @@ Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
|
|
|
755
784
|
}
|
|
756
785
|
catch (std::exception &ex)
|
|
757
786
|
{
|
|
758
|
-
Napi::Error::New(env, std::string("libdatachannel error
|
|
787
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
759
788
|
return Napi::Number::New(info.Env(), 0);
|
|
760
789
|
}
|
|
761
790
|
}
|
|
@@ -763,6 +792,7 @@ Napi::Value PeerConnectionWrapper::bytesReceived(const Napi::CallbackInfo &info)
|
|
|
763
792
|
Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
|
|
764
793
|
{
|
|
765
794
|
Napi::Env env = info.Env();
|
|
795
|
+
|
|
766
796
|
if (!mRtcPeerConnPtr)
|
|
767
797
|
{
|
|
768
798
|
return Napi::Number::New(info.Env(), 0);
|
|
@@ -774,7 +804,7 @@ Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
|
|
|
774
804
|
}
|
|
775
805
|
catch (std::exception &ex)
|
|
776
806
|
{
|
|
777
|
-
Napi::Error::New(env, std::string("libdatachannel error
|
|
807
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
778
808
|
return Napi::Number::New(info.Env(), -1);
|
|
779
809
|
}
|
|
780
810
|
}
|
|
@@ -782,16 +812,17 @@ Napi::Value PeerConnectionWrapper::rtt(const Napi::CallbackInfo &info)
|
|
|
782
812
|
Napi::Value PeerConnectionWrapper::getSelectedCandidatePair(const Napi::CallbackInfo &info)
|
|
783
813
|
{
|
|
784
814
|
Napi::Env env = info.Env();
|
|
815
|
+
|
|
785
816
|
if (!mRtcPeerConnPtr)
|
|
786
817
|
{
|
|
787
|
-
return
|
|
818
|
+
return env.Null();
|
|
788
819
|
}
|
|
789
820
|
|
|
790
821
|
try
|
|
791
822
|
{
|
|
792
823
|
rtc::Candidate local, remote;
|
|
793
824
|
if (!mRtcPeerConnPtr->getSelectedCandidatePair(&local, &remote))
|
|
794
|
-
return
|
|
825
|
+
return env.Null();
|
|
795
826
|
|
|
796
827
|
Napi::Object retvalue = Napi::Object::New(env);
|
|
797
828
|
Napi::Object localObj = Napi::Object::New(env);
|
|
@@ -814,7 +845,7 @@ Napi::Value PeerConnectionWrapper::getSelectedCandidatePair(const Napi::Callback
|
|
|
814
845
|
}
|
|
815
846
|
catch (std::exception &ex)
|
|
816
847
|
{
|
|
817
|
-
Napi::Error::New(env, std::string("libdatachannel error
|
|
848
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
818
849
|
return Napi::Number::New(info.Env(), -1);
|
|
819
850
|
}
|
|
820
851
|
}
|
|
@@ -862,7 +893,7 @@ Napi::Value PeerConnectionWrapper::addTrack(const Napi::CallbackInfo &info)
|
|
|
862
893
|
|
|
863
894
|
if (!mRtcPeerConnPtr)
|
|
864
895
|
{
|
|
865
|
-
Napi::Error::New(
|
|
896
|
+
Napi::Error::New(env, "addTrack() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
866
897
|
return env.Null();
|
|
867
898
|
}
|
|
868
899
|
|
|
@@ -896,7 +927,7 @@ Napi::Value PeerConnectionWrapper::addTrack(const Napi::CallbackInfo &info)
|
|
|
896
927
|
}
|
|
897
928
|
catch (std::exception &ex)
|
|
898
929
|
{
|
|
899
|
-
Napi::Error::New(env, std::string("libdatachannel error
|
|
930
|
+
Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
|
|
900
931
|
return env.Null();
|
|
901
932
|
}
|
|
902
933
|
}
|
|
@@ -906,6 +937,12 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
|
|
|
906
937
|
Napi::Env env = info.Env();
|
|
907
938
|
int length = info.Length();
|
|
908
939
|
|
|
940
|
+
if (!mRtcPeerConnPtr)
|
|
941
|
+
{
|
|
942
|
+
Napi::Error::New(env, "onGatheringStateChange() called on destroyed peer connection").ThrowAsJavaScriptException();
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
|
|
909
946
|
if (length < 1 || !info[0].IsFunction())
|
|
910
947
|
{
|
|
911
948
|
Napi::TypeError::New(env, "Function expected").ThrowAsJavaScriptException();
|
|
@@ -915,8 +952,7 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
|
|
|
915
952
|
// Callback
|
|
916
953
|
mOnTrackCallback = std::make_unique<ThreadSafeCallback>(info[0].As<Napi::Function>());
|
|
917
954
|
|
|
918
|
-
mRtcPeerConnPtr->onTrack([&](std::shared_ptr<rtc::Track> track)
|
|
919
|
-
{
|
|
955
|
+
mRtcPeerConnPtr->onTrack([&](std::shared_ptr<rtc::Track> track) {
|
|
920
956
|
if (mOnTrackCallback)
|
|
921
957
|
mOnTrackCallback->call([this, track](Napi::Env env, std::vector<napi_value> &args) {
|
|
922
958
|
// Check the peer connection is not closed
|
|
@@ -934,14 +970,14 @@ void PeerConnectionWrapper::onTrack(const Napi::CallbackInfo &info)
|
|
|
934
970
|
Napi::Value PeerConnectionWrapper::hasMedia(const Napi::CallbackInfo &info)
|
|
935
971
|
{
|
|
936
972
|
Napi::Env env = info.Env();
|
|
937
|
-
return Napi::Boolean::New(env, mRtcPeerConnPtr->hasMedia());
|
|
973
|
+
return Napi::Boolean::New(env, mRtcPeerConnPtr ? mRtcPeerConnPtr->hasMedia() : false);
|
|
938
974
|
}
|
|
939
975
|
|
|
940
976
|
Napi::Value PeerConnectionWrapper::state(const Napi::CallbackInfo &info)
|
|
941
977
|
{
|
|
942
978
|
Napi::Env env = info.Env();
|
|
943
979
|
std::ostringstream stream;
|
|
944
|
-
stream << mRtcPeerConnPtr->state();
|
|
980
|
+
stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->state() : rtc::PeerConnection::State::Closed);
|
|
945
981
|
return Napi::String::New(env, stream.str());
|
|
946
982
|
}
|
|
947
983
|
|
|
@@ -949,7 +985,7 @@ Napi::Value PeerConnectionWrapper::signalingState(const Napi::CallbackInfo &info
|
|
|
949
985
|
{
|
|
950
986
|
Napi::Env env = info.Env();
|
|
951
987
|
std::ostringstream stream;
|
|
952
|
-
stream << mRtcPeerConnPtr->signalingState();
|
|
988
|
+
stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->signalingState() : rtc::PeerConnection::SignalingState::Stable);
|
|
953
989
|
return Napi::String::New(env, stream.str());
|
|
954
990
|
}
|
|
955
991
|
|
|
@@ -957,6 +993,6 @@ Napi::Value PeerConnectionWrapper::gatheringState(const Napi::CallbackInfo &info
|
|
|
957
993
|
{
|
|
958
994
|
Napi::Env env = info.Env();
|
|
959
995
|
std::ostringstream stream;
|
|
960
|
-
stream << mRtcPeerConnPtr->gatheringState();
|
|
996
|
+
stream << (mRtcPeerConnPtr ? mRtcPeerConnPtr->gatheringState() : rtc::PeerConnection::GatheringState::Complete);
|
|
961
997
|
return Napi::String::New(env, stream.str());
|
|
962
998
|
}
|
package/test/connectivity.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1
2
|
const nodeDataChannel = require('../lib/index');
|
|
2
3
|
|
|
3
|
-
nodeDataChannel.initLogger(
|
|
4
|
+
nodeDataChannel.initLogger('Debug');
|
|
4
5
|
nodeDataChannel.preload();
|
|
5
6
|
|
|
6
7
|
let dc1 = null;
|
|
@@ -24,51 +25,51 @@ let dc2 = null;
|
|
|
24
25
|
// TURN Server Example (TCP) : turn:USERNAME:PASSWORD@TURN_IP_OR_ADDRESS:PORT?transport=tcp
|
|
25
26
|
// TURN Server Example (TLS) : turns:USERNAME:PASSWORD@TURN_IP_OR_ADDRESS:PORT
|
|
26
27
|
|
|
27
|
-
let peer1 = new nodeDataChannel.PeerConnection(
|
|
28
|
+
let peer1 = new nodeDataChannel.PeerConnection('Peer1', { iceServers: ['stun:stun.l.google.com:19302'] });
|
|
28
29
|
|
|
29
30
|
// Set Callbacks
|
|
30
31
|
peer1.onStateChange((state) => {
|
|
31
|
-
console.log(
|
|
32
|
+
console.log('Peer1 State:', state);
|
|
32
33
|
});
|
|
33
34
|
peer1.onGatheringStateChange((state) => {
|
|
34
|
-
console.log(
|
|
35
|
+
console.log('Peer1 GatheringState:', state);
|
|
35
36
|
});
|
|
36
37
|
peer1.onLocalDescription((sdp, type) => {
|
|
37
|
-
console.log(
|
|
38
|
+
console.log('Peer1 SDP:', sdp, ' Type:', type);
|
|
38
39
|
peer2.setRemoteDescription(sdp, type);
|
|
39
40
|
});
|
|
40
41
|
peer1.onLocalCandidate((candidate, mid) => {
|
|
41
|
-
console.log(
|
|
42
|
+
console.log('Peer1 Candidate:', candidate);
|
|
42
43
|
peer2.addRemoteCandidate(candidate, mid);
|
|
43
44
|
});
|
|
44
45
|
|
|
45
|
-
let peer2 = new nodeDataChannel.PeerConnection(
|
|
46
|
+
let peer2 = new nodeDataChannel.PeerConnection('Peer2', { iceServers: ['stun:stun.l.google.com:19302'] });
|
|
46
47
|
|
|
47
48
|
// Set Callbacks
|
|
48
49
|
peer2.onStateChange((state) => {
|
|
49
|
-
console.log(
|
|
50
|
+
console.log('Peer2 State:', state);
|
|
50
51
|
});
|
|
51
52
|
peer2.onGatheringStateChange((state) => {
|
|
52
|
-
console.log(
|
|
53
|
+
console.log('Peer2 GatheringState:', state);
|
|
53
54
|
});
|
|
54
55
|
peer2.onLocalDescription((sdp, type) => {
|
|
55
|
-
console.log(
|
|
56
|
+
console.log('Peer2 SDP:', sdp, ' Type:', type);
|
|
56
57
|
peer1.setRemoteDescription(sdp, type);
|
|
57
58
|
});
|
|
58
59
|
peer2.onLocalCandidate((candidate, mid) => {
|
|
59
|
-
console.log(
|
|
60
|
+
console.log('Peer2 Candidate:', candidate);
|
|
60
61
|
peer1.addRemoteCandidate(candidate, mid);
|
|
61
62
|
});
|
|
62
63
|
peer2.onDataChannel((dc) => {
|
|
63
|
-
console.log(
|
|
64
|
+
console.log('Peer2 Got DataChannel: ', dc.getLabel());
|
|
64
65
|
dc2 = dc;
|
|
65
66
|
dc2.onMessage((msg) => {
|
|
66
67
|
console.log('Peer2 Received Msg:', msg);
|
|
67
68
|
});
|
|
68
|
-
dc2.sendMessage(
|
|
69
|
+
dc2.sendMessage('Hello From Peer2');
|
|
69
70
|
dc2.onClosed(() => {
|
|
70
71
|
console.log('dc2 closed');
|
|
71
|
-
|
|
72
|
+
});
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
// DataChannel Options
|
|
@@ -80,16 +81,16 @@ peer2.onDataChannel((dc) => {
|
|
|
80
81
|
// maxPacketLifeTime?: number;
|
|
81
82
|
// maxRetransmits?: number;
|
|
82
83
|
// }
|
|
83
|
-
dc1 = peer1.createDataChannel(
|
|
84
|
+
dc1 = peer1.createDataChannel('test');
|
|
84
85
|
dc1.onOpen(() => {
|
|
85
|
-
dc1.sendMessage(
|
|
86
|
+
dc1.sendMessage('Hello from Peer1');
|
|
86
87
|
// Binary message: Use sendMessageBinary(Buffer)
|
|
87
88
|
});
|
|
88
89
|
dc1.onMessage((msg) => {
|
|
89
90
|
console.log('Peer1 Received Msg:', msg);
|
|
90
91
|
});
|
|
91
92
|
dc1.onClosed(() => {
|
|
92
|
-
|
|
93
|
+
console.log('dc1 closed');
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
setTimeout(() => {
|