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.
Files changed (50) hide show
  1. package/.github/workflows/lint.yml +22 -0
  2. package/CMakeLists.txt +2 -2
  3. package/examples/client-server/client-benchmark.js +43 -32
  4. package/examples/client-server/client-periodic.js +30 -14
  5. package/examples/client-server/client.js +6 -5
  6. package/examples/client-server/package-lock.json +183 -44
  7. package/examples/client-server/signaling-server.js +3 -5
  8. package/examples/media/media.js +9 -9
  9. package/lib/index.d.ts +100 -100
  10. package/node_modules/lru-cache/package.json +2 -4
  11. package/node_modules/minimist/package.json +0 -1
  12. package/node_modules/node-abi/node_modules/semver/README.md +3 -1
  13. package/node_modules/node-abi/node_modules/semver/bin/semver.js +19 -9
  14. package/node_modules/node-abi/node_modules/semver/classes/comparator.js +3 -2
  15. package/node_modules/node-abi/node_modules/semver/classes/index.js +1 -1
  16. package/node_modules/node-abi/node_modules/semver/classes/range.js +31 -22
  17. package/node_modules/node-abi/node_modules/semver/classes/semver.js +1 -1
  18. package/node_modules/node-abi/node_modules/semver/functions/cmp.js +8 -4
  19. package/node_modules/node-abi/node_modules/semver/functions/coerce.js +3 -2
  20. package/node_modules/node-abi/node_modules/semver/functions/inc.js +4 -1
  21. package/node_modules/node-abi/node_modules/semver/functions/parse.js +1 -1
  22. package/node_modules/node-abi/node_modules/semver/internal/constants.js +2 -2
  23. package/node_modules/node-abi/node_modules/semver/internal/identifiers.js +1 -1
  24. package/node_modules/node-abi/node_modules/semver/internal/parse-options.js +3 -3
  25. package/node_modules/node-abi/node_modules/semver/internal/re.js +3 -3
  26. package/node_modules/node-abi/node_modules/semver/package.json +51 -18
  27. package/node_modules/node-abi/node_modules/semver/ranges/min-version.js +2 -1
  28. package/node_modules/node-abi/node_modules/semver/ranges/outside.js +1 -1
  29. package/node_modules/node-abi/node_modules/semver/ranges/simplify.js +15 -12
  30. package/node_modules/node-abi/node_modules/semver/ranges/subset.js +53 -31
  31. package/node_modules/npmlog/node_modules/are-we-there-yet/package.json +10 -10
  32. package/node_modules/npmlog/package.json +1 -1
  33. package/node_modules/tar-stream/node_modules/bl/.travis.yml +4 -3
  34. package/node_modules/tar-stream/node_modules/bl/BufferList.js +1 -1
  35. package/node_modules/tar-stream/node_modules/bl/package.json +10 -10
  36. package/node_modules/tar-stream/node_modules/bl/test/test.js +20 -2
  37. package/node_modules/wide-align/LICENSE +0 -0
  38. package/node_modules/wide-align/README.md +0 -0
  39. package/node_modules/wide-align/align.js +0 -0
  40. package/node_modules/wide-align/package.json +14 -14
  41. package/package.json +2 -2
  42. package/src/data-channel-wrapper.cpp +69 -53
  43. package/src/data-channel-wrapper.h +0 -1
  44. package/src/media-track-wrapper.cpp +91 -52
  45. package/src/media-track-wrapper.h +0 -1
  46. package/src/peer-connection-wrapper.cpp +106 -70
  47. package/src/peer-connection-wrapper.h +0 -2
  48. package/test/connectivity.js +18 -17
  49. package/test/test.js +22 -30
  50. 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) & Configuration (Object) expected").ThrowAsJavaScriptException();
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 peerConnection# ") + ex.what()).ThrowAsJavaScriptException();
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 && !mDoCloseFlag)
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::cout << std::string("libdatachannel error while closing peerConnection# ") + ex.what() << std::endl;
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(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
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(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
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 decsription # ") + ex.what()).ThrowAsJavaScriptException();
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
- std::optional<rtc::Description> desc = mRtcPeerConnPtr->localDescription();
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(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
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# ") + ex.what()).ThrowAsJavaScriptException();
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(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
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# ") + ex.what()).ThrowAsJavaScriptException();
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([&](const rtc::Description &sdp) {
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([&](const rtc::Candidate &candidate) {
596
+ mRtcPeerConnPtr->onLocalCandidate([&](rtc::Candidate cand) {
606
597
  if (mOnLocalCandidateCallback)
607
- mOnLocalCandidateCallback->call([this, candidate](Napi::Env env, std::vector<napi_value> &args) {
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(candidate)),
616
- Napi::String::New(env, candidate.mid())};
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
- // onState cb will be called from constructor
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# ") + ex.what()).ThrowAsJavaScriptException();
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# ") + ex.what()).ThrowAsJavaScriptException();
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# ") + ex.what()).ThrowAsJavaScriptException();
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 Napi::Number::New(info.Env(), 0);
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 info.Env().Null();
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# ") + ex.what()).ThrowAsJavaScriptException();
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(info.Env(), "It seems peer-connection is closed").ThrowAsJavaScriptException();
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# ") + ex.what()).ThrowAsJavaScriptException();
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
  }
@@ -55,8 +55,6 @@ private:
55
55
  static std::unordered_set<PeerConnectionWrapper *> instances;
56
56
 
57
57
  void doClose();
58
- void cleanCbsAndEraseInstance();
59
- bool mDoCloseFlag = false;
60
58
 
61
59
  std::string mPeerName;
62
60
  std::unique_ptr<rtc::PeerConnection> mRtcPeerConnPtr = nullptr;
@@ -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("Debug");
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("Peer1", { iceServers: ["stun:stun.l.google.com:19302"] });
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("Peer1 State:", state);
32
+ console.log('Peer1 State:', state);
32
33
  });
33
34
  peer1.onGatheringStateChange((state) => {
34
- console.log("Peer1 GatheringState:", state);
35
+ console.log('Peer1 GatheringState:', state);
35
36
  });
36
37
  peer1.onLocalDescription((sdp, type) => {
37
- console.log("Peer1 SDP:", sdp, " Type:", type);
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("Peer1 Candidate:", candidate);
42
+ console.log('Peer1 Candidate:', candidate);
42
43
  peer2.addRemoteCandidate(candidate, mid);
43
44
  });
44
45
 
45
- let peer2 = new nodeDataChannel.PeerConnection("Peer2", { iceServers: ["stun:stun.l.google.com:19302"] });
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("Peer2 State:", state);
50
+ console.log('Peer2 State:', state);
50
51
  });
51
52
  peer2.onGatheringStateChange((state) => {
52
- console.log("Peer2 GatheringState:", state);
53
+ console.log('Peer2 GatheringState:', state);
53
54
  });
54
55
  peer2.onLocalDescription((sdp, type) => {
55
- console.log("Peer2 SDP:", sdp, " Type:", type);
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("Peer2 Candidate:", candidate);
60
+ console.log('Peer2 Candidate:', candidate);
60
61
  peer1.addRemoteCandidate(candidate, mid);
61
62
  });
62
63
  peer2.onDataChannel((dc) => {
63
- console.log("Peer2 Got DataChannel: ", dc.getLabel());
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("Hello From Peer2");
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("test");
84
+ dc1 = peer1.createDataChannel('test');
84
85
  dc1.onOpen(() => {
85
- dc1.sendMessage("Hello from Peer1");
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
- console.log('dc1 closed');
93
+ console.log('dc1 closed');
93
94
  });
94
95
 
95
96
  setTimeout(() => {